162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Combined GPIO and pin controller support for Renesas RZ/A1 (r7s72100) SoC 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017 Jacopo Mondi 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * This pin controller/gpio combined driver supports Renesas devices of RZ/A1 1062306a36Sopenharmony_ci * family. 1162306a36Sopenharmony_ci * This includes SoCs which are sub- or super- sets of this particular line, 1262306a36Sopenharmony_ci * as RZ/A1H (r7s721000), RZ/A1M (r7s721010) and RZ/A1L (r7s721020). 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/bitops.h> 1662306a36Sopenharmony_ci#include <linux/err.h> 1762306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1862306a36Sopenharmony_ci#include <linux/init.h> 1962306a36Sopenharmony_ci#include <linux/ioport.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/of.h> 2262306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 2362306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h> 2462306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 2562306a36Sopenharmony_ci#include <linux/platform_device.h> 2662306a36Sopenharmony_ci#include <linux/property.h> 2762306a36Sopenharmony_ci#include <linux/slab.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include "../core.h" 3062306a36Sopenharmony_ci#include "../devicetree.h" 3162306a36Sopenharmony_ci#include "../pinconf.h" 3262306a36Sopenharmony_ci#include "../pinmux.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define DRIVER_NAME "pinctrl-rza1" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define RZA1_P_REG 0x0000 3762306a36Sopenharmony_ci#define RZA1_PPR_REG 0x0200 3862306a36Sopenharmony_ci#define RZA1_PM_REG 0x0300 3962306a36Sopenharmony_ci#define RZA1_PMC_REG 0x0400 4062306a36Sopenharmony_ci#define RZA1_PFC_REG 0x0500 4162306a36Sopenharmony_ci#define RZA1_PFCE_REG 0x0600 4262306a36Sopenharmony_ci#define RZA1_PFCEA_REG 0x0a00 4362306a36Sopenharmony_ci#define RZA1_PIBC_REG 0x4000 4462306a36Sopenharmony_ci#define RZA1_PBDC_REG 0x4100 4562306a36Sopenharmony_ci#define RZA1_PIPC_REG 0x4200 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define RZA1_ADDR(mem, reg, port) ((mem) + (reg) + ((port) * 4)) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define RZA1_NPORTS 12 5062306a36Sopenharmony_ci#define RZA1_PINS_PER_PORT 16 5162306a36Sopenharmony_ci#define RZA1_NPINS (RZA1_PINS_PER_PORT * RZA1_NPORTS) 5262306a36Sopenharmony_ci#define RZA1_PIN_ID_TO_PORT(id) ((id) / RZA1_PINS_PER_PORT) 5362306a36Sopenharmony_ci#define RZA1_PIN_ID_TO_PIN(id) ((id) % RZA1_PINS_PER_PORT) 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* 5662306a36Sopenharmony_ci * Use 16 lower bits [15:0] for pin identifier 5762306a36Sopenharmony_ci * Use 16 higher bits [31:16] for pin mux function 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci#define MUX_PIN_ID_MASK GENMASK(15, 0) 6062306a36Sopenharmony_ci#define MUX_FUNC_MASK GENMASK(31, 16) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define MUX_FUNC_OFFS 16 6362306a36Sopenharmony_ci#define MUX_FUNC(pinconf) \ 6462306a36Sopenharmony_ci ((pinconf & MUX_FUNC_MASK) >> MUX_FUNC_OFFS) 6562306a36Sopenharmony_ci#define MUX_FUNC_PFC_MASK BIT(0) 6662306a36Sopenharmony_ci#define MUX_FUNC_PFCE_MASK BIT(1) 6762306a36Sopenharmony_ci#define MUX_FUNC_PFCEA_MASK BIT(2) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* Pin mux flags */ 7062306a36Sopenharmony_ci#define MUX_FLAGS_BIDIR BIT(0) 7162306a36Sopenharmony_ci#define MUX_FLAGS_SWIO_INPUT BIT(1) 7262306a36Sopenharmony_ci#define MUX_FLAGS_SWIO_OUTPUT BIT(2) 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 7562306a36Sopenharmony_ci * RZ/A1 pinmux flags 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* 7962306a36Sopenharmony_ci * rza1_bidir_pin - describe a single pin that needs bidir flag applied. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_cistruct rza1_bidir_pin { 8262306a36Sopenharmony_ci u8 pin: 4; 8362306a36Sopenharmony_ci u8 func: 4; 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * rza1_bidir_entry - describe a list of pins that needs bidir flag applied. 8862306a36Sopenharmony_ci * Each struct rza1_bidir_entry describes a port. 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_cistruct rza1_bidir_entry { 9162306a36Sopenharmony_ci const unsigned int npins; 9262306a36Sopenharmony_ci const struct rza1_bidir_pin *pins; 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/* 9662306a36Sopenharmony_ci * rza1_swio_pin - describe a single pin that needs swio flag applied. 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_cistruct rza1_swio_pin { 9962306a36Sopenharmony_ci u16 pin: 4; 10062306a36Sopenharmony_ci u16 port: 4; 10162306a36Sopenharmony_ci u16 func: 4; 10262306a36Sopenharmony_ci u16 input: 1; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* 10662306a36Sopenharmony_ci * rza1_swio_entry - describe a list of pins that needs swio flag applied 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_cistruct rza1_swio_entry { 10962306a36Sopenharmony_ci const unsigned int npins; 11062306a36Sopenharmony_ci const struct rza1_swio_pin *pins; 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/* 11462306a36Sopenharmony_ci * rza1_pinmux_conf - group together bidir and swio pinmux flag tables 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_cistruct rza1_pinmux_conf { 11762306a36Sopenharmony_ci const struct rza1_bidir_entry *bidir_entries; 11862306a36Sopenharmony_ci const struct rza1_swio_entry *swio_entries; 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 12262306a36Sopenharmony_ci * RZ/A1H (r7s72100) pinmux flags 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p1[] = { 12662306a36Sopenharmony_ci { .pin = 0, .func = 1 }, 12762306a36Sopenharmony_ci { .pin = 1, .func = 1 }, 12862306a36Sopenharmony_ci { .pin = 2, .func = 1 }, 12962306a36Sopenharmony_ci { .pin = 3, .func = 1 }, 13062306a36Sopenharmony_ci { .pin = 4, .func = 1 }, 13162306a36Sopenharmony_ci { .pin = 5, .func = 1 }, 13262306a36Sopenharmony_ci { .pin = 6, .func = 1 }, 13362306a36Sopenharmony_ci { .pin = 7, .func = 1 }, 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p2[] = { 13762306a36Sopenharmony_ci { .pin = 0, .func = 1 }, 13862306a36Sopenharmony_ci { .pin = 1, .func = 1 }, 13962306a36Sopenharmony_ci { .pin = 2, .func = 1 }, 14062306a36Sopenharmony_ci { .pin = 3, .func = 1 }, 14162306a36Sopenharmony_ci { .pin = 4, .func = 1 }, 14262306a36Sopenharmony_ci { .pin = 0, .func = 4 }, 14362306a36Sopenharmony_ci { .pin = 1, .func = 4 }, 14462306a36Sopenharmony_ci { .pin = 2, .func = 4 }, 14562306a36Sopenharmony_ci { .pin = 3, .func = 4 }, 14662306a36Sopenharmony_ci { .pin = 5, .func = 1 }, 14762306a36Sopenharmony_ci { .pin = 6, .func = 1 }, 14862306a36Sopenharmony_ci { .pin = 7, .func = 1 }, 14962306a36Sopenharmony_ci { .pin = 8, .func = 1 }, 15062306a36Sopenharmony_ci { .pin = 9, .func = 1 }, 15162306a36Sopenharmony_ci { .pin = 10, .func = 1 }, 15262306a36Sopenharmony_ci { .pin = 11, .func = 1 }, 15362306a36Sopenharmony_ci { .pin = 12, .func = 1 }, 15462306a36Sopenharmony_ci { .pin = 13, .func = 1 }, 15562306a36Sopenharmony_ci { .pin = 14, .func = 1 }, 15662306a36Sopenharmony_ci { .pin = 15, .func = 1 }, 15762306a36Sopenharmony_ci { .pin = 12, .func = 4 }, 15862306a36Sopenharmony_ci { .pin = 13, .func = 4 }, 15962306a36Sopenharmony_ci { .pin = 14, .func = 4 }, 16062306a36Sopenharmony_ci { .pin = 15, .func = 4 }, 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p3[] = { 16462306a36Sopenharmony_ci { .pin = 3, .func = 2 }, 16562306a36Sopenharmony_ci { .pin = 10, .func = 7 }, 16662306a36Sopenharmony_ci { .pin = 11, .func = 7 }, 16762306a36Sopenharmony_ci { .pin = 13, .func = 7 }, 16862306a36Sopenharmony_ci { .pin = 14, .func = 7 }, 16962306a36Sopenharmony_ci { .pin = 15, .func = 7 }, 17062306a36Sopenharmony_ci { .pin = 10, .func = 8 }, 17162306a36Sopenharmony_ci { .pin = 11, .func = 8 }, 17262306a36Sopenharmony_ci { .pin = 13, .func = 8 }, 17362306a36Sopenharmony_ci { .pin = 14, .func = 8 }, 17462306a36Sopenharmony_ci { .pin = 15, .func = 8 }, 17562306a36Sopenharmony_ci}; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p4[] = { 17862306a36Sopenharmony_ci { .pin = 0, .func = 8 }, 17962306a36Sopenharmony_ci { .pin = 1, .func = 8 }, 18062306a36Sopenharmony_ci { .pin = 2, .func = 8 }, 18162306a36Sopenharmony_ci { .pin = 3, .func = 8 }, 18262306a36Sopenharmony_ci { .pin = 10, .func = 3 }, 18362306a36Sopenharmony_ci { .pin = 11, .func = 3 }, 18462306a36Sopenharmony_ci { .pin = 13, .func = 3 }, 18562306a36Sopenharmony_ci { .pin = 14, .func = 3 }, 18662306a36Sopenharmony_ci { .pin = 15, .func = 3 }, 18762306a36Sopenharmony_ci { .pin = 10, .func = 4 }, 18862306a36Sopenharmony_ci { .pin = 11, .func = 4 }, 18962306a36Sopenharmony_ci { .pin = 13, .func = 4 }, 19062306a36Sopenharmony_ci { .pin = 14, .func = 4 }, 19162306a36Sopenharmony_ci { .pin = 15, .func = 4 }, 19262306a36Sopenharmony_ci { .pin = 12, .func = 5 }, 19362306a36Sopenharmony_ci { .pin = 13, .func = 5 }, 19462306a36Sopenharmony_ci { .pin = 14, .func = 5 }, 19562306a36Sopenharmony_ci { .pin = 15, .func = 5 }, 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p6[] = { 19962306a36Sopenharmony_ci { .pin = 0, .func = 1 }, 20062306a36Sopenharmony_ci { .pin = 1, .func = 1 }, 20162306a36Sopenharmony_ci { .pin = 2, .func = 1 }, 20262306a36Sopenharmony_ci { .pin = 3, .func = 1 }, 20362306a36Sopenharmony_ci { .pin = 4, .func = 1 }, 20462306a36Sopenharmony_ci { .pin = 5, .func = 1 }, 20562306a36Sopenharmony_ci { .pin = 6, .func = 1 }, 20662306a36Sopenharmony_ci { .pin = 7, .func = 1 }, 20762306a36Sopenharmony_ci { .pin = 8, .func = 1 }, 20862306a36Sopenharmony_ci { .pin = 9, .func = 1 }, 20962306a36Sopenharmony_ci { .pin = 10, .func = 1 }, 21062306a36Sopenharmony_ci { .pin = 11, .func = 1 }, 21162306a36Sopenharmony_ci { .pin = 12, .func = 1 }, 21262306a36Sopenharmony_ci { .pin = 13, .func = 1 }, 21362306a36Sopenharmony_ci { .pin = 14, .func = 1 }, 21462306a36Sopenharmony_ci { .pin = 15, .func = 1 }, 21562306a36Sopenharmony_ci}; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p7[] = { 21862306a36Sopenharmony_ci { .pin = 13, .func = 3 }, 21962306a36Sopenharmony_ci}; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p8[] = { 22262306a36Sopenharmony_ci { .pin = 8, .func = 3 }, 22362306a36Sopenharmony_ci { .pin = 9, .func = 3 }, 22462306a36Sopenharmony_ci { .pin = 10, .func = 3 }, 22562306a36Sopenharmony_ci { .pin = 11, .func = 3 }, 22662306a36Sopenharmony_ci { .pin = 14, .func = 2 }, 22762306a36Sopenharmony_ci { .pin = 15, .func = 2 }, 22862306a36Sopenharmony_ci { .pin = 14, .func = 3 }, 22962306a36Sopenharmony_ci { .pin = 15, .func = 3 }, 23062306a36Sopenharmony_ci}; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p9[] = { 23362306a36Sopenharmony_ci { .pin = 0, .func = 2 }, 23462306a36Sopenharmony_ci { .pin = 1, .func = 2 }, 23562306a36Sopenharmony_ci { .pin = 4, .func = 2 }, 23662306a36Sopenharmony_ci { .pin = 5, .func = 2 }, 23762306a36Sopenharmony_ci { .pin = 6, .func = 2 }, 23862306a36Sopenharmony_ci { .pin = 7, .func = 2 }, 23962306a36Sopenharmony_ci}; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p11[] = { 24262306a36Sopenharmony_ci { .pin = 6, .func = 2 }, 24362306a36Sopenharmony_ci { .pin = 7, .func = 2 }, 24462306a36Sopenharmony_ci { .pin = 9, .func = 2 }, 24562306a36Sopenharmony_ci { .pin = 6, .func = 4 }, 24662306a36Sopenharmony_ci { .pin = 7, .func = 4 }, 24762306a36Sopenharmony_ci { .pin = 9, .func = 4 }, 24862306a36Sopenharmony_ci { .pin = 10, .func = 2 }, 24962306a36Sopenharmony_ci { .pin = 11, .func = 2 }, 25062306a36Sopenharmony_ci { .pin = 10, .func = 4 }, 25162306a36Sopenharmony_ci { .pin = 11, .func = 4 }, 25262306a36Sopenharmony_ci { .pin = 12, .func = 4 }, 25362306a36Sopenharmony_ci { .pin = 13, .func = 4 }, 25462306a36Sopenharmony_ci { .pin = 14, .func = 4 }, 25562306a36Sopenharmony_ci { .pin = 15, .func = 4 }, 25662306a36Sopenharmony_ci}; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic const struct rza1_swio_pin rza1h_swio_pins[] = { 25962306a36Sopenharmony_ci { .port = 2, .pin = 7, .func = 4, .input = 0 }, 26062306a36Sopenharmony_ci { .port = 2, .pin = 11, .func = 4, .input = 0 }, 26162306a36Sopenharmony_ci { .port = 3, .pin = 7, .func = 3, .input = 0 }, 26262306a36Sopenharmony_ci { .port = 3, .pin = 7, .func = 8, .input = 0 }, 26362306a36Sopenharmony_ci { .port = 4, .pin = 7, .func = 5, .input = 0 }, 26462306a36Sopenharmony_ci { .port = 4, .pin = 7, .func = 11, .input = 0 }, 26562306a36Sopenharmony_ci { .port = 4, .pin = 15, .func = 6, .input = 0 }, 26662306a36Sopenharmony_ci { .port = 5, .pin = 0, .func = 1, .input = 1 }, 26762306a36Sopenharmony_ci { .port = 5, .pin = 1, .func = 1, .input = 1 }, 26862306a36Sopenharmony_ci { .port = 5, .pin = 2, .func = 1, .input = 1 }, 26962306a36Sopenharmony_ci { .port = 5, .pin = 3, .func = 1, .input = 1 }, 27062306a36Sopenharmony_ci { .port = 5, .pin = 4, .func = 1, .input = 1 }, 27162306a36Sopenharmony_ci { .port = 5, .pin = 5, .func = 1, .input = 1 }, 27262306a36Sopenharmony_ci { .port = 5, .pin = 6, .func = 1, .input = 1 }, 27362306a36Sopenharmony_ci { .port = 5, .pin = 7, .func = 1, .input = 1 }, 27462306a36Sopenharmony_ci { .port = 7, .pin = 4, .func = 6, .input = 0 }, 27562306a36Sopenharmony_ci { .port = 7, .pin = 11, .func = 2, .input = 0 }, 27662306a36Sopenharmony_ci { .port = 8, .pin = 10, .func = 8, .input = 0 }, 27762306a36Sopenharmony_ci { .port = 10, .pin = 15, .func = 2, .input = 0 }, 27862306a36Sopenharmony_ci}; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic const struct rza1_bidir_entry rza1h_bidir_entries[RZA1_NPORTS] = { 28162306a36Sopenharmony_ci [1] = { ARRAY_SIZE(rza1h_bidir_pins_p1), rza1h_bidir_pins_p1 }, 28262306a36Sopenharmony_ci [2] = { ARRAY_SIZE(rza1h_bidir_pins_p2), rza1h_bidir_pins_p2 }, 28362306a36Sopenharmony_ci [3] = { ARRAY_SIZE(rza1h_bidir_pins_p3), rza1h_bidir_pins_p3 }, 28462306a36Sopenharmony_ci [4] = { ARRAY_SIZE(rza1h_bidir_pins_p4), rza1h_bidir_pins_p4 }, 28562306a36Sopenharmony_ci [6] = { ARRAY_SIZE(rza1h_bidir_pins_p6), rza1h_bidir_pins_p6 }, 28662306a36Sopenharmony_ci [7] = { ARRAY_SIZE(rza1h_bidir_pins_p7), rza1h_bidir_pins_p7 }, 28762306a36Sopenharmony_ci [8] = { ARRAY_SIZE(rza1h_bidir_pins_p8), rza1h_bidir_pins_p8 }, 28862306a36Sopenharmony_ci [9] = { ARRAY_SIZE(rza1h_bidir_pins_p9), rza1h_bidir_pins_p9 }, 28962306a36Sopenharmony_ci [11] = { ARRAY_SIZE(rza1h_bidir_pins_p11), rza1h_bidir_pins_p11 }, 29062306a36Sopenharmony_ci}; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic const struct rza1_swio_entry rza1h_swio_entries[] = { 29362306a36Sopenharmony_ci [0] = { ARRAY_SIZE(rza1h_swio_pins), rza1h_swio_pins }, 29462306a36Sopenharmony_ci}; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci/* RZ/A1H (r7s72100x) pinmux flags table */ 29762306a36Sopenharmony_cistatic const struct rza1_pinmux_conf rza1h_pmx_conf = { 29862306a36Sopenharmony_ci .bidir_entries = rza1h_bidir_entries, 29962306a36Sopenharmony_ci .swio_entries = rza1h_swio_entries, 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 30362306a36Sopenharmony_ci * RZ/A1L (r7s72102) pinmux flags 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p1[] = { 30762306a36Sopenharmony_ci { .pin = 0, .func = 1 }, 30862306a36Sopenharmony_ci { .pin = 1, .func = 1 }, 30962306a36Sopenharmony_ci { .pin = 2, .func = 1 }, 31062306a36Sopenharmony_ci { .pin = 3, .func = 1 }, 31162306a36Sopenharmony_ci { .pin = 4, .func = 1 }, 31262306a36Sopenharmony_ci { .pin = 5, .func = 1 }, 31362306a36Sopenharmony_ci { .pin = 6, .func = 1 }, 31462306a36Sopenharmony_ci { .pin = 7, .func = 1 }, 31562306a36Sopenharmony_ci}; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p3[] = { 31862306a36Sopenharmony_ci { .pin = 0, .func = 2 }, 31962306a36Sopenharmony_ci { .pin = 1, .func = 2 }, 32062306a36Sopenharmony_ci { .pin = 2, .func = 2 }, 32162306a36Sopenharmony_ci { .pin = 4, .func = 2 }, 32262306a36Sopenharmony_ci { .pin = 5, .func = 2 }, 32362306a36Sopenharmony_ci { .pin = 10, .func = 2 }, 32462306a36Sopenharmony_ci { .pin = 11, .func = 2 }, 32562306a36Sopenharmony_ci { .pin = 12, .func = 2 }, 32662306a36Sopenharmony_ci { .pin = 13, .func = 2 }, 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p4[] = { 33062306a36Sopenharmony_ci { .pin = 1, .func = 4 }, 33162306a36Sopenharmony_ci { .pin = 2, .func = 2 }, 33262306a36Sopenharmony_ci { .pin = 3, .func = 2 }, 33362306a36Sopenharmony_ci { .pin = 6, .func = 2 }, 33462306a36Sopenharmony_ci { .pin = 7, .func = 2 }, 33562306a36Sopenharmony_ci}; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p5[] = { 33862306a36Sopenharmony_ci { .pin = 0, .func = 1 }, 33962306a36Sopenharmony_ci { .pin = 1, .func = 1 }, 34062306a36Sopenharmony_ci { .pin = 2, .func = 1 }, 34162306a36Sopenharmony_ci { .pin = 3, .func = 1 }, 34262306a36Sopenharmony_ci { .pin = 4, .func = 1 }, 34362306a36Sopenharmony_ci { .pin = 5, .func = 1 }, 34462306a36Sopenharmony_ci { .pin = 6, .func = 1 }, 34562306a36Sopenharmony_ci { .pin = 7, .func = 1 }, 34662306a36Sopenharmony_ci { .pin = 8, .func = 1 }, 34762306a36Sopenharmony_ci { .pin = 9, .func = 1 }, 34862306a36Sopenharmony_ci { .pin = 10, .func = 1 }, 34962306a36Sopenharmony_ci { .pin = 11, .func = 1 }, 35062306a36Sopenharmony_ci { .pin = 12, .func = 1 }, 35162306a36Sopenharmony_ci { .pin = 13, .func = 1 }, 35262306a36Sopenharmony_ci { .pin = 14, .func = 1 }, 35362306a36Sopenharmony_ci { .pin = 15, .func = 1 }, 35462306a36Sopenharmony_ci { .pin = 0, .func = 2 }, 35562306a36Sopenharmony_ci { .pin = 1, .func = 2 }, 35662306a36Sopenharmony_ci { .pin = 2, .func = 2 }, 35762306a36Sopenharmony_ci { .pin = 3, .func = 2 }, 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p6[] = { 36162306a36Sopenharmony_ci { .pin = 0, .func = 1 }, 36262306a36Sopenharmony_ci { .pin = 1, .func = 1 }, 36362306a36Sopenharmony_ci { .pin = 2, .func = 1 }, 36462306a36Sopenharmony_ci { .pin = 3, .func = 1 }, 36562306a36Sopenharmony_ci { .pin = 4, .func = 1 }, 36662306a36Sopenharmony_ci { .pin = 5, .func = 1 }, 36762306a36Sopenharmony_ci { .pin = 6, .func = 1 }, 36862306a36Sopenharmony_ci { .pin = 7, .func = 1 }, 36962306a36Sopenharmony_ci { .pin = 8, .func = 1 }, 37062306a36Sopenharmony_ci { .pin = 9, .func = 1 }, 37162306a36Sopenharmony_ci { .pin = 10, .func = 1 }, 37262306a36Sopenharmony_ci { .pin = 11, .func = 1 }, 37362306a36Sopenharmony_ci { .pin = 12, .func = 1 }, 37462306a36Sopenharmony_ci { .pin = 13, .func = 1 }, 37562306a36Sopenharmony_ci { .pin = 14, .func = 1 }, 37662306a36Sopenharmony_ci { .pin = 15, .func = 1 }, 37762306a36Sopenharmony_ci}; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p7[] = { 38062306a36Sopenharmony_ci { .pin = 2, .func = 2 }, 38162306a36Sopenharmony_ci { .pin = 3, .func = 2 }, 38262306a36Sopenharmony_ci { .pin = 5, .func = 2 }, 38362306a36Sopenharmony_ci { .pin = 6, .func = 2 }, 38462306a36Sopenharmony_ci { .pin = 7, .func = 2 }, 38562306a36Sopenharmony_ci { .pin = 2, .func = 3 }, 38662306a36Sopenharmony_ci { .pin = 3, .func = 3 }, 38762306a36Sopenharmony_ci { .pin = 5, .func = 3 }, 38862306a36Sopenharmony_ci { .pin = 6, .func = 3 }, 38962306a36Sopenharmony_ci { .pin = 7, .func = 3 }, 39062306a36Sopenharmony_ci}; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p9[] = { 39362306a36Sopenharmony_ci { .pin = 1, .func = 2 }, 39462306a36Sopenharmony_ci { .pin = 0, .func = 3 }, 39562306a36Sopenharmony_ci { .pin = 1, .func = 3 }, 39662306a36Sopenharmony_ci { .pin = 3, .func = 3 }, 39762306a36Sopenharmony_ci { .pin = 4, .func = 3 }, 39862306a36Sopenharmony_ci { .pin = 5, .func = 3 }, 39962306a36Sopenharmony_ci}; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic const struct rza1_swio_pin rza1l_swio_pins[] = { 40262306a36Sopenharmony_ci { .port = 2, .pin = 8, .func = 2, .input = 0 }, 40362306a36Sopenharmony_ci { .port = 5, .pin = 6, .func = 3, .input = 0 }, 40462306a36Sopenharmony_ci { .port = 6, .pin = 6, .func = 3, .input = 0 }, 40562306a36Sopenharmony_ci { .port = 6, .pin = 10, .func = 3, .input = 0 }, 40662306a36Sopenharmony_ci { .port = 7, .pin = 10, .func = 2, .input = 0 }, 40762306a36Sopenharmony_ci { .port = 8, .pin = 2, .func = 3, .input = 0 }, 40862306a36Sopenharmony_ci}; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic const struct rza1_bidir_entry rza1l_bidir_entries[RZA1_NPORTS] = { 41162306a36Sopenharmony_ci [1] = { ARRAY_SIZE(rza1l_bidir_pins_p1), rza1l_bidir_pins_p1 }, 41262306a36Sopenharmony_ci [3] = { ARRAY_SIZE(rza1l_bidir_pins_p3), rza1l_bidir_pins_p3 }, 41362306a36Sopenharmony_ci [4] = { ARRAY_SIZE(rza1l_bidir_pins_p4), rza1l_bidir_pins_p4 }, 41462306a36Sopenharmony_ci [5] = { ARRAY_SIZE(rza1l_bidir_pins_p4), rza1l_bidir_pins_p5 }, 41562306a36Sopenharmony_ci [6] = { ARRAY_SIZE(rza1l_bidir_pins_p6), rza1l_bidir_pins_p6 }, 41662306a36Sopenharmony_ci [7] = { ARRAY_SIZE(rza1l_bidir_pins_p7), rza1l_bidir_pins_p7 }, 41762306a36Sopenharmony_ci [9] = { ARRAY_SIZE(rza1l_bidir_pins_p9), rza1l_bidir_pins_p9 }, 41862306a36Sopenharmony_ci}; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic const struct rza1_swio_entry rza1l_swio_entries[] = { 42162306a36Sopenharmony_ci [0] = { ARRAY_SIZE(rza1l_swio_pins), rza1l_swio_pins }, 42262306a36Sopenharmony_ci}; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci/* RZ/A1L (r7s72102x) pinmux flags table */ 42562306a36Sopenharmony_cistatic const struct rza1_pinmux_conf rza1l_pmx_conf = { 42662306a36Sopenharmony_ci .bidir_entries = rza1l_bidir_entries, 42762306a36Sopenharmony_ci .swio_entries = rza1l_swio_entries, 42862306a36Sopenharmony_ci}; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 43162306a36Sopenharmony_ci * RZ/A1 types 43262306a36Sopenharmony_ci */ 43362306a36Sopenharmony_ci/** 43462306a36Sopenharmony_ci * struct rza1_mux_conf - describes a pin multiplexing operation 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci * @id: the pin identifier from 0 to RZA1_NPINS 43762306a36Sopenharmony_ci * @port: the port where pin sits on 43862306a36Sopenharmony_ci * @pin: pin id 43962306a36Sopenharmony_ci * @mux_func: alternate function id number 44062306a36Sopenharmony_ci * @mux_flags: alternate function flags 44162306a36Sopenharmony_ci * @value: output value to set the pin to 44262306a36Sopenharmony_ci */ 44362306a36Sopenharmony_cistruct rza1_mux_conf { 44462306a36Sopenharmony_ci u16 id; 44562306a36Sopenharmony_ci u8 port; 44662306a36Sopenharmony_ci u8 pin; 44762306a36Sopenharmony_ci u8 mux_func; 44862306a36Sopenharmony_ci u8 mux_flags; 44962306a36Sopenharmony_ci u8 value; 45062306a36Sopenharmony_ci}; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci/** 45362306a36Sopenharmony_ci * struct rza1_port - describes a pin port 45462306a36Sopenharmony_ci * 45562306a36Sopenharmony_ci * This is mostly useful to lock register writes per-bank and not globally. 45662306a36Sopenharmony_ci * 45762306a36Sopenharmony_ci * @lock: protect access to HW registers 45862306a36Sopenharmony_ci * @id: port number 45962306a36Sopenharmony_ci * @base: logical address base 46062306a36Sopenharmony_ci * @pins: pins sitting on this port 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_cistruct rza1_port { 46362306a36Sopenharmony_ci spinlock_t lock; 46462306a36Sopenharmony_ci unsigned int id; 46562306a36Sopenharmony_ci void __iomem *base; 46662306a36Sopenharmony_ci struct pinctrl_pin_desc *pins; 46762306a36Sopenharmony_ci}; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/** 47062306a36Sopenharmony_ci * struct rza1_pinctrl - RZ pincontroller device 47162306a36Sopenharmony_ci * 47262306a36Sopenharmony_ci * @dev: parent device structure 47362306a36Sopenharmony_ci * @mutex: protect [pinctrl|pinmux]_generic functions 47462306a36Sopenharmony_ci * @base: logical address base 47562306a36Sopenharmony_ci * @nport: number of pin controller ports 47662306a36Sopenharmony_ci * @ports: pin controller banks 47762306a36Sopenharmony_ci * @pins: pin array for pinctrl core 47862306a36Sopenharmony_ci * @desc: pincontroller desc for pinctrl core 47962306a36Sopenharmony_ci * @pctl: pinctrl device 48062306a36Sopenharmony_ci * @data: device specific data 48162306a36Sopenharmony_ci */ 48262306a36Sopenharmony_cistruct rza1_pinctrl { 48362306a36Sopenharmony_ci struct device *dev; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci struct mutex mutex; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci void __iomem *base; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci unsigned int nport; 49062306a36Sopenharmony_ci struct rza1_port *ports; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci struct pinctrl_pin_desc *pins; 49362306a36Sopenharmony_ci struct pinctrl_desc desc; 49462306a36Sopenharmony_ci struct pinctrl_dev *pctl; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci const void *data; 49762306a36Sopenharmony_ci}; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 50062306a36Sopenharmony_ci * RZ/A1 pinmux flags 50162306a36Sopenharmony_ci */ 50262306a36Sopenharmony_cistatic inline bool rza1_pinmux_get_bidir(unsigned int port, 50362306a36Sopenharmony_ci unsigned int pin, 50462306a36Sopenharmony_ci unsigned int func, 50562306a36Sopenharmony_ci const struct rza1_bidir_entry *table) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci const struct rza1_bidir_entry *entry = &table[port]; 50862306a36Sopenharmony_ci const struct rza1_bidir_pin *bidir_pin; 50962306a36Sopenharmony_ci unsigned int i; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci for (i = 0; i < entry->npins; ++i) { 51262306a36Sopenharmony_ci bidir_pin = &entry->pins[i]; 51362306a36Sopenharmony_ci if (bidir_pin->pin == pin && bidir_pin->func == func) 51462306a36Sopenharmony_ci return true; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci return false; 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_cistatic inline int rza1_pinmux_get_swio(unsigned int port, 52162306a36Sopenharmony_ci unsigned int pin, 52262306a36Sopenharmony_ci unsigned int func, 52362306a36Sopenharmony_ci const struct rza1_swio_entry *table) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci const struct rza1_swio_pin *swio_pin; 52662306a36Sopenharmony_ci unsigned int i; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci for (i = 0; i < table->npins; ++i) { 53062306a36Sopenharmony_ci swio_pin = &table->pins[i]; 53162306a36Sopenharmony_ci if (swio_pin->port == port && swio_pin->pin == pin && 53262306a36Sopenharmony_ci swio_pin->func == func) 53362306a36Sopenharmony_ci return swio_pin->input; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci return -ENOENT; 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci/* 54062306a36Sopenharmony_ci * rza1_pinmux_get_flags() - return pinmux flags associated to a pin 54162306a36Sopenharmony_ci */ 54262306a36Sopenharmony_cistatic unsigned int rza1_pinmux_get_flags(unsigned int port, unsigned int pin, 54362306a36Sopenharmony_ci unsigned int func, 54462306a36Sopenharmony_ci struct rza1_pinctrl *rza1_pctl) 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci const struct rza1_pinmux_conf *pmx_conf = rza1_pctl->data; 54862306a36Sopenharmony_ci const struct rza1_bidir_entry *bidir_entries = pmx_conf->bidir_entries; 54962306a36Sopenharmony_ci const struct rza1_swio_entry *swio_entries = pmx_conf->swio_entries; 55062306a36Sopenharmony_ci unsigned int pmx_flags = 0; 55162306a36Sopenharmony_ci int ret; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (rza1_pinmux_get_bidir(port, pin, func, bidir_entries)) 55462306a36Sopenharmony_ci pmx_flags |= MUX_FLAGS_BIDIR; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci ret = rza1_pinmux_get_swio(port, pin, func, swio_entries); 55762306a36Sopenharmony_ci if (ret == 0) 55862306a36Sopenharmony_ci pmx_flags |= MUX_FLAGS_SWIO_OUTPUT; 55962306a36Sopenharmony_ci else if (ret > 0) 56062306a36Sopenharmony_ci pmx_flags |= MUX_FLAGS_SWIO_INPUT; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci return pmx_flags; 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 56662306a36Sopenharmony_ci * RZ/A1 SoC operations 56762306a36Sopenharmony_ci */ 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci/* 57062306a36Sopenharmony_ci * rza1_set_bit() - un-locked set/clear a single bit in pin configuration 57162306a36Sopenharmony_ci * registers 57262306a36Sopenharmony_ci */ 57362306a36Sopenharmony_cistatic inline void rza1_set_bit(struct rza1_port *port, unsigned int reg, 57462306a36Sopenharmony_ci unsigned int bit, bool set) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci void __iomem *mem = RZA1_ADDR(port->base, reg, port->id); 57762306a36Sopenharmony_ci u16 val = ioread16(mem); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (set) 58062306a36Sopenharmony_ci val |= BIT(bit); 58162306a36Sopenharmony_ci else 58262306a36Sopenharmony_ci val &= ~BIT(bit); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci iowrite16(val, mem); 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_cistatic inline unsigned int rza1_get_bit(struct rza1_port *port, 58862306a36Sopenharmony_ci unsigned int reg, unsigned int bit) 58962306a36Sopenharmony_ci{ 59062306a36Sopenharmony_ci void __iomem *mem = RZA1_ADDR(port->base, reg, port->id); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci return ioread16(mem) & BIT(bit); 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci/** 59662306a36Sopenharmony_ci * rza1_pin_reset() - reset a pin to default initial state 59762306a36Sopenharmony_ci * 59862306a36Sopenharmony_ci * Reset pin state disabling input buffer and bi-directional control, 59962306a36Sopenharmony_ci * and configure it as input port. 60062306a36Sopenharmony_ci * Note that pin is now configured with direction as input but with input 60162306a36Sopenharmony_ci * buffer disabled. This implies the pin value cannot be read in this state. 60262306a36Sopenharmony_ci * 60362306a36Sopenharmony_ci * @port: port where pin sits on 60462306a36Sopenharmony_ci * @pin: pin offset 60562306a36Sopenharmony_ci */ 60662306a36Sopenharmony_cistatic void rza1_pin_reset(struct rza1_port *port, unsigned int pin) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci unsigned long irqflags; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, irqflags); 61162306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PIBC_REG, pin, 0); 61262306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PBDC_REG, pin, 0); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PM_REG, pin, 1); 61562306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PMC_REG, pin, 0); 61662306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PIPC_REG, pin, 0); 61762306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, irqflags); 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci/** 62162306a36Sopenharmony_ci * rza1_pin_set_direction() - set I/O direction on a pin in port mode 62262306a36Sopenharmony_ci * 62362306a36Sopenharmony_ci * When running in output port mode keep PBDC enabled to allow reading the 62462306a36Sopenharmony_ci * pin value from PPR. 62562306a36Sopenharmony_ci * 62662306a36Sopenharmony_ci * @port: port where pin sits on 62762306a36Sopenharmony_ci * @pin: pin offset 62862306a36Sopenharmony_ci * @input: input enable/disable flag 62962306a36Sopenharmony_ci */ 63062306a36Sopenharmony_cistatic inline void rza1_pin_set_direction(struct rza1_port *port, 63162306a36Sopenharmony_ci unsigned int pin, bool input) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci unsigned long irqflags; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, irqflags); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PIBC_REG, pin, 1); 63862306a36Sopenharmony_ci if (input) { 63962306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PM_REG, pin, 1); 64062306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PBDC_REG, pin, 0); 64162306a36Sopenharmony_ci } else { 64262306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PM_REG, pin, 0); 64362306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PBDC_REG, pin, 1); 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, irqflags); 64762306a36Sopenharmony_ci} 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_cistatic inline void rza1_pin_set(struct rza1_port *port, unsigned int pin, 65062306a36Sopenharmony_ci unsigned int value) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci unsigned long irqflags; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, irqflags); 65562306a36Sopenharmony_ci rza1_set_bit(port, RZA1_P_REG, pin, !!value); 65662306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, irqflags); 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cistatic inline int rza1_pin_get(struct rza1_port *port, unsigned int pin) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci return rza1_get_bit(port, RZA1_PPR_REG, pin); 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci/** 66562306a36Sopenharmony_ci * rza1_pin_mux_single() - configure pin multiplexing on a single pin 66662306a36Sopenharmony_ci * 66762306a36Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device 66862306a36Sopenharmony_ci * @mux_conf: pin multiplexing descriptor 66962306a36Sopenharmony_ci */ 67062306a36Sopenharmony_cistatic int rza1_pin_mux_single(struct rza1_pinctrl *rza1_pctl, 67162306a36Sopenharmony_ci struct rza1_mux_conf *mux_conf) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci struct rza1_port *port = &rza1_pctl->ports[mux_conf->port]; 67462306a36Sopenharmony_ci unsigned int pin = mux_conf->pin; 67562306a36Sopenharmony_ci u8 mux_func = mux_conf->mux_func; 67662306a36Sopenharmony_ci u8 mux_flags = mux_conf->mux_flags; 67762306a36Sopenharmony_ci u8 mux_flags_from_table; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci rza1_pin_reset(port, pin); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci /* SWIO pinmux flags coming from DT are high precedence */ 68262306a36Sopenharmony_ci mux_flags_from_table = rza1_pinmux_get_flags(port->id, pin, mux_func, 68362306a36Sopenharmony_ci rza1_pctl); 68462306a36Sopenharmony_ci if (mux_flags) 68562306a36Sopenharmony_ci mux_flags |= (mux_flags_from_table & MUX_FLAGS_BIDIR); 68662306a36Sopenharmony_ci else 68762306a36Sopenharmony_ci mux_flags = mux_flags_from_table; 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci if (mux_flags & MUX_FLAGS_BIDIR) 69062306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PBDC_REG, pin, 1); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci /* 69362306a36Sopenharmony_ci * Enable alternate function mode and select it. 69462306a36Sopenharmony_ci * 69562306a36Sopenharmony_ci * Be careful here: the pin mux sub-nodes in device tree 69662306a36Sopenharmony_ci * enumerate alternate functions from 1 to 8; 69762306a36Sopenharmony_ci * subtract 1 before using macros to match registers configuration 69862306a36Sopenharmony_ci * which expects numbers from 0 to 7 instead. 69962306a36Sopenharmony_ci * 70062306a36Sopenharmony_ci * ---------------------------------------------------- 70162306a36Sopenharmony_ci * Alternate mode selection table: 70262306a36Sopenharmony_ci * 70362306a36Sopenharmony_ci * PMC PFC PFCE PFCAE (mux_func - 1) 70462306a36Sopenharmony_ci * 1 0 0 0 0 70562306a36Sopenharmony_ci * 1 1 0 0 1 70662306a36Sopenharmony_ci * 1 0 1 0 2 70762306a36Sopenharmony_ci * 1 1 1 0 3 70862306a36Sopenharmony_ci * 1 0 0 1 4 70962306a36Sopenharmony_ci * 1 1 0 1 5 71062306a36Sopenharmony_ci * 1 0 1 1 6 71162306a36Sopenharmony_ci * 1 1 1 1 7 71262306a36Sopenharmony_ci * ---------------------------------------------------- 71362306a36Sopenharmony_ci */ 71462306a36Sopenharmony_ci mux_func -= 1; 71562306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PFC_REG, pin, mux_func & MUX_FUNC_PFC_MASK); 71662306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PFCE_REG, pin, mux_func & MUX_FUNC_PFCE_MASK); 71762306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PFCEA_REG, pin, mux_func & MUX_FUNC_PFCEA_MASK); 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* 72062306a36Sopenharmony_ci * All alternate functions except a few need PIPCn = 1. 72162306a36Sopenharmony_ci * If PIPCn has to stay disabled (SW IO mode), configure PMn according 72262306a36Sopenharmony_ci * to I/O direction specified by pin configuration -after- PMC has been 72362306a36Sopenharmony_ci * set to one. 72462306a36Sopenharmony_ci */ 72562306a36Sopenharmony_ci if (mux_flags & (MUX_FLAGS_SWIO_INPUT | MUX_FLAGS_SWIO_OUTPUT)) 72662306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PM_REG, pin, 72762306a36Sopenharmony_ci mux_flags & MUX_FLAGS_SWIO_INPUT); 72862306a36Sopenharmony_ci else 72962306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PIPC_REG, pin, 1); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci rza1_set_bit(port, RZA1_PMC_REG, pin, 1); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci return 0; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 73762306a36Sopenharmony_ci * gpio operations 73862306a36Sopenharmony_ci */ 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci/** 74162306a36Sopenharmony_ci * rza1_gpio_request() - configure pin in port mode 74262306a36Sopenharmony_ci * 74362306a36Sopenharmony_ci * Configure a pin as gpio (port mode). 74462306a36Sopenharmony_ci * After reset, the pin is in input mode with input buffer disabled. 74562306a36Sopenharmony_ci * To use the pin as input or output, set_direction shall be called first 74662306a36Sopenharmony_ci * 74762306a36Sopenharmony_ci * @chip: gpio chip where the gpio sits on 74862306a36Sopenharmony_ci * @gpio: gpio offset 74962306a36Sopenharmony_ci */ 75062306a36Sopenharmony_cistatic int rza1_gpio_request(struct gpio_chip *chip, unsigned int gpio) 75162306a36Sopenharmony_ci{ 75262306a36Sopenharmony_ci struct rza1_port *port = gpiochip_get_data(chip); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci rza1_pin_reset(port, gpio); 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci return 0; 75762306a36Sopenharmony_ci} 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci/** 76062306a36Sopenharmony_ci * rza1_gpio_free() - reset a pin 76162306a36Sopenharmony_ci * 76262306a36Sopenharmony_ci * Surprisingly, freeing a gpio is equivalent to requesting it. 76362306a36Sopenharmony_ci * Reset pin to port mode, with input buffer disabled. This overwrites all 76462306a36Sopenharmony_ci * port direction settings applied with set_direction 76562306a36Sopenharmony_ci * 76662306a36Sopenharmony_ci * @chip: gpio chip where the gpio sits on 76762306a36Sopenharmony_ci * @gpio: gpio offset 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_cistatic void rza1_gpio_free(struct gpio_chip *chip, unsigned int gpio) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci struct rza1_port *port = gpiochip_get_data(chip); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci rza1_pin_reset(port, gpio); 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_cistatic int rza1_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci struct rza1_port *port = gpiochip_get_data(chip); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci if (rza1_get_bit(port, RZA1_PM_REG, gpio)) 78162306a36Sopenharmony_ci return GPIO_LINE_DIRECTION_IN; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci return GPIO_LINE_DIRECTION_OUT; 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_cistatic int rza1_gpio_direction_input(struct gpio_chip *chip, 78762306a36Sopenharmony_ci unsigned int gpio) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci struct rza1_port *port = gpiochip_get_data(chip); 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci rza1_pin_set_direction(port, gpio, true); 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci return 0; 79462306a36Sopenharmony_ci} 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_cistatic int rza1_gpio_direction_output(struct gpio_chip *chip, 79762306a36Sopenharmony_ci unsigned int gpio, 79862306a36Sopenharmony_ci int value) 79962306a36Sopenharmony_ci{ 80062306a36Sopenharmony_ci struct rza1_port *port = gpiochip_get_data(chip); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci /* Set value before driving pin direction */ 80362306a36Sopenharmony_ci rza1_pin_set(port, gpio, value); 80462306a36Sopenharmony_ci rza1_pin_set_direction(port, gpio, false); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci return 0; 80762306a36Sopenharmony_ci} 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci/** 81062306a36Sopenharmony_ci * rza1_gpio_get() - read a gpio pin value 81162306a36Sopenharmony_ci * 81262306a36Sopenharmony_ci * Read gpio pin value through PPR register. 81362306a36Sopenharmony_ci * Requires bi-directional mode to work when reading the value of a pin 81462306a36Sopenharmony_ci * in output mode 81562306a36Sopenharmony_ci * 81662306a36Sopenharmony_ci * @chip: gpio chip where the gpio sits on 81762306a36Sopenharmony_ci * @gpio: gpio offset 81862306a36Sopenharmony_ci */ 81962306a36Sopenharmony_cistatic int rza1_gpio_get(struct gpio_chip *chip, unsigned int gpio) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci struct rza1_port *port = gpiochip_get_data(chip); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci return rza1_pin_get(port, gpio); 82462306a36Sopenharmony_ci} 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_cistatic void rza1_gpio_set(struct gpio_chip *chip, unsigned int gpio, 82762306a36Sopenharmony_ci int value) 82862306a36Sopenharmony_ci{ 82962306a36Sopenharmony_ci struct rza1_port *port = gpiochip_get_data(chip); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci rza1_pin_set(port, gpio, value); 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_cistatic const struct gpio_chip rza1_gpiochip_template = { 83562306a36Sopenharmony_ci .request = rza1_gpio_request, 83662306a36Sopenharmony_ci .free = rza1_gpio_free, 83762306a36Sopenharmony_ci .get_direction = rza1_gpio_get_direction, 83862306a36Sopenharmony_ci .direction_input = rza1_gpio_direction_input, 83962306a36Sopenharmony_ci .direction_output = rza1_gpio_direction_output, 84062306a36Sopenharmony_ci .get = rza1_gpio_get, 84162306a36Sopenharmony_ci .set = rza1_gpio_set, 84262306a36Sopenharmony_ci}; 84362306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 84462306a36Sopenharmony_ci * pinctrl operations 84562306a36Sopenharmony_ci */ 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci/** 84862306a36Sopenharmony_ci * rza1_dt_node_pin_count() - Count number of pins in a dt node or in all its 84962306a36Sopenharmony_ci * children sub-nodes 85062306a36Sopenharmony_ci * 85162306a36Sopenharmony_ci * @np: device tree node to parse 85262306a36Sopenharmony_ci */ 85362306a36Sopenharmony_cistatic int rza1_dt_node_pin_count(struct device_node *np) 85462306a36Sopenharmony_ci{ 85562306a36Sopenharmony_ci struct device_node *child; 85662306a36Sopenharmony_ci struct property *of_pins; 85762306a36Sopenharmony_ci unsigned int npins; 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci of_pins = of_find_property(np, "pinmux", NULL); 86062306a36Sopenharmony_ci if (of_pins) 86162306a36Sopenharmony_ci return of_pins->length / sizeof(u32); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci npins = 0; 86462306a36Sopenharmony_ci for_each_child_of_node(np, child) { 86562306a36Sopenharmony_ci of_pins = of_find_property(child, "pinmux", NULL); 86662306a36Sopenharmony_ci if (!of_pins) { 86762306a36Sopenharmony_ci of_node_put(child); 86862306a36Sopenharmony_ci return -EINVAL; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci npins += of_pins->length / sizeof(u32); 87262306a36Sopenharmony_ci } 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci return npins; 87562306a36Sopenharmony_ci} 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci/** 87862306a36Sopenharmony_ci * rza1_parse_pinmux_node() - parse a pin mux sub-node 87962306a36Sopenharmony_ci * 88062306a36Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device 88162306a36Sopenharmony_ci * @np: of pmx sub-node 88262306a36Sopenharmony_ci * @mux_confs: array of pin mux configurations to fill with parsed info 88362306a36Sopenharmony_ci * @grpins: array of pin ids to mux 88462306a36Sopenharmony_ci */ 88562306a36Sopenharmony_cistatic int rza1_parse_pinmux_node(struct rza1_pinctrl *rza1_pctl, 88662306a36Sopenharmony_ci struct device_node *np, 88762306a36Sopenharmony_ci struct rza1_mux_conf *mux_confs, 88862306a36Sopenharmony_ci unsigned int *grpins) 88962306a36Sopenharmony_ci{ 89062306a36Sopenharmony_ci struct pinctrl_dev *pctldev = rza1_pctl->pctl; 89162306a36Sopenharmony_ci char const *prop_name = "pinmux"; 89262306a36Sopenharmony_ci unsigned long *pin_configs; 89362306a36Sopenharmony_ci unsigned int npin_configs; 89462306a36Sopenharmony_ci struct property *of_pins; 89562306a36Sopenharmony_ci unsigned int npins; 89662306a36Sopenharmony_ci u8 pinmux_flags; 89762306a36Sopenharmony_ci unsigned int i; 89862306a36Sopenharmony_ci int ret; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci of_pins = of_find_property(np, prop_name, NULL); 90162306a36Sopenharmony_ci if (!of_pins) { 90262306a36Sopenharmony_ci dev_dbg(rza1_pctl->dev, "Missing %s property\n", prop_name); 90362306a36Sopenharmony_ci return -ENOENT; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci npins = of_pins->length / sizeof(u32); 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci /* 90862306a36Sopenharmony_ci * Collect pin configuration properties: they apply to all pins in 90962306a36Sopenharmony_ci * this sub-node 91062306a36Sopenharmony_ci */ 91162306a36Sopenharmony_ci ret = pinconf_generic_parse_dt_config(np, pctldev, &pin_configs, 91262306a36Sopenharmony_ci &npin_configs); 91362306a36Sopenharmony_ci if (ret) { 91462306a36Sopenharmony_ci dev_err(rza1_pctl->dev, 91562306a36Sopenharmony_ci "Unable to parse pin configuration options for %pOFn\n", 91662306a36Sopenharmony_ci np); 91762306a36Sopenharmony_ci return ret; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci /* 92162306a36Sopenharmony_ci * Create a mask with pinmux flags from pin configuration; 92262306a36Sopenharmony_ci * very few pins (TIOC[0-4][A|B|C|D] require SWIO direction 92362306a36Sopenharmony_ci * specified in device tree. 92462306a36Sopenharmony_ci */ 92562306a36Sopenharmony_ci pinmux_flags = 0; 92662306a36Sopenharmony_ci for (i = 0; i < npin_configs && pinmux_flags == 0; i++) 92762306a36Sopenharmony_ci switch (pinconf_to_config_param(pin_configs[i])) { 92862306a36Sopenharmony_ci case PIN_CONFIG_INPUT_ENABLE: 92962306a36Sopenharmony_ci pinmux_flags |= MUX_FLAGS_SWIO_INPUT; 93062306a36Sopenharmony_ci break; 93162306a36Sopenharmony_ci case PIN_CONFIG_OUTPUT: /* for DT backwards compatibility */ 93262306a36Sopenharmony_ci case PIN_CONFIG_OUTPUT_ENABLE: 93362306a36Sopenharmony_ci pinmux_flags |= MUX_FLAGS_SWIO_OUTPUT; 93462306a36Sopenharmony_ci break; 93562306a36Sopenharmony_ci default: 93662306a36Sopenharmony_ci break; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci kfree(pin_configs); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci /* Collect pin positions and their mux settings. */ 94362306a36Sopenharmony_ci for (i = 0; i < npins; ++i) { 94462306a36Sopenharmony_ci u32 of_pinconf; 94562306a36Sopenharmony_ci struct rza1_mux_conf *mux_conf = &mux_confs[i]; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci ret = of_property_read_u32_index(np, prop_name, i, &of_pinconf); 94862306a36Sopenharmony_ci if (ret) 94962306a36Sopenharmony_ci return ret; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci mux_conf->id = of_pinconf & MUX_PIN_ID_MASK; 95262306a36Sopenharmony_ci mux_conf->port = RZA1_PIN_ID_TO_PORT(mux_conf->id); 95362306a36Sopenharmony_ci mux_conf->pin = RZA1_PIN_ID_TO_PIN(mux_conf->id); 95462306a36Sopenharmony_ci mux_conf->mux_func = MUX_FUNC(of_pinconf); 95562306a36Sopenharmony_ci mux_conf->mux_flags = pinmux_flags; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci if (mux_conf->port >= RZA1_NPORTS || 95862306a36Sopenharmony_ci mux_conf->pin >= RZA1_PINS_PER_PORT) { 95962306a36Sopenharmony_ci dev_err(rza1_pctl->dev, 96062306a36Sopenharmony_ci "Wrong port %u pin %u for %s property\n", 96162306a36Sopenharmony_ci mux_conf->port, mux_conf->pin, prop_name); 96262306a36Sopenharmony_ci return -EINVAL; 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci grpins[i] = mux_conf->id; 96662306a36Sopenharmony_ci } 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci return npins; 96962306a36Sopenharmony_ci} 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci/** 97262306a36Sopenharmony_ci * rza1_dt_node_to_map() - map a pin mux node to a function/group 97362306a36Sopenharmony_ci * 97462306a36Sopenharmony_ci * Parse and register a pin mux function. 97562306a36Sopenharmony_ci * 97662306a36Sopenharmony_ci * @pctldev: pin controller device 97762306a36Sopenharmony_ci * @np: device tree node to parse 97862306a36Sopenharmony_ci * @map: pointer to pin map (output) 97962306a36Sopenharmony_ci * @num_maps: number of collected maps (output) 98062306a36Sopenharmony_ci */ 98162306a36Sopenharmony_cistatic int rza1_dt_node_to_map(struct pinctrl_dev *pctldev, 98262306a36Sopenharmony_ci struct device_node *np, 98362306a36Sopenharmony_ci struct pinctrl_map **map, 98462306a36Sopenharmony_ci unsigned int *num_maps) 98562306a36Sopenharmony_ci{ 98662306a36Sopenharmony_ci struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev); 98762306a36Sopenharmony_ci struct rza1_mux_conf *mux_confs, *mux_conf; 98862306a36Sopenharmony_ci unsigned int *grpins, *grpin; 98962306a36Sopenharmony_ci struct device_node *child; 99062306a36Sopenharmony_ci const char *grpname; 99162306a36Sopenharmony_ci const char **fngrps; 99262306a36Sopenharmony_ci int ret, npins; 99362306a36Sopenharmony_ci int gsel, fsel; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci npins = rza1_dt_node_pin_count(np); 99662306a36Sopenharmony_ci if (npins < 0) { 99762306a36Sopenharmony_ci dev_err(rza1_pctl->dev, "invalid pinmux node structure\n"); 99862306a36Sopenharmony_ci return -EINVAL; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci /* 100262306a36Sopenharmony_ci * Functions are made of 1 group only; 100362306a36Sopenharmony_ci * in fact, functions and groups are identical for this pin controller 100462306a36Sopenharmony_ci * except that functions carry an array of per-pin mux configuration 100562306a36Sopenharmony_ci * settings. 100662306a36Sopenharmony_ci */ 100762306a36Sopenharmony_ci mux_confs = devm_kcalloc(rza1_pctl->dev, npins, sizeof(*mux_confs), 100862306a36Sopenharmony_ci GFP_KERNEL); 100962306a36Sopenharmony_ci grpins = devm_kcalloc(rza1_pctl->dev, npins, sizeof(*grpins), 101062306a36Sopenharmony_ci GFP_KERNEL); 101162306a36Sopenharmony_ci fngrps = devm_kzalloc(rza1_pctl->dev, sizeof(*fngrps), GFP_KERNEL); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci if (!mux_confs || !grpins || !fngrps) 101462306a36Sopenharmony_ci return -ENOMEM; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci /* 101762306a36Sopenharmony_ci * Parse the pinmux node. 101862306a36Sopenharmony_ci * If the node does not contain "pinmux" property (-ENOENT) 101962306a36Sopenharmony_ci * that property shall be specified in all its children sub-nodes. 102062306a36Sopenharmony_ci */ 102162306a36Sopenharmony_ci mux_conf = &mux_confs[0]; 102262306a36Sopenharmony_ci grpin = &grpins[0]; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci ret = rza1_parse_pinmux_node(rza1_pctl, np, mux_conf, grpin); 102562306a36Sopenharmony_ci if (ret == -ENOENT) 102662306a36Sopenharmony_ci for_each_child_of_node(np, child) { 102762306a36Sopenharmony_ci ret = rza1_parse_pinmux_node(rza1_pctl, child, mux_conf, 102862306a36Sopenharmony_ci grpin); 102962306a36Sopenharmony_ci if (ret < 0) { 103062306a36Sopenharmony_ci of_node_put(child); 103162306a36Sopenharmony_ci return ret; 103262306a36Sopenharmony_ci } 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci grpin += ret; 103562306a36Sopenharmony_ci mux_conf += ret; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci else if (ret < 0) 103862306a36Sopenharmony_ci return ret; 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci /* Register pin group and function name to pinctrl_generic */ 104162306a36Sopenharmony_ci grpname = np->name; 104262306a36Sopenharmony_ci fngrps[0] = grpname; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci mutex_lock(&rza1_pctl->mutex); 104562306a36Sopenharmony_ci gsel = pinctrl_generic_add_group(pctldev, grpname, grpins, npins, 104662306a36Sopenharmony_ci NULL); 104762306a36Sopenharmony_ci if (gsel < 0) { 104862306a36Sopenharmony_ci mutex_unlock(&rza1_pctl->mutex); 104962306a36Sopenharmony_ci return gsel; 105062306a36Sopenharmony_ci } 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci fsel = pinmux_generic_add_function(pctldev, grpname, fngrps, 1, 105362306a36Sopenharmony_ci mux_confs); 105462306a36Sopenharmony_ci if (fsel < 0) { 105562306a36Sopenharmony_ci ret = fsel; 105662306a36Sopenharmony_ci goto remove_group; 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci dev_info(rza1_pctl->dev, "Parsed function and group %s with %d pins\n", 106062306a36Sopenharmony_ci grpname, npins); 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci /* Create map where to retrieve function and mux settings from */ 106362306a36Sopenharmony_ci *num_maps = 0; 106462306a36Sopenharmony_ci *map = kzalloc(sizeof(**map), GFP_KERNEL); 106562306a36Sopenharmony_ci if (!*map) { 106662306a36Sopenharmony_ci ret = -ENOMEM; 106762306a36Sopenharmony_ci goto remove_function; 106862306a36Sopenharmony_ci } 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci (*map)->type = PIN_MAP_TYPE_MUX_GROUP; 107162306a36Sopenharmony_ci (*map)->data.mux.group = np->name; 107262306a36Sopenharmony_ci (*map)->data.mux.function = np->name; 107362306a36Sopenharmony_ci *num_maps = 1; 107462306a36Sopenharmony_ci mutex_unlock(&rza1_pctl->mutex); 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci return 0; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ciremove_function: 107962306a36Sopenharmony_ci pinmux_generic_remove_function(pctldev, fsel); 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ciremove_group: 108262306a36Sopenharmony_ci pinctrl_generic_remove_group(pctldev, gsel); 108362306a36Sopenharmony_ci mutex_unlock(&rza1_pctl->mutex); 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci dev_info(rza1_pctl->dev, "Unable to parse function and group %s\n", 108662306a36Sopenharmony_ci grpname); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci return ret; 108962306a36Sopenharmony_ci} 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_cistatic void rza1_dt_free_map(struct pinctrl_dev *pctldev, 109262306a36Sopenharmony_ci struct pinctrl_map *map, unsigned int num_maps) 109362306a36Sopenharmony_ci{ 109462306a36Sopenharmony_ci kfree(map); 109562306a36Sopenharmony_ci} 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_cistatic const struct pinctrl_ops rza1_pinctrl_ops = { 109862306a36Sopenharmony_ci .get_groups_count = pinctrl_generic_get_group_count, 109962306a36Sopenharmony_ci .get_group_name = pinctrl_generic_get_group_name, 110062306a36Sopenharmony_ci .get_group_pins = pinctrl_generic_get_group_pins, 110162306a36Sopenharmony_ci .dt_node_to_map = rza1_dt_node_to_map, 110262306a36Sopenharmony_ci .dt_free_map = rza1_dt_free_map, 110362306a36Sopenharmony_ci}; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 110662306a36Sopenharmony_ci * pinmux operations 110762306a36Sopenharmony_ci */ 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci/** 111062306a36Sopenharmony_ci * rza1_set_mux() - retrieve pins from a group and apply their mux settings 111162306a36Sopenharmony_ci * 111262306a36Sopenharmony_ci * @pctldev: pin controller device 111362306a36Sopenharmony_ci * @selector: function selector 111462306a36Sopenharmony_ci * @group: group selector 111562306a36Sopenharmony_ci */ 111662306a36Sopenharmony_cistatic int rza1_set_mux(struct pinctrl_dev *pctldev, unsigned int selector, 111762306a36Sopenharmony_ci unsigned int group) 111862306a36Sopenharmony_ci{ 111962306a36Sopenharmony_ci struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev); 112062306a36Sopenharmony_ci struct rza1_mux_conf *mux_confs; 112162306a36Sopenharmony_ci struct function_desc *func; 112262306a36Sopenharmony_ci struct group_desc *grp; 112362306a36Sopenharmony_ci int i; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci grp = pinctrl_generic_get_group(pctldev, group); 112662306a36Sopenharmony_ci if (!grp) 112762306a36Sopenharmony_ci return -EINVAL; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci func = pinmux_generic_get_function(pctldev, selector); 113062306a36Sopenharmony_ci if (!func) 113162306a36Sopenharmony_ci return -EINVAL; 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci mux_confs = (struct rza1_mux_conf *)func->data; 113462306a36Sopenharmony_ci for (i = 0; i < grp->num_pins; ++i) { 113562306a36Sopenharmony_ci int ret; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci ret = rza1_pin_mux_single(rza1_pctl, &mux_confs[i]); 113862306a36Sopenharmony_ci if (ret) 113962306a36Sopenharmony_ci return ret; 114062306a36Sopenharmony_ci } 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci return 0; 114362306a36Sopenharmony_ci} 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_cistatic const struct pinmux_ops rza1_pinmux_ops = { 114662306a36Sopenharmony_ci .get_functions_count = pinmux_generic_get_function_count, 114762306a36Sopenharmony_ci .get_function_name = pinmux_generic_get_function_name, 114862306a36Sopenharmony_ci .get_function_groups = pinmux_generic_get_function_groups, 114962306a36Sopenharmony_ci .set_mux = rza1_set_mux, 115062306a36Sopenharmony_ci .strict = true, 115162306a36Sopenharmony_ci}; 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 115462306a36Sopenharmony_ci * RZ/A1 pin controller driver operations 115562306a36Sopenharmony_ci */ 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci/** 115862306a36Sopenharmony_ci * rza1_parse_gpiochip() - parse and register a gpio chip and pin range 115962306a36Sopenharmony_ci * 116062306a36Sopenharmony_ci * The gpio controller subnode shall provide a "gpio-ranges" list property as 116162306a36Sopenharmony_ci * defined by gpio device tree binding documentation. 116262306a36Sopenharmony_ci * 116362306a36Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device 116462306a36Sopenharmony_ci * @fwnode: gpio-controller firmware node 116562306a36Sopenharmony_ci * @chip: gpio chip to register to gpiolib 116662306a36Sopenharmony_ci * @range: pin range to register to pinctrl core 116762306a36Sopenharmony_ci */ 116862306a36Sopenharmony_cistatic int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl, 116962306a36Sopenharmony_ci struct fwnode_handle *fwnode, 117062306a36Sopenharmony_ci struct gpio_chip *chip, 117162306a36Sopenharmony_ci struct pinctrl_gpio_range *range) 117262306a36Sopenharmony_ci{ 117362306a36Sopenharmony_ci const char *list_name = "gpio-ranges"; 117462306a36Sopenharmony_ci struct fwnode_reference_args args; 117562306a36Sopenharmony_ci unsigned int gpioport; 117662306a36Sopenharmony_ci u32 pinctrl_base; 117762306a36Sopenharmony_ci int ret; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci ret = fwnode_property_get_reference_args(fwnode, list_name, NULL, 3, 0, &args); 118062306a36Sopenharmony_ci if (ret) { 118162306a36Sopenharmony_ci dev_err(rza1_pctl->dev, "Unable to parse %s list property\n", 118262306a36Sopenharmony_ci list_name); 118362306a36Sopenharmony_ci return ret; 118462306a36Sopenharmony_ci } 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci /* 118762306a36Sopenharmony_ci * Find out on which port this gpio-chip maps to by inspecting the 118862306a36Sopenharmony_ci * second argument of the "gpio-ranges" property. 118962306a36Sopenharmony_ci */ 119062306a36Sopenharmony_ci pinctrl_base = args.args[1]; 119162306a36Sopenharmony_ci gpioport = RZA1_PIN_ID_TO_PORT(pinctrl_base); 119262306a36Sopenharmony_ci if (gpioport >= RZA1_NPORTS) { 119362306a36Sopenharmony_ci dev_err(rza1_pctl->dev, 119462306a36Sopenharmony_ci "Invalid values in property %s\n", list_name); 119562306a36Sopenharmony_ci return -EINVAL; 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci *chip = rza1_gpiochip_template; 119962306a36Sopenharmony_ci chip->base = -1; 120062306a36Sopenharmony_ci chip->ngpio = args.args[2]; 120162306a36Sopenharmony_ci chip->label = devm_kasprintf(rza1_pctl->dev, GFP_KERNEL, "%pfwP", fwnode); 120262306a36Sopenharmony_ci if (!chip->label) 120362306a36Sopenharmony_ci return -ENOMEM; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci chip->fwnode = fwnode; 120662306a36Sopenharmony_ci chip->parent = rza1_pctl->dev; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci range->id = gpioport; 120962306a36Sopenharmony_ci range->name = chip->label; 121062306a36Sopenharmony_ci range->pin_base = range->base = pinctrl_base; 121162306a36Sopenharmony_ci range->npins = args.args[2]; 121262306a36Sopenharmony_ci range->gc = chip; 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci ret = devm_gpiochip_add_data(rza1_pctl->dev, chip, 121562306a36Sopenharmony_ci &rza1_pctl->ports[gpioport]); 121662306a36Sopenharmony_ci if (ret) 121762306a36Sopenharmony_ci return ret; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci pinctrl_add_gpio_range(rza1_pctl->pctl, range); 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci dev_dbg(rza1_pctl->dev, "Parsed gpiochip %s with %d pins\n", 122262306a36Sopenharmony_ci chip->label, chip->ngpio); 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci return 0; 122562306a36Sopenharmony_ci} 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci/** 122862306a36Sopenharmony_ci * rza1_gpio_register() - parse DT to collect gpio-chips and gpio-ranges 122962306a36Sopenharmony_ci * 123062306a36Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device 123162306a36Sopenharmony_ci */ 123262306a36Sopenharmony_cistatic int rza1_gpio_register(struct rza1_pinctrl *rza1_pctl) 123362306a36Sopenharmony_ci{ 123462306a36Sopenharmony_ci struct pinctrl_gpio_range *gpio_ranges; 123562306a36Sopenharmony_ci struct gpio_chip *gpio_chips; 123662306a36Sopenharmony_ci struct fwnode_handle *child; 123762306a36Sopenharmony_ci unsigned int ngpiochips; 123862306a36Sopenharmony_ci unsigned int i; 123962306a36Sopenharmony_ci int ret; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci ngpiochips = gpiochip_node_count(rza1_pctl->dev); 124262306a36Sopenharmony_ci if (ngpiochips == 0) { 124362306a36Sopenharmony_ci dev_dbg(rza1_pctl->dev, "No gpiochip registered\n"); 124462306a36Sopenharmony_ci return 0; 124562306a36Sopenharmony_ci } 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci gpio_chips = devm_kcalloc(rza1_pctl->dev, ngpiochips, 124862306a36Sopenharmony_ci sizeof(*gpio_chips), GFP_KERNEL); 124962306a36Sopenharmony_ci gpio_ranges = devm_kcalloc(rza1_pctl->dev, ngpiochips, 125062306a36Sopenharmony_ci sizeof(*gpio_ranges), GFP_KERNEL); 125162306a36Sopenharmony_ci if (!gpio_chips || !gpio_ranges) 125262306a36Sopenharmony_ci return -ENOMEM; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci i = 0; 125562306a36Sopenharmony_ci for_each_gpiochip_node(rza1_pctl->dev, child) { 125662306a36Sopenharmony_ci ret = rza1_parse_gpiochip(rza1_pctl, child, &gpio_chips[i], 125762306a36Sopenharmony_ci &gpio_ranges[i]); 125862306a36Sopenharmony_ci if (ret) { 125962306a36Sopenharmony_ci fwnode_handle_put(child); 126062306a36Sopenharmony_ci return ret; 126162306a36Sopenharmony_ci } 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci ++i; 126462306a36Sopenharmony_ci } 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci dev_info(rza1_pctl->dev, "Registered %u gpio controllers\n", i); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci return 0; 126962306a36Sopenharmony_ci} 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci/** 127262306a36Sopenharmony_ci * rza1_pinctrl_register() - Enumerate pins, ports and gpiochips; register 127362306a36Sopenharmony_ci * them to pinctrl and gpio cores. 127462306a36Sopenharmony_ci * 127562306a36Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device 127662306a36Sopenharmony_ci */ 127762306a36Sopenharmony_cistatic int rza1_pinctrl_register(struct rza1_pinctrl *rza1_pctl) 127862306a36Sopenharmony_ci{ 127962306a36Sopenharmony_ci struct pinctrl_pin_desc *pins; 128062306a36Sopenharmony_ci struct rza1_port *ports; 128162306a36Sopenharmony_ci unsigned int i; 128262306a36Sopenharmony_ci int ret; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci pins = devm_kcalloc(rza1_pctl->dev, RZA1_NPINS, sizeof(*pins), 128562306a36Sopenharmony_ci GFP_KERNEL); 128662306a36Sopenharmony_ci ports = devm_kcalloc(rza1_pctl->dev, RZA1_NPORTS, sizeof(*ports), 128762306a36Sopenharmony_ci GFP_KERNEL); 128862306a36Sopenharmony_ci if (!pins || !ports) 128962306a36Sopenharmony_ci return -ENOMEM; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci rza1_pctl->pins = pins; 129262306a36Sopenharmony_ci rza1_pctl->desc.pins = pins; 129362306a36Sopenharmony_ci rza1_pctl->desc.npins = RZA1_NPINS; 129462306a36Sopenharmony_ci rza1_pctl->ports = ports; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci for (i = 0; i < RZA1_NPINS; ++i) { 129762306a36Sopenharmony_ci unsigned int pin = RZA1_PIN_ID_TO_PIN(i); 129862306a36Sopenharmony_ci unsigned int port = RZA1_PIN_ID_TO_PORT(i); 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci pins[i].number = i; 130162306a36Sopenharmony_ci pins[i].name = devm_kasprintf(rza1_pctl->dev, GFP_KERNEL, 130262306a36Sopenharmony_ci "P%u-%u", port, pin); 130362306a36Sopenharmony_ci if (!pins[i].name) 130462306a36Sopenharmony_ci return -ENOMEM; 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci if (i % RZA1_PINS_PER_PORT == 0) { 130762306a36Sopenharmony_ci /* 130862306a36Sopenharmony_ci * Setup ports; 130962306a36Sopenharmony_ci * they provide per-port lock and logical base address. 131062306a36Sopenharmony_ci */ 131162306a36Sopenharmony_ci unsigned int port_id = RZA1_PIN_ID_TO_PORT(i); 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci ports[port_id].id = port_id; 131462306a36Sopenharmony_ci ports[port_id].base = rza1_pctl->base; 131562306a36Sopenharmony_ci ports[port_id].pins = &pins[i]; 131662306a36Sopenharmony_ci spin_lock_init(&ports[port_id].lock); 131762306a36Sopenharmony_ci } 131862306a36Sopenharmony_ci } 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci ret = devm_pinctrl_register_and_init(rza1_pctl->dev, &rza1_pctl->desc, 132162306a36Sopenharmony_ci rza1_pctl, &rza1_pctl->pctl); 132262306a36Sopenharmony_ci if (ret) { 132362306a36Sopenharmony_ci dev_err(rza1_pctl->dev, 132462306a36Sopenharmony_ci "RZ/A1 pin controller registration failed\n"); 132562306a36Sopenharmony_ci return ret; 132662306a36Sopenharmony_ci } 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci ret = pinctrl_enable(rza1_pctl->pctl); 132962306a36Sopenharmony_ci if (ret) { 133062306a36Sopenharmony_ci dev_err(rza1_pctl->dev, 133162306a36Sopenharmony_ci "RZ/A1 pin controller failed to start\n"); 133262306a36Sopenharmony_ci return ret; 133362306a36Sopenharmony_ci } 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci ret = rza1_gpio_register(rza1_pctl); 133662306a36Sopenharmony_ci if (ret) { 133762306a36Sopenharmony_ci dev_err(rza1_pctl->dev, "RZ/A1 GPIO registration failed\n"); 133862306a36Sopenharmony_ci return ret; 133962306a36Sopenharmony_ci } 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci return 0; 134262306a36Sopenharmony_ci} 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_cistatic int rza1_pinctrl_probe(struct platform_device *pdev) 134562306a36Sopenharmony_ci{ 134662306a36Sopenharmony_ci struct rza1_pinctrl *rza1_pctl; 134762306a36Sopenharmony_ci int ret; 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci rza1_pctl = devm_kzalloc(&pdev->dev, sizeof(*rza1_pctl), GFP_KERNEL); 135062306a36Sopenharmony_ci if (!rza1_pctl) 135162306a36Sopenharmony_ci return -ENOMEM; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci rza1_pctl->dev = &pdev->dev; 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci rza1_pctl->base = devm_platform_ioremap_resource(pdev, 0); 135662306a36Sopenharmony_ci if (IS_ERR(rza1_pctl->base)) 135762306a36Sopenharmony_ci return PTR_ERR(rza1_pctl->base); 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci mutex_init(&rza1_pctl->mutex); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci platform_set_drvdata(pdev, rza1_pctl); 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci rza1_pctl->desc.name = DRIVER_NAME; 136462306a36Sopenharmony_ci rza1_pctl->desc.pctlops = &rza1_pinctrl_ops; 136562306a36Sopenharmony_ci rza1_pctl->desc.pmxops = &rza1_pinmux_ops; 136662306a36Sopenharmony_ci rza1_pctl->desc.owner = THIS_MODULE; 136762306a36Sopenharmony_ci rza1_pctl->data = of_device_get_match_data(&pdev->dev); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci ret = rza1_pinctrl_register(rza1_pctl); 137062306a36Sopenharmony_ci if (ret) 137162306a36Sopenharmony_ci return ret; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci dev_info(&pdev->dev, 137462306a36Sopenharmony_ci "RZ/A1 pin controller and gpio successfully registered\n"); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci return 0; 137762306a36Sopenharmony_ci} 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_cistatic const struct of_device_id rza1_pinctrl_of_match[] = { 138062306a36Sopenharmony_ci { 138162306a36Sopenharmony_ci /* RZ/A1H, RZ/A1M */ 138262306a36Sopenharmony_ci .compatible = "renesas,r7s72100-ports", 138362306a36Sopenharmony_ci .data = &rza1h_pmx_conf, 138462306a36Sopenharmony_ci }, 138562306a36Sopenharmony_ci { 138662306a36Sopenharmony_ci /* RZ/A1L */ 138762306a36Sopenharmony_ci .compatible = "renesas,r7s72102-ports", 138862306a36Sopenharmony_ci .data = &rza1l_pmx_conf, 138962306a36Sopenharmony_ci }, 139062306a36Sopenharmony_ci { /* sentinel */ } 139162306a36Sopenharmony_ci}; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_cistatic struct platform_driver rza1_pinctrl_driver = { 139462306a36Sopenharmony_ci .driver = { 139562306a36Sopenharmony_ci .name = DRIVER_NAME, 139662306a36Sopenharmony_ci .of_match_table = rza1_pinctrl_of_match, 139762306a36Sopenharmony_ci }, 139862306a36Sopenharmony_ci .probe = rza1_pinctrl_probe, 139962306a36Sopenharmony_ci}; 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic int __init rza1_pinctrl_init(void) 140262306a36Sopenharmony_ci{ 140362306a36Sopenharmony_ci return platform_driver_register(&rza1_pinctrl_driver); 140462306a36Sopenharmony_ci} 140562306a36Sopenharmony_cicore_initcall(rza1_pinctrl_init); 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ciMODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org"); 140862306a36Sopenharmony_ciMODULE_DESCRIPTION("Pin and gpio controller driver for Reneas RZ/A1 SoC"); 1409