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