18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0 OR MIT) 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Microsemi SoCs pinctrl driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: <alexandre.belloni@free-electrons.com> 68c2ecf20Sopenharmony_ci * License: Dual MIT/GPL 78c2ecf20Sopenharmony_ci * Copyright (c) 2017 Microsemi Corporation 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 118c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/of_device.h> 148c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 158c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 168c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinctrl.h> 178c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 188c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf.h> 198c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 208c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 218c2ecf20Sopenharmony_ci#include <linux/regmap.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "core.h" 258c2ecf20Sopenharmony_ci#include "pinconf.h" 268c2ecf20Sopenharmony_ci#include "pinmux.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define ocelot_clrsetbits(addr, clear, set) \ 298c2ecf20Sopenharmony_ci writel((readl(addr) & ~(clear)) | (set), (addr)) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/* PINCONFIG bits (sparx5 only) */ 328c2ecf20Sopenharmony_cienum { 338c2ecf20Sopenharmony_ci PINCONF_BIAS, 348c2ecf20Sopenharmony_ci PINCONF_SCHMITT, 358c2ecf20Sopenharmony_ci PINCONF_DRIVE_STRENGTH, 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define BIAS_PD_BIT BIT(4) 398c2ecf20Sopenharmony_ci#define BIAS_PU_BIT BIT(3) 408c2ecf20Sopenharmony_ci#define BIAS_BITS (BIAS_PD_BIT|BIAS_PU_BIT) 418c2ecf20Sopenharmony_ci#define SCHMITT_BIT BIT(2) 428c2ecf20Sopenharmony_ci#define DRIVE_BITS GENMASK(1, 0) 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* GPIO standard registers */ 458c2ecf20Sopenharmony_ci#define OCELOT_GPIO_OUT_SET 0x0 468c2ecf20Sopenharmony_ci#define OCELOT_GPIO_OUT_CLR 0x4 478c2ecf20Sopenharmony_ci#define OCELOT_GPIO_OUT 0x8 488c2ecf20Sopenharmony_ci#define OCELOT_GPIO_IN 0xc 498c2ecf20Sopenharmony_ci#define OCELOT_GPIO_OE 0x10 508c2ecf20Sopenharmony_ci#define OCELOT_GPIO_INTR 0x14 518c2ecf20Sopenharmony_ci#define OCELOT_GPIO_INTR_ENA 0x18 528c2ecf20Sopenharmony_ci#define OCELOT_GPIO_INTR_IDENT 0x1c 538c2ecf20Sopenharmony_ci#define OCELOT_GPIO_ALT0 0x20 548c2ecf20Sopenharmony_ci#define OCELOT_GPIO_ALT1 0x24 558c2ecf20Sopenharmony_ci#define OCELOT_GPIO_SD_MAP 0x28 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#define OCELOT_FUNC_PER_PIN 4 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cienum { 608c2ecf20Sopenharmony_ci FUNC_NONE, 618c2ecf20Sopenharmony_ci FUNC_GPIO, 628c2ecf20Sopenharmony_ci FUNC_IRQ0, 638c2ecf20Sopenharmony_ci FUNC_IRQ0_IN, 648c2ecf20Sopenharmony_ci FUNC_IRQ0_OUT, 658c2ecf20Sopenharmony_ci FUNC_IRQ1, 668c2ecf20Sopenharmony_ci FUNC_IRQ1_IN, 678c2ecf20Sopenharmony_ci FUNC_IRQ1_OUT, 688c2ecf20Sopenharmony_ci FUNC_EXT_IRQ, 698c2ecf20Sopenharmony_ci FUNC_MIIM, 708c2ecf20Sopenharmony_ci FUNC_PHY_LED, 718c2ecf20Sopenharmony_ci FUNC_PCI_WAKE, 728c2ecf20Sopenharmony_ci FUNC_MD, 738c2ecf20Sopenharmony_ci FUNC_PTP0, 748c2ecf20Sopenharmony_ci FUNC_PTP1, 758c2ecf20Sopenharmony_ci FUNC_PTP2, 768c2ecf20Sopenharmony_ci FUNC_PTP3, 778c2ecf20Sopenharmony_ci FUNC_PWM, 788c2ecf20Sopenharmony_ci FUNC_RECO_CLK, 798c2ecf20Sopenharmony_ci FUNC_SFP, 808c2ecf20Sopenharmony_ci FUNC_SG0, 818c2ecf20Sopenharmony_ci FUNC_SG1, 828c2ecf20Sopenharmony_ci FUNC_SG2, 838c2ecf20Sopenharmony_ci FUNC_SI, 848c2ecf20Sopenharmony_ci FUNC_SI2, 858c2ecf20Sopenharmony_ci FUNC_TACHO, 868c2ecf20Sopenharmony_ci FUNC_TWI, 878c2ecf20Sopenharmony_ci FUNC_TWI2, 888c2ecf20Sopenharmony_ci FUNC_TWI3, 898c2ecf20Sopenharmony_ci FUNC_TWI_SCL_M, 908c2ecf20Sopenharmony_ci FUNC_UART, 918c2ecf20Sopenharmony_ci FUNC_UART2, 928c2ecf20Sopenharmony_ci FUNC_UART3, 938c2ecf20Sopenharmony_ci FUNC_PLL_STAT, 948c2ecf20Sopenharmony_ci FUNC_EMMC, 958c2ecf20Sopenharmony_ci FUNC_REF_CLK, 968c2ecf20Sopenharmony_ci FUNC_RCVRD_CLK, 978c2ecf20Sopenharmony_ci FUNC_MAX 988c2ecf20Sopenharmony_ci}; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic const char *const ocelot_function_names[] = { 1018c2ecf20Sopenharmony_ci [FUNC_NONE] = "none", 1028c2ecf20Sopenharmony_ci [FUNC_GPIO] = "gpio", 1038c2ecf20Sopenharmony_ci [FUNC_IRQ0] = "irq0", 1048c2ecf20Sopenharmony_ci [FUNC_IRQ0_IN] = "irq0_in", 1058c2ecf20Sopenharmony_ci [FUNC_IRQ0_OUT] = "irq0_out", 1068c2ecf20Sopenharmony_ci [FUNC_IRQ1] = "irq1", 1078c2ecf20Sopenharmony_ci [FUNC_IRQ1_IN] = "irq1_in", 1088c2ecf20Sopenharmony_ci [FUNC_IRQ1_OUT] = "irq1_out", 1098c2ecf20Sopenharmony_ci [FUNC_EXT_IRQ] = "ext_irq", 1108c2ecf20Sopenharmony_ci [FUNC_MIIM] = "miim", 1118c2ecf20Sopenharmony_ci [FUNC_PHY_LED] = "phy_led", 1128c2ecf20Sopenharmony_ci [FUNC_PCI_WAKE] = "pci_wake", 1138c2ecf20Sopenharmony_ci [FUNC_MD] = "md", 1148c2ecf20Sopenharmony_ci [FUNC_PTP0] = "ptp0", 1158c2ecf20Sopenharmony_ci [FUNC_PTP1] = "ptp1", 1168c2ecf20Sopenharmony_ci [FUNC_PTP2] = "ptp2", 1178c2ecf20Sopenharmony_ci [FUNC_PTP3] = "ptp3", 1188c2ecf20Sopenharmony_ci [FUNC_PWM] = "pwm", 1198c2ecf20Sopenharmony_ci [FUNC_RECO_CLK] = "reco_clk", 1208c2ecf20Sopenharmony_ci [FUNC_SFP] = "sfp", 1218c2ecf20Sopenharmony_ci [FUNC_SG0] = "sg0", 1228c2ecf20Sopenharmony_ci [FUNC_SG1] = "sg1", 1238c2ecf20Sopenharmony_ci [FUNC_SG2] = "sg2", 1248c2ecf20Sopenharmony_ci [FUNC_SI] = "si", 1258c2ecf20Sopenharmony_ci [FUNC_SI2] = "si2", 1268c2ecf20Sopenharmony_ci [FUNC_TACHO] = "tacho", 1278c2ecf20Sopenharmony_ci [FUNC_TWI] = "twi", 1288c2ecf20Sopenharmony_ci [FUNC_TWI2] = "twi2", 1298c2ecf20Sopenharmony_ci [FUNC_TWI3] = "twi3", 1308c2ecf20Sopenharmony_ci [FUNC_TWI_SCL_M] = "twi_scl_m", 1318c2ecf20Sopenharmony_ci [FUNC_UART] = "uart", 1328c2ecf20Sopenharmony_ci [FUNC_UART2] = "uart2", 1338c2ecf20Sopenharmony_ci [FUNC_UART3] = "uart3", 1348c2ecf20Sopenharmony_ci [FUNC_PLL_STAT] = "pll_stat", 1358c2ecf20Sopenharmony_ci [FUNC_EMMC] = "emmc", 1368c2ecf20Sopenharmony_ci [FUNC_REF_CLK] = "ref_clk", 1378c2ecf20Sopenharmony_ci [FUNC_RCVRD_CLK] = "rcvrd_clk", 1388c2ecf20Sopenharmony_ci}; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistruct ocelot_pmx_func { 1418c2ecf20Sopenharmony_ci const char **groups; 1428c2ecf20Sopenharmony_ci unsigned int ngroups; 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistruct ocelot_pin_caps { 1468c2ecf20Sopenharmony_ci unsigned int pin; 1478c2ecf20Sopenharmony_ci unsigned char functions[OCELOT_FUNC_PER_PIN]; 1488c2ecf20Sopenharmony_ci}; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistruct ocelot_pinctrl { 1518c2ecf20Sopenharmony_ci struct device *dev; 1528c2ecf20Sopenharmony_ci struct pinctrl_dev *pctl; 1538c2ecf20Sopenharmony_ci struct gpio_chip gpio_chip; 1548c2ecf20Sopenharmony_ci struct regmap *map; 1558c2ecf20Sopenharmony_ci void __iomem *pincfg; 1568c2ecf20Sopenharmony_ci struct pinctrl_desc *desc; 1578c2ecf20Sopenharmony_ci struct ocelot_pmx_func func[FUNC_MAX]; 1588c2ecf20Sopenharmony_ci u8 stride; 1598c2ecf20Sopenharmony_ci}; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci#define OCELOT_P(p, f0, f1, f2) \ 1628c2ecf20Sopenharmony_cistatic struct ocelot_pin_caps ocelot_pin_##p = { \ 1638c2ecf20Sopenharmony_ci .pin = p, \ 1648c2ecf20Sopenharmony_ci .functions = { \ 1658c2ecf20Sopenharmony_ci FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2, \ 1668c2ecf20Sopenharmony_ci }, \ 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ciOCELOT_P(0, SG0, NONE, NONE); 1708c2ecf20Sopenharmony_ciOCELOT_P(1, SG0, NONE, NONE); 1718c2ecf20Sopenharmony_ciOCELOT_P(2, SG0, NONE, NONE); 1728c2ecf20Sopenharmony_ciOCELOT_P(3, SG0, NONE, NONE); 1738c2ecf20Sopenharmony_ciOCELOT_P(4, IRQ0_IN, IRQ0_OUT, TWI_SCL_M); 1748c2ecf20Sopenharmony_ciOCELOT_P(5, IRQ1_IN, IRQ1_OUT, PCI_WAKE); 1758c2ecf20Sopenharmony_ciOCELOT_P(6, UART, TWI_SCL_M, NONE); 1768c2ecf20Sopenharmony_ciOCELOT_P(7, UART, TWI_SCL_M, NONE); 1778c2ecf20Sopenharmony_ciOCELOT_P(8, SI, TWI_SCL_M, IRQ0_OUT); 1788c2ecf20Sopenharmony_ciOCELOT_P(9, SI, TWI_SCL_M, IRQ1_OUT); 1798c2ecf20Sopenharmony_ciOCELOT_P(10, PTP2, TWI_SCL_M, SFP); 1808c2ecf20Sopenharmony_ciOCELOT_P(11, PTP3, TWI_SCL_M, SFP); 1818c2ecf20Sopenharmony_ciOCELOT_P(12, UART2, TWI_SCL_M, SFP); 1828c2ecf20Sopenharmony_ciOCELOT_P(13, UART2, TWI_SCL_M, SFP); 1838c2ecf20Sopenharmony_ciOCELOT_P(14, MIIM, TWI_SCL_M, SFP); 1848c2ecf20Sopenharmony_ciOCELOT_P(15, MIIM, TWI_SCL_M, SFP); 1858c2ecf20Sopenharmony_ciOCELOT_P(16, TWI, NONE, SI); 1868c2ecf20Sopenharmony_ciOCELOT_P(17, TWI, TWI_SCL_M, SI); 1878c2ecf20Sopenharmony_ciOCELOT_P(18, PTP0, TWI_SCL_M, NONE); 1888c2ecf20Sopenharmony_ciOCELOT_P(19, PTP1, TWI_SCL_M, NONE); 1898c2ecf20Sopenharmony_ciOCELOT_P(20, RECO_CLK, TACHO, TWI_SCL_M); 1908c2ecf20Sopenharmony_ciOCELOT_P(21, RECO_CLK, PWM, TWI_SCL_M); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci#define OCELOT_PIN(n) { \ 1938c2ecf20Sopenharmony_ci .number = n, \ 1948c2ecf20Sopenharmony_ci .name = "GPIO_"#n, \ 1958c2ecf20Sopenharmony_ci .drv_data = &ocelot_pin_##n \ 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic const struct pinctrl_pin_desc ocelot_pins[] = { 1998c2ecf20Sopenharmony_ci OCELOT_PIN(0), 2008c2ecf20Sopenharmony_ci OCELOT_PIN(1), 2018c2ecf20Sopenharmony_ci OCELOT_PIN(2), 2028c2ecf20Sopenharmony_ci OCELOT_PIN(3), 2038c2ecf20Sopenharmony_ci OCELOT_PIN(4), 2048c2ecf20Sopenharmony_ci OCELOT_PIN(5), 2058c2ecf20Sopenharmony_ci OCELOT_PIN(6), 2068c2ecf20Sopenharmony_ci OCELOT_PIN(7), 2078c2ecf20Sopenharmony_ci OCELOT_PIN(8), 2088c2ecf20Sopenharmony_ci OCELOT_PIN(9), 2098c2ecf20Sopenharmony_ci OCELOT_PIN(10), 2108c2ecf20Sopenharmony_ci OCELOT_PIN(11), 2118c2ecf20Sopenharmony_ci OCELOT_PIN(12), 2128c2ecf20Sopenharmony_ci OCELOT_PIN(13), 2138c2ecf20Sopenharmony_ci OCELOT_PIN(14), 2148c2ecf20Sopenharmony_ci OCELOT_PIN(15), 2158c2ecf20Sopenharmony_ci OCELOT_PIN(16), 2168c2ecf20Sopenharmony_ci OCELOT_PIN(17), 2178c2ecf20Sopenharmony_ci OCELOT_PIN(18), 2188c2ecf20Sopenharmony_ci OCELOT_PIN(19), 2198c2ecf20Sopenharmony_ci OCELOT_PIN(20), 2208c2ecf20Sopenharmony_ci OCELOT_PIN(21), 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci#define JAGUAR2_P(p, f0, f1) \ 2248c2ecf20Sopenharmony_cistatic struct ocelot_pin_caps jaguar2_pin_##p = { \ 2258c2ecf20Sopenharmony_ci .pin = p, \ 2268c2ecf20Sopenharmony_ci .functions = { \ 2278c2ecf20Sopenharmony_ci FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_NONE \ 2288c2ecf20Sopenharmony_ci }, \ 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciJAGUAR2_P(0, SG0, NONE); 2328c2ecf20Sopenharmony_ciJAGUAR2_P(1, SG0, NONE); 2338c2ecf20Sopenharmony_ciJAGUAR2_P(2, SG0, NONE); 2348c2ecf20Sopenharmony_ciJAGUAR2_P(3, SG0, NONE); 2358c2ecf20Sopenharmony_ciJAGUAR2_P(4, SG1, NONE); 2368c2ecf20Sopenharmony_ciJAGUAR2_P(5, SG1, NONE); 2378c2ecf20Sopenharmony_ciJAGUAR2_P(6, IRQ0_IN, IRQ0_OUT); 2388c2ecf20Sopenharmony_ciJAGUAR2_P(7, IRQ1_IN, IRQ1_OUT); 2398c2ecf20Sopenharmony_ciJAGUAR2_P(8, PTP0, NONE); 2408c2ecf20Sopenharmony_ciJAGUAR2_P(9, PTP1, NONE); 2418c2ecf20Sopenharmony_ciJAGUAR2_P(10, UART, NONE); 2428c2ecf20Sopenharmony_ciJAGUAR2_P(11, UART, NONE); 2438c2ecf20Sopenharmony_ciJAGUAR2_P(12, SG1, NONE); 2448c2ecf20Sopenharmony_ciJAGUAR2_P(13, SG1, NONE); 2458c2ecf20Sopenharmony_ciJAGUAR2_P(14, TWI, TWI_SCL_M); 2468c2ecf20Sopenharmony_ciJAGUAR2_P(15, TWI, NONE); 2478c2ecf20Sopenharmony_ciJAGUAR2_P(16, SI, TWI_SCL_M); 2488c2ecf20Sopenharmony_ciJAGUAR2_P(17, SI, TWI_SCL_M); 2498c2ecf20Sopenharmony_ciJAGUAR2_P(18, SI, TWI_SCL_M); 2508c2ecf20Sopenharmony_ciJAGUAR2_P(19, PCI_WAKE, NONE); 2518c2ecf20Sopenharmony_ciJAGUAR2_P(20, IRQ0_OUT, TWI_SCL_M); 2528c2ecf20Sopenharmony_ciJAGUAR2_P(21, IRQ1_OUT, TWI_SCL_M); 2538c2ecf20Sopenharmony_ciJAGUAR2_P(22, TACHO, NONE); 2548c2ecf20Sopenharmony_ciJAGUAR2_P(23, PWM, NONE); 2558c2ecf20Sopenharmony_ciJAGUAR2_P(24, UART2, NONE); 2568c2ecf20Sopenharmony_ciJAGUAR2_P(25, UART2, SI); 2578c2ecf20Sopenharmony_ciJAGUAR2_P(26, PTP2, SI); 2588c2ecf20Sopenharmony_ciJAGUAR2_P(27, PTP3, SI); 2598c2ecf20Sopenharmony_ciJAGUAR2_P(28, TWI2, SI); 2608c2ecf20Sopenharmony_ciJAGUAR2_P(29, TWI2, SI); 2618c2ecf20Sopenharmony_ciJAGUAR2_P(30, SG2, SI); 2628c2ecf20Sopenharmony_ciJAGUAR2_P(31, SG2, SI); 2638c2ecf20Sopenharmony_ciJAGUAR2_P(32, SG2, SI); 2648c2ecf20Sopenharmony_ciJAGUAR2_P(33, SG2, SI); 2658c2ecf20Sopenharmony_ciJAGUAR2_P(34, NONE, TWI_SCL_M); 2668c2ecf20Sopenharmony_ciJAGUAR2_P(35, NONE, TWI_SCL_M); 2678c2ecf20Sopenharmony_ciJAGUAR2_P(36, NONE, TWI_SCL_M); 2688c2ecf20Sopenharmony_ciJAGUAR2_P(37, NONE, TWI_SCL_M); 2698c2ecf20Sopenharmony_ciJAGUAR2_P(38, NONE, TWI_SCL_M); 2708c2ecf20Sopenharmony_ciJAGUAR2_P(39, NONE, TWI_SCL_M); 2718c2ecf20Sopenharmony_ciJAGUAR2_P(40, NONE, TWI_SCL_M); 2728c2ecf20Sopenharmony_ciJAGUAR2_P(41, NONE, TWI_SCL_M); 2738c2ecf20Sopenharmony_ciJAGUAR2_P(42, NONE, TWI_SCL_M); 2748c2ecf20Sopenharmony_ciJAGUAR2_P(43, NONE, TWI_SCL_M); 2758c2ecf20Sopenharmony_ciJAGUAR2_P(44, NONE, SFP); 2768c2ecf20Sopenharmony_ciJAGUAR2_P(45, NONE, SFP); 2778c2ecf20Sopenharmony_ciJAGUAR2_P(46, NONE, SFP); 2788c2ecf20Sopenharmony_ciJAGUAR2_P(47, NONE, SFP); 2798c2ecf20Sopenharmony_ciJAGUAR2_P(48, SFP, NONE); 2808c2ecf20Sopenharmony_ciJAGUAR2_P(49, SFP, SI); 2818c2ecf20Sopenharmony_ciJAGUAR2_P(50, SFP, SI); 2828c2ecf20Sopenharmony_ciJAGUAR2_P(51, SFP, SI); 2838c2ecf20Sopenharmony_ciJAGUAR2_P(52, SFP, NONE); 2848c2ecf20Sopenharmony_ciJAGUAR2_P(53, SFP, NONE); 2858c2ecf20Sopenharmony_ciJAGUAR2_P(54, SFP, NONE); 2868c2ecf20Sopenharmony_ciJAGUAR2_P(55, SFP, NONE); 2878c2ecf20Sopenharmony_ciJAGUAR2_P(56, MIIM, SFP); 2888c2ecf20Sopenharmony_ciJAGUAR2_P(57, MIIM, SFP); 2898c2ecf20Sopenharmony_ciJAGUAR2_P(58, MIIM, SFP); 2908c2ecf20Sopenharmony_ciJAGUAR2_P(59, MIIM, SFP); 2918c2ecf20Sopenharmony_ciJAGUAR2_P(60, NONE, NONE); 2928c2ecf20Sopenharmony_ciJAGUAR2_P(61, NONE, NONE); 2938c2ecf20Sopenharmony_ciJAGUAR2_P(62, NONE, NONE); 2948c2ecf20Sopenharmony_ciJAGUAR2_P(63, NONE, NONE); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci#define JAGUAR2_PIN(n) { \ 2978c2ecf20Sopenharmony_ci .number = n, \ 2988c2ecf20Sopenharmony_ci .name = "GPIO_"#n, \ 2998c2ecf20Sopenharmony_ci .drv_data = &jaguar2_pin_##n \ 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic const struct pinctrl_pin_desc jaguar2_pins[] = { 3038c2ecf20Sopenharmony_ci JAGUAR2_PIN(0), 3048c2ecf20Sopenharmony_ci JAGUAR2_PIN(1), 3058c2ecf20Sopenharmony_ci JAGUAR2_PIN(2), 3068c2ecf20Sopenharmony_ci JAGUAR2_PIN(3), 3078c2ecf20Sopenharmony_ci JAGUAR2_PIN(4), 3088c2ecf20Sopenharmony_ci JAGUAR2_PIN(5), 3098c2ecf20Sopenharmony_ci JAGUAR2_PIN(6), 3108c2ecf20Sopenharmony_ci JAGUAR2_PIN(7), 3118c2ecf20Sopenharmony_ci JAGUAR2_PIN(8), 3128c2ecf20Sopenharmony_ci JAGUAR2_PIN(9), 3138c2ecf20Sopenharmony_ci JAGUAR2_PIN(10), 3148c2ecf20Sopenharmony_ci JAGUAR2_PIN(11), 3158c2ecf20Sopenharmony_ci JAGUAR2_PIN(12), 3168c2ecf20Sopenharmony_ci JAGUAR2_PIN(13), 3178c2ecf20Sopenharmony_ci JAGUAR2_PIN(14), 3188c2ecf20Sopenharmony_ci JAGUAR2_PIN(15), 3198c2ecf20Sopenharmony_ci JAGUAR2_PIN(16), 3208c2ecf20Sopenharmony_ci JAGUAR2_PIN(17), 3218c2ecf20Sopenharmony_ci JAGUAR2_PIN(18), 3228c2ecf20Sopenharmony_ci JAGUAR2_PIN(19), 3238c2ecf20Sopenharmony_ci JAGUAR2_PIN(20), 3248c2ecf20Sopenharmony_ci JAGUAR2_PIN(21), 3258c2ecf20Sopenharmony_ci JAGUAR2_PIN(22), 3268c2ecf20Sopenharmony_ci JAGUAR2_PIN(23), 3278c2ecf20Sopenharmony_ci JAGUAR2_PIN(24), 3288c2ecf20Sopenharmony_ci JAGUAR2_PIN(25), 3298c2ecf20Sopenharmony_ci JAGUAR2_PIN(26), 3308c2ecf20Sopenharmony_ci JAGUAR2_PIN(27), 3318c2ecf20Sopenharmony_ci JAGUAR2_PIN(28), 3328c2ecf20Sopenharmony_ci JAGUAR2_PIN(29), 3338c2ecf20Sopenharmony_ci JAGUAR2_PIN(30), 3348c2ecf20Sopenharmony_ci JAGUAR2_PIN(31), 3358c2ecf20Sopenharmony_ci JAGUAR2_PIN(32), 3368c2ecf20Sopenharmony_ci JAGUAR2_PIN(33), 3378c2ecf20Sopenharmony_ci JAGUAR2_PIN(34), 3388c2ecf20Sopenharmony_ci JAGUAR2_PIN(35), 3398c2ecf20Sopenharmony_ci JAGUAR2_PIN(36), 3408c2ecf20Sopenharmony_ci JAGUAR2_PIN(37), 3418c2ecf20Sopenharmony_ci JAGUAR2_PIN(38), 3428c2ecf20Sopenharmony_ci JAGUAR2_PIN(39), 3438c2ecf20Sopenharmony_ci JAGUAR2_PIN(40), 3448c2ecf20Sopenharmony_ci JAGUAR2_PIN(41), 3458c2ecf20Sopenharmony_ci JAGUAR2_PIN(42), 3468c2ecf20Sopenharmony_ci JAGUAR2_PIN(43), 3478c2ecf20Sopenharmony_ci JAGUAR2_PIN(44), 3488c2ecf20Sopenharmony_ci JAGUAR2_PIN(45), 3498c2ecf20Sopenharmony_ci JAGUAR2_PIN(46), 3508c2ecf20Sopenharmony_ci JAGUAR2_PIN(47), 3518c2ecf20Sopenharmony_ci JAGUAR2_PIN(48), 3528c2ecf20Sopenharmony_ci JAGUAR2_PIN(49), 3538c2ecf20Sopenharmony_ci JAGUAR2_PIN(50), 3548c2ecf20Sopenharmony_ci JAGUAR2_PIN(51), 3558c2ecf20Sopenharmony_ci JAGUAR2_PIN(52), 3568c2ecf20Sopenharmony_ci JAGUAR2_PIN(53), 3578c2ecf20Sopenharmony_ci JAGUAR2_PIN(54), 3588c2ecf20Sopenharmony_ci JAGUAR2_PIN(55), 3598c2ecf20Sopenharmony_ci JAGUAR2_PIN(56), 3608c2ecf20Sopenharmony_ci JAGUAR2_PIN(57), 3618c2ecf20Sopenharmony_ci JAGUAR2_PIN(58), 3628c2ecf20Sopenharmony_ci JAGUAR2_PIN(59), 3638c2ecf20Sopenharmony_ci JAGUAR2_PIN(60), 3648c2ecf20Sopenharmony_ci JAGUAR2_PIN(61), 3658c2ecf20Sopenharmony_ci JAGUAR2_PIN(62), 3668c2ecf20Sopenharmony_ci JAGUAR2_PIN(63), 3678c2ecf20Sopenharmony_ci}; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci#define SPARX5_P(p, f0, f1, f2) \ 3708c2ecf20Sopenharmony_cistatic struct ocelot_pin_caps sparx5_pin_##p = { \ 3718c2ecf20Sopenharmony_ci .pin = p, \ 3728c2ecf20Sopenharmony_ci .functions = { \ 3738c2ecf20Sopenharmony_ci FUNC_GPIO, FUNC_##f0, FUNC_##f1, FUNC_##f2 \ 3748c2ecf20Sopenharmony_ci }, \ 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ciSPARX5_P(0, SG0, PLL_STAT, NONE); 3788c2ecf20Sopenharmony_ciSPARX5_P(1, SG0, NONE, NONE); 3798c2ecf20Sopenharmony_ciSPARX5_P(2, SG0, NONE, NONE); 3808c2ecf20Sopenharmony_ciSPARX5_P(3, SG0, NONE, NONE); 3818c2ecf20Sopenharmony_ciSPARX5_P(4, SG1, NONE, NONE); 3828c2ecf20Sopenharmony_ciSPARX5_P(5, SG1, NONE, NONE); 3838c2ecf20Sopenharmony_ciSPARX5_P(6, IRQ0_IN, IRQ0_OUT, SFP); 3848c2ecf20Sopenharmony_ciSPARX5_P(7, IRQ1_IN, IRQ1_OUT, SFP); 3858c2ecf20Sopenharmony_ciSPARX5_P(8, PTP0, NONE, SFP); 3868c2ecf20Sopenharmony_ciSPARX5_P(9, PTP1, SFP, TWI_SCL_M); 3878c2ecf20Sopenharmony_ciSPARX5_P(10, UART, NONE, NONE); 3888c2ecf20Sopenharmony_ciSPARX5_P(11, UART, NONE, NONE); 3898c2ecf20Sopenharmony_ciSPARX5_P(12, SG1, NONE, NONE); 3908c2ecf20Sopenharmony_ciSPARX5_P(13, SG1, NONE, NONE); 3918c2ecf20Sopenharmony_ciSPARX5_P(14, TWI, TWI_SCL_M, NONE); 3928c2ecf20Sopenharmony_ciSPARX5_P(15, TWI, NONE, NONE); 3938c2ecf20Sopenharmony_ciSPARX5_P(16, SI, TWI_SCL_M, SFP); 3948c2ecf20Sopenharmony_ciSPARX5_P(17, SI, TWI_SCL_M, SFP); 3958c2ecf20Sopenharmony_ciSPARX5_P(18, SI, TWI_SCL_M, SFP); 3968c2ecf20Sopenharmony_ciSPARX5_P(19, PCI_WAKE, TWI_SCL_M, SFP); 3978c2ecf20Sopenharmony_ciSPARX5_P(20, IRQ0_OUT, TWI_SCL_M, SFP); 3988c2ecf20Sopenharmony_ciSPARX5_P(21, IRQ1_OUT, TACHO, SFP); 3998c2ecf20Sopenharmony_ciSPARX5_P(22, TACHO, IRQ0_OUT, TWI_SCL_M); 4008c2ecf20Sopenharmony_ciSPARX5_P(23, PWM, UART3, TWI_SCL_M); 4018c2ecf20Sopenharmony_ciSPARX5_P(24, PTP2, UART3, TWI_SCL_M); 4028c2ecf20Sopenharmony_ciSPARX5_P(25, PTP3, SI, TWI_SCL_M); 4038c2ecf20Sopenharmony_ciSPARX5_P(26, UART2, SI, TWI_SCL_M); 4048c2ecf20Sopenharmony_ciSPARX5_P(27, UART2, SI, TWI_SCL_M); 4058c2ecf20Sopenharmony_ciSPARX5_P(28, TWI2, SI, SFP); 4068c2ecf20Sopenharmony_ciSPARX5_P(29, TWI2, SI, SFP); 4078c2ecf20Sopenharmony_ciSPARX5_P(30, SG2, SI, PWM); 4088c2ecf20Sopenharmony_ciSPARX5_P(31, SG2, SI, TWI_SCL_M); 4098c2ecf20Sopenharmony_ciSPARX5_P(32, SG2, SI, TWI_SCL_M); 4108c2ecf20Sopenharmony_ciSPARX5_P(33, SG2, SI, SFP); 4118c2ecf20Sopenharmony_ciSPARX5_P(34, NONE, TWI_SCL_M, EMMC); 4128c2ecf20Sopenharmony_ciSPARX5_P(35, SFP, TWI_SCL_M, EMMC); 4138c2ecf20Sopenharmony_ciSPARX5_P(36, SFP, TWI_SCL_M, EMMC); 4148c2ecf20Sopenharmony_ciSPARX5_P(37, SFP, NONE, EMMC); 4158c2ecf20Sopenharmony_ciSPARX5_P(38, NONE, TWI_SCL_M, EMMC); 4168c2ecf20Sopenharmony_ciSPARX5_P(39, SI2, TWI_SCL_M, EMMC); 4178c2ecf20Sopenharmony_ciSPARX5_P(40, SI2, TWI_SCL_M, EMMC); 4188c2ecf20Sopenharmony_ciSPARX5_P(41, SI2, TWI_SCL_M, EMMC); 4198c2ecf20Sopenharmony_ciSPARX5_P(42, SI2, TWI_SCL_M, EMMC); 4208c2ecf20Sopenharmony_ciSPARX5_P(43, SI2, TWI_SCL_M, EMMC); 4218c2ecf20Sopenharmony_ciSPARX5_P(44, SI, SFP, EMMC); 4228c2ecf20Sopenharmony_ciSPARX5_P(45, SI, SFP, EMMC); 4238c2ecf20Sopenharmony_ciSPARX5_P(46, NONE, SFP, EMMC); 4248c2ecf20Sopenharmony_ciSPARX5_P(47, NONE, SFP, EMMC); 4258c2ecf20Sopenharmony_ciSPARX5_P(48, TWI3, SI, SFP); 4268c2ecf20Sopenharmony_ciSPARX5_P(49, TWI3, NONE, SFP); 4278c2ecf20Sopenharmony_ciSPARX5_P(50, SFP, NONE, TWI_SCL_M); 4288c2ecf20Sopenharmony_ciSPARX5_P(51, SFP, SI, TWI_SCL_M); 4298c2ecf20Sopenharmony_ciSPARX5_P(52, SFP, MIIM, TWI_SCL_M); 4308c2ecf20Sopenharmony_ciSPARX5_P(53, SFP, MIIM, TWI_SCL_M); 4318c2ecf20Sopenharmony_ciSPARX5_P(54, SFP, PTP2, TWI_SCL_M); 4328c2ecf20Sopenharmony_ciSPARX5_P(55, SFP, PTP3, PCI_WAKE); 4338c2ecf20Sopenharmony_ciSPARX5_P(56, MIIM, SFP, TWI_SCL_M); 4348c2ecf20Sopenharmony_ciSPARX5_P(57, MIIM, SFP, TWI_SCL_M); 4358c2ecf20Sopenharmony_ciSPARX5_P(58, MIIM, SFP, TWI_SCL_M); 4368c2ecf20Sopenharmony_ciSPARX5_P(59, MIIM, SFP, NONE); 4378c2ecf20Sopenharmony_ciSPARX5_P(60, RECO_CLK, NONE, NONE); 4388c2ecf20Sopenharmony_ciSPARX5_P(61, RECO_CLK, NONE, NONE); 4398c2ecf20Sopenharmony_ciSPARX5_P(62, RECO_CLK, PLL_STAT, NONE); 4408c2ecf20Sopenharmony_ciSPARX5_P(63, RECO_CLK, NONE, NONE); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci#define SPARX5_PIN(n) { \ 4438c2ecf20Sopenharmony_ci .number = n, \ 4448c2ecf20Sopenharmony_ci .name = "GPIO_"#n, \ 4458c2ecf20Sopenharmony_ci .drv_data = &sparx5_pin_##n \ 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_cistatic const struct pinctrl_pin_desc sparx5_pins[] = { 4498c2ecf20Sopenharmony_ci SPARX5_PIN(0), 4508c2ecf20Sopenharmony_ci SPARX5_PIN(1), 4518c2ecf20Sopenharmony_ci SPARX5_PIN(2), 4528c2ecf20Sopenharmony_ci SPARX5_PIN(3), 4538c2ecf20Sopenharmony_ci SPARX5_PIN(4), 4548c2ecf20Sopenharmony_ci SPARX5_PIN(5), 4558c2ecf20Sopenharmony_ci SPARX5_PIN(6), 4568c2ecf20Sopenharmony_ci SPARX5_PIN(7), 4578c2ecf20Sopenharmony_ci SPARX5_PIN(8), 4588c2ecf20Sopenharmony_ci SPARX5_PIN(9), 4598c2ecf20Sopenharmony_ci SPARX5_PIN(10), 4608c2ecf20Sopenharmony_ci SPARX5_PIN(11), 4618c2ecf20Sopenharmony_ci SPARX5_PIN(12), 4628c2ecf20Sopenharmony_ci SPARX5_PIN(13), 4638c2ecf20Sopenharmony_ci SPARX5_PIN(14), 4648c2ecf20Sopenharmony_ci SPARX5_PIN(15), 4658c2ecf20Sopenharmony_ci SPARX5_PIN(16), 4668c2ecf20Sopenharmony_ci SPARX5_PIN(17), 4678c2ecf20Sopenharmony_ci SPARX5_PIN(18), 4688c2ecf20Sopenharmony_ci SPARX5_PIN(19), 4698c2ecf20Sopenharmony_ci SPARX5_PIN(20), 4708c2ecf20Sopenharmony_ci SPARX5_PIN(21), 4718c2ecf20Sopenharmony_ci SPARX5_PIN(22), 4728c2ecf20Sopenharmony_ci SPARX5_PIN(23), 4738c2ecf20Sopenharmony_ci SPARX5_PIN(24), 4748c2ecf20Sopenharmony_ci SPARX5_PIN(25), 4758c2ecf20Sopenharmony_ci SPARX5_PIN(26), 4768c2ecf20Sopenharmony_ci SPARX5_PIN(27), 4778c2ecf20Sopenharmony_ci SPARX5_PIN(28), 4788c2ecf20Sopenharmony_ci SPARX5_PIN(29), 4798c2ecf20Sopenharmony_ci SPARX5_PIN(30), 4808c2ecf20Sopenharmony_ci SPARX5_PIN(31), 4818c2ecf20Sopenharmony_ci SPARX5_PIN(32), 4828c2ecf20Sopenharmony_ci SPARX5_PIN(33), 4838c2ecf20Sopenharmony_ci SPARX5_PIN(34), 4848c2ecf20Sopenharmony_ci SPARX5_PIN(35), 4858c2ecf20Sopenharmony_ci SPARX5_PIN(36), 4868c2ecf20Sopenharmony_ci SPARX5_PIN(37), 4878c2ecf20Sopenharmony_ci SPARX5_PIN(38), 4888c2ecf20Sopenharmony_ci SPARX5_PIN(39), 4898c2ecf20Sopenharmony_ci SPARX5_PIN(40), 4908c2ecf20Sopenharmony_ci SPARX5_PIN(41), 4918c2ecf20Sopenharmony_ci SPARX5_PIN(42), 4928c2ecf20Sopenharmony_ci SPARX5_PIN(43), 4938c2ecf20Sopenharmony_ci SPARX5_PIN(44), 4948c2ecf20Sopenharmony_ci SPARX5_PIN(45), 4958c2ecf20Sopenharmony_ci SPARX5_PIN(46), 4968c2ecf20Sopenharmony_ci SPARX5_PIN(47), 4978c2ecf20Sopenharmony_ci SPARX5_PIN(48), 4988c2ecf20Sopenharmony_ci SPARX5_PIN(49), 4998c2ecf20Sopenharmony_ci SPARX5_PIN(50), 5008c2ecf20Sopenharmony_ci SPARX5_PIN(51), 5018c2ecf20Sopenharmony_ci SPARX5_PIN(52), 5028c2ecf20Sopenharmony_ci SPARX5_PIN(53), 5038c2ecf20Sopenharmony_ci SPARX5_PIN(54), 5048c2ecf20Sopenharmony_ci SPARX5_PIN(55), 5058c2ecf20Sopenharmony_ci SPARX5_PIN(56), 5068c2ecf20Sopenharmony_ci SPARX5_PIN(57), 5078c2ecf20Sopenharmony_ci SPARX5_PIN(58), 5088c2ecf20Sopenharmony_ci SPARX5_PIN(59), 5098c2ecf20Sopenharmony_ci SPARX5_PIN(60), 5108c2ecf20Sopenharmony_ci SPARX5_PIN(61), 5118c2ecf20Sopenharmony_ci SPARX5_PIN(62), 5128c2ecf20Sopenharmony_ci SPARX5_PIN(63), 5138c2ecf20Sopenharmony_ci}; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic int ocelot_get_functions_count(struct pinctrl_dev *pctldev) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci return ARRAY_SIZE(ocelot_function_names); 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic const char *ocelot_get_function_name(struct pinctrl_dev *pctldev, 5218c2ecf20Sopenharmony_ci unsigned int function) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci return ocelot_function_names[function]; 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic int ocelot_get_function_groups(struct pinctrl_dev *pctldev, 5278c2ecf20Sopenharmony_ci unsigned int function, 5288c2ecf20Sopenharmony_ci const char *const **groups, 5298c2ecf20Sopenharmony_ci unsigned *const num_groups) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci *groups = info->func[function].groups; 5348c2ecf20Sopenharmony_ci *num_groups = info->func[function].ngroups; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci return 0; 5378c2ecf20Sopenharmony_ci} 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_cistatic int ocelot_pin_function_idx(struct ocelot_pinctrl *info, 5408c2ecf20Sopenharmony_ci unsigned int pin, unsigned int function) 5418c2ecf20Sopenharmony_ci{ 5428c2ecf20Sopenharmony_ci struct ocelot_pin_caps *p = info->desc->pins[pin].drv_data; 5438c2ecf20Sopenharmony_ci int i; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci for (i = 0; i < OCELOT_FUNC_PER_PIN; i++) { 5468c2ecf20Sopenharmony_ci if (function == p->functions[i]) 5478c2ecf20Sopenharmony_ci return i; 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci return -1; 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci#define REG_ALT(msb, info, p) (OCELOT_GPIO_ALT0 * (info)->stride + 4 * ((msb) + ((info)->stride * ((p) / 32)))) 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_cistatic int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev, 5568c2ecf20Sopenharmony_ci unsigned int selector, unsigned int group) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 5598c2ecf20Sopenharmony_ci struct ocelot_pin_caps *pin = info->desc->pins[group].drv_data; 5608c2ecf20Sopenharmony_ci unsigned int p = pin->pin % 32; 5618c2ecf20Sopenharmony_ci int f; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci f = ocelot_pin_function_idx(info, group, selector); 5648c2ecf20Sopenharmony_ci if (f < 0) 5658c2ecf20Sopenharmony_ci return -EINVAL; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci /* 5688c2ecf20Sopenharmony_ci * f is encoded on two bits. 5698c2ecf20Sopenharmony_ci * bit 0 of f goes in BIT(pin) of ALT[0], bit 1 of f goes in BIT(pin) of 5708c2ecf20Sopenharmony_ci * ALT[1] 5718c2ecf20Sopenharmony_ci * This is racy because both registers can't be updated at the same time 5728c2ecf20Sopenharmony_ci * but it doesn't matter much for now. 5738c2ecf20Sopenharmony_ci * Note: ALT0/ALT1 are organized specially for 64 gpio targets 5748c2ecf20Sopenharmony_ci */ 5758c2ecf20Sopenharmony_ci regmap_update_bits(info->map, REG_ALT(0, info, pin->pin), 5768c2ecf20Sopenharmony_ci BIT(p), f << p); 5778c2ecf20Sopenharmony_ci regmap_update_bits(info->map, REG_ALT(1, info, pin->pin), 5788c2ecf20Sopenharmony_ci BIT(p), (f >> 1) << p); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci return 0; 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci#define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32))) 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_cistatic int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev, 5868c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, 5878c2ecf20Sopenharmony_ci unsigned int pin, bool input) 5888c2ecf20Sopenharmony_ci{ 5898c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 5908c2ecf20Sopenharmony_ci unsigned int p = pin % 32; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci regmap_update_bits(info->map, REG(OCELOT_GPIO_OE, info, pin), BIT(p), 5938c2ecf20Sopenharmony_ci input ? 0 : BIT(p)); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci return 0; 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_cistatic int ocelot_gpio_request_enable(struct pinctrl_dev *pctldev, 5998c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, 6008c2ecf20Sopenharmony_ci unsigned int offset) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 6038c2ecf20Sopenharmony_ci unsigned int p = offset % 32; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci regmap_update_bits(info->map, REG_ALT(0, info, offset), 6068c2ecf20Sopenharmony_ci BIT(p), 0); 6078c2ecf20Sopenharmony_ci regmap_update_bits(info->map, REG_ALT(1, info, offset), 6088c2ecf20Sopenharmony_ci BIT(p), 0); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci return 0; 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_cistatic const struct pinmux_ops ocelot_pmx_ops = { 6148c2ecf20Sopenharmony_ci .get_functions_count = ocelot_get_functions_count, 6158c2ecf20Sopenharmony_ci .get_function_name = ocelot_get_function_name, 6168c2ecf20Sopenharmony_ci .get_function_groups = ocelot_get_function_groups, 6178c2ecf20Sopenharmony_ci .set_mux = ocelot_pinmux_set_mux, 6188c2ecf20Sopenharmony_ci .gpio_set_direction = ocelot_gpio_set_direction, 6198c2ecf20Sopenharmony_ci .gpio_request_enable = ocelot_gpio_request_enable, 6208c2ecf20Sopenharmony_ci}; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cistatic int ocelot_pctl_get_groups_count(struct pinctrl_dev *pctldev) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci return info->desc->npins; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic const char *ocelot_pctl_get_group_name(struct pinctrl_dev *pctldev, 6308c2ecf20Sopenharmony_ci unsigned int group) 6318c2ecf20Sopenharmony_ci{ 6328c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci return info->desc->pins[group].name; 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic int ocelot_pctl_get_group_pins(struct pinctrl_dev *pctldev, 6388c2ecf20Sopenharmony_ci unsigned int group, 6398c2ecf20Sopenharmony_ci const unsigned int **pins, 6408c2ecf20Sopenharmony_ci unsigned int *num_pins) 6418c2ecf20Sopenharmony_ci{ 6428c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci *pins = &info->desc->pins[group].number; 6458c2ecf20Sopenharmony_ci *num_pins = 1; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci return 0; 6488c2ecf20Sopenharmony_ci} 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_cistatic int ocelot_hw_get_value(struct ocelot_pinctrl *info, 6518c2ecf20Sopenharmony_ci unsigned int pin, 6528c2ecf20Sopenharmony_ci unsigned int reg, 6538c2ecf20Sopenharmony_ci int *val) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci int ret = -EOPNOTSUPP; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci if (info->pincfg) { 6588c2ecf20Sopenharmony_ci u32 regcfg = readl(info->pincfg + (pin * sizeof(u32))); 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci ret = 0; 6618c2ecf20Sopenharmony_ci switch (reg) { 6628c2ecf20Sopenharmony_ci case PINCONF_BIAS: 6638c2ecf20Sopenharmony_ci *val = regcfg & BIAS_BITS; 6648c2ecf20Sopenharmony_ci break; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci case PINCONF_SCHMITT: 6678c2ecf20Sopenharmony_ci *val = regcfg & SCHMITT_BIT; 6688c2ecf20Sopenharmony_ci break; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci case PINCONF_DRIVE_STRENGTH: 6718c2ecf20Sopenharmony_ci *val = regcfg & DRIVE_BITS; 6728c2ecf20Sopenharmony_ci break; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci default: 6758c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 6768c2ecf20Sopenharmony_ci break; 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci return ret; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_cistatic int ocelot_hw_set_value(struct ocelot_pinctrl *info, 6838c2ecf20Sopenharmony_ci unsigned int pin, 6848c2ecf20Sopenharmony_ci unsigned int reg, 6858c2ecf20Sopenharmony_ci int val) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci int ret = -EOPNOTSUPP; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci if (info->pincfg) { 6908c2ecf20Sopenharmony_ci void __iomem *regaddr = info->pincfg + (pin * sizeof(u32)); 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci ret = 0; 6938c2ecf20Sopenharmony_ci switch (reg) { 6948c2ecf20Sopenharmony_ci case PINCONF_BIAS: 6958c2ecf20Sopenharmony_ci ocelot_clrsetbits(regaddr, BIAS_BITS, val); 6968c2ecf20Sopenharmony_ci break; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci case PINCONF_SCHMITT: 6998c2ecf20Sopenharmony_ci ocelot_clrsetbits(regaddr, SCHMITT_BIT, val); 7008c2ecf20Sopenharmony_ci break; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci case PINCONF_DRIVE_STRENGTH: 7038c2ecf20Sopenharmony_ci if (val <= 3) 7048c2ecf20Sopenharmony_ci ocelot_clrsetbits(regaddr, DRIVE_BITS, val); 7058c2ecf20Sopenharmony_ci else 7068c2ecf20Sopenharmony_ci ret = -EINVAL; 7078c2ecf20Sopenharmony_ci break; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci default: 7108c2ecf20Sopenharmony_ci ret = -EOPNOTSUPP; 7118c2ecf20Sopenharmony_ci break; 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci return ret; 7158c2ecf20Sopenharmony_ci} 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_cistatic int ocelot_pinconf_get(struct pinctrl_dev *pctldev, 7188c2ecf20Sopenharmony_ci unsigned int pin, unsigned long *config) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 7218c2ecf20Sopenharmony_ci u32 param = pinconf_to_config_param(*config); 7228c2ecf20Sopenharmony_ci int val, err; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci switch (param) { 7258c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 7268c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 7278c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 7288c2ecf20Sopenharmony_ci err = ocelot_hw_get_value(info, pin, PINCONF_BIAS, &val); 7298c2ecf20Sopenharmony_ci if (err) 7308c2ecf20Sopenharmony_ci return err; 7318c2ecf20Sopenharmony_ci if (param == PIN_CONFIG_BIAS_DISABLE) 7328c2ecf20Sopenharmony_ci val = (val == 0 ? true : false); 7338c2ecf20Sopenharmony_ci else if (param == PIN_CONFIG_BIAS_PULL_DOWN) 7348c2ecf20Sopenharmony_ci val = (val & BIAS_PD_BIT ? true : false); 7358c2ecf20Sopenharmony_ci else /* PIN_CONFIG_BIAS_PULL_UP */ 7368c2ecf20Sopenharmony_ci val = (val & BIAS_PU_BIT ? true : false); 7378c2ecf20Sopenharmony_ci break; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 7408c2ecf20Sopenharmony_ci err = ocelot_hw_get_value(info, pin, PINCONF_SCHMITT, &val); 7418c2ecf20Sopenharmony_ci if (err) 7428c2ecf20Sopenharmony_ci return err; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci val = (val & SCHMITT_BIT ? true : false); 7458c2ecf20Sopenharmony_ci break; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci case PIN_CONFIG_DRIVE_STRENGTH: 7488c2ecf20Sopenharmony_ci err = ocelot_hw_get_value(info, pin, PINCONF_DRIVE_STRENGTH, 7498c2ecf20Sopenharmony_ci &val); 7508c2ecf20Sopenharmony_ci if (err) 7518c2ecf20Sopenharmony_ci return err; 7528c2ecf20Sopenharmony_ci break; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT: 7558c2ecf20Sopenharmony_ci err = regmap_read(info->map, REG(OCELOT_GPIO_OUT, info, pin), 7568c2ecf20Sopenharmony_ci &val); 7578c2ecf20Sopenharmony_ci if (err) 7588c2ecf20Sopenharmony_ci return err; 7598c2ecf20Sopenharmony_ci val = !!(val & BIT(pin % 32)); 7608c2ecf20Sopenharmony_ci break; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_ENABLE: 7638c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT_ENABLE: 7648c2ecf20Sopenharmony_ci err = regmap_read(info->map, REG(OCELOT_GPIO_OE, info, pin), 7658c2ecf20Sopenharmony_ci &val); 7668c2ecf20Sopenharmony_ci if (err) 7678c2ecf20Sopenharmony_ci return err; 7688c2ecf20Sopenharmony_ci val = val & BIT(pin % 32); 7698c2ecf20Sopenharmony_ci if (param == PIN_CONFIG_OUTPUT_ENABLE) 7708c2ecf20Sopenharmony_ci val = !!val; 7718c2ecf20Sopenharmony_ci else 7728c2ecf20Sopenharmony_ci val = !val; 7738c2ecf20Sopenharmony_ci break; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci default: 7768c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci *config = pinconf_to_config_packed(param, val); 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci return 0; 7828c2ecf20Sopenharmony_ci} 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_cistatic int ocelot_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 7858c2ecf20Sopenharmony_ci unsigned long *configs, unsigned int num_configs) 7868c2ecf20Sopenharmony_ci{ 7878c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 7888c2ecf20Sopenharmony_ci u32 param, arg, p; 7898c2ecf20Sopenharmony_ci int cfg, err = 0; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci for (cfg = 0; cfg < num_configs; cfg++) { 7928c2ecf20Sopenharmony_ci param = pinconf_to_config_param(configs[cfg]); 7938c2ecf20Sopenharmony_ci arg = pinconf_to_config_argument(configs[cfg]); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci switch (param) { 7968c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 7978c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 7988c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 7998c2ecf20Sopenharmony_ci arg = (param == PIN_CONFIG_BIAS_DISABLE) ? 0 : 8008c2ecf20Sopenharmony_ci (param == PIN_CONFIG_BIAS_PULL_UP) ? BIAS_PU_BIT : 8018c2ecf20Sopenharmony_ci BIAS_PD_BIT; 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci err = ocelot_hw_set_value(info, pin, PINCONF_BIAS, arg); 8048c2ecf20Sopenharmony_ci if (err) 8058c2ecf20Sopenharmony_ci goto err; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci break; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 8108c2ecf20Sopenharmony_ci arg = arg ? SCHMITT_BIT : 0; 8118c2ecf20Sopenharmony_ci err = ocelot_hw_set_value(info, pin, PINCONF_SCHMITT, 8128c2ecf20Sopenharmony_ci arg); 8138c2ecf20Sopenharmony_ci if (err) 8148c2ecf20Sopenharmony_ci goto err; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci break; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci case PIN_CONFIG_DRIVE_STRENGTH: 8198c2ecf20Sopenharmony_ci err = ocelot_hw_set_value(info, pin, 8208c2ecf20Sopenharmony_ci PINCONF_DRIVE_STRENGTH, 8218c2ecf20Sopenharmony_ci arg); 8228c2ecf20Sopenharmony_ci if (err) 8238c2ecf20Sopenharmony_ci goto err; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci break; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT_ENABLE: 8288c2ecf20Sopenharmony_ci case PIN_CONFIG_INPUT_ENABLE: 8298c2ecf20Sopenharmony_ci case PIN_CONFIG_OUTPUT: 8308c2ecf20Sopenharmony_ci p = pin % 32; 8318c2ecf20Sopenharmony_ci if (arg) 8328c2ecf20Sopenharmony_ci regmap_write(info->map, 8338c2ecf20Sopenharmony_ci REG(OCELOT_GPIO_OUT_SET, info, 8348c2ecf20Sopenharmony_ci pin), 8358c2ecf20Sopenharmony_ci BIT(p)); 8368c2ecf20Sopenharmony_ci else 8378c2ecf20Sopenharmony_ci regmap_write(info->map, 8388c2ecf20Sopenharmony_ci REG(OCELOT_GPIO_OUT_CLR, info, 8398c2ecf20Sopenharmony_ci pin), 8408c2ecf20Sopenharmony_ci BIT(p)); 8418c2ecf20Sopenharmony_ci regmap_update_bits(info->map, 8428c2ecf20Sopenharmony_ci REG(OCELOT_GPIO_OE, info, pin), 8438c2ecf20Sopenharmony_ci BIT(p), 8448c2ecf20Sopenharmony_ci param == PIN_CONFIG_INPUT_ENABLE ? 8458c2ecf20Sopenharmony_ci 0 : BIT(p)); 8468c2ecf20Sopenharmony_ci break; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci default: 8498c2ecf20Sopenharmony_ci err = -EOPNOTSUPP; 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_cierr: 8538c2ecf20Sopenharmony_ci return err; 8548c2ecf20Sopenharmony_ci} 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_cistatic const struct pinconf_ops ocelot_confops = { 8578c2ecf20Sopenharmony_ci .is_generic = true, 8588c2ecf20Sopenharmony_ci .pin_config_get = ocelot_pinconf_get, 8598c2ecf20Sopenharmony_ci .pin_config_set = ocelot_pinconf_set, 8608c2ecf20Sopenharmony_ci .pin_config_config_dbg_show = pinconf_generic_dump_config, 8618c2ecf20Sopenharmony_ci}; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_cistatic const struct pinctrl_ops ocelot_pctl_ops = { 8648c2ecf20Sopenharmony_ci .get_groups_count = ocelot_pctl_get_groups_count, 8658c2ecf20Sopenharmony_ci .get_group_name = ocelot_pctl_get_group_name, 8668c2ecf20Sopenharmony_ci .get_group_pins = ocelot_pctl_get_group_pins, 8678c2ecf20Sopenharmony_ci .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 8688c2ecf20Sopenharmony_ci .dt_free_map = pinconf_generic_dt_free_map, 8698c2ecf20Sopenharmony_ci}; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_cistatic struct pinctrl_desc ocelot_desc = { 8728c2ecf20Sopenharmony_ci .name = "ocelot-pinctrl", 8738c2ecf20Sopenharmony_ci .pins = ocelot_pins, 8748c2ecf20Sopenharmony_ci .npins = ARRAY_SIZE(ocelot_pins), 8758c2ecf20Sopenharmony_ci .pctlops = &ocelot_pctl_ops, 8768c2ecf20Sopenharmony_ci .pmxops = &ocelot_pmx_ops, 8778c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 8788c2ecf20Sopenharmony_ci}; 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_cistatic struct pinctrl_desc jaguar2_desc = { 8818c2ecf20Sopenharmony_ci .name = "jaguar2-pinctrl", 8828c2ecf20Sopenharmony_ci .pins = jaguar2_pins, 8838c2ecf20Sopenharmony_ci .npins = ARRAY_SIZE(jaguar2_pins), 8848c2ecf20Sopenharmony_ci .pctlops = &ocelot_pctl_ops, 8858c2ecf20Sopenharmony_ci .pmxops = &ocelot_pmx_ops, 8868c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 8878c2ecf20Sopenharmony_ci}; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_cistatic struct pinctrl_desc sparx5_desc = { 8908c2ecf20Sopenharmony_ci .name = "sparx5-pinctrl", 8918c2ecf20Sopenharmony_ci .pins = sparx5_pins, 8928c2ecf20Sopenharmony_ci .npins = ARRAY_SIZE(sparx5_pins), 8938c2ecf20Sopenharmony_ci .pctlops = &ocelot_pctl_ops, 8948c2ecf20Sopenharmony_ci .pmxops = &ocelot_pmx_ops, 8958c2ecf20Sopenharmony_ci .confops = &ocelot_confops, 8968c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 8978c2ecf20Sopenharmony_ci}; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_cistatic int ocelot_create_group_func_map(struct device *dev, 9008c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info) 9018c2ecf20Sopenharmony_ci{ 9028c2ecf20Sopenharmony_ci int f, npins, i; 9038c2ecf20Sopenharmony_ci u8 *pins = kcalloc(info->desc->npins, sizeof(u8), GFP_KERNEL); 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci if (!pins) 9068c2ecf20Sopenharmony_ci return -ENOMEM; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci for (f = 0; f < FUNC_MAX; f++) { 9098c2ecf20Sopenharmony_ci for (npins = 0, i = 0; i < info->desc->npins; i++) { 9108c2ecf20Sopenharmony_ci if (ocelot_pin_function_idx(info, i, f) >= 0) 9118c2ecf20Sopenharmony_ci pins[npins++] = i; 9128c2ecf20Sopenharmony_ci } 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci if (!npins) 9158c2ecf20Sopenharmony_ci continue; 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci info->func[f].ngroups = npins; 9188c2ecf20Sopenharmony_ci info->func[f].groups = devm_kcalloc(dev, npins, sizeof(char *), 9198c2ecf20Sopenharmony_ci GFP_KERNEL); 9208c2ecf20Sopenharmony_ci if (!info->func[f].groups) { 9218c2ecf20Sopenharmony_ci kfree(pins); 9228c2ecf20Sopenharmony_ci return -ENOMEM; 9238c2ecf20Sopenharmony_ci } 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci for (i = 0; i < npins; i++) 9268c2ecf20Sopenharmony_ci info->func[f].groups[i] = 9278c2ecf20Sopenharmony_ci info->desc->pins[pins[i]].name; 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci kfree(pins); 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci return 0; 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic int ocelot_pinctrl_register(struct platform_device *pdev, 9368c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info) 9378c2ecf20Sopenharmony_ci{ 9388c2ecf20Sopenharmony_ci int ret; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci ret = ocelot_create_group_func_map(&pdev->dev, info); 9418c2ecf20Sopenharmony_ci if (ret) { 9428c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to create group func map.\n"); 9438c2ecf20Sopenharmony_ci return ret; 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci info->pctl = devm_pinctrl_register(&pdev->dev, info->desc, info); 9478c2ecf20Sopenharmony_ci if (IS_ERR(info->pctl)) { 9488c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Failed to register pinctrl\n"); 9498c2ecf20Sopenharmony_ci return PTR_ERR(info->pctl); 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci return 0; 9538c2ecf20Sopenharmony_ci} 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_cistatic int ocelot_gpio_get(struct gpio_chip *chip, unsigned int offset) 9568c2ecf20Sopenharmony_ci{ 9578c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 9588c2ecf20Sopenharmony_ci unsigned int val; 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci regmap_read(info->map, REG(OCELOT_GPIO_IN, info, offset), &val); 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci return !!(val & BIT(offset % 32)); 9638c2ecf20Sopenharmony_ci} 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_cistatic void ocelot_gpio_set(struct gpio_chip *chip, unsigned int offset, 9668c2ecf20Sopenharmony_ci int value) 9678c2ecf20Sopenharmony_ci{ 9688c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci if (value) 9718c2ecf20Sopenharmony_ci regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset), 9728c2ecf20Sopenharmony_ci BIT(offset % 32)); 9738c2ecf20Sopenharmony_ci else 9748c2ecf20Sopenharmony_ci regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset), 9758c2ecf20Sopenharmony_ci BIT(offset % 32)); 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cistatic int ocelot_gpio_get_direction(struct gpio_chip *chip, 9798c2ecf20Sopenharmony_ci unsigned int offset) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 9828c2ecf20Sopenharmony_ci unsigned int val; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci regmap_read(info->map, REG(OCELOT_GPIO_OE, info, offset), &val); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci if (val & BIT(offset % 32)) 9878c2ecf20Sopenharmony_ci return GPIO_LINE_DIRECTION_OUT; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci return GPIO_LINE_DIRECTION_IN; 9908c2ecf20Sopenharmony_ci} 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_cistatic int ocelot_gpio_direction_input(struct gpio_chip *chip, 9938c2ecf20Sopenharmony_ci unsigned int offset) 9948c2ecf20Sopenharmony_ci{ 9958c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_input(chip->base + offset); 9968c2ecf20Sopenharmony_ci} 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_cistatic int ocelot_gpio_direction_output(struct gpio_chip *chip, 9998c2ecf20Sopenharmony_ci unsigned int offset, int value) 10008c2ecf20Sopenharmony_ci{ 10018c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 10028c2ecf20Sopenharmony_ci unsigned int pin = BIT(offset % 32); 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci if (value) 10058c2ecf20Sopenharmony_ci regmap_write(info->map, REG(OCELOT_GPIO_OUT_SET, info, offset), 10068c2ecf20Sopenharmony_ci pin); 10078c2ecf20Sopenharmony_ci else 10088c2ecf20Sopenharmony_ci regmap_write(info->map, REG(OCELOT_GPIO_OUT_CLR, info, offset), 10098c2ecf20Sopenharmony_ci pin); 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_output(chip->base + offset); 10128c2ecf20Sopenharmony_ci} 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cistatic const struct gpio_chip ocelot_gpiolib_chip = { 10158c2ecf20Sopenharmony_ci .request = gpiochip_generic_request, 10168c2ecf20Sopenharmony_ci .free = gpiochip_generic_free, 10178c2ecf20Sopenharmony_ci .set = ocelot_gpio_set, 10188c2ecf20Sopenharmony_ci .get = ocelot_gpio_get, 10198c2ecf20Sopenharmony_ci .get_direction = ocelot_gpio_get_direction, 10208c2ecf20Sopenharmony_ci .direction_input = ocelot_gpio_direction_input, 10218c2ecf20Sopenharmony_ci .direction_output = ocelot_gpio_direction_output, 10228c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 10238c2ecf20Sopenharmony_ci}; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_cistatic void ocelot_irq_mask(struct irq_data *data) 10268c2ecf20Sopenharmony_ci{ 10278c2ecf20Sopenharmony_ci struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 10288c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 10298c2ecf20Sopenharmony_ci unsigned int gpio = irqd_to_hwirq(data); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 10328c2ecf20Sopenharmony_ci BIT(gpio % 32), 0); 10338c2ecf20Sopenharmony_ci} 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_cistatic void ocelot_irq_unmask(struct irq_data *data) 10368c2ecf20Sopenharmony_ci{ 10378c2ecf20Sopenharmony_ci struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 10388c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 10398c2ecf20Sopenharmony_ci unsigned int gpio = irqd_to_hwirq(data); 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 10428c2ecf20Sopenharmony_ci BIT(gpio % 32), BIT(gpio % 32)); 10438c2ecf20Sopenharmony_ci} 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_cistatic void ocelot_irq_ack(struct irq_data *data) 10468c2ecf20Sopenharmony_ci{ 10478c2ecf20Sopenharmony_ci struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 10488c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 10498c2ecf20Sopenharmony_ci unsigned int gpio = irqd_to_hwirq(data); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci regmap_write_bits(info->map, REG(OCELOT_GPIO_INTR, info, gpio), 10528c2ecf20Sopenharmony_ci BIT(gpio % 32), BIT(gpio % 32)); 10538c2ecf20Sopenharmony_ci} 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_cistatic int ocelot_irq_set_type(struct irq_data *data, unsigned int type); 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_cistatic struct irq_chip ocelot_eoi_irqchip = { 10588c2ecf20Sopenharmony_ci .name = "gpio", 10598c2ecf20Sopenharmony_ci .irq_mask = ocelot_irq_mask, 10608c2ecf20Sopenharmony_ci .irq_eoi = ocelot_irq_ack, 10618c2ecf20Sopenharmony_ci .irq_unmask = ocelot_irq_unmask, 10628c2ecf20Sopenharmony_ci .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, 10638c2ecf20Sopenharmony_ci .irq_set_type = ocelot_irq_set_type, 10648c2ecf20Sopenharmony_ci}; 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_cistatic struct irq_chip ocelot_irqchip = { 10678c2ecf20Sopenharmony_ci .name = "gpio", 10688c2ecf20Sopenharmony_ci .irq_mask = ocelot_irq_mask, 10698c2ecf20Sopenharmony_ci .irq_ack = ocelot_irq_ack, 10708c2ecf20Sopenharmony_ci .irq_unmask = ocelot_irq_unmask, 10718c2ecf20Sopenharmony_ci .irq_set_type = ocelot_irq_set_type, 10728c2ecf20Sopenharmony_ci}; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_cistatic int ocelot_irq_set_type(struct irq_data *data, unsigned int type) 10758c2ecf20Sopenharmony_ci{ 10768c2ecf20Sopenharmony_ci type &= IRQ_TYPE_SENSE_MASK; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (!(type & (IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_HIGH))) 10798c2ecf20Sopenharmony_ci return -EINVAL; 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci if (type & IRQ_TYPE_LEVEL_HIGH) 10828c2ecf20Sopenharmony_ci irq_set_chip_handler_name_locked(data, &ocelot_eoi_irqchip, 10838c2ecf20Sopenharmony_ci handle_fasteoi_irq, NULL); 10848c2ecf20Sopenharmony_ci if (type & IRQ_TYPE_EDGE_BOTH) 10858c2ecf20Sopenharmony_ci irq_set_chip_handler_name_locked(data, &ocelot_irqchip, 10868c2ecf20Sopenharmony_ci handle_edge_irq, NULL); 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci return 0; 10898c2ecf20Sopenharmony_ci} 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_cistatic void ocelot_irq_handler(struct irq_desc *desc) 10928c2ecf20Sopenharmony_ci{ 10938c2ecf20Sopenharmony_ci struct irq_chip *parent_chip = irq_desc_get_chip(desc); 10948c2ecf20Sopenharmony_ci struct gpio_chip *chip = irq_desc_get_handler_data(desc); 10958c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info = gpiochip_get_data(chip); 10968c2ecf20Sopenharmony_ci unsigned int id_reg = OCELOT_GPIO_INTR_IDENT * info->stride; 10978c2ecf20Sopenharmony_ci unsigned int reg = 0, irq, i; 10988c2ecf20Sopenharmony_ci unsigned long irqs; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci for (i = 0; i < info->stride; i++) { 11018c2ecf20Sopenharmony_ci regmap_read(info->map, id_reg + 4 * i, ®); 11028c2ecf20Sopenharmony_ci if (!reg) 11038c2ecf20Sopenharmony_ci continue; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci chained_irq_enter(parent_chip, desc); 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci irqs = reg; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci for_each_set_bit(irq, &irqs, 11108c2ecf20Sopenharmony_ci min(32U, info->desc->npins - 32 * i)) 11118c2ecf20Sopenharmony_ci generic_handle_irq(irq_linear_revmap(chip->irq.domain, 11128c2ecf20Sopenharmony_ci irq + 32 * i)); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci chained_irq_exit(parent_chip, desc); 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci} 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_cistatic int ocelot_gpiochip_register(struct platform_device *pdev, 11198c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info) 11208c2ecf20Sopenharmony_ci{ 11218c2ecf20Sopenharmony_ci struct gpio_chip *gc; 11228c2ecf20Sopenharmony_ci struct gpio_irq_chip *girq; 11238c2ecf20Sopenharmony_ci int irq; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci info->gpio_chip = ocelot_gpiolib_chip; 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci gc = &info->gpio_chip; 11288c2ecf20Sopenharmony_ci gc->ngpio = info->desc->npins; 11298c2ecf20Sopenharmony_ci gc->parent = &pdev->dev; 11308c2ecf20Sopenharmony_ci gc->base = 0; 11318c2ecf20Sopenharmony_ci gc->of_node = info->dev->of_node; 11328c2ecf20Sopenharmony_ci gc->label = "ocelot-gpio"; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci irq = irq_of_parse_and_map(gc->of_node, 0); 11358c2ecf20Sopenharmony_ci if (irq) { 11368c2ecf20Sopenharmony_ci girq = &gc->irq; 11378c2ecf20Sopenharmony_ci girq->chip = &ocelot_irqchip; 11388c2ecf20Sopenharmony_ci girq->parent_handler = ocelot_irq_handler; 11398c2ecf20Sopenharmony_ci girq->num_parents = 1; 11408c2ecf20Sopenharmony_ci girq->parents = devm_kcalloc(&pdev->dev, 1, 11418c2ecf20Sopenharmony_ci sizeof(*girq->parents), 11428c2ecf20Sopenharmony_ci GFP_KERNEL); 11438c2ecf20Sopenharmony_ci if (!girq->parents) 11448c2ecf20Sopenharmony_ci return -ENOMEM; 11458c2ecf20Sopenharmony_ci girq->parents[0] = irq; 11468c2ecf20Sopenharmony_ci girq->default_type = IRQ_TYPE_NONE; 11478c2ecf20Sopenharmony_ci girq->handler = handle_edge_irq; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci return devm_gpiochip_add_data(&pdev->dev, gc, info); 11518c2ecf20Sopenharmony_ci} 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_cistatic const struct of_device_id ocelot_pinctrl_of_match[] = { 11548c2ecf20Sopenharmony_ci { .compatible = "mscc,ocelot-pinctrl", .data = &ocelot_desc }, 11558c2ecf20Sopenharmony_ci { .compatible = "mscc,jaguar2-pinctrl", .data = &jaguar2_desc }, 11568c2ecf20Sopenharmony_ci { .compatible = "microchip,sparx5-pinctrl", .data = &sparx5_desc }, 11578c2ecf20Sopenharmony_ci {}, 11588c2ecf20Sopenharmony_ci}; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_cistatic int ocelot_pinctrl_probe(struct platform_device *pdev) 11618c2ecf20Sopenharmony_ci{ 11628c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 11638c2ecf20Sopenharmony_ci struct ocelot_pinctrl *info; 11648c2ecf20Sopenharmony_ci void __iomem *base; 11658c2ecf20Sopenharmony_ci struct resource *res; 11668c2ecf20Sopenharmony_ci int ret; 11678c2ecf20Sopenharmony_ci struct regmap_config regmap_config = { 11688c2ecf20Sopenharmony_ci .reg_bits = 32, 11698c2ecf20Sopenharmony_ci .val_bits = 32, 11708c2ecf20Sopenharmony_ci .reg_stride = 4, 11718c2ecf20Sopenharmony_ci }; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 11748c2ecf20Sopenharmony_ci if (!info) 11758c2ecf20Sopenharmony_ci return -ENOMEM; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci info->desc = (struct pinctrl_desc *)device_get_match_data(dev); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci base = devm_ioremap_resource(dev, 11808c2ecf20Sopenharmony_ci platform_get_resource(pdev, IORESOURCE_MEM, 0)); 11818c2ecf20Sopenharmony_ci if (IS_ERR(base)) { 11828c2ecf20Sopenharmony_ci dev_err(dev, "Failed to ioremap registers\n"); 11838c2ecf20Sopenharmony_ci return PTR_ERR(base); 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci info->stride = 1 + (info->desc->npins - 1) / 32; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci info->map = devm_regmap_init_mmio(dev, base, ®map_config); 11918c2ecf20Sopenharmony_ci if (IS_ERR(info->map)) { 11928c2ecf20Sopenharmony_ci dev_err(dev, "Failed to create regmap\n"); 11938c2ecf20Sopenharmony_ci return PTR_ERR(info->map); 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci dev_set_drvdata(dev, info->map); 11968c2ecf20Sopenharmony_ci info->dev = dev; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci /* Pinconf registers */ 11998c2ecf20Sopenharmony_ci if (info->desc->confops) { 12008c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 12018c2ecf20Sopenharmony_ci base = devm_ioremap_resource(dev, res); 12028c2ecf20Sopenharmony_ci if (IS_ERR(base)) 12038c2ecf20Sopenharmony_ci dev_dbg(dev, "Failed to ioremap config registers (no extended pinconf)\n"); 12048c2ecf20Sopenharmony_ci else 12058c2ecf20Sopenharmony_ci info->pincfg = base; 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci ret = ocelot_pinctrl_register(pdev, info); 12098c2ecf20Sopenharmony_ci if (ret) 12108c2ecf20Sopenharmony_ci return ret; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci ret = ocelot_gpiochip_register(pdev, info); 12138c2ecf20Sopenharmony_ci if (ret) 12148c2ecf20Sopenharmony_ci return ret; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci dev_info(dev, "driver registered\n"); 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci return 0; 12198c2ecf20Sopenharmony_ci} 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_cistatic struct platform_driver ocelot_pinctrl_driver = { 12228c2ecf20Sopenharmony_ci .driver = { 12238c2ecf20Sopenharmony_ci .name = "pinctrl-ocelot", 12248c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(ocelot_pinctrl_of_match), 12258c2ecf20Sopenharmony_ci .suppress_bind_attrs = true, 12268c2ecf20Sopenharmony_ci }, 12278c2ecf20Sopenharmony_ci .probe = ocelot_pinctrl_probe, 12288c2ecf20Sopenharmony_ci}; 12298c2ecf20Sopenharmony_cibuiltin_platform_driver(ocelot_pinctrl_driver); 1230