18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Combined GPIO and pin controller support for Renesas RZ/A1 (r7s72100) SoC
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2017 Jacopo Mondi
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * This pin controller/gpio combined driver supports Renesas devices of RZ/A1
108c2ecf20Sopenharmony_ci * family.
118c2ecf20Sopenharmony_ci * This includes SoCs which are sub- or super- sets of this particular line,
128c2ecf20Sopenharmony_ci * as RZ/A1H (r7s721000), RZ/A1M (r7s721010) and RZ/A1L (r7s721020).
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/bitops.h>
168c2ecf20Sopenharmony_ci#include <linux/err.h>
178c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h>
188c2ecf20Sopenharmony_ci#include <linux/init.h>
198c2ecf20Sopenharmony_ci#include <linux/ioport.h>
208c2ecf20Sopenharmony_ci#include <linux/module.h>
218c2ecf20Sopenharmony_ci#include <linux/of.h>
228c2ecf20Sopenharmony_ci#include <linux/of_address.h>
238c2ecf20Sopenharmony_ci#include <linux/of_device.h>
248c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h>
258c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
268c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinmux.h>
278c2ecf20Sopenharmony_ci#include <linux/slab.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include "../core.h"
308c2ecf20Sopenharmony_ci#include "../devicetree.h"
318c2ecf20Sopenharmony_ci#include "../pinconf.h"
328c2ecf20Sopenharmony_ci#include "../pinmux.h"
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define DRIVER_NAME			"pinctrl-rza1"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define RZA1_P_REG			0x0000
378c2ecf20Sopenharmony_ci#define RZA1_PPR_REG			0x0200
388c2ecf20Sopenharmony_ci#define RZA1_PM_REG			0x0300
398c2ecf20Sopenharmony_ci#define RZA1_PMC_REG			0x0400
408c2ecf20Sopenharmony_ci#define RZA1_PFC_REG			0x0500
418c2ecf20Sopenharmony_ci#define RZA1_PFCE_REG			0x0600
428c2ecf20Sopenharmony_ci#define RZA1_PFCEA_REG			0x0a00
438c2ecf20Sopenharmony_ci#define RZA1_PIBC_REG			0x4000
448c2ecf20Sopenharmony_ci#define RZA1_PBDC_REG			0x4100
458c2ecf20Sopenharmony_ci#define RZA1_PIPC_REG			0x4200
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define RZA1_ADDR(mem, reg, port)	((mem) + (reg) + ((port) * 4))
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define RZA1_NPORTS			12
508c2ecf20Sopenharmony_ci#define RZA1_PINS_PER_PORT		16
518c2ecf20Sopenharmony_ci#define RZA1_NPINS			(RZA1_PINS_PER_PORT * RZA1_NPORTS)
528c2ecf20Sopenharmony_ci#define RZA1_PIN_ID_TO_PORT(id)		((id) / RZA1_PINS_PER_PORT)
538c2ecf20Sopenharmony_ci#define RZA1_PIN_ID_TO_PIN(id)		((id) % RZA1_PINS_PER_PORT)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/*
568c2ecf20Sopenharmony_ci * Use 16 lower bits [15:0] for pin identifier
578c2ecf20Sopenharmony_ci * Use 16 higher bits [31:16] for pin mux function
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_ci#define MUX_PIN_ID_MASK			GENMASK(15, 0)
608c2ecf20Sopenharmony_ci#define MUX_FUNC_MASK			GENMASK(31, 16)
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define MUX_FUNC_OFFS			16
638c2ecf20Sopenharmony_ci#define MUX_FUNC(pinconf)		\
648c2ecf20Sopenharmony_ci	((pinconf & MUX_FUNC_MASK) >> MUX_FUNC_OFFS)
658c2ecf20Sopenharmony_ci#define MUX_FUNC_PFC_MASK		BIT(0)
668c2ecf20Sopenharmony_ci#define MUX_FUNC_PFCE_MASK		BIT(1)
678c2ecf20Sopenharmony_ci#define MUX_FUNC_PFCEA_MASK		BIT(2)
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/* Pin mux flags */
708c2ecf20Sopenharmony_ci#define MUX_FLAGS_BIDIR			BIT(0)
718c2ecf20Sopenharmony_ci#define MUX_FLAGS_SWIO_INPUT		BIT(1)
728c2ecf20Sopenharmony_ci#define MUX_FLAGS_SWIO_OUTPUT		BIT(2)
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
758c2ecf20Sopenharmony_ci * RZ/A1 pinmux flags
768c2ecf20Sopenharmony_ci */
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/*
798c2ecf20Sopenharmony_ci * rza1_bidir_pin - describe a single pin that needs bidir flag applied.
808c2ecf20Sopenharmony_ci */
818c2ecf20Sopenharmony_cistruct rza1_bidir_pin {
828c2ecf20Sopenharmony_ci	u8 pin: 4;
838c2ecf20Sopenharmony_ci	u8 func: 4;
848c2ecf20Sopenharmony_ci};
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci/*
878c2ecf20Sopenharmony_ci * rza1_bidir_entry - describe a list of pins that needs bidir flag applied.
888c2ecf20Sopenharmony_ci *		      Each struct rza1_bidir_entry describes a port.
898c2ecf20Sopenharmony_ci */
908c2ecf20Sopenharmony_cistruct rza1_bidir_entry {
918c2ecf20Sopenharmony_ci	const unsigned int npins;
928c2ecf20Sopenharmony_ci	const struct rza1_bidir_pin *pins;
938c2ecf20Sopenharmony_ci};
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/*
968c2ecf20Sopenharmony_ci * rza1_swio_pin - describe a single pin that needs swio flag applied.
978c2ecf20Sopenharmony_ci */
988c2ecf20Sopenharmony_cistruct rza1_swio_pin {
998c2ecf20Sopenharmony_ci	u16 pin: 4;
1008c2ecf20Sopenharmony_ci	u16 port: 4;
1018c2ecf20Sopenharmony_ci	u16 func: 4;
1028c2ecf20Sopenharmony_ci	u16 input: 1;
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/*
1068c2ecf20Sopenharmony_ci * rza1_swio_entry - describe a list of pins that needs swio flag applied
1078c2ecf20Sopenharmony_ci */
1088c2ecf20Sopenharmony_cistruct rza1_swio_entry {
1098c2ecf20Sopenharmony_ci	const unsigned int npins;
1108c2ecf20Sopenharmony_ci	const struct rza1_swio_pin *pins;
1118c2ecf20Sopenharmony_ci};
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci/*
1148c2ecf20Sopenharmony_ci * rza1_pinmux_conf - group together bidir and swio pinmux flag tables
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_cistruct rza1_pinmux_conf {
1178c2ecf20Sopenharmony_ci	const struct rza1_bidir_entry *bidir_entries;
1188c2ecf20Sopenharmony_ci	const struct rza1_swio_entry *swio_entries;
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
1228c2ecf20Sopenharmony_ci * RZ/A1H (r7s72100) pinmux flags
1238c2ecf20Sopenharmony_ci */
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p1[] = {
1268c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 1 },
1278c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 1 },
1288c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 1 },
1298c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 1 },
1308c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 1 },
1318c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 1 },
1328c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 1 },
1338c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 1 },
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p2[] = {
1378c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 1 },
1388c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 1 },
1398c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 1 },
1408c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 1 },
1418c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 1 },
1428c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 4 },
1438c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 4 },
1448c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 4 },
1458c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 4 },
1468c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 1 },
1478c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 1 },
1488c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 1 },
1498c2ecf20Sopenharmony_ci	{ .pin = 8, .func = 1 },
1508c2ecf20Sopenharmony_ci	{ .pin = 9, .func = 1 },
1518c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 1 },
1528c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 1 },
1538c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 1 },
1548c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 1 },
1558c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 1 },
1568c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 1 },
1578c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 4 },
1588c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 4 },
1598c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 4 },
1608c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 4 },
1618c2ecf20Sopenharmony_ci};
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p3[] = {
1648c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 2 },
1658c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 7 },
1668c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 7 },
1678c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 7 },
1688c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 7 },
1698c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 7 },
1708c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 8 },
1718c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 8 },
1728c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 8 },
1738c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 8 },
1748c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 8 },
1758c2ecf20Sopenharmony_ci};
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p4[] = {
1788c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 8 },
1798c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 8 },
1808c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 8 },
1818c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 8 },
1828c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 3 },
1838c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 3 },
1848c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 3 },
1858c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 3 },
1868c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 3 },
1878c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 4 },
1888c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 4 },
1898c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 4 },
1908c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 4 },
1918c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 4 },
1928c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 5 },
1938c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 5 },
1948c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 5 },
1958c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 5 },
1968c2ecf20Sopenharmony_ci};
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p6[] = {
1998c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 1 },
2008c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 1 },
2018c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 1 },
2028c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 1 },
2038c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 1 },
2048c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 1 },
2058c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 1 },
2068c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 1 },
2078c2ecf20Sopenharmony_ci	{ .pin = 8, .func = 1 },
2088c2ecf20Sopenharmony_ci	{ .pin = 9, .func = 1 },
2098c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 1 },
2108c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 1 },
2118c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 1 },
2128c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 1 },
2138c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 1 },
2148c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 1 },
2158c2ecf20Sopenharmony_ci};
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p7[] = {
2188c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 3 },
2198c2ecf20Sopenharmony_ci};
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p8[] = {
2228c2ecf20Sopenharmony_ci	{ .pin = 8, .func = 3 },
2238c2ecf20Sopenharmony_ci	{ .pin = 9, .func = 3 },
2248c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 3 },
2258c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 3 },
2268c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 2 },
2278c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 2 },
2288c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 3 },
2298c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 3 },
2308c2ecf20Sopenharmony_ci};
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p9[] = {
2338c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 2 },
2348c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 2 },
2358c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 2 },
2368c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 2 },
2378c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 2 },
2388c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 2 },
2398c2ecf20Sopenharmony_ci};
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1h_bidir_pins_p11[] = {
2428c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 2 },
2438c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 2 },
2448c2ecf20Sopenharmony_ci	{ .pin = 9, .func = 2 },
2458c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 4 },
2468c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 4 },
2478c2ecf20Sopenharmony_ci	{ .pin = 9, .func = 4 },
2488c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 2 },
2498c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 2 },
2508c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 4 },
2518c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 4 },
2528c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 4 },
2538c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 4 },
2548c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 4 },
2558c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 4 },
2568c2ecf20Sopenharmony_ci};
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_cistatic const struct rza1_swio_pin rza1h_swio_pins[] = {
2598c2ecf20Sopenharmony_ci	{ .port = 2, .pin = 7, .func = 4, .input = 0 },
2608c2ecf20Sopenharmony_ci	{ .port = 2, .pin = 11, .func = 4, .input = 0 },
2618c2ecf20Sopenharmony_ci	{ .port = 3, .pin = 7, .func = 3, .input = 0 },
2628c2ecf20Sopenharmony_ci	{ .port = 3, .pin = 7, .func = 8, .input = 0 },
2638c2ecf20Sopenharmony_ci	{ .port = 4, .pin = 7, .func = 5, .input = 0 },
2648c2ecf20Sopenharmony_ci	{ .port = 4, .pin = 7, .func = 11, .input = 0 },
2658c2ecf20Sopenharmony_ci	{ .port = 4, .pin = 15, .func = 6, .input = 0 },
2668c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 0, .func = 1, .input = 1 },
2678c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 1, .func = 1, .input = 1 },
2688c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 2, .func = 1, .input = 1 },
2698c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 3, .func = 1, .input = 1 },
2708c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 4, .func = 1, .input = 1 },
2718c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 5, .func = 1, .input = 1 },
2728c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 6, .func = 1, .input = 1 },
2738c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 7, .func = 1, .input = 1 },
2748c2ecf20Sopenharmony_ci	{ .port = 7, .pin = 4, .func = 6, .input = 0 },
2758c2ecf20Sopenharmony_ci	{ .port = 7, .pin = 11, .func = 2, .input = 0 },
2768c2ecf20Sopenharmony_ci	{ .port = 8, .pin = 10, .func = 8, .input = 0 },
2778c2ecf20Sopenharmony_ci	{ .port = 10, .pin = 15, .func = 2, .input = 0 },
2788c2ecf20Sopenharmony_ci};
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic const struct rza1_bidir_entry rza1h_bidir_entries[RZA1_NPORTS] = {
2818c2ecf20Sopenharmony_ci	[1] = { ARRAY_SIZE(rza1h_bidir_pins_p1), rza1h_bidir_pins_p1 },
2828c2ecf20Sopenharmony_ci	[2] = { ARRAY_SIZE(rza1h_bidir_pins_p2), rza1h_bidir_pins_p2 },
2838c2ecf20Sopenharmony_ci	[3] = { ARRAY_SIZE(rza1h_bidir_pins_p3), rza1h_bidir_pins_p3 },
2848c2ecf20Sopenharmony_ci	[4] = { ARRAY_SIZE(rza1h_bidir_pins_p4), rza1h_bidir_pins_p4 },
2858c2ecf20Sopenharmony_ci	[6] = { ARRAY_SIZE(rza1h_bidir_pins_p6), rza1h_bidir_pins_p6 },
2868c2ecf20Sopenharmony_ci	[7] = { ARRAY_SIZE(rza1h_bidir_pins_p7), rza1h_bidir_pins_p7 },
2878c2ecf20Sopenharmony_ci	[8] = { ARRAY_SIZE(rza1h_bidir_pins_p8), rza1h_bidir_pins_p8 },
2888c2ecf20Sopenharmony_ci	[9] = { ARRAY_SIZE(rza1h_bidir_pins_p9), rza1h_bidir_pins_p9 },
2898c2ecf20Sopenharmony_ci	[11] = { ARRAY_SIZE(rza1h_bidir_pins_p11), rza1h_bidir_pins_p11 },
2908c2ecf20Sopenharmony_ci};
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_cistatic const struct rza1_swio_entry rza1h_swio_entries[] = {
2938c2ecf20Sopenharmony_ci	[0] = { ARRAY_SIZE(rza1h_swio_pins), rza1h_swio_pins },
2948c2ecf20Sopenharmony_ci};
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci/* RZ/A1H (r7s72100x) pinmux flags table */
2978c2ecf20Sopenharmony_cistatic const struct rza1_pinmux_conf rza1h_pmx_conf = {
2988c2ecf20Sopenharmony_ci	.bidir_entries	= rza1h_bidir_entries,
2998c2ecf20Sopenharmony_ci	.swio_entries	= rza1h_swio_entries,
3008c2ecf20Sopenharmony_ci};
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
3038c2ecf20Sopenharmony_ci * RZ/A1L (r7s72102) pinmux flags
3048c2ecf20Sopenharmony_ci */
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p1[] = {
3078c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 1 },
3088c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 1 },
3098c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 1 },
3108c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 1 },
3118c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 1 },
3128c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 1 },
3138c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 1 },
3148c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 1 },
3158c2ecf20Sopenharmony_ci};
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p3[] = {
3188c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 2 },
3198c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 2 },
3208c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 2 },
3218c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 2 },
3228c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 2 },
3238c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 2 },
3248c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 2 },
3258c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 2 },
3268c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 2 },
3278c2ecf20Sopenharmony_ci};
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p4[] = {
3308c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 4 },
3318c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 2 },
3328c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 2 },
3338c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 2 },
3348c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 2 },
3358c2ecf20Sopenharmony_ci};
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p5[] = {
3388c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 1 },
3398c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 1 },
3408c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 1 },
3418c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 1 },
3428c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 1 },
3438c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 1 },
3448c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 1 },
3458c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 1 },
3468c2ecf20Sopenharmony_ci	{ .pin = 8, .func = 1 },
3478c2ecf20Sopenharmony_ci	{ .pin = 9, .func = 1 },
3488c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 1 },
3498c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 1 },
3508c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 1 },
3518c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 1 },
3528c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 1 },
3538c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 1 },
3548c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 2 },
3558c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 2 },
3568c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 2 },
3578c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 2 },
3588c2ecf20Sopenharmony_ci};
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p6[] = {
3618c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 1 },
3628c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 1 },
3638c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 1 },
3648c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 1 },
3658c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 1 },
3668c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 1 },
3678c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 1 },
3688c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 1 },
3698c2ecf20Sopenharmony_ci	{ .pin = 8, .func = 1 },
3708c2ecf20Sopenharmony_ci	{ .pin = 9, .func = 1 },
3718c2ecf20Sopenharmony_ci	{ .pin = 10, .func = 1 },
3728c2ecf20Sopenharmony_ci	{ .pin = 11, .func = 1 },
3738c2ecf20Sopenharmony_ci	{ .pin = 12, .func = 1 },
3748c2ecf20Sopenharmony_ci	{ .pin = 13, .func = 1 },
3758c2ecf20Sopenharmony_ci	{ .pin = 14, .func = 1 },
3768c2ecf20Sopenharmony_ci	{ .pin = 15, .func = 1 },
3778c2ecf20Sopenharmony_ci};
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p7[] = {
3808c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 2 },
3818c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 2 },
3828c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 2 },
3838c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 2 },
3848c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 2 },
3858c2ecf20Sopenharmony_ci	{ .pin = 2, .func = 3 },
3868c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 3 },
3878c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 3 },
3888c2ecf20Sopenharmony_ci	{ .pin = 6, .func = 3 },
3898c2ecf20Sopenharmony_ci	{ .pin = 7, .func = 3 },
3908c2ecf20Sopenharmony_ci};
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic const struct rza1_bidir_pin rza1l_bidir_pins_p9[] = {
3938c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 2 },
3948c2ecf20Sopenharmony_ci	{ .pin = 0, .func = 3 },
3958c2ecf20Sopenharmony_ci	{ .pin = 1, .func = 3 },
3968c2ecf20Sopenharmony_ci	{ .pin = 3, .func = 3 },
3978c2ecf20Sopenharmony_ci	{ .pin = 4, .func = 3 },
3988c2ecf20Sopenharmony_ci	{ .pin = 5, .func = 3 },
3998c2ecf20Sopenharmony_ci};
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic const struct rza1_swio_pin rza1l_swio_pins[] = {
4028c2ecf20Sopenharmony_ci	{ .port = 2, .pin = 8, .func = 2, .input = 0 },
4038c2ecf20Sopenharmony_ci	{ .port = 5, .pin = 6, .func = 3, .input = 0 },
4048c2ecf20Sopenharmony_ci	{ .port = 6, .pin = 6, .func = 3, .input = 0 },
4058c2ecf20Sopenharmony_ci	{ .port = 6, .pin = 10, .func = 3, .input = 0 },
4068c2ecf20Sopenharmony_ci	{ .port = 7, .pin = 10, .func = 2, .input = 0 },
4078c2ecf20Sopenharmony_ci	{ .port = 8, .pin = 2, .func = 3, .input = 0 },
4088c2ecf20Sopenharmony_ci};
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic const struct rza1_bidir_entry rza1l_bidir_entries[RZA1_NPORTS] = {
4118c2ecf20Sopenharmony_ci	[1] = { ARRAY_SIZE(rza1l_bidir_pins_p1), rza1l_bidir_pins_p1 },
4128c2ecf20Sopenharmony_ci	[3] = { ARRAY_SIZE(rza1l_bidir_pins_p3), rza1l_bidir_pins_p3 },
4138c2ecf20Sopenharmony_ci	[4] = { ARRAY_SIZE(rza1l_bidir_pins_p4), rza1l_bidir_pins_p4 },
4148c2ecf20Sopenharmony_ci	[5] = { ARRAY_SIZE(rza1l_bidir_pins_p4), rza1l_bidir_pins_p5 },
4158c2ecf20Sopenharmony_ci	[6] = { ARRAY_SIZE(rza1l_bidir_pins_p6), rza1l_bidir_pins_p6 },
4168c2ecf20Sopenharmony_ci	[7] = { ARRAY_SIZE(rza1l_bidir_pins_p7), rza1l_bidir_pins_p7 },
4178c2ecf20Sopenharmony_ci	[9] = { ARRAY_SIZE(rza1l_bidir_pins_p9), rza1l_bidir_pins_p9 },
4188c2ecf20Sopenharmony_ci};
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic const struct rza1_swio_entry rza1l_swio_entries[] = {
4218c2ecf20Sopenharmony_ci	[0] = { ARRAY_SIZE(rza1l_swio_pins), rza1l_swio_pins },
4228c2ecf20Sopenharmony_ci};
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci/* RZ/A1L (r7s72102x) pinmux flags table */
4258c2ecf20Sopenharmony_cistatic const struct rza1_pinmux_conf rza1l_pmx_conf = {
4268c2ecf20Sopenharmony_ci	.bidir_entries	= rza1l_bidir_entries,
4278c2ecf20Sopenharmony_ci	.swio_entries	= rza1l_swio_entries,
4288c2ecf20Sopenharmony_ci};
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
4318c2ecf20Sopenharmony_ci * RZ/A1 types
4328c2ecf20Sopenharmony_ci */
4338c2ecf20Sopenharmony_ci/**
4348c2ecf20Sopenharmony_ci * struct rza1_mux_conf - describes a pin multiplexing operation
4358c2ecf20Sopenharmony_ci *
4368c2ecf20Sopenharmony_ci * @id: the pin identifier from 0 to RZA1_NPINS
4378c2ecf20Sopenharmony_ci * @port: the port where pin sits on
4388c2ecf20Sopenharmony_ci * @pin: pin id
4398c2ecf20Sopenharmony_ci * @mux_func: alternate function id number
4408c2ecf20Sopenharmony_ci * @mux_flags: alternate function flags
4418c2ecf20Sopenharmony_ci * @value: output value to set the pin to
4428c2ecf20Sopenharmony_ci */
4438c2ecf20Sopenharmony_cistruct rza1_mux_conf {
4448c2ecf20Sopenharmony_ci	u16 id;
4458c2ecf20Sopenharmony_ci	u8 port;
4468c2ecf20Sopenharmony_ci	u8 pin;
4478c2ecf20Sopenharmony_ci	u8 mux_func;
4488c2ecf20Sopenharmony_ci	u8 mux_flags;
4498c2ecf20Sopenharmony_ci	u8 value;
4508c2ecf20Sopenharmony_ci};
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci/**
4538c2ecf20Sopenharmony_ci * struct rza1_port - describes a pin port
4548c2ecf20Sopenharmony_ci *
4558c2ecf20Sopenharmony_ci * This is mostly useful to lock register writes per-bank and not globally.
4568c2ecf20Sopenharmony_ci *
4578c2ecf20Sopenharmony_ci * @lock: protect access to HW registers
4588c2ecf20Sopenharmony_ci * @id: port number
4598c2ecf20Sopenharmony_ci * @base: logical address base
4608c2ecf20Sopenharmony_ci * @pins: pins sitting on this port
4618c2ecf20Sopenharmony_ci */
4628c2ecf20Sopenharmony_cistruct rza1_port {
4638c2ecf20Sopenharmony_ci	spinlock_t lock;
4648c2ecf20Sopenharmony_ci	unsigned int id;
4658c2ecf20Sopenharmony_ci	void __iomem *base;
4668c2ecf20Sopenharmony_ci	struct pinctrl_pin_desc *pins;
4678c2ecf20Sopenharmony_ci};
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci/**
4708c2ecf20Sopenharmony_ci * struct rza1_pinctrl - RZ pincontroller device
4718c2ecf20Sopenharmony_ci *
4728c2ecf20Sopenharmony_ci * @dev: parent device structure
4738c2ecf20Sopenharmony_ci * @mutex: protect [pinctrl|pinmux]_generic functions
4748c2ecf20Sopenharmony_ci * @base: logical address base
4758c2ecf20Sopenharmony_ci * @nport: number of pin controller ports
4768c2ecf20Sopenharmony_ci * @ports: pin controller banks
4778c2ecf20Sopenharmony_ci * @pins: pin array for pinctrl core
4788c2ecf20Sopenharmony_ci * @desc: pincontroller desc for pinctrl core
4798c2ecf20Sopenharmony_ci * @pctl: pinctrl device
4808c2ecf20Sopenharmony_ci * @data: device specific data
4818c2ecf20Sopenharmony_ci */
4828c2ecf20Sopenharmony_cistruct rza1_pinctrl {
4838c2ecf20Sopenharmony_ci	struct device *dev;
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	struct mutex mutex;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	void __iomem *base;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	unsigned int nport;
4908c2ecf20Sopenharmony_ci	struct rza1_port *ports;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	struct pinctrl_pin_desc *pins;
4938c2ecf20Sopenharmony_ci	struct pinctrl_desc desc;
4948c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctl;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	const void *data;
4978c2ecf20Sopenharmony_ci};
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
5008c2ecf20Sopenharmony_ci * RZ/A1 pinmux flags
5018c2ecf20Sopenharmony_ci */
5028c2ecf20Sopenharmony_cistatic inline bool rza1_pinmux_get_bidir(unsigned int port,
5038c2ecf20Sopenharmony_ci					 unsigned int pin,
5048c2ecf20Sopenharmony_ci					 unsigned int func,
5058c2ecf20Sopenharmony_ci					 const struct rza1_bidir_entry *table)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	const struct rza1_bidir_entry *entry = &table[port];
5088c2ecf20Sopenharmony_ci	const struct rza1_bidir_pin *bidir_pin;
5098c2ecf20Sopenharmony_ci	unsigned int i;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	for (i = 0; i < entry->npins; ++i) {
5128c2ecf20Sopenharmony_ci		bidir_pin = &entry->pins[i];
5138c2ecf20Sopenharmony_ci		if (bidir_pin->pin == pin && bidir_pin->func == func)
5148c2ecf20Sopenharmony_ci			return true;
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	return false;
5188c2ecf20Sopenharmony_ci}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_cistatic inline int rza1_pinmux_get_swio(unsigned int port,
5218c2ecf20Sopenharmony_ci				       unsigned int pin,
5228c2ecf20Sopenharmony_ci				       unsigned int func,
5238c2ecf20Sopenharmony_ci				       const struct rza1_swio_entry *table)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	const struct rza1_swio_pin *swio_pin;
5268c2ecf20Sopenharmony_ci	unsigned int i;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	for (i = 0; i < table->npins; ++i) {
5308c2ecf20Sopenharmony_ci		swio_pin = &table->pins[i];
5318c2ecf20Sopenharmony_ci		if (swio_pin->port == port && swio_pin->pin == pin &&
5328c2ecf20Sopenharmony_ci		    swio_pin->func == func)
5338c2ecf20Sopenharmony_ci			return swio_pin->input;
5348c2ecf20Sopenharmony_ci	}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	return -ENOENT;
5378c2ecf20Sopenharmony_ci}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci/*
5408c2ecf20Sopenharmony_ci * rza1_pinmux_get_flags() - return pinmux flags associated to a pin
5418c2ecf20Sopenharmony_ci */
5428c2ecf20Sopenharmony_cistatic unsigned int rza1_pinmux_get_flags(unsigned int port, unsigned int pin,
5438c2ecf20Sopenharmony_ci					  unsigned int func,
5448c2ecf20Sopenharmony_ci					  struct rza1_pinctrl *rza1_pctl)
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci{
5478c2ecf20Sopenharmony_ci	const struct rza1_pinmux_conf *pmx_conf = rza1_pctl->data;
5488c2ecf20Sopenharmony_ci	const struct rza1_bidir_entry *bidir_entries = pmx_conf->bidir_entries;
5498c2ecf20Sopenharmony_ci	const struct rza1_swio_entry *swio_entries = pmx_conf->swio_entries;
5508c2ecf20Sopenharmony_ci	unsigned int pmx_flags = 0;
5518c2ecf20Sopenharmony_ci	int ret;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	if (rza1_pinmux_get_bidir(port, pin, func, bidir_entries))
5548c2ecf20Sopenharmony_ci		pmx_flags |= MUX_FLAGS_BIDIR;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	ret = rza1_pinmux_get_swio(port, pin, func, swio_entries);
5578c2ecf20Sopenharmony_ci	if (ret == 0)
5588c2ecf20Sopenharmony_ci		pmx_flags |= MUX_FLAGS_SWIO_OUTPUT;
5598c2ecf20Sopenharmony_ci	else if (ret > 0)
5608c2ecf20Sopenharmony_ci		pmx_flags |= MUX_FLAGS_SWIO_INPUT;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	return pmx_flags;
5638c2ecf20Sopenharmony_ci}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
5668c2ecf20Sopenharmony_ci * RZ/A1 SoC operations
5678c2ecf20Sopenharmony_ci */
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci/*
5708c2ecf20Sopenharmony_ci * rza1_set_bit() - un-locked set/clear a single bit in pin configuration
5718c2ecf20Sopenharmony_ci *		    registers
5728c2ecf20Sopenharmony_ci */
5738c2ecf20Sopenharmony_cistatic inline void rza1_set_bit(struct rza1_port *port, unsigned int reg,
5748c2ecf20Sopenharmony_ci				unsigned int bit, bool set)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
5778c2ecf20Sopenharmony_ci	u16 val = ioread16(mem);
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	if (set)
5808c2ecf20Sopenharmony_ci		val |= BIT(bit);
5818c2ecf20Sopenharmony_ci	else
5828c2ecf20Sopenharmony_ci		val &= ~BIT(bit);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	iowrite16(val, mem);
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic inline unsigned int rza1_get_bit(struct rza1_port *port,
5888c2ecf20Sopenharmony_ci					unsigned int reg, unsigned int bit)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	void __iomem *mem = RZA1_ADDR(port->base, reg, port->id);
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	return ioread16(mem) & BIT(bit);
5938c2ecf20Sopenharmony_ci}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci/**
5968c2ecf20Sopenharmony_ci * rza1_pin_reset() - reset a pin to default initial state
5978c2ecf20Sopenharmony_ci *
5988c2ecf20Sopenharmony_ci * Reset pin state disabling input buffer and bi-directional control,
5998c2ecf20Sopenharmony_ci * and configure it as input port.
6008c2ecf20Sopenharmony_ci * Note that pin is now configured with direction as input but with input
6018c2ecf20Sopenharmony_ci * buffer disabled. This implies the pin value cannot be read in this state.
6028c2ecf20Sopenharmony_ci *
6038c2ecf20Sopenharmony_ci * @port: port where pin sits on
6048c2ecf20Sopenharmony_ci * @pin: pin offset
6058c2ecf20Sopenharmony_ci */
6068c2ecf20Sopenharmony_cistatic void rza1_pin_reset(struct rza1_port *port, unsigned int pin)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	unsigned long irqflags;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, irqflags);
6118c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PIBC_REG, pin, 0);
6128c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PBDC_REG, pin, 0);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PM_REG, pin, 1);
6158c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PMC_REG, pin, 0);
6168c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PIPC_REG, pin, 0);
6178c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, irqflags);
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci/**
6218c2ecf20Sopenharmony_ci * rza1_pin_set_direction() - set I/O direction on a pin in port mode
6228c2ecf20Sopenharmony_ci *
6238c2ecf20Sopenharmony_ci * When running in output port mode keep PBDC enabled to allow reading the
6248c2ecf20Sopenharmony_ci * pin value from PPR.
6258c2ecf20Sopenharmony_ci *
6268c2ecf20Sopenharmony_ci * @port: port where pin sits on
6278c2ecf20Sopenharmony_ci * @pin: pin offset
6288c2ecf20Sopenharmony_ci * @input: input enable/disable flag
6298c2ecf20Sopenharmony_ci */
6308c2ecf20Sopenharmony_cistatic inline void rza1_pin_set_direction(struct rza1_port *port,
6318c2ecf20Sopenharmony_ci					  unsigned int pin, bool input)
6328c2ecf20Sopenharmony_ci{
6338c2ecf20Sopenharmony_ci	unsigned long irqflags;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, irqflags);
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PIBC_REG, pin, 1);
6388c2ecf20Sopenharmony_ci	if (input) {
6398c2ecf20Sopenharmony_ci		rza1_set_bit(port, RZA1_PM_REG, pin, 1);
6408c2ecf20Sopenharmony_ci		rza1_set_bit(port, RZA1_PBDC_REG, pin, 0);
6418c2ecf20Sopenharmony_ci	} else {
6428c2ecf20Sopenharmony_ci		rza1_set_bit(port, RZA1_PM_REG, pin, 0);
6438c2ecf20Sopenharmony_ci		rza1_set_bit(port, RZA1_PBDC_REG, pin, 1);
6448c2ecf20Sopenharmony_ci	}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, irqflags);
6478c2ecf20Sopenharmony_ci}
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_cistatic inline void rza1_pin_set(struct rza1_port *port, unsigned int pin,
6508c2ecf20Sopenharmony_ci				unsigned int value)
6518c2ecf20Sopenharmony_ci{
6528c2ecf20Sopenharmony_ci	unsigned long irqflags;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	spin_lock_irqsave(&port->lock, irqflags);
6558c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_P_REG, pin, !!value);
6568c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&port->lock, irqflags);
6578c2ecf20Sopenharmony_ci}
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_cistatic inline int rza1_pin_get(struct rza1_port *port, unsigned int pin)
6608c2ecf20Sopenharmony_ci{
6618c2ecf20Sopenharmony_ci	return rza1_get_bit(port, RZA1_PPR_REG, pin);
6628c2ecf20Sopenharmony_ci}
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci/**
6658c2ecf20Sopenharmony_ci * rza1_pin_mux_single() - configure pin multiplexing on a single pin
6668c2ecf20Sopenharmony_ci *
6678c2ecf20Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device
6688c2ecf20Sopenharmony_ci * @mux_conf: pin multiplexing descriptor
6698c2ecf20Sopenharmony_ci */
6708c2ecf20Sopenharmony_cistatic int rza1_pin_mux_single(struct rza1_pinctrl *rza1_pctl,
6718c2ecf20Sopenharmony_ci			       struct rza1_mux_conf *mux_conf)
6728c2ecf20Sopenharmony_ci{
6738c2ecf20Sopenharmony_ci	struct rza1_port *port = &rza1_pctl->ports[mux_conf->port];
6748c2ecf20Sopenharmony_ci	unsigned int pin = mux_conf->pin;
6758c2ecf20Sopenharmony_ci	u8 mux_func = mux_conf->mux_func;
6768c2ecf20Sopenharmony_ci	u8 mux_flags = mux_conf->mux_flags;
6778c2ecf20Sopenharmony_ci	u8 mux_flags_from_table;
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	rza1_pin_reset(port, pin);
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	/* SWIO pinmux flags coming from DT are high precedence */
6828c2ecf20Sopenharmony_ci	mux_flags_from_table = rza1_pinmux_get_flags(port->id, pin, mux_func,
6838c2ecf20Sopenharmony_ci						     rza1_pctl);
6848c2ecf20Sopenharmony_ci	if (mux_flags)
6858c2ecf20Sopenharmony_ci		mux_flags |= (mux_flags_from_table & MUX_FLAGS_BIDIR);
6868c2ecf20Sopenharmony_ci	else
6878c2ecf20Sopenharmony_ci		mux_flags = mux_flags_from_table;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	if (mux_flags & MUX_FLAGS_BIDIR)
6908c2ecf20Sopenharmony_ci		rza1_set_bit(port, RZA1_PBDC_REG, pin, 1);
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	/*
6938c2ecf20Sopenharmony_ci	 * Enable alternate function mode and select it.
6948c2ecf20Sopenharmony_ci	 *
6958c2ecf20Sopenharmony_ci	 * Be careful here: the pin mux sub-nodes in device tree
6968c2ecf20Sopenharmony_ci	 * enumerate alternate functions from 1 to 8;
6978c2ecf20Sopenharmony_ci	 * subtract 1 before using macros to match registers configuration
6988c2ecf20Sopenharmony_ci	 * which expects numbers from 0 to 7 instead.
6998c2ecf20Sopenharmony_ci	 *
7008c2ecf20Sopenharmony_ci	 * ----------------------------------------------------
7018c2ecf20Sopenharmony_ci	 * Alternate mode selection table:
7028c2ecf20Sopenharmony_ci	 *
7038c2ecf20Sopenharmony_ci	 * PMC	PFC	PFCE	PFCAE	(mux_func - 1)
7048c2ecf20Sopenharmony_ci	 * 1	0	0	0	0
7058c2ecf20Sopenharmony_ci	 * 1	1	0	0	1
7068c2ecf20Sopenharmony_ci	 * 1	0	1	0	2
7078c2ecf20Sopenharmony_ci	 * 1	1	1	0	3
7088c2ecf20Sopenharmony_ci	 * 1	0	0	1	4
7098c2ecf20Sopenharmony_ci	 * 1	1	0	1	5
7108c2ecf20Sopenharmony_ci	 * 1	0	1	1	6
7118c2ecf20Sopenharmony_ci	 * 1	1	1	1	7
7128c2ecf20Sopenharmony_ci	 * ----------------------------------------------------
7138c2ecf20Sopenharmony_ci	 */
7148c2ecf20Sopenharmony_ci	mux_func -= 1;
7158c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PFC_REG, pin, mux_func & MUX_FUNC_PFC_MASK);
7168c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PFCE_REG, pin, mux_func & MUX_FUNC_PFCE_MASK);
7178c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PFCEA_REG, pin, mux_func & MUX_FUNC_PFCEA_MASK);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	/*
7208c2ecf20Sopenharmony_ci	 * All alternate functions except a few need PIPCn = 1.
7218c2ecf20Sopenharmony_ci	 * If PIPCn has to stay disabled (SW IO mode), configure PMn according
7228c2ecf20Sopenharmony_ci	 * to I/O direction specified by pin configuration -after- PMC has been
7238c2ecf20Sopenharmony_ci	 * set to one.
7248c2ecf20Sopenharmony_ci	 */
7258c2ecf20Sopenharmony_ci	if (mux_flags & (MUX_FLAGS_SWIO_INPUT | MUX_FLAGS_SWIO_OUTPUT))
7268c2ecf20Sopenharmony_ci		rza1_set_bit(port, RZA1_PM_REG, pin,
7278c2ecf20Sopenharmony_ci			     mux_flags & MUX_FLAGS_SWIO_INPUT);
7288c2ecf20Sopenharmony_ci	else
7298c2ecf20Sopenharmony_ci		rza1_set_bit(port, RZA1_PIPC_REG, pin, 1);
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	rza1_set_bit(port, RZA1_PMC_REG, pin, 1);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	return 0;
7348c2ecf20Sopenharmony_ci}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
7378c2ecf20Sopenharmony_ci * gpio operations
7388c2ecf20Sopenharmony_ci */
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci/**
7418c2ecf20Sopenharmony_ci * rza1_gpio_request() - configure pin in port mode
7428c2ecf20Sopenharmony_ci *
7438c2ecf20Sopenharmony_ci * Configure a pin as gpio (port mode).
7448c2ecf20Sopenharmony_ci * After reset, the pin is in input mode with input buffer disabled.
7458c2ecf20Sopenharmony_ci * To use the pin as input or output, set_direction shall be called first
7468c2ecf20Sopenharmony_ci *
7478c2ecf20Sopenharmony_ci * @chip: gpio chip where the gpio sits on
7488c2ecf20Sopenharmony_ci * @gpio: gpio offset
7498c2ecf20Sopenharmony_ci */
7508c2ecf20Sopenharmony_cistatic int rza1_gpio_request(struct gpio_chip *chip, unsigned int gpio)
7518c2ecf20Sopenharmony_ci{
7528c2ecf20Sopenharmony_ci	struct rza1_port *port = gpiochip_get_data(chip);
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	rza1_pin_reset(port, gpio);
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	return 0;
7578c2ecf20Sopenharmony_ci}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci/**
7608c2ecf20Sopenharmony_ci * rza1_gpio_disable_free() - reset a pin
7618c2ecf20Sopenharmony_ci *
7628c2ecf20Sopenharmony_ci * Surprisingly, disable_free a gpio, is equivalent to request it.
7638c2ecf20Sopenharmony_ci * Reset pin to port mode, with input buffer disabled. This overwrites all
7648c2ecf20Sopenharmony_ci * port direction settings applied with set_direction
7658c2ecf20Sopenharmony_ci *
7668c2ecf20Sopenharmony_ci * @chip: gpio chip where the gpio sits on
7678c2ecf20Sopenharmony_ci * @gpio: gpio offset
7688c2ecf20Sopenharmony_ci */
7698c2ecf20Sopenharmony_cistatic void rza1_gpio_free(struct gpio_chip *chip, unsigned int gpio)
7708c2ecf20Sopenharmony_ci{
7718c2ecf20Sopenharmony_ci	struct rza1_port *port = gpiochip_get_data(chip);
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	rza1_pin_reset(port, gpio);
7748c2ecf20Sopenharmony_ci}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_cistatic int rza1_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
7778c2ecf20Sopenharmony_ci{
7788c2ecf20Sopenharmony_ci	struct rza1_port *port = gpiochip_get_data(chip);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	if (rza1_get_bit(port, RZA1_PM_REG, gpio))
7818c2ecf20Sopenharmony_ci		return GPIO_LINE_DIRECTION_IN;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	return GPIO_LINE_DIRECTION_OUT;
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic int rza1_gpio_direction_input(struct gpio_chip *chip,
7878c2ecf20Sopenharmony_ci				     unsigned int gpio)
7888c2ecf20Sopenharmony_ci{
7898c2ecf20Sopenharmony_ci	struct rza1_port *port = gpiochip_get_data(chip);
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	rza1_pin_set_direction(port, gpio, true);
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	return 0;
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_cistatic int rza1_gpio_direction_output(struct gpio_chip *chip,
7978c2ecf20Sopenharmony_ci				      unsigned int gpio,
7988c2ecf20Sopenharmony_ci				      int value)
7998c2ecf20Sopenharmony_ci{
8008c2ecf20Sopenharmony_ci	struct rza1_port *port = gpiochip_get_data(chip);
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	/* Set value before driving pin direction */
8038c2ecf20Sopenharmony_ci	rza1_pin_set(port, gpio, value);
8048c2ecf20Sopenharmony_ci	rza1_pin_set_direction(port, gpio, false);
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci	return 0;
8078c2ecf20Sopenharmony_ci}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci/**
8108c2ecf20Sopenharmony_ci * rza1_gpio_get() - read a gpio pin value
8118c2ecf20Sopenharmony_ci *
8128c2ecf20Sopenharmony_ci * Read gpio pin value through PPR register.
8138c2ecf20Sopenharmony_ci * Requires bi-directional mode to work when reading the value of a pin
8148c2ecf20Sopenharmony_ci * in output mode
8158c2ecf20Sopenharmony_ci *
8168c2ecf20Sopenharmony_ci * @chip: gpio chip where the gpio sits on
8178c2ecf20Sopenharmony_ci * @gpio: gpio offset
8188c2ecf20Sopenharmony_ci */
8198c2ecf20Sopenharmony_cistatic int rza1_gpio_get(struct gpio_chip *chip, unsigned int gpio)
8208c2ecf20Sopenharmony_ci{
8218c2ecf20Sopenharmony_ci	struct rza1_port *port = gpiochip_get_data(chip);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	return rza1_pin_get(port, gpio);
8248c2ecf20Sopenharmony_ci}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_cistatic void rza1_gpio_set(struct gpio_chip *chip, unsigned int gpio,
8278c2ecf20Sopenharmony_ci			  int value)
8288c2ecf20Sopenharmony_ci{
8298c2ecf20Sopenharmony_ci	struct rza1_port *port = gpiochip_get_data(chip);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	rza1_pin_set(port, gpio, value);
8328c2ecf20Sopenharmony_ci}
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_cistatic const struct gpio_chip rza1_gpiochip_template = {
8358c2ecf20Sopenharmony_ci	.request		= rza1_gpio_request,
8368c2ecf20Sopenharmony_ci	.free			= rza1_gpio_free,
8378c2ecf20Sopenharmony_ci	.get_direction		= rza1_gpio_get_direction,
8388c2ecf20Sopenharmony_ci	.direction_input	= rza1_gpio_direction_input,
8398c2ecf20Sopenharmony_ci	.direction_output	= rza1_gpio_direction_output,
8408c2ecf20Sopenharmony_ci	.get			= rza1_gpio_get,
8418c2ecf20Sopenharmony_ci	.set			= rza1_gpio_set,
8428c2ecf20Sopenharmony_ci};
8438c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
8448c2ecf20Sopenharmony_ci * pinctrl operations
8458c2ecf20Sopenharmony_ci */
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci/**
8488c2ecf20Sopenharmony_ci * rza1_dt_node_pin_count() - Count number of pins in a dt node or in all its
8498c2ecf20Sopenharmony_ci *			      children sub-nodes
8508c2ecf20Sopenharmony_ci *
8518c2ecf20Sopenharmony_ci * @np: device tree node to parse
8528c2ecf20Sopenharmony_ci */
8538c2ecf20Sopenharmony_cistatic int rza1_dt_node_pin_count(struct device_node *np)
8548c2ecf20Sopenharmony_ci{
8558c2ecf20Sopenharmony_ci	struct device_node *child;
8568c2ecf20Sopenharmony_ci	struct property *of_pins;
8578c2ecf20Sopenharmony_ci	unsigned int npins;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	of_pins = of_find_property(np, "pinmux", NULL);
8608c2ecf20Sopenharmony_ci	if (of_pins)
8618c2ecf20Sopenharmony_ci		return of_pins->length / sizeof(u32);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	npins = 0;
8648c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
8658c2ecf20Sopenharmony_ci		of_pins = of_find_property(child, "pinmux", NULL);
8668c2ecf20Sopenharmony_ci		if (!of_pins) {
8678c2ecf20Sopenharmony_ci			of_node_put(child);
8688c2ecf20Sopenharmony_ci			return -EINVAL;
8698c2ecf20Sopenharmony_ci		}
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci		npins += of_pins->length / sizeof(u32);
8728c2ecf20Sopenharmony_ci	}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	return npins;
8758c2ecf20Sopenharmony_ci}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci/**
8788c2ecf20Sopenharmony_ci * rza1_parse_pmx_function() - parse a pin mux sub-node
8798c2ecf20Sopenharmony_ci *
8808c2ecf20Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device
8818c2ecf20Sopenharmony_ci * @np: of pmx sub-node
8828c2ecf20Sopenharmony_ci * @mux_confs: array of pin mux configurations to fill with parsed info
8838c2ecf20Sopenharmony_ci * @grpins: array of pin ids to mux
8848c2ecf20Sopenharmony_ci */
8858c2ecf20Sopenharmony_cistatic int rza1_parse_pinmux_node(struct rza1_pinctrl *rza1_pctl,
8868c2ecf20Sopenharmony_ci				  struct device_node *np,
8878c2ecf20Sopenharmony_ci				  struct rza1_mux_conf *mux_confs,
8888c2ecf20Sopenharmony_ci				  unsigned int *grpins)
8898c2ecf20Sopenharmony_ci{
8908c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctldev = rza1_pctl->pctl;
8918c2ecf20Sopenharmony_ci	char const *prop_name = "pinmux";
8928c2ecf20Sopenharmony_ci	unsigned long *pin_configs;
8938c2ecf20Sopenharmony_ci	unsigned int npin_configs;
8948c2ecf20Sopenharmony_ci	struct property *of_pins;
8958c2ecf20Sopenharmony_ci	unsigned int npins;
8968c2ecf20Sopenharmony_ci	u8 pinmux_flags;
8978c2ecf20Sopenharmony_ci	unsigned int i;
8988c2ecf20Sopenharmony_ci	int ret;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	of_pins = of_find_property(np, prop_name, NULL);
9018c2ecf20Sopenharmony_ci	if (!of_pins) {
9028c2ecf20Sopenharmony_ci		dev_dbg(rza1_pctl->dev, "Missing %s property\n", prop_name);
9038c2ecf20Sopenharmony_ci		return -ENOENT;
9048c2ecf20Sopenharmony_ci	}
9058c2ecf20Sopenharmony_ci	npins = of_pins->length / sizeof(u32);
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	/*
9088c2ecf20Sopenharmony_ci	 * Collect pin configuration properties: they apply to all pins in
9098c2ecf20Sopenharmony_ci	 * this sub-node
9108c2ecf20Sopenharmony_ci	 */
9118c2ecf20Sopenharmony_ci	ret = pinconf_generic_parse_dt_config(np, pctldev, &pin_configs,
9128c2ecf20Sopenharmony_ci					      &npin_configs);
9138c2ecf20Sopenharmony_ci	if (ret) {
9148c2ecf20Sopenharmony_ci		dev_err(rza1_pctl->dev,
9158c2ecf20Sopenharmony_ci			"Unable to parse pin configuration options for %pOFn\n",
9168c2ecf20Sopenharmony_ci			np);
9178c2ecf20Sopenharmony_ci		return ret;
9188c2ecf20Sopenharmony_ci	}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	/*
9218c2ecf20Sopenharmony_ci	 * Create a mask with pinmux flags from pin configuration;
9228c2ecf20Sopenharmony_ci	 * very few pins (TIOC[0-4][A|B|C|D] require SWIO direction
9238c2ecf20Sopenharmony_ci	 * specified in device tree.
9248c2ecf20Sopenharmony_ci	 */
9258c2ecf20Sopenharmony_ci	pinmux_flags = 0;
9268c2ecf20Sopenharmony_ci	for (i = 0; i < npin_configs && pinmux_flags == 0; i++)
9278c2ecf20Sopenharmony_ci		switch (pinconf_to_config_param(pin_configs[i])) {
9288c2ecf20Sopenharmony_ci		case PIN_CONFIG_INPUT_ENABLE:
9298c2ecf20Sopenharmony_ci			pinmux_flags |= MUX_FLAGS_SWIO_INPUT;
9308c2ecf20Sopenharmony_ci			break;
9318c2ecf20Sopenharmony_ci		case PIN_CONFIG_OUTPUT:	/* for DT backwards compatibility */
9328c2ecf20Sopenharmony_ci		case PIN_CONFIG_OUTPUT_ENABLE:
9338c2ecf20Sopenharmony_ci			pinmux_flags |= MUX_FLAGS_SWIO_OUTPUT;
9348c2ecf20Sopenharmony_ci		default:
9358c2ecf20Sopenharmony_ci			break;
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci		}
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci	kfree(pin_configs);
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	/* Collect pin positions and their mux settings. */
9428c2ecf20Sopenharmony_ci	for (i = 0; i < npins; ++i) {
9438c2ecf20Sopenharmony_ci		u32 of_pinconf;
9448c2ecf20Sopenharmony_ci		struct rza1_mux_conf *mux_conf = &mux_confs[i];
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci		ret = of_property_read_u32_index(np, prop_name, i, &of_pinconf);
9478c2ecf20Sopenharmony_ci		if (ret)
9488c2ecf20Sopenharmony_ci			return ret;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci		mux_conf->id		= of_pinconf & MUX_PIN_ID_MASK;
9518c2ecf20Sopenharmony_ci		mux_conf->port		= RZA1_PIN_ID_TO_PORT(mux_conf->id);
9528c2ecf20Sopenharmony_ci		mux_conf->pin		= RZA1_PIN_ID_TO_PIN(mux_conf->id);
9538c2ecf20Sopenharmony_ci		mux_conf->mux_func	= MUX_FUNC(of_pinconf);
9548c2ecf20Sopenharmony_ci		mux_conf->mux_flags	= pinmux_flags;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci		if (mux_conf->port >= RZA1_NPORTS ||
9578c2ecf20Sopenharmony_ci		    mux_conf->pin >= RZA1_PINS_PER_PORT) {
9588c2ecf20Sopenharmony_ci			dev_err(rza1_pctl->dev,
9598c2ecf20Sopenharmony_ci				"Wrong port %u pin %u for %s property\n",
9608c2ecf20Sopenharmony_ci				mux_conf->port, mux_conf->pin, prop_name);
9618c2ecf20Sopenharmony_ci			return -EINVAL;
9628c2ecf20Sopenharmony_ci		}
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci		grpins[i] = mux_conf->id;
9658c2ecf20Sopenharmony_ci	}
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	return npins;
9688c2ecf20Sopenharmony_ci}
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci/**
9718c2ecf20Sopenharmony_ci * rza1_dt_node_to_map() - map a pin mux node to a function/group
9728c2ecf20Sopenharmony_ci *
9738c2ecf20Sopenharmony_ci * Parse and register a pin mux function.
9748c2ecf20Sopenharmony_ci *
9758c2ecf20Sopenharmony_ci * @pctldev: pin controller device
9768c2ecf20Sopenharmony_ci * @np: device tree node to parse
9778c2ecf20Sopenharmony_ci * @map: pointer to pin map (output)
9788c2ecf20Sopenharmony_ci * @num_maps: number of collected maps (output)
9798c2ecf20Sopenharmony_ci */
9808c2ecf20Sopenharmony_cistatic int rza1_dt_node_to_map(struct pinctrl_dev *pctldev,
9818c2ecf20Sopenharmony_ci			       struct device_node *np,
9828c2ecf20Sopenharmony_ci			       struct pinctrl_map **map,
9838c2ecf20Sopenharmony_ci			       unsigned int *num_maps)
9848c2ecf20Sopenharmony_ci{
9858c2ecf20Sopenharmony_ci	struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev);
9868c2ecf20Sopenharmony_ci	struct rza1_mux_conf *mux_confs, *mux_conf;
9878c2ecf20Sopenharmony_ci	unsigned int *grpins, *grpin;
9888c2ecf20Sopenharmony_ci	struct device_node *child;
9898c2ecf20Sopenharmony_ci	const char *grpname;
9908c2ecf20Sopenharmony_ci	const char **fngrps;
9918c2ecf20Sopenharmony_ci	int ret, npins;
9928c2ecf20Sopenharmony_ci	int gsel, fsel;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	npins = rza1_dt_node_pin_count(np);
9958c2ecf20Sopenharmony_ci	if (npins < 0) {
9968c2ecf20Sopenharmony_ci		dev_err(rza1_pctl->dev, "invalid pinmux node structure\n");
9978c2ecf20Sopenharmony_ci		return -EINVAL;
9988c2ecf20Sopenharmony_ci	}
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	/*
10018c2ecf20Sopenharmony_ci	 * Functions are made of 1 group only;
10028c2ecf20Sopenharmony_ci	 * in fact, functions and groups are identical for this pin controller
10038c2ecf20Sopenharmony_ci	 * except that functions carry an array of per-pin mux configuration
10048c2ecf20Sopenharmony_ci	 * settings.
10058c2ecf20Sopenharmony_ci	 */
10068c2ecf20Sopenharmony_ci	mux_confs = devm_kcalloc(rza1_pctl->dev, npins, sizeof(*mux_confs),
10078c2ecf20Sopenharmony_ci				 GFP_KERNEL);
10088c2ecf20Sopenharmony_ci	grpins = devm_kcalloc(rza1_pctl->dev, npins, sizeof(*grpins),
10098c2ecf20Sopenharmony_ci			      GFP_KERNEL);
10108c2ecf20Sopenharmony_ci	fngrps = devm_kzalloc(rza1_pctl->dev, sizeof(*fngrps), GFP_KERNEL);
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	if (!mux_confs || !grpins || !fngrps)
10138c2ecf20Sopenharmony_ci		return -ENOMEM;
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	/*
10168c2ecf20Sopenharmony_ci	 * Parse the pinmux node.
10178c2ecf20Sopenharmony_ci	 * If the node does not contain "pinmux" property (-ENOENT)
10188c2ecf20Sopenharmony_ci	 * that property shall be specified in all its children sub-nodes.
10198c2ecf20Sopenharmony_ci	 */
10208c2ecf20Sopenharmony_ci	mux_conf = &mux_confs[0];
10218c2ecf20Sopenharmony_ci	grpin = &grpins[0];
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	ret = rza1_parse_pinmux_node(rza1_pctl, np, mux_conf, grpin);
10248c2ecf20Sopenharmony_ci	if (ret == -ENOENT)
10258c2ecf20Sopenharmony_ci		for_each_child_of_node(np, child) {
10268c2ecf20Sopenharmony_ci			ret = rza1_parse_pinmux_node(rza1_pctl, child, mux_conf,
10278c2ecf20Sopenharmony_ci						     grpin);
10288c2ecf20Sopenharmony_ci			if (ret < 0) {
10298c2ecf20Sopenharmony_ci				of_node_put(child);
10308c2ecf20Sopenharmony_ci				return ret;
10318c2ecf20Sopenharmony_ci			}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci			grpin += ret;
10348c2ecf20Sopenharmony_ci			mux_conf += ret;
10358c2ecf20Sopenharmony_ci		}
10368c2ecf20Sopenharmony_ci	else if (ret < 0)
10378c2ecf20Sopenharmony_ci		return ret;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	/* Register pin group and function name to pinctrl_generic */
10408c2ecf20Sopenharmony_ci	grpname	= np->name;
10418c2ecf20Sopenharmony_ci	fngrps[0] = grpname;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	mutex_lock(&rza1_pctl->mutex);
10448c2ecf20Sopenharmony_ci	gsel = pinctrl_generic_add_group(pctldev, grpname, grpins, npins,
10458c2ecf20Sopenharmony_ci					 NULL);
10468c2ecf20Sopenharmony_ci	if (gsel < 0) {
10478c2ecf20Sopenharmony_ci		mutex_unlock(&rza1_pctl->mutex);
10488c2ecf20Sopenharmony_ci		return gsel;
10498c2ecf20Sopenharmony_ci	}
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	fsel = pinmux_generic_add_function(pctldev, grpname, fngrps, 1,
10528c2ecf20Sopenharmony_ci					   mux_confs);
10538c2ecf20Sopenharmony_ci	if (fsel < 0) {
10548c2ecf20Sopenharmony_ci		ret = fsel;
10558c2ecf20Sopenharmony_ci		goto remove_group;
10568c2ecf20Sopenharmony_ci	}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	dev_info(rza1_pctl->dev, "Parsed function and group %s with %d pins\n",
10598c2ecf20Sopenharmony_ci				 grpname, npins);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	/* Create map where to retrieve function and mux settings from */
10628c2ecf20Sopenharmony_ci	*num_maps = 0;
10638c2ecf20Sopenharmony_ci	*map = kzalloc(sizeof(**map), GFP_KERNEL);
10648c2ecf20Sopenharmony_ci	if (!*map) {
10658c2ecf20Sopenharmony_ci		ret = -ENOMEM;
10668c2ecf20Sopenharmony_ci		goto remove_function;
10678c2ecf20Sopenharmony_ci	}
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	(*map)->type = PIN_MAP_TYPE_MUX_GROUP;
10708c2ecf20Sopenharmony_ci	(*map)->data.mux.group = np->name;
10718c2ecf20Sopenharmony_ci	(*map)->data.mux.function = np->name;
10728c2ecf20Sopenharmony_ci	*num_maps = 1;
10738c2ecf20Sopenharmony_ci	mutex_unlock(&rza1_pctl->mutex);
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	return 0;
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ciremove_function:
10788c2ecf20Sopenharmony_ci	pinmux_generic_remove_function(pctldev, fsel);
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ciremove_group:
10818c2ecf20Sopenharmony_ci	pinctrl_generic_remove_group(pctldev, gsel);
10828c2ecf20Sopenharmony_ci	mutex_unlock(&rza1_pctl->mutex);
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	dev_info(rza1_pctl->dev, "Unable to parse function and group %s\n",
10858c2ecf20Sopenharmony_ci				 grpname);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	return ret;
10888c2ecf20Sopenharmony_ci}
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_cistatic void rza1_dt_free_map(struct pinctrl_dev *pctldev,
10918c2ecf20Sopenharmony_ci			     struct pinctrl_map *map, unsigned int num_maps)
10928c2ecf20Sopenharmony_ci{
10938c2ecf20Sopenharmony_ci	kfree(map);
10948c2ecf20Sopenharmony_ci}
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_cistatic const struct pinctrl_ops rza1_pinctrl_ops = {
10978c2ecf20Sopenharmony_ci	.get_groups_count	= pinctrl_generic_get_group_count,
10988c2ecf20Sopenharmony_ci	.get_group_name		= pinctrl_generic_get_group_name,
10998c2ecf20Sopenharmony_ci	.get_group_pins		= pinctrl_generic_get_group_pins,
11008c2ecf20Sopenharmony_ci	.dt_node_to_map		= rza1_dt_node_to_map,
11018c2ecf20Sopenharmony_ci	.dt_free_map		= rza1_dt_free_map,
11028c2ecf20Sopenharmony_ci};
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
11058c2ecf20Sopenharmony_ci * pinmux operations
11068c2ecf20Sopenharmony_ci */
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci/**
11098c2ecf20Sopenharmony_ci * rza1_set_mux() - retrieve pins from a group and apply their mux settings
11108c2ecf20Sopenharmony_ci *
11118c2ecf20Sopenharmony_ci * @pctldev: pin controller device
11128c2ecf20Sopenharmony_ci * @selector: function selector
11138c2ecf20Sopenharmony_ci * @group: group selector
11148c2ecf20Sopenharmony_ci */
11158c2ecf20Sopenharmony_cistatic int rza1_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
11168c2ecf20Sopenharmony_ci			   unsigned int group)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	struct rza1_pinctrl *rza1_pctl = pinctrl_dev_get_drvdata(pctldev);
11198c2ecf20Sopenharmony_ci	struct rza1_mux_conf *mux_confs;
11208c2ecf20Sopenharmony_ci	struct function_desc *func;
11218c2ecf20Sopenharmony_ci	struct group_desc *grp;
11228c2ecf20Sopenharmony_ci	int i;
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	grp = pinctrl_generic_get_group(pctldev, group);
11258c2ecf20Sopenharmony_ci	if (!grp)
11268c2ecf20Sopenharmony_ci		return -EINVAL;
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	func = pinmux_generic_get_function(pctldev, selector);
11298c2ecf20Sopenharmony_ci	if (!func)
11308c2ecf20Sopenharmony_ci		return -EINVAL;
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	mux_confs = (struct rza1_mux_conf *)func->data;
11338c2ecf20Sopenharmony_ci	for (i = 0; i < grp->num_pins; ++i) {
11348c2ecf20Sopenharmony_ci		int ret;
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci		ret = rza1_pin_mux_single(rza1_pctl, &mux_confs[i]);
11378c2ecf20Sopenharmony_ci		if (ret)
11388c2ecf20Sopenharmony_ci			return ret;
11398c2ecf20Sopenharmony_ci	}
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	return 0;
11428c2ecf20Sopenharmony_ci}
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_cistatic const struct pinmux_ops rza1_pinmux_ops = {
11458c2ecf20Sopenharmony_ci	.get_functions_count	= pinmux_generic_get_function_count,
11468c2ecf20Sopenharmony_ci	.get_function_name	= pinmux_generic_get_function_name,
11478c2ecf20Sopenharmony_ci	.get_function_groups	= pinmux_generic_get_function_groups,
11488c2ecf20Sopenharmony_ci	.set_mux		= rza1_set_mux,
11498c2ecf20Sopenharmony_ci	.strict			= true,
11508c2ecf20Sopenharmony_ci};
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------
11538c2ecf20Sopenharmony_ci * RZ/A1 pin controller driver operations
11548c2ecf20Sopenharmony_ci */
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_cistatic unsigned int rza1_count_gpio_chips(struct device_node *np)
11578c2ecf20Sopenharmony_ci{
11588c2ecf20Sopenharmony_ci	struct device_node *child;
11598c2ecf20Sopenharmony_ci	unsigned int count = 0;
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
11628c2ecf20Sopenharmony_ci		if (!of_property_read_bool(child, "gpio-controller"))
11638c2ecf20Sopenharmony_ci			continue;
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci		count++;
11668c2ecf20Sopenharmony_ci	}
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	return count;
11698c2ecf20Sopenharmony_ci}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci/**
11728c2ecf20Sopenharmony_ci * rza1_parse_gpiochip() - parse and register a gpio chip and pin range
11738c2ecf20Sopenharmony_ci *
11748c2ecf20Sopenharmony_ci * The gpio controller subnode shall provide a "gpio-ranges" list property as
11758c2ecf20Sopenharmony_ci * defined by gpio device tree binding documentation.
11768c2ecf20Sopenharmony_ci *
11778c2ecf20Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device
11788c2ecf20Sopenharmony_ci * @np: of gpio-controller node
11798c2ecf20Sopenharmony_ci * @chip: gpio chip to register to gpiolib
11808c2ecf20Sopenharmony_ci * @range: pin range to register to pinctrl core
11818c2ecf20Sopenharmony_ci */
11828c2ecf20Sopenharmony_cistatic int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
11838c2ecf20Sopenharmony_ci			       struct device_node *np,
11848c2ecf20Sopenharmony_ci			       struct gpio_chip *chip,
11858c2ecf20Sopenharmony_ci			       struct pinctrl_gpio_range *range)
11868c2ecf20Sopenharmony_ci{
11878c2ecf20Sopenharmony_ci	const char *list_name = "gpio-ranges";
11888c2ecf20Sopenharmony_ci	struct of_phandle_args of_args;
11898c2ecf20Sopenharmony_ci	unsigned int gpioport;
11908c2ecf20Sopenharmony_ci	u32 pinctrl_base;
11918c2ecf20Sopenharmony_ci	int ret;
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	ret = of_parse_phandle_with_fixed_args(np, list_name, 3, 0, &of_args);
11948c2ecf20Sopenharmony_ci	if (ret) {
11958c2ecf20Sopenharmony_ci		dev_err(rza1_pctl->dev, "Unable to parse %s list property\n",
11968c2ecf20Sopenharmony_ci			list_name);
11978c2ecf20Sopenharmony_ci		return ret;
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	/*
12018c2ecf20Sopenharmony_ci	 * Find out on which port this gpio-chip maps to by inspecting the
12028c2ecf20Sopenharmony_ci	 * second argument of the "gpio-ranges" property.
12038c2ecf20Sopenharmony_ci	 */
12048c2ecf20Sopenharmony_ci	pinctrl_base = of_args.args[1];
12058c2ecf20Sopenharmony_ci	gpioport = RZA1_PIN_ID_TO_PORT(pinctrl_base);
12068c2ecf20Sopenharmony_ci	if (gpioport >= RZA1_NPORTS) {
12078c2ecf20Sopenharmony_ci		dev_err(rza1_pctl->dev,
12088c2ecf20Sopenharmony_ci			"Invalid values in property %s\n", list_name);
12098c2ecf20Sopenharmony_ci		return -EINVAL;
12108c2ecf20Sopenharmony_ci	}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	*chip		= rza1_gpiochip_template;
12138c2ecf20Sopenharmony_ci	chip->base	= -1;
12148c2ecf20Sopenharmony_ci	chip->label	= devm_kasprintf(rza1_pctl->dev, GFP_KERNEL, "%pOFn",
12158c2ecf20Sopenharmony_ci					 np);
12168c2ecf20Sopenharmony_ci	if (!chip->label)
12178c2ecf20Sopenharmony_ci		return -ENOMEM;
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	chip->ngpio	= of_args.args[2];
12208c2ecf20Sopenharmony_ci	chip->of_node	= np;
12218c2ecf20Sopenharmony_ci	chip->parent	= rza1_pctl->dev;
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ci	range->id	= gpioport;
12248c2ecf20Sopenharmony_ci	range->name	= chip->label;
12258c2ecf20Sopenharmony_ci	range->pin_base	= range->base = pinctrl_base;
12268c2ecf20Sopenharmony_ci	range->npins	= of_args.args[2];
12278c2ecf20Sopenharmony_ci	range->gc	= chip;
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	ret = devm_gpiochip_add_data(rza1_pctl->dev, chip,
12308c2ecf20Sopenharmony_ci				     &rza1_pctl->ports[gpioport]);
12318c2ecf20Sopenharmony_ci	if (ret)
12328c2ecf20Sopenharmony_ci		return ret;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	pinctrl_add_gpio_range(rza1_pctl->pctl, range);
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	dev_dbg(rza1_pctl->dev, "Parsed gpiochip %s with %d pins\n",
12378c2ecf20Sopenharmony_ci		chip->label, chip->ngpio);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	return 0;
12408c2ecf20Sopenharmony_ci}
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci/**
12438c2ecf20Sopenharmony_ci * rza1_gpio_register() - parse DT to collect gpio-chips and gpio-ranges
12448c2ecf20Sopenharmony_ci *
12458c2ecf20Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device
12468c2ecf20Sopenharmony_ci */
12478c2ecf20Sopenharmony_cistatic int rza1_gpio_register(struct rza1_pinctrl *rza1_pctl)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	struct device_node *np = rza1_pctl->dev->of_node;
12508c2ecf20Sopenharmony_ci	struct pinctrl_gpio_range *gpio_ranges;
12518c2ecf20Sopenharmony_ci	struct gpio_chip *gpio_chips;
12528c2ecf20Sopenharmony_ci	struct device_node *child;
12538c2ecf20Sopenharmony_ci	unsigned int ngpiochips;
12548c2ecf20Sopenharmony_ci	unsigned int i;
12558c2ecf20Sopenharmony_ci	int ret;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	ngpiochips = rza1_count_gpio_chips(np);
12588c2ecf20Sopenharmony_ci	if (ngpiochips == 0) {
12598c2ecf20Sopenharmony_ci		dev_dbg(rza1_pctl->dev, "No gpiochip registered\n");
12608c2ecf20Sopenharmony_ci		return 0;
12618c2ecf20Sopenharmony_ci	}
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	gpio_chips = devm_kcalloc(rza1_pctl->dev, ngpiochips,
12648c2ecf20Sopenharmony_ci				  sizeof(*gpio_chips), GFP_KERNEL);
12658c2ecf20Sopenharmony_ci	gpio_ranges = devm_kcalloc(rza1_pctl->dev, ngpiochips,
12668c2ecf20Sopenharmony_ci				   sizeof(*gpio_ranges), GFP_KERNEL);
12678c2ecf20Sopenharmony_ci	if (!gpio_chips || !gpio_ranges)
12688c2ecf20Sopenharmony_ci		return -ENOMEM;
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	i = 0;
12718c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
12728c2ecf20Sopenharmony_ci		if (!of_property_read_bool(child, "gpio-controller"))
12738c2ecf20Sopenharmony_ci			continue;
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci		ret = rza1_parse_gpiochip(rza1_pctl, child, &gpio_chips[i],
12768c2ecf20Sopenharmony_ci					  &gpio_ranges[i]);
12778c2ecf20Sopenharmony_ci		if (ret) {
12788c2ecf20Sopenharmony_ci			of_node_put(child);
12798c2ecf20Sopenharmony_ci			return ret;
12808c2ecf20Sopenharmony_ci		}
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci		++i;
12838c2ecf20Sopenharmony_ci	}
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	dev_info(rza1_pctl->dev, "Registered %u gpio controllers\n", i);
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	return 0;
12888c2ecf20Sopenharmony_ci}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci/**
12918c2ecf20Sopenharmony_ci * rza1_pinctrl_register() - Enumerate pins, ports and gpiochips; register
12928c2ecf20Sopenharmony_ci *			     them to pinctrl and gpio cores.
12938c2ecf20Sopenharmony_ci *
12948c2ecf20Sopenharmony_ci * @rza1_pctl: RZ/A1 pin controller device
12958c2ecf20Sopenharmony_ci */
12968c2ecf20Sopenharmony_cistatic int rza1_pinctrl_register(struct rza1_pinctrl *rza1_pctl)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	struct pinctrl_pin_desc *pins;
12998c2ecf20Sopenharmony_ci	struct rza1_port *ports;
13008c2ecf20Sopenharmony_ci	unsigned int i;
13018c2ecf20Sopenharmony_ci	int ret;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	pins = devm_kcalloc(rza1_pctl->dev, RZA1_NPINS, sizeof(*pins),
13048c2ecf20Sopenharmony_ci			    GFP_KERNEL);
13058c2ecf20Sopenharmony_ci	ports = devm_kcalloc(rza1_pctl->dev, RZA1_NPORTS, sizeof(*ports),
13068c2ecf20Sopenharmony_ci			     GFP_KERNEL);
13078c2ecf20Sopenharmony_ci	if (!pins || !ports)
13088c2ecf20Sopenharmony_ci		return -ENOMEM;
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	rza1_pctl->pins		= pins;
13118c2ecf20Sopenharmony_ci	rza1_pctl->desc.pins	= pins;
13128c2ecf20Sopenharmony_ci	rza1_pctl->desc.npins	= RZA1_NPINS;
13138c2ecf20Sopenharmony_ci	rza1_pctl->ports	= ports;
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	for (i = 0; i < RZA1_NPINS; ++i) {
13168c2ecf20Sopenharmony_ci		unsigned int pin = RZA1_PIN_ID_TO_PIN(i);
13178c2ecf20Sopenharmony_ci		unsigned int port = RZA1_PIN_ID_TO_PORT(i);
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci		pins[i].number = i;
13208c2ecf20Sopenharmony_ci		pins[i].name = devm_kasprintf(rza1_pctl->dev, GFP_KERNEL,
13218c2ecf20Sopenharmony_ci					      "P%u-%u", port, pin);
13228c2ecf20Sopenharmony_ci		if (!pins[i].name)
13238c2ecf20Sopenharmony_ci			return -ENOMEM;
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci		if (i % RZA1_PINS_PER_PORT == 0) {
13268c2ecf20Sopenharmony_ci			/*
13278c2ecf20Sopenharmony_ci			 * Setup ports;
13288c2ecf20Sopenharmony_ci			 * they provide per-port lock and logical base address.
13298c2ecf20Sopenharmony_ci			 */
13308c2ecf20Sopenharmony_ci			unsigned int port_id = RZA1_PIN_ID_TO_PORT(i);
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci			ports[port_id].id	= port_id;
13338c2ecf20Sopenharmony_ci			ports[port_id].base	= rza1_pctl->base;
13348c2ecf20Sopenharmony_ci			ports[port_id].pins	= &pins[i];
13358c2ecf20Sopenharmony_ci			spin_lock_init(&ports[port_id].lock);
13368c2ecf20Sopenharmony_ci		}
13378c2ecf20Sopenharmony_ci	}
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci	ret = devm_pinctrl_register_and_init(rza1_pctl->dev, &rza1_pctl->desc,
13408c2ecf20Sopenharmony_ci					     rza1_pctl, &rza1_pctl->pctl);
13418c2ecf20Sopenharmony_ci	if (ret) {
13428c2ecf20Sopenharmony_ci		dev_err(rza1_pctl->dev,
13438c2ecf20Sopenharmony_ci			"RZ/A1 pin controller registration failed\n");
13448c2ecf20Sopenharmony_ci		return ret;
13458c2ecf20Sopenharmony_ci	}
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci	ret = pinctrl_enable(rza1_pctl->pctl);
13488c2ecf20Sopenharmony_ci	if (ret) {
13498c2ecf20Sopenharmony_ci		dev_err(rza1_pctl->dev,
13508c2ecf20Sopenharmony_ci			"RZ/A1 pin controller failed to start\n");
13518c2ecf20Sopenharmony_ci		return ret;
13528c2ecf20Sopenharmony_ci	}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	ret = rza1_gpio_register(rza1_pctl);
13558c2ecf20Sopenharmony_ci	if (ret) {
13568c2ecf20Sopenharmony_ci		dev_err(rza1_pctl->dev, "RZ/A1 GPIO registration failed\n");
13578c2ecf20Sopenharmony_ci		return ret;
13588c2ecf20Sopenharmony_ci	}
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	return 0;
13618c2ecf20Sopenharmony_ci}
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_cistatic int rza1_pinctrl_probe(struct platform_device *pdev)
13648c2ecf20Sopenharmony_ci{
13658c2ecf20Sopenharmony_ci	struct rza1_pinctrl *rza1_pctl;
13668c2ecf20Sopenharmony_ci	int ret;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	rza1_pctl = devm_kzalloc(&pdev->dev, sizeof(*rza1_pctl), GFP_KERNEL);
13698c2ecf20Sopenharmony_ci	if (!rza1_pctl)
13708c2ecf20Sopenharmony_ci		return -ENOMEM;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	rza1_pctl->dev = &pdev->dev;
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_ci	rza1_pctl->base = devm_platform_ioremap_resource(pdev, 0);
13758c2ecf20Sopenharmony_ci	if (IS_ERR(rza1_pctl->base))
13768c2ecf20Sopenharmony_ci		return PTR_ERR(rza1_pctl->base);
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	mutex_init(&rza1_pctl->mutex);
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, rza1_pctl);
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci	rza1_pctl->desc.name	= DRIVER_NAME;
13838c2ecf20Sopenharmony_ci	rza1_pctl->desc.pctlops	= &rza1_pinctrl_ops;
13848c2ecf20Sopenharmony_ci	rza1_pctl->desc.pmxops	= &rza1_pinmux_ops;
13858c2ecf20Sopenharmony_ci	rza1_pctl->desc.owner	= THIS_MODULE;
13868c2ecf20Sopenharmony_ci	rza1_pctl->data		= of_device_get_match_data(&pdev->dev);
13878c2ecf20Sopenharmony_ci
13888c2ecf20Sopenharmony_ci	ret = rza1_pinctrl_register(rza1_pctl);
13898c2ecf20Sopenharmony_ci	if (ret)
13908c2ecf20Sopenharmony_ci		return ret;
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	dev_info(&pdev->dev,
13938c2ecf20Sopenharmony_ci		 "RZ/A1 pin controller and gpio successfully registered\n");
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	return 0;
13968c2ecf20Sopenharmony_ci}
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_cistatic const struct of_device_id rza1_pinctrl_of_match[] = {
13998c2ecf20Sopenharmony_ci	{
14008c2ecf20Sopenharmony_ci		/* RZ/A1H, RZ/A1M */
14018c2ecf20Sopenharmony_ci		.compatible	= "renesas,r7s72100-ports",
14028c2ecf20Sopenharmony_ci		.data		= &rza1h_pmx_conf,
14038c2ecf20Sopenharmony_ci	},
14048c2ecf20Sopenharmony_ci	{
14058c2ecf20Sopenharmony_ci		/* RZ/A1L */
14068c2ecf20Sopenharmony_ci		.compatible	= "renesas,r7s72102-ports",
14078c2ecf20Sopenharmony_ci		.data		= &rza1l_pmx_conf,
14088c2ecf20Sopenharmony_ci	},
14098c2ecf20Sopenharmony_ci	{ }
14108c2ecf20Sopenharmony_ci};
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_cistatic struct platform_driver rza1_pinctrl_driver = {
14138c2ecf20Sopenharmony_ci	.driver = {
14148c2ecf20Sopenharmony_ci		.name = DRIVER_NAME,
14158c2ecf20Sopenharmony_ci		.of_match_table = rza1_pinctrl_of_match,
14168c2ecf20Sopenharmony_ci	},
14178c2ecf20Sopenharmony_ci	.probe = rza1_pinctrl_probe,
14188c2ecf20Sopenharmony_ci};
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_cistatic int __init rza1_pinctrl_init(void)
14218c2ecf20Sopenharmony_ci{
14228c2ecf20Sopenharmony_ci	return platform_driver_register(&rza1_pinctrl_driver);
14238c2ecf20Sopenharmony_ci}
14248c2ecf20Sopenharmony_cicore_initcall(rza1_pinctrl_init);
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org");
14278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Pin and gpio controller driver for Reneas RZ/A1 SoC");
14288c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1429