18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2014-2018 Renesas Electronics Europe Limited
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Phil Edworthy <phil.edworthy@renesas.com>
68c2ecf20Sopenharmony_ci * Based on a driver originally written by Michel Pollet at Renesas.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <dt-bindings/pinctrl/rzn1-pinctrl.h>
108c2ecf20Sopenharmony_ci#include <linux/clk.h>
118c2ecf20Sopenharmony_ci#include <linux/device.h>
128c2ecf20Sopenharmony_ci#include <linux/io.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/of.h>
158c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h>
168c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
178c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinmux.h>
188c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
198c2ecf20Sopenharmony_ci#include <linux/slab.h>
208c2ecf20Sopenharmony_ci#include "../core.h"
218c2ecf20Sopenharmony_ci#include "../pinconf.h"
228c2ecf20Sopenharmony_ci#include "../pinctrl-utils.h"
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/* Field positions and masks in the pinmux registers */
258c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_DRIVE_STRENGTH	10
268c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_DRIVE_STRENGTH_4MA	0
278c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_DRIVE_STRENGTH_6MA	1
288c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_DRIVE_STRENGTH_8MA	2
298c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_DRIVE_STRENGTH_12MA	3
308c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_PULL		8
318c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_PULL_NONE		0
328c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_PULL_UP		1
338c2ecf20Sopenharmony_ci#define RZN1_L1_PIN_PULL_DOWN		3
348c2ecf20Sopenharmony_ci#define RZN1_L1_FUNCTION		0
358c2ecf20Sopenharmony_ci#define RZN1_L1_FUNC_MASK		0xf
368c2ecf20Sopenharmony_ci#define RZN1_L1_FUNCTION_L2		0xf
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * The hardware manual describes two levels of multiplexing, but it's more
408c2ecf20Sopenharmony_ci * logical to think of the hardware as three levels, with level 3 consisting of
418c2ecf20Sopenharmony_ci * the multiplexing for Ethernet MDIO signals.
428c2ecf20Sopenharmony_ci *
438c2ecf20Sopenharmony_ci * Level 1 functions go from 0 to 9, with level 1 function '15' (0xf) specifying
448c2ecf20Sopenharmony_ci * that level 2 functions are used instead. Level 2 has a lot more options,
458c2ecf20Sopenharmony_ci * going from 0 to 61. Level 3 allows selection of MDIO functions which can be
468c2ecf20Sopenharmony_ci * floating, or one of seven internal peripherals. Unfortunately, there are two
478c2ecf20Sopenharmony_ci * level 2 functions that can select MDIO, and two MDIO channels so we have four
488c2ecf20Sopenharmony_ci * sets of level 3 functions.
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci * For this driver, we've compounded the numbers together, so:
518c2ecf20Sopenharmony_ci *    0 to   9 is level 1
528c2ecf20Sopenharmony_ci *   10 to  71 is 10 + level 2 number
538c2ecf20Sopenharmony_ci *   72 to  79 is 72 + MDIO0 source for level 2 MDIO function.
548c2ecf20Sopenharmony_ci *   80 to  87 is 80 + MDIO0 source for level 2 MDIO_E1 function.
558c2ecf20Sopenharmony_ci *   88 to  95 is 88 + MDIO1 source for level 2 MDIO function.
568c2ecf20Sopenharmony_ci *   96 to 103 is 96 + MDIO1 source for level 2 MDIO_E1 function.
578c2ecf20Sopenharmony_ci * Examples:
588c2ecf20Sopenharmony_ci *  Function 28 corresponds UART0
598c2ecf20Sopenharmony_ci *  Function 73 corresponds to MDIO0 to GMAC0
608c2ecf20Sopenharmony_ci *
618c2ecf20Sopenharmony_ci * There are 170 configurable pins (called PL_GPIO in the datasheet).
628c2ecf20Sopenharmony_ci */
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/*
658c2ecf20Sopenharmony_ci * Structure detailing the HW registers on the RZ/N1 devices.
668c2ecf20Sopenharmony_ci * Both the Level 1 mux registers and Level 2 mux registers have the same
678c2ecf20Sopenharmony_ci * structure. The only difference is that Level 2 has additional MDIO registers
688c2ecf20Sopenharmony_ci * at the end.
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_cistruct rzn1_pinctrl_regs {
718c2ecf20Sopenharmony_ci	u32	conf[170];
728c2ecf20Sopenharmony_ci	u32	pad0[86];
738c2ecf20Sopenharmony_ci	u32	status_protect;	/* 0x400 */
748c2ecf20Sopenharmony_ci	/* MDIO mux registers, level2 only */
758c2ecf20Sopenharmony_ci	u32	l2_mdio[2];
768c2ecf20Sopenharmony_ci};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/**
798c2ecf20Sopenharmony_ci * struct rzn1_pmx_func - describes rzn1 pinmux functions
808c2ecf20Sopenharmony_ci * @name: the name of this specific function
818c2ecf20Sopenharmony_ci * @groups: corresponding pin groups
828c2ecf20Sopenharmony_ci * @num_groups: the number of groups
838c2ecf20Sopenharmony_ci */
848c2ecf20Sopenharmony_cistruct rzn1_pmx_func {
858c2ecf20Sopenharmony_ci	const char *name;
868c2ecf20Sopenharmony_ci	const char **groups;
878c2ecf20Sopenharmony_ci	unsigned int num_groups;
888c2ecf20Sopenharmony_ci};
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/**
918c2ecf20Sopenharmony_ci * struct rzn1_pin_group - describes an rzn1 pin group
928c2ecf20Sopenharmony_ci * @name: the name of this specific pin group
938c2ecf20Sopenharmony_ci * @func: the name of the function selected by this group
948c2ecf20Sopenharmony_ci * @npins: the number of pins in this group array, i.e. the number of
958c2ecf20Sopenharmony_ci *	elements in .pins so we can iterate over that array
968c2ecf20Sopenharmony_ci * @pins: array of pins. Needed due to pinctrl_ops.get_group_pins()
978c2ecf20Sopenharmony_ci * @pin_ids: array of pin_ids, i.e. the value used to select the mux
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_cistruct rzn1_pin_group {
1008c2ecf20Sopenharmony_ci	const char *name;
1018c2ecf20Sopenharmony_ci	const char *func;
1028c2ecf20Sopenharmony_ci	unsigned int npins;
1038c2ecf20Sopenharmony_ci	unsigned int *pins;
1048c2ecf20Sopenharmony_ci	u8 *pin_ids;
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistruct rzn1_pinctrl {
1088c2ecf20Sopenharmony_ci	struct device *dev;
1098c2ecf20Sopenharmony_ci	struct clk *clk;
1108c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctl;
1118c2ecf20Sopenharmony_ci	struct rzn1_pinctrl_regs __iomem *lev1;
1128c2ecf20Sopenharmony_ci	struct rzn1_pinctrl_regs __iomem *lev2;
1138c2ecf20Sopenharmony_ci	u32 lev1_protect_phys;
1148c2ecf20Sopenharmony_ci	u32 lev2_protect_phys;
1158c2ecf20Sopenharmony_ci	int mdio_func[2];
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	struct rzn1_pin_group *groups;
1188c2ecf20Sopenharmony_ci	unsigned int ngroups;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	struct rzn1_pmx_func *functions;
1218c2ecf20Sopenharmony_ci	unsigned int nfunctions;
1228c2ecf20Sopenharmony_ci};
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci#define RZN1_PINS_PROP "pinmux"
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci#define RZN1_PIN(pin) PINCTRL_PIN(pin, "pl_gpio"#pin)
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic const struct pinctrl_pin_desc rzn1_pins[] = {
1298c2ecf20Sopenharmony_ci	RZN1_PIN(0), RZN1_PIN(1), RZN1_PIN(2), RZN1_PIN(3), RZN1_PIN(4),
1308c2ecf20Sopenharmony_ci	RZN1_PIN(5), RZN1_PIN(6), RZN1_PIN(7), RZN1_PIN(8), RZN1_PIN(9),
1318c2ecf20Sopenharmony_ci	RZN1_PIN(10), RZN1_PIN(11), RZN1_PIN(12), RZN1_PIN(13), RZN1_PIN(14),
1328c2ecf20Sopenharmony_ci	RZN1_PIN(15), RZN1_PIN(16), RZN1_PIN(17), RZN1_PIN(18), RZN1_PIN(19),
1338c2ecf20Sopenharmony_ci	RZN1_PIN(20), RZN1_PIN(21), RZN1_PIN(22), RZN1_PIN(23), RZN1_PIN(24),
1348c2ecf20Sopenharmony_ci	RZN1_PIN(25), RZN1_PIN(26), RZN1_PIN(27), RZN1_PIN(28), RZN1_PIN(29),
1358c2ecf20Sopenharmony_ci	RZN1_PIN(30), RZN1_PIN(31), RZN1_PIN(32), RZN1_PIN(33), RZN1_PIN(34),
1368c2ecf20Sopenharmony_ci	RZN1_PIN(35), RZN1_PIN(36), RZN1_PIN(37), RZN1_PIN(38), RZN1_PIN(39),
1378c2ecf20Sopenharmony_ci	RZN1_PIN(40), RZN1_PIN(41), RZN1_PIN(42), RZN1_PIN(43), RZN1_PIN(44),
1388c2ecf20Sopenharmony_ci	RZN1_PIN(45), RZN1_PIN(46), RZN1_PIN(47), RZN1_PIN(48), RZN1_PIN(49),
1398c2ecf20Sopenharmony_ci	RZN1_PIN(50), RZN1_PIN(51), RZN1_PIN(52), RZN1_PIN(53), RZN1_PIN(54),
1408c2ecf20Sopenharmony_ci	RZN1_PIN(55), RZN1_PIN(56), RZN1_PIN(57), RZN1_PIN(58), RZN1_PIN(59),
1418c2ecf20Sopenharmony_ci	RZN1_PIN(60), RZN1_PIN(61), RZN1_PIN(62), RZN1_PIN(63), RZN1_PIN(64),
1428c2ecf20Sopenharmony_ci	RZN1_PIN(65), RZN1_PIN(66), RZN1_PIN(67), RZN1_PIN(68), RZN1_PIN(69),
1438c2ecf20Sopenharmony_ci	RZN1_PIN(70), RZN1_PIN(71), RZN1_PIN(72), RZN1_PIN(73), RZN1_PIN(74),
1448c2ecf20Sopenharmony_ci	RZN1_PIN(75), RZN1_PIN(76), RZN1_PIN(77), RZN1_PIN(78), RZN1_PIN(79),
1458c2ecf20Sopenharmony_ci	RZN1_PIN(80), RZN1_PIN(81), RZN1_PIN(82), RZN1_PIN(83), RZN1_PIN(84),
1468c2ecf20Sopenharmony_ci	RZN1_PIN(85), RZN1_PIN(86), RZN1_PIN(87), RZN1_PIN(88), RZN1_PIN(89),
1478c2ecf20Sopenharmony_ci	RZN1_PIN(90), RZN1_PIN(91), RZN1_PIN(92), RZN1_PIN(93), RZN1_PIN(94),
1488c2ecf20Sopenharmony_ci	RZN1_PIN(95), RZN1_PIN(96), RZN1_PIN(97), RZN1_PIN(98), RZN1_PIN(99),
1498c2ecf20Sopenharmony_ci	RZN1_PIN(100), RZN1_PIN(101), RZN1_PIN(102), RZN1_PIN(103),
1508c2ecf20Sopenharmony_ci	RZN1_PIN(104), RZN1_PIN(105), RZN1_PIN(106), RZN1_PIN(107),
1518c2ecf20Sopenharmony_ci	RZN1_PIN(108), RZN1_PIN(109), RZN1_PIN(110), RZN1_PIN(111),
1528c2ecf20Sopenharmony_ci	RZN1_PIN(112), RZN1_PIN(113), RZN1_PIN(114), RZN1_PIN(115),
1538c2ecf20Sopenharmony_ci	RZN1_PIN(116), RZN1_PIN(117), RZN1_PIN(118), RZN1_PIN(119),
1548c2ecf20Sopenharmony_ci	RZN1_PIN(120), RZN1_PIN(121), RZN1_PIN(122), RZN1_PIN(123),
1558c2ecf20Sopenharmony_ci	RZN1_PIN(124), RZN1_PIN(125), RZN1_PIN(126), RZN1_PIN(127),
1568c2ecf20Sopenharmony_ci	RZN1_PIN(128), RZN1_PIN(129), RZN1_PIN(130), RZN1_PIN(131),
1578c2ecf20Sopenharmony_ci	RZN1_PIN(132), RZN1_PIN(133), RZN1_PIN(134), RZN1_PIN(135),
1588c2ecf20Sopenharmony_ci	RZN1_PIN(136), RZN1_PIN(137), RZN1_PIN(138), RZN1_PIN(139),
1598c2ecf20Sopenharmony_ci	RZN1_PIN(140), RZN1_PIN(141), RZN1_PIN(142), RZN1_PIN(143),
1608c2ecf20Sopenharmony_ci	RZN1_PIN(144), RZN1_PIN(145), RZN1_PIN(146), RZN1_PIN(147),
1618c2ecf20Sopenharmony_ci	RZN1_PIN(148), RZN1_PIN(149), RZN1_PIN(150), RZN1_PIN(151),
1628c2ecf20Sopenharmony_ci	RZN1_PIN(152), RZN1_PIN(153), RZN1_PIN(154), RZN1_PIN(155),
1638c2ecf20Sopenharmony_ci	RZN1_PIN(156), RZN1_PIN(157), RZN1_PIN(158), RZN1_PIN(159),
1648c2ecf20Sopenharmony_ci	RZN1_PIN(160), RZN1_PIN(161), RZN1_PIN(162), RZN1_PIN(163),
1658c2ecf20Sopenharmony_ci	RZN1_PIN(164), RZN1_PIN(165), RZN1_PIN(166), RZN1_PIN(167),
1668c2ecf20Sopenharmony_ci	RZN1_PIN(168), RZN1_PIN(169),
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cienum {
1708c2ecf20Sopenharmony_ci	LOCK_LEVEL1 = 0x1,
1718c2ecf20Sopenharmony_ci	LOCK_LEVEL2 = 0x2,
1728c2ecf20Sopenharmony_ci	LOCK_ALL = LOCK_LEVEL1 | LOCK_LEVEL2,
1738c2ecf20Sopenharmony_ci};
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_cistatic void rzn1_hw_set_lock(struct rzn1_pinctrl *ipctl, u8 lock, u8 value)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	/*
1788c2ecf20Sopenharmony_ci	 * The pinmux configuration is locked by writing the physical address of
1798c2ecf20Sopenharmony_ci	 * the status_protect register to itself. It is unlocked by writing the
1808c2ecf20Sopenharmony_ci	 * address | 1.
1818c2ecf20Sopenharmony_ci	 */
1828c2ecf20Sopenharmony_ci	if (lock & LOCK_LEVEL1) {
1838c2ecf20Sopenharmony_ci		u32 val = ipctl->lev1_protect_phys | !(value & LOCK_LEVEL1);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci		writel(val, &ipctl->lev1->status_protect);
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	if (lock & LOCK_LEVEL2) {
1898c2ecf20Sopenharmony_ci		u32 val = ipctl->lev2_protect_phys | !(value & LOCK_LEVEL2);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci		writel(val, &ipctl->lev2->status_protect);
1928c2ecf20Sopenharmony_ci	}
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cistatic void rzn1_pinctrl_mdio_select(struct rzn1_pinctrl *ipctl, int mdio,
1968c2ecf20Sopenharmony_ci				     u32 func)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	if (ipctl->mdio_func[mdio] >= 0 && ipctl->mdio_func[mdio] != func)
1998c2ecf20Sopenharmony_ci		dev_warn(ipctl->dev, "conflicting setting for mdio%d!\n", mdio);
2008c2ecf20Sopenharmony_ci	ipctl->mdio_func[mdio] = func;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "setting mdio%d to %u\n", mdio, func);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	writel(func, &ipctl->lev2->l2_mdio[mdio]);
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci/*
2088c2ecf20Sopenharmony_ci * Using a composite pin description, set the hardware pinmux registers
2098c2ecf20Sopenharmony_ci * with the corresponding values.
2108c2ecf20Sopenharmony_ci * Make sure to unlock write protection and reset it afterward.
2118c2ecf20Sopenharmony_ci *
2128c2ecf20Sopenharmony_ci * NOTE: There is no protection for potential concurrency, it is assumed these
2138c2ecf20Sopenharmony_ci * calls are serialized already.
2148c2ecf20Sopenharmony_ci */
2158c2ecf20Sopenharmony_cistatic int rzn1_set_hw_pin_func(struct rzn1_pinctrl *ipctl, unsigned int pin,
2168c2ecf20Sopenharmony_ci				u32 pin_config, u8 use_locks)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	u32 l1_cache;
2198c2ecf20Sopenharmony_ci	u32 l2_cache;
2208c2ecf20Sopenharmony_ci	u32 l1;
2218c2ecf20Sopenharmony_ci	u32 l2;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	/* Level 3 MDIO multiplexing */
2248c2ecf20Sopenharmony_ci	if (pin_config >= RZN1_FUNC_MDIO0_HIGHZ &&
2258c2ecf20Sopenharmony_ci	    pin_config <= RZN1_FUNC_MDIO1_E1_SWITCH) {
2268c2ecf20Sopenharmony_ci		int mdio_channel;
2278c2ecf20Sopenharmony_ci		u32 mdio_func;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci		if (pin_config <= RZN1_FUNC_MDIO1_HIGHZ)
2308c2ecf20Sopenharmony_ci			mdio_channel = 0;
2318c2ecf20Sopenharmony_ci		else
2328c2ecf20Sopenharmony_ci			mdio_channel = 1;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci		/* Get MDIO func, and convert the func to the level 2 number */
2358c2ecf20Sopenharmony_ci		if (pin_config <= RZN1_FUNC_MDIO0_SWITCH) {
2368c2ecf20Sopenharmony_ci			mdio_func = pin_config - RZN1_FUNC_MDIO0_HIGHZ;
2378c2ecf20Sopenharmony_ci			pin_config = RZN1_FUNC_ETH_MDIO;
2388c2ecf20Sopenharmony_ci		} else if (pin_config <= RZN1_FUNC_MDIO0_E1_SWITCH) {
2398c2ecf20Sopenharmony_ci			mdio_func = pin_config - RZN1_FUNC_MDIO0_E1_HIGHZ;
2408c2ecf20Sopenharmony_ci			pin_config = RZN1_FUNC_ETH_MDIO_E1;
2418c2ecf20Sopenharmony_ci		} else if (pin_config <= RZN1_FUNC_MDIO1_SWITCH) {
2428c2ecf20Sopenharmony_ci			mdio_func = pin_config - RZN1_FUNC_MDIO1_HIGHZ;
2438c2ecf20Sopenharmony_ci			pin_config = RZN1_FUNC_ETH_MDIO;
2448c2ecf20Sopenharmony_ci		} else {
2458c2ecf20Sopenharmony_ci			mdio_func = pin_config - RZN1_FUNC_MDIO1_E1_HIGHZ;
2468c2ecf20Sopenharmony_ci			pin_config = RZN1_FUNC_ETH_MDIO_E1;
2478c2ecf20Sopenharmony_ci		}
2488c2ecf20Sopenharmony_ci		rzn1_pinctrl_mdio_select(ipctl, mdio_channel, mdio_func);
2498c2ecf20Sopenharmony_ci	}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	/* Note here, we do not allow anything past the MDIO Mux values */
2528c2ecf20Sopenharmony_ci	if (pin >= ARRAY_SIZE(ipctl->lev1->conf) ||
2538c2ecf20Sopenharmony_ci	    pin_config >= RZN1_FUNC_MDIO0_HIGHZ)
2548c2ecf20Sopenharmony_ci		return -EINVAL;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	l1 = readl(&ipctl->lev1->conf[pin]);
2578c2ecf20Sopenharmony_ci	l1_cache = l1;
2588c2ecf20Sopenharmony_ci	l2 = readl(&ipctl->lev2->conf[pin]);
2598c2ecf20Sopenharmony_ci	l2_cache = l2;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "setting func for pin %u to %u\n", pin, pin_config);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	l1 &= ~(RZN1_L1_FUNC_MASK << RZN1_L1_FUNCTION);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	if (pin_config < RZN1_FUNC_L2_OFFSET) {
2668c2ecf20Sopenharmony_ci		l1 |= (pin_config << RZN1_L1_FUNCTION);
2678c2ecf20Sopenharmony_ci	} else {
2688c2ecf20Sopenharmony_ci		l1 |= (RZN1_L1_FUNCTION_L2 << RZN1_L1_FUNCTION);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci		l2 = pin_config - RZN1_FUNC_L2_OFFSET;
2718c2ecf20Sopenharmony_ci	}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	/* If either configuration changes, we update both anyway */
2748c2ecf20Sopenharmony_ci	if (l1 != l1_cache || l2 != l2_cache) {
2758c2ecf20Sopenharmony_ci		writel(l1, &ipctl->lev1->conf[pin]);
2768c2ecf20Sopenharmony_ci		writel(l2, &ipctl->lev2->conf[pin]);
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	return 0;
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_cistatic const struct rzn1_pin_group *rzn1_pinctrl_find_group_by_name(
2838c2ecf20Sopenharmony_ci	const struct rzn1_pinctrl *ipctl, const char *name)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	unsigned int i;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	for (i = 0; i < ipctl->ngroups; i++) {
2888c2ecf20Sopenharmony_ci		if (!strcmp(ipctl->groups[i].name, name))
2898c2ecf20Sopenharmony_ci			return &ipctl->groups[i];
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	return NULL;
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistatic int rzn1_get_groups_count(struct pinctrl_dev *pctldev)
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	return ipctl->ngroups;
3008c2ecf20Sopenharmony_ci}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_cistatic const char *rzn1_get_group_name(struct pinctrl_dev *pctldev,
3038c2ecf20Sopenharmony_ci				       unsigned int selector)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	return ipctl->groups[selector].name;
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_cistatic int rzn1_get_group_pins(struct pinctrl_dev *pctldev,
3118c2ecf20Sopenharmony_ci			       unsigned int selector, const unsigned int **pins,
3128c2ecf20Sopenharmony_ci			       unsigned int *npins)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	if (selector >= ipctl->ngroups)
3178c2ecf20Sopenharmony_ci		return -EINVAL;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	*pins = ipctl->groups[selector].pins;
3208c2ecf20Sopenharmony_ci	*npins = ipctl->groups[selector].npins;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	return 0;
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci/*
3268c2ecf20Sopenharmony_ci * This function is called for each pinctl 'Function' node.
3278c2ecf20Sopenharmony_ci * Sub-nodes can be used to describe multiple 'Groups' for the 'Function'
3288c2ecf20Sopenharmony_ci * If there aren't any sub-nodes, the 'Group' is essentially the 'Function'.
3298c2ecf20Sopenharmony_ci * Each 'Group' uses pinmux = <...> to detail the pins and data used to select
3308c2ecf20Sopenharmony_ci * the functionality. Each 'Group' has optional pin configurations that apply
3318c2ecf20Sopenharmony_ci * to all pins in the 'Group'.
3328c2ecf20Sopenharmony_ci */
3338c2ecf20Sopenharmony_cistatic int rzn1_dt_node_to_map_one(struct pinctrl_dev *pctldev,
3348c2ecf20Sopenharmony_ci				   struct device_node *np,
3358c2ecf20Sopenharmony_ci				   struct pinctrl_map **map,
3368c2ecf20Sopenharmony_ci				   unsigned int *num_maps)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
3398c2ecf20Sopenharmony_ci	const struct rzn1_pin_group *grp;
3408c2ecf20Sopenharmony_ci	unsigned long *configs = NULL;
3418c2ecf20Sopenharmony_ci	unsigned int reserved_maps = *num_maps;
3428c2ecf20Sopenharmony_ci	unsigned int num_configs = 0;
3438c2ecf20Sopenharmony_ci	unsigned int reserve = 1;
3448c2ecf20Sopenharmony_ci	int ret;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "processing node %pOF\n", np);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	grp = rzn1_pinctrl_find_group_by_name(ipctl, np->name);
3498c2ecf20Sopenharmony_ci	if (!grp) {
3508c2ecf20Sopenharmony_ci		dev_err(ipctl->dev, "unable to find group for node %pOF\n", np);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci		return -EINVAL;
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	/* Get the group's pin configuration */
3568c2ecf20Sopenharmony_ci	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
3578c2ecf20Sopenharmony_ci					      &num_configs);
3588c2ecf20Sopenharmony_ci	if (ret < 0) {
3598c2ecf20Sopenharmony_ci		dev_err(ipctl->dev, "%pOF: could not parse property\n", np);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci		return ret;
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	if (num_configs)
3658c2ecf20Sopenharmony_ci		reserve++;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	/* Increase the number of maps to cover this group */
3688c2ecf20Sopenharmony_ci	ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, num_maps,
3698c2ecf20Sopenharmony_ci					reserve);
3708c2ecf20Sopenharmony_ci	if (ret < 0)
3718c2ecf20Sopenharmony_ci		goto out;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/* Associate the group with the function */
3748c2ecf20Sopenharmony_ci	ret = pinctrl_utils_add_map_mux(pctldev, map, &reserved_maps, num_maps,
3758c2ecf20Sopenharmony_ci					grp->name, grp->func);
3768c2ecf20Sopenharmony_ci	if (ret < 0)
3778c2ecf20Sopenharmony_ci		goto out;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	if (num_configs) {
3808c2ecf20Sopenharmony_ci		/* Associate the group's pin configuration with the group */
3818c2ecf20Sopenharmony_ci		ret = pinctrl_utils_add_map_configs(pctldev, map,
3828c2ecf20Sopenharmony_ci				&reserved_maps, num_maps, grp->name,
3838c2ecf20Sopenharmony_ci				configs, num_configs,
3848c2ecf20Sopenharmony_ci				PIN_MAP_TYPE_CONFIGS_GROUP);
3858c2ecf20Sopenharmony_ci		if (ret < 0)
3868c2ecf20Sopenharmony_ci			goto out;
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	dev_dbg(pctldev->dev, "maps: function %s group %s (%d pins)\n",
3908c2ecf20Sopenharmony_ci		grp->func, grp->name, grp->npins);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ciout:
3938c2ecf20Sopenharmony_ci	kfree(configs);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	return ret;
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic int rzn1_dt_node_to_map(struct pinctrl_dev *pctldev,
3998c2ecf20Sopenharmony_ci			       struct device_node *np,
4008c2ecf20Sopenharmony_ci			       struct pinctrl_map **map,
4018c2ecf20Sopenharmony_ci			       unsigned int *num_maps)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	struct device_node *child;
4048c2ecf20Sopenharmony_ci	int ret;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	*map = NULL;
4078c2ecf20Sopenharmony_ci	*num_maps = 0;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	ret = rzn1_dt_node_to_map_one(pctldev, np, map, num_maps);
4108c2ecf20Sopenharmony_ci	if (ret < 0)
4118c2ecf20Sopenharmony_ci		return ret;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
4148c2ecf20Sopenharmony_ci		ret = rzn1_dt_node_to_map_one(pctldev, child, map, num_maps);
4158c2ecf20Sopenharmony_ci		if (ret < 0) {
4168c2ecf20Sopenharmony_ci			of_node_put(child);
4178c2ecf20Sopenharmony_ci			return ret;
4188c2ecf20Sopenharmony_ci		}
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	return 0;
4228c2ecf20Sopenharmony_ci}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_cistatic const struct pinctrl_ops rzn1_pctrl_ops = {
4258c2ecf20Sopenharmony_ci	.get_groups_count = rzn1_get_groups_count,
4268c2ecf20Sopenharmony_ci	.get_group_name = rzn1_get_group_name,
4278c2ecf20Sopenharmony_ci	.get_group_pins = rzn1_get_group_pins,
4288c2ecf20Sopenharmony_ci	.dt_node_to_map = rzn1_dt_node_to_map,
4298c2ecf20Sopenharmony_ci	.dt_free_map = pinctrl_utils_free_map,
4308c2ecf20Sopenharmony_ci};
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic int rzn1_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	return ipctl->nfunctions;
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_cistatic const char *rzn1_pmx_get_func_name(struct pinctrl_dev *pctldev,
4408c2ecf20Sopenharmony_ci					  unsigned int selector)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	return ipctl->functions[selector].name;
4458c2ecf20Sopenharmony_ci}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic int rzn1_pmx_get_groups(struct pinctrl_dev *pctldev,
4488c2ecf20Sopenharmony_ci			       unsigned int selector,
4498c2ecf20Sopenharmony_ci			       const char * const **groups,
4508c2ecf20Sopenharmony_ci			       unsigned int * const num_groups)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	*groups = ipctl->functions[selector].groups;
4558c2ecf20Sopenharmony_ci	*num_groups = ipctl->functions[selector].num_groups;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	return 0;
4588c2ecf20Sopenharmony_ci}
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_cistatic int rzn1_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
4618c2ecf20Sopenharmony_ci			unsigned int group)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
4648c2ecf20Sopenharmony_ci	struct rzn1_pin_group *grp = &ipctl->groups[group];
4658c2ecf20Sopenharmony_ci	unsigned int i, grp_pins = grp->npins;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "set mux %s(%d) group %s(%d)\n",
4688c2ecf20Sopenharmony_ci		ipctl->functions[selector].name, selector, grp->name, group);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	rzn1_hw_set_lock(ipctl, LOCK_ALL, LOCK_ALL);
4718c2ecf20Sopenharmony_ci	for (i = 0; i < grp_pins; i++)
4728c2ecf20Sopenharmony_ci		rzn1_set_hw_pin_func(ipctl, grp->pins[i], grp->pin_ids[i], 0);
4738c2ecf20Sopenharmony_ci	rzn1_hw_set_lock(ipctl, LOCK_ALL, 0);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	return 0;
4768c2ecf20Sopenharmony_ci}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_cistatic const struct pinmux_ops rzn1_pmx_ops = {
4798c2ecf20Sopenharmony_ci	.get_functions_count = rzn1_pmx_get_funcs_count,
4808c2ecf20Sopenharmony_ci	.get_function_name = rzn1_pmx_get_func_name,
4818c2ecf20Sopenharmony_ci	.get_function_groups = rzn1_pmx_get_groups,
4828c2ecf20Sopenharmony_ci	.set_mux = rzn1_set_mux,
4838c2ecf20Sopenharmony_ci};
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic int rzn1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
4868c2ecf20Sopenharmony_ci			    unsigned long *config)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
4898c2ecf20Sopenharmony_ci	enum pin_config_param param = pinconf_to_config_param(*config);
4908c2ecf20Sopenharmony_ci	static const u32 reg_drive[4] = { 4, 6, 8, 12 };
4918c2ecf20Sopenharmony_ci	u32 pull, drive, l1mux;
4928c2ecf20Sopenharmony_ci	u32 l1, l2, arg = 0;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	if (pin >= ARRAY_SIZE(ipctl->lev1->conf))
4958c2ecf20Sopenharmony_ci		return -EINVAL;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	l1 = readl(&ipctl->lev1->conf[pin]);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	l1mux = l1 & RZN1_L1_FUNC_MASK;
5008c2ecf20Sopenharmony_ci	pull = (l1 >> RZN1_L1_PIN_PULL) & 0x3;
5018c2ecf20Sopenharmony_ci	drive = (l1 >> RZN1_L1_PIN_DRIVE_STRENGTH) & 0x3;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	switch (param) {
5048c2ecf20Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_UP:
5058c2ecf20Sopenharmony_ci		if (pull != RZN1_L1_PIN_PULL_UP)
5068c2ecf20Sopenharmony_ci			return -EINVAL;
5078c2ecf20Sopenharmony_ci		break;
5088c2ecf20Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_DOWN:
5098c2ecf20Sopenharmony_ci		if (pull != RZN1_L1_PIN_PULL_DOWN)
5108c2ecf20Sopenharmony_ci			return -EINVAL;
5118c2ecf20Sopenharmony_ci		break;
5128c2ecf20Sopenharmony_ci	case PIN_CONFIG_BIAS_DISABLE:
5138c2ecf20Sopenharmony_ci		if (pull != RZN1_L1_PIN_PULL_NONE)
5148c2ecf20Sopenharmony_ci			return -EINVAL;
5158c2ecf20Sopenharmony_ci		break;
5168c2ecf20Sopenharmony_ci	case PIN_CONFIG_DRIVE_STRENGTH:
5178c2ecf20Sopenharmony_ci		arg = reg_drive[drive];
5188c2ecf20Sopenharmony_ci		break;
5198c2ecf20Sopenharmony_ci	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
5208c2ecf20Sopenharmony_ci		l2 = readl(&ipctl->lev2->conf[pin]);
5218c2ecf20Sopenharmony_ci		if (l1mux == RZN1_L1_FUNCTION_L2) {
5228c2ecf20Sopenharmony_ci			if (l2 != 0)
5238c2ecf20Sopenharmony_ci				return -EINVAL;
5248c2ecf20Sopenharmony_ci		} else if (l1mux != RZN1_FUNC_HIGHZ) {
5258c2ecf20Sopenharmony_ci			return -EINVAL;
5268c2ecf20Sopenharmony_ci		}
5278c2ecf20Sopenharmony_ci		break;
5288c2ecf20Sopenharmony_ci	default:
5298c2ecf20Sopenharmony_ci		return -ENOTSUPP;
5308c2ecf20Sopenharmony_ci	}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	*config = pinconf_to_config_packed(param, arg);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	return 0;
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_cistatic int rzn1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
5388c2ecf20Sopenharmony_ci			    unsigned long *configs, unsigned int num_configs)
5398c2ecf20Sopenharmony_ci{
5408c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
5418c2ecf20Sopenharmony_ci	enum pin_config_param param;
5428c2ecf20Sopenharmony_ci	unsigned int i;
5438c2ecf20Sopenharmony_ci	u32 l1, l1_cache;
5448c2ecf20Sopenharmony_ci	u32 drv;
5458c2ecf20Sopenharmony_ci	u32 arg;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	if (pin >= ARRAY_SIZE(ipctl->lev1->conf))
5488c2ecf20Sopenharmony_ci		return -EINVAL;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	l1 = readl(&ipctl->lev1->conf[pin]);
5518c2ecf20Sopenharmony_ci	l1_cache = l1;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	for (i = 0; i < num_configs; i++) {
5548c2ecf20Sopenharmony_ci		param = pinconf_to_config_param(configs[i]);
5558c2ecf20Sopenharmony_ci		arg = pinconf_to_config_argument(configs[i]);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci		switch (param) {
5588c2ecf20Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_UP:
5598c2ecf20Sopenharmony_ci			dev_dbg(ipctl->dev, "set pin %d pull up\n", pin);
5608c2ecf20Sopenharmony_ci			l1 &= ~(0x3 << RZN1_L1_PIN_PULL);
5618c2ecf20Sopenharmony_ci			l1 |= (RZN1_L1_PIN_PULL_UP << RZN1_L1_PIN_PULL);
5628c2ecf20Sopenharmony_ci			break;
5638c2ecf20Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_DOWN:
5648c2ecf20Sopenharmony_ci			dev_dbg(ipctl->dev, "set pin %d pull down\n", pin);
5658c2ecf20Sopenharmony_ci			l1 &= ~(0x3 << RZN1_L1_PIN_PULL);
5668c2ecf20Sopenharmony_ci			l1 |= (RZN1_L1_PIN_PULL_DOWN << RZN1_L1_PIN_PULL);
5678c2ecf20Sopenharmony_ci			break;
5688c2ecf20Sopenharmony_ci		case PIN_CONFIG_BIAS_DISABLE:
5698c2ecf20Sopenharmony_ci			dev_dbg(ipctl->dev, "set pin %d bias off\n", pin);
5708c2ecf20Sopenharmony_ci			l1 &= ~(0x3 << RZN1_L1_PIN_PULL);
5718c2ecf20Sopenharmony_ci			l1 |= (RZN1_L1_PIN_PULL_NONE << RZN1_L1_PIN_PULL);
5728c2ecf20Sopenharmony_ci			break;
5738c2ecf20Sopenharmony_ci		case PIN_CONFIG_DRIVE_STRENGTH:
5748c2ecf20Sopenharmony_ci			dev_dbg(ipctl->dev, "set pin %d drv %umA\n", pin, arg);
5758c2ecf20Sopenharmony_ci			switch (arg) {
5768c2ecf20Sopenharmony_ci			case 4:
5778c2ecf20Sopenharmony_ci				drv = RZN1_L1_PIN_DRIVE_STRENGTH_4MA;
5788c2ecf20Sopenharmony_ci				break;
5798c2ecf20Sopenharmony_ci			case 6:
5808c2ecf20Sopenharmony_ci				drv = RZN1_L1_PIN_DRIVE_STRENGTH_6MA;
5818c2ecf20Sopenharmony_ci				break;
5828c2ecf20Sopenharmony_ci			case 8:
5838c2ecf20Sopenharmony_ci				drv = RZN1_L1_PIN_DRIVE_STRENGTH_8MA;
5848c2ecf20Sopenharmony_ci				break;
5858c2ecf20Sopenharmony_ci			case 12:
5868c2ecf20Sopenharmony_ci				drv = RZN1_L1_PIN_DRIVE_STRENGTH_12MA;
5878c2ecf20Sopenharmony_ci				break;
5888c2ecf20Sopenharmony_ci			default:
5898c2ecf20Sopenharmony_ci				dev_err(ipctl->dev,
5908c2ecf20Sopenharmony_ci					"Drive strength %umA not supported\n",
5918c2ecf20Sopenharmony_ci					arg);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci				return -EINVAL;
5948c2ecf20Sopenharmony_ci			}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci			l1 &= ~(0x3 << RZN1_L1_PIN_DRIVE_STRENGTH);
5978c2ecf20Sopenharmony_ci			l1 |= (drv << RZN1_L1_PIN_DRIVE_STRENGTH);
5988c2ecf20Sopenharmony_ci			break;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci		case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
6018c2ecf20Sopenharmony_ci			dev_dbg(ipctl->dev, "set pin %d High-Z\n", pin);
6028c2ecf20Sopenharmony_ci			l1 &= ~RZN1_L1_FUNC_MASK;
6038c2ecf20Sopenharmony_ci			l1 |= RZN1_FUNC_HIGHZ;
6048c2ecf20Sopenharmony_ci			break;
6058c2ecf20Sopenharmony_ci		default:
6068c2ecf20Sopenharmony_ci			return -ENOTSUPP;
6078c2ecf20Sopenharmony_ci		}
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	if (l1 != l1_cache) {
6118c2ecf20Sopenharmony_ci		rzn1_hw_set_lock(ipctl, LOCK_LEVEL1, LOCK_LEVEL1);
6128c2ecf20Sopenharmony_ci		writel(l1, &ipctl->lev1->conf[pin]);
6138c2ecf20Sopenharmony_ci		rzn1_hw_set_lock(ipctl, LOCK_LEVEL1, 0);
6148c2ecf20Sopenharmony_ci	}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	return 0;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic int rzn1_pinconf_group_get(struct pinctrl_dev *pctldev,
6208c2ecf20Sopenharmony_ci				  unsigned int selector,
6218c2ecf20Sopenharmony_ci				  unsigned long *config)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
6248c2ecf20Sopenharmony_ci	struct rzn1_pin_group *grp = &ipctl->groups[selector];
6258c2ecf20Sopenharmony_ci	unsigned long old = 0;
6268c2ecf20Sopenharmony_ci	unsigned int i;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "group get %s selector:%u\n", grp->name, selector);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	for (i = 0; i < grp->npins; i++) {
6318c2ecf20Sopenharmony_ci		if (rzn1_pinconf_get(pctldev, grp->pins[i], config))
6328c2ecf20Sopenharmony_ci			return -ENOTSUPP;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci		/* configs do not match between two pins */
6358c2ecf20Sopenharmony_ci		if (i && (old != *config))
6368c2ecf20Sopenharmony_ci			return -ENOTSUPP;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci		old = *config;
6398c2ecf20Sopenharmony_ci	}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	return 0;
6428c2ecf20Sopenharmony_ci}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_cistatic int rzn1_pinconf_group_set(struct pinctrl_dev *pctldev,
6458c2ecf20Sopenharmony_ci				  unsigned int selector,
6468c2ecf20Sopenharmony_ci				  unsigned long *configs,
6478c2ecf20Sopenharmony_ci				  unsigned int num_configs)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
6508c2ecf20Sopenharmony_ci	struct rzn1_pin_group *grp = &ipctl->groups[selector];
6518c2ecf20Sopenharmony_ci	unsigned int i;
6528c2ecf20Sopenharmony_ci	int ret;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "group set %s selector:%u configs:%p/%d\n",
6558c2ecf20Sopenharmony_ci		grp->name, selector, configs, num_configs);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	for (i = 0; i < grp->npins; i++) {
6588c2ecf20Sopenharmony_ci		unsigned int pin = grp->pins[i];
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci		ret = rzn1_pinconf_set(pctldev, pin, configs, num_configs);
6618c2ecf20Sopenharmony_ci		if (ret)
6628c2ecf20Sopenharmony_ci			return ret;
6638c2ecf20Sopenharmony_ci	}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	return 0;
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistatic const struct pinconf_ops rzn1_pinconf_ops = {
6698c2ecf20Sopenharmony_ci	.is_generic = true,
6708c2ecf20Sopenharmony_ci	.pin_config_get = rzn1_pinconf_get,
6718c2ecf20Sopenharmony_ci	.pin_config_set = rzn1_pinconf_set,
6728c2ecf20Sopenharmony_ci	.pin_config_group_get = rzn1_pinconf_group_get,
6738c2ecf20Sopenharmony_ci	.pin_config_group_set = rzn1_pinconf_group_set,
6748c2ecf20Sopenharmony_ci	.pin_config_config_dbg_show = pinconf_generic_dump_config,
6758c2ecf20Sopenharmony_ci};
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_cistatic struct pinctrl_desc rzn1_pinctrl_desc = {
6788c2ecf20Sopenharmony_ci	.pctlops = &rzn1_pctrl_ops,
6798c2ecf20Sopenharmony_ci	.pmxops = &rzn1_pmx_ops,
6808c2ecf20Sopenharmony_ci	.confops = &rzn1_pinconf_ops,
6818c2ecf20Sopenharmony_ci	.owner = THIS_MODULE,
6828c2ecf20Sopenharmony_ci};
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_cistatic int rzn1_pinctrl_parse_groups(struct device_node *np,
6858c2ecf20Sopenharmony_ci				     struct rzn1_pin_group *grp,
6868c2ecf20Sopenharmony_ci				     struct rzn1_pinctrl *ipctl)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	const __be32 *list;
6898c2ecf20Sopenharmony_ci	unsigned int i;
6908c2ecf20Sopenharmony_ci	int size;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "%s: %s\n", __func__, np->name);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	/* Initialise group */
6958c2ecf20Sopenharmony_ci	grp->name = np->name;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	/*
6988c2ecf20Sopenharmony_ci	 * The binding format is
6998c2ecf20Sopenharmony_ci	 *	pinmux = <PIN_FUNC_ID CONFIG ...>,
7008c2ecf20Sopenharmony_ci	 * do sanity check and calculate pins number
7018c2ecf20Sopenharmony_ci	 */
7028c2ecf20Sopenharmony_ci	list = of_get_property(np, RZN1_PINS_PROP, &size);
7038c2ecf20Sopenharmony_ci	if (!list) {
7048c2ecf20Sopenharmony_ci		dev_err(ipctl->dev,
7058c2ecf20Sopenharmony_ci			"no " RZN1_PINS_PROP " property in node %pOF\n", np);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci		return -EINVAL;
7088c2ecf20Sopenharmony_ci	}
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	if (!size) {
7118c2ecf20Sopenharmony_ci		dev_err(ipctl->dev, "Invalid " RZN1_PINS_PROP " in node %pOF\n",
7128c2ecf20Sopenharmony_ci			np);
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci		return -EINVAL;
7158c2ecf20Sopenharmony_ci	}
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	grp->npins = size / sizeof(list[0]);
7188c2ecf20Sopenharmony_ci	grp->pin_ids = devm_kmalloc_array(ipctl->dev,
7198c2ecf20Sopenharmony_ci					  grp->npins, sizeof(grp->pin_ids[0]),
7208c2ecf20Sopenharmony_ci					  GFP_KERNEL);
7218c2ecf20Sopenharmony_ci	grp->pins = devm_kmalloc_array(ipctl->dev,
7228c2ecf20Sopenharmony_ci				       grp->npins, sizeof(grp->pins[0]),
7238c2ecf20Sopenharmony_ci				       GFP_KERNEL);
7248c2ecf20Sopenharmony_ci	if (!grp->pin_ids || !grp->pins)
7258c2ecf20Sopenharmony_ci		return -ENOMEM;
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	for (i = 0; i < grp->npins; i++) {
7288c2ecf20Sopenharmony_ci		u32 pin_id = be32_to_cpu(*list++);
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci		grp->pins[i] = pin_id & 0xff;
7318c2ecf20Sopenharmony_ci		grp->pin_ids[i] = (pin_id >> 8) & 0x7f;
7328c2ecf20Sopenharmony_ci	}
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	return grp->npins;
7358c2ecf20Sopenharmony_ci}
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_cistatic int rzn1_pinctrl_count_function_groups(struct device_node *np)
7388c2ecf20Sopenharmony_ci{
7398c2ecf20Sopenharmony_ci	struct device_node *child;
7408c2ecf20Sopenharmony_ci	int count = 0;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	if (of_property_count_u32_elems(np, RZN1_PINS_PROP) > 0)
7438c2ecf20Sopenharmony_ci		count++;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
7468c2ecf20Sopenharmony_ci		if (of_property_count_u32_elems(child, RZN1_PINS_PROP) > 0)
7478c2ecf20Sopenharmony_ci			count++;
7488c2ecf20Sopenharmony_ci	}
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	return count;
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_cistatic int rzn1_pinctrl_parse_functions(struct device_node *np,
7548c2ecf20Sopenharmony_ci					struct rzn1_pinctrl *ipctl,
7558c2ecf20Sopenharmony_ci					unsigned int index)
7568c2ecf20Sopenharmony_ci{
7578c2ecf20Sopenharmony_ci	struct rzn1_pmx_func *func;
7588c2ecf20Sopenharmony_ci	struct rzn1_pin_group *grp;
7598c2ecf20Sopenharmony_ci	struct device_node *child;
7608c2ecf20Sopenharmony_ci	unsigned int i = 0;
7618c2ecf20Sopenharmony_ci	int ret;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	func = &ipctl->functions[index];
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	/* Initialise function */
7668c2ecf20Sopenharmony_ci	func->name = np->name;
7678c2ecf20Sopenharmony_ci	func->num_groups = rzn1_pinctrl_count_function_groups(np);
7688c2ecf20Sopenharmony_ci	if (func->num_groups == 0) {
7698c2ecf20Sopenharmony_ci		dev_err(ipctl->dev, "no groups defined in %pOF\n", np);
7708c2ecf20Sopenharmony_ci		return -EINVAL;
7718c2ecf20Sopenharmony_ci	}
7728c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "function %s has %d groups\n",
7738c2ecf20Sopenharmony_ci		np->name, func->num_groups);
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	func->groups = devm_kmalloc_array(ipctl->dev,
7768c2ecf20Sopenharmony_ci					  func->num_groups, sizeof(char *),
7778c2ecf20Sopenharmony_ci					  GFP_KERNEL);
7788c2ecf20Sopenharmony_ci	if (!func->groups)
7798c2ecf20Sopenharmony_ci		return -ENOMEM;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	if (of_property_count_u32_elems(np, RZN1_PINS_PROP) > 0) {
7828c2ecf20Sopenharmony_ci		func->groups[i] = np->name;
7838c2ecf20Sopenharmony_ci		grp = &ipctl->groups[ipctl->ngroups];
7848c2ecf20Sopenharmony_ci		grp->func = func->name;
7858c2ecf20Sopenharmony_ci		ret = rzn1_pinctrl_parse_groups(np, grp, ipctl);
7868c2ecf20Sopenharmony_ci		if (ret < 0)
7878c2ecf20Sopenharmony_ci			return ret;
7888c2ecf20Sopenharmony_ci		i++;
7898c2ecf20Sopenharmony_ci		ipctl->ngroups++;
7908c2ecf20Sopenharmony_ci	}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
7938c2ecf20Sopenharmony_ci		func->groups[i] = child->name;
7948c2ecf20Sopenharmony_ci		grp = &ipctl->groups[ipctl->ngroups];
7958c2ecf20Sopenharmony_ci		grp->func = func->name;
7968c2ecf20Sopenharmony_ci		ret = rzn1_pinctrl_parse_groups(child, grp, ipctl);
7978c2ecf20Sopenharmony_ci		if (ret < 0) {
7988c2ecf20Sopenharmony_ci			of_node_put(child);
7998c2ecf20Sopenharmony_ci			return ret;
8008c2ecf20Sopenharmony_ci		}
8018c2ecf20Sopenharmony_ci		i++;
8028c2ecf20Sopenharmony_ci		ipctl->ngroups++;
8038c2ecf20Sopenharmony_ci	}
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	dev_dbg(ipctl->dev, "function %s parsed %u/%u groups\n",
8068c2ecf20Sopenharmony_ci		np->name, i, func->num_groups);
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	return 0;
8098c2ecf20Sopenharmony_ci}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_cistatic int rzn1_pinctrl_probe_dt(struct platform_device *pdev,
8128c2ecf20Sopenharmony_ci				 struct rzn1_pinctrl *ipctl)
8138c2ecf20Sopenharmony_ci{
8148c2ecf20Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
8158c2ecf20Sopenharmony_ci	struct device_node *child;
8168c2ecf20Sopenharmony_ci	unsigned int maxgroups = 0;
8178c2ecf20Sopenharmony_ci	unsigned int i = 0;
8188c2ecf20Sopenharmony_ci	int nfuncs = 0;
8198c2ecf20Sopenharmony_ci	int ret;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	nfuncs = of_get_child_count(np);
8228c2ecf20Sopenharmony_ci	if (nfuncs <= 0)
8238c2ecf20Sopenharmony_ci		return 0;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	ipctl->nfunctions = nfuncs;
8268c2ecf20Sopenharmony_ci	ipctl->functions = devm_kmalloc_array(&pdev->dev, nfuncs,
8278c2ecf20Sopenharmony_ci					      sizeof(*ipctl->functions),
8288c2ecf20Sopenharmony_ci					      GFP_KERNEL);
8298c2ecf20Sopenharmony_ci	if (!ipctl->functions)
8308c2ecf20Sopenharmony_ci		return -ENOMEM;
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	ipctl->ngroups = 0;
8338c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child)
8348c2ecf20Sopenharmony_ci		maxgroups += rzn1_pinctrl_count_function_groups(child);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	ipctl->groups = devm_kmalloc_array(&pdev->dev,
8378c2ecf20Sopenharmony_ci					   maxgroups,
8388c2ecf20Sopenharmony_ci					   sizeof(*ipctl->groups),
8398c2ecf20Sopenharmony_ci					   GFP_KERNEL);
8408c2ecf20Sopenharmony_ci	if (!ipctl->groups)
8418c2ecf20Sopenharmony_ci		return -ENOMEM;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	for_each_child_of_node(np, child) {
8448c2ecf20Sopenharmony_ci		ret = rzn1_pinctrl_parse_functions(child, ipctl, i++);
8458c2ecf20Sopenharmony_ci		if (ret < 0) {
8468c2ecf20Sopenharmony_ci			of_node_put(child);
8478c2ecf20Sopenharmony_ci			return ret;
8488c2ecf20Sopenharmony_ci		}
8498c2ecf20Sopenharmony_ci	}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	return 0;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_cistatic int rzn1_pinctrl_probe(struct platform_device *pdev)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl;
8578c2ecf20Sopenharmony_ci	struct resource *res;
8588c2ecf20Sopenharmony_ci	int ret;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	/* Create state holders etc for this driver */
8618c2ecf20Sopenharmony_ci	ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
8628c2ecf20Sopenharmony_ci	if (!ipctl)
8638c2ecf20Sopenharmony_ci		return -ENOMEM;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	ipctl->mdio_func[0] = -1;
8668c2ecf20Sopenharmony_ci	ipctl->mdio_func[1] = -1;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	ipctl->lev1 = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
8698c2ecf20Sopenharmony_ci	if (IS_ERR(ipctl->lev1))
8708c2ecf20Sopenharmony_ci		return PTR_ERR(ipctl->lev1);
8718c2ecf20Sopenharmony_ci	ipctl->lev1_protect_phys = (u32)res->start + 0x400;
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	ipctl->lev2 = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
8748c2ecf20Sopenharmony_ci	if (IS_ERR(ipctl->lev2))
8758c2ecf20Sopenharmony_ci		return PTR_ERR(ipctl->lev2);
8768c2ecf20Sopenharmony_ci	ipctl->lev2_protect_phys = (u32)res->start + 0x400;
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	ipctl->clk = devm_clk_get(&pdev->dev, NULL);
8798c2ecf20Sopenharmony_ci	if (IS_ERR(ipctl->clk))
8808c2ecf20Sopenharmony_ci		return PTR_ERR(ipctl->clk);
8818c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(ipctl->clk);
8828c2ecf20Sopenharmony_ci	if (ret)
8838c2ecf20Sopenharmony_ci		return ret;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	ipctl->dev = &pdev->dev;
8868c2ecf20Sopenharmony_ci	rzn1_pinctrl_desc.name = dev_name(&pdev->dev);
8878c2ecf20Sopenharmony_ci	rzn1_pinctrl_desc.pins = rzn1_pins;
8888c2ecf20Sopenharmony_ci	rzn1_pinctrl_desc.npins = ARRAY_SIZE(rzn1_pins);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	ret = rzn1_pinctrl_probe_dt(pdev, ipctl);
8918c2ecf20Sopenharmony_ci	if (ret) {
8928c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "fail to probe dt properties\n");
8938c2ecf20Sopenharmony_ci		goto err_clk;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, ipctl);
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci	ret = devm_pinctrl_register_and_init(&pdev->dev, &rzn1_pinctrl_desc,
8998c2ecf20Sopenharmony_ci					     ipctl, &ipctl->pctl);
9008c2ecf20Sopenharmony_ci	if (ret) {
9018c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "could not register rzn1 pinctrl driver\n");
9028c2ecf20Sopenharmony_ci		goto err_clk;
9038c2ecf20Sopenharmony_ci	}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	ret = pinctrl_enable(ipctl->pctl);
9068c2ecf20Sopenharmony_ci	if (ret)
9078c2ecf20Sopenharmony_ci		goto err_clk;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "probed\n");
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	return 0;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_cierr_clk:
9148c2ecf20Sopenharmony_ci	clk_disable_unprepare(ipctl->clk);
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	return ret;
9178c2ecf20Sopenharmony_ci}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_cistatic int rzn1_pinctrl_remove(struct platform_device *pdev)
9208c2ecf20Sopenharmony_ci{
9218c2ecf20Sopenharmony_ci	struct rzn1_pinctrl *ipctl = platform_get_drvdata(pdev);
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	clk_disable_unprepare(ipctl->clk);
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci	return 0;
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_cistatic const struct of_device_id rzn1_pinctrl_match[] = {
9298c2ecf20Sopenharmony_ci	{ .compatible = "renesas,rzn1-pinctrl", },
9308c2ecf20Sopenharmony_ci	{}
9318c2ecf20Sopenharmony_ci};
9328c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rzn1_pinctrl_match);
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_cistatic struct platform_driver rzn1_pinctrl_driver = {
9358c2ecf20Sopenharmony_ci	.probe	= rzn1_pinctrl_probe,
9368c2ecf20Sopenharmony_ci	.remove = rzn1_pinctrl_remove,
9378c2ecf20Sopenharmony_ci	.driver	= {
9388c2ecf20Sopenharmony_ci		.name		= "rzn1-pinctrl",
9398c2ecf20Sopenharmony_ci		.of_match_table	= rzn1_pinctrl_match,
9408c2ecf20Sopenharmony_ci	},
9418c2ecf20Sopenharmony_ci};
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_cistatic int __init _pinctrl_drv_register(void)
9448c2ecf20Sopenharmony_ci{
9458c2ecf20Sopenharmony_ci	return platform_driver_register(&rzn1_pinctrl_driver);
9468c2ecf20Sopenharmony_ci}
9478c2ecf20Sopenharmony_cisubsys_initcall(_pinctrl_drv_register);
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ciMODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
9508c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Renesas RZ/N1 pinctrl driver");
9518c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
952