162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Pinctrl / GPIO driver for StarFive JH7110 SoC aon controller 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2022 StarFive Technology Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/err.h> 962306a36Sopenharmony_ci#include <linux/gpio/driver.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/interrupt.h> 1262306a36Sopenharmony_ci#include <linux/io.h> 1362306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/pinctrl/pinconf.h> 1662306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 1762306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h> 1862306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 1962306a36Sopenharmony_ci#include <linux/platform_device.h> 2062306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2162306a36Sopenharmony_ci#include <linux/regmap.h> 2262306a36Sopenharmony_ci#include <linux/slab.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <dt-bindings/pinctrl/starfive,jh7110-pinctrl.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include "../core.h" 2762306a36Sopenharmony_ci#include "../pinconf.h" 2862306a36Sopenharmony_ci#include "../pinmux.h" 2962306a36Sopenharmony_ci#include "pinctrl-starfive-jh7110.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define JH7110_AON_NGPIO 4 3262306a36Sopenharmony_ci#define JH7110_AON_GC_BASE 64 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define JH7110_AON_REGS_NUM 37 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* registers */ 3762306a36Sopenharmony_ci#define JH7110_AON_DOEN 0x0 3862306a36Sopenharmony_ci#define JH7110_AON_DOUT 0x4 3962306a36Sopenharmony_ci#define JH7110_AON_GPI 0x8 4062306a36Sopenharmony_ci#define JH7110_AON_GPIOIN 0x2c 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define JH7110_AON_GPIOEN 0xc 4362306a36Sopenharmony_ci#define JH7110_AON_GPIOIS 0x10 4462306a36Sopenharmony_ci#define JH7110_AON_GPIOIC 0x14 4562306a36Sopenharmony_ci#define JH7110_AON_GPIOIBE 0x18 4662306a36Sopenharmony_ci#define JH7110_AON_GPIOIEV 0x1c 4762306a36Sopenharmony_ci#define JH7110_AON_GPIOIE 0x20 4862306a36Sopenharmony_ci#define JH7110_AON_GPIORIS 0x28 4962306a36Sopenharmony_ci#define JH7110_AON_GPIOMIS 0x28 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define JH7110_AON_GPO_PDA_0_5_CFG 0x30 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic const struct pinctrl_pin_desc jh7110_aon_pins[] = { 5462306a36Sopenharmony_ci PINCTRL_PIN(PAD_TESTEN, "TESTEN"), 5562306a36Sopenharmony_ci PINCTRL_PIN(PAD_RGPIO0, "RGPIO0"), 5662306a36Sopenharmony_ci PINCTRL_PIN(PAD_RGPIO1, "RGPIO1"), 5762306a36Sopenharmony_ci PINCTRL_PIN(PAD_RGPIO2, "RGPIO2"), 5862306a36Sopenharmony_ci PINCTRL_PIN(PAD_RGPIO3, "RGPIO3"), 5962306a36Sopenharmony_ci PINCTRL_PIN(PAD_RSTN, "RSTN"), 6062306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_MDC, "GMAC0_MDC"), 6162306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_MDIO, "GMAC0_MDIO"), 6262306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_RXD0, "GMAC0_RXD0"), 6362306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_RXD1, "GMAC0_RXD1"), 6462306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_RXD2, "GMAC0_RXD2"), 6562306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_RXD3, "GMAC0_RXD3"), 6662306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_RXDV, "GMAC0_RXDV"), 6762306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_RXC, "GMAC0_RXC"), 6862306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_TXD0, "GMAC0_TXD0"), 6962306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_TXD1, "GMAC0_TXD1"), 7062306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_TXD2, "GMAC0_TXD2"), 7162306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_TXD3, "GMAC0_TXD3"), 7262306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_TXEN, "GMAC0_TXEN"), 7362306a36Sopenharmony_ci PINCTRL_PIN(PAD_GMAC0_TXC, "GMAC0_TXC"), 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic int jh7110_aon_set_one_pin_mux(struct jh7110_pinctrl *sfp, 7762306a36Sopenharmony_ci unsigned int pin, 7862306a36Sopenharmony_ci unsigned int din, u32 dout, 7962306a36Sopenharmony_ci u32 doen, u32 func) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci if (pin < sfp->gc.ngpio && func == 0) 8262306a36Sopenharmony_ci jh7110_set_gpiomux(sfp, pin, din, dout, doen); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic int jh7110_aon_get_padcfg_base(struct jh7110_pinctrl *sfp, 8862306a36Sopenharmony_ci unsigned int pin) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci if (pin < PAD_GMAC0_MDC) 9162306a36Sopenharmony_ci return JH7110_AON_GPO_PDA_0_5_CFG; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci return -1; 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic void jh7110_aon_irq_handler(struct irq_desc *desc) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci struct jh7110_pinctrl *sfp = jh7110_from_irq_desc(desc); 9962306a36Sopenharmony_ci struct irq_chip *chip = irq_desc_get_chip(desc); 10062306a36Sopenharmony_ci unsigned long mis; 10162306a36Sopenharmony_ci unsigned int pin; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci chained_irq_enter(chip, desc); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci mis = readl_relaxed(sfp->base + JH7110_AON_GPIOMIS); 10662306a36Sopenharmony_ci for_each_set_bit(pin, &mis, JH7110_AON_NGPIO) 10762306a36Sopenharmony_ci generic_handle_domain_irq(sfp->gc.irq.domain, pin); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci chained_irq_exit(chip, desc); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic int jh7110_aon_init_hw(struct gpio_chip *gc) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct jh7110_pinctrl *sfp = container_of(gc, 11562306a36Sopenharmony_ci struct jh7110_pinctrl, gc); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* mask all GPIO interrupts */ 11862306a36Sopenharmony_ci writel_relaxed(0, sfp->base + JH7110_AON_GPIOIE); 11962306a36Sopenharmony_ci /* clear edge interrupt flags */ 12062306a36Sopenharmony_ci writel_relaxed(0, sfp->base + JH7110_AON_GPIOIC); 12162306a36Sopenharmony_ci writel_relaxed(0x0f, sfp->base + JH7110_AON_GPIOIC); 12262306a36Sopenharmony_ci /* enable GPIO interrupts */ 12362306a36Sopenharmony_ci writel_relaxed(1, sfp->base + JH7110_AON_GPIOEN); 12462306a36Sopenharmony_ci return 0; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic const struct jh7110_gpio_irq_reg jh7110_aon_irq_reg = { 12862306a36Sopenharmony_ci .is_reg_base = JH7110_AON_GPIOIS, 12962306a36Sopenharmony_ci .ic_reg_base = JH7110_AON_GPIOIC, 13062306a36Sopenharmony_ci .ibe_reg_base = JH7110_AON_GPIOIBE, 13162306a36Sopenharmony_ci .iev_reg_base = JH7110_AON_GPIOIEV, 13262306a36Sopenharmony_ci .ie_reg_base = JH7110_AON_GPIOIE, 13362306a36Sopenharmony_ci .ris_reg_base = JH7110_AON_GPIORIS, 13462306a36Sopenharmony_ci .mis_reg_base = JH7110_AON_GPIOMIS, 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic const struct jh7110_pinctrl_soc_info jh7110_aon_pinctrl_info = { 13862306a36Sopenharmony_ci .pins = jh7110_aon_pins, 13962306a36Sopenharmony_ci .npins = ARRAY_SIZE(jh7110_aon_pins), 14062306a36Sopenharmony_ci .ngpios = JH7110_AON_NGPIO, 14162306a36Sopenharmony_ci .gc_base = JH7110_AON_GC_BASE, 14262306a36Sopenharmony_ci .dout_reg_base = JH7110_AON_DOUT, 14362306a36Sopenharmony_ci .dout_mask = GENMASK(3, 0), 14462306a36Sopenharmony_ci .doen_reg_base = JH7110_AON_DOEN, 14562306a36Sopenharmony_ci .doen_mask = GENMASK(2, 0), 14662306a36Sopenharmony_ci .gpi_reg_base = JH7110_AON_GPI, 14762306a36Sopenharmony_ci .gpi_mask = GENMASK(3, 0), 14862306a36Sopenharmony_ci .gpioin_reg_base = JH7110_AON_GPIOIN, 14962306a36Sopenharmony_ci .irq_reg = &jh7110_aon_irq_reg, 15062306a36Sopenharmony_ci .nsaved_regs = JH7110_AON_REGS_NUM, 15162306a36Sopenharmony_ci .jh7110_set_one_pin_mux = jh7110_aon_set_one_pin_mux, 15262306a36Sopenharmony_ci .jh7110_get_padcfg_base = jh7110_aon_get_padcfg_base, 15362306a36Sopenharmony_ci .jh7110_gpio_irq_handler = jh7110_aon_irq_handler, 15462306a36Sopenharmony_ci .jh7110_gpio_init_hw = jh7110_aon_init_hw, 15562306a36Sopenharmony_ci}; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic const struct of_device_id jh7110_aon_pinctrl_of_match[] = { 15862306a36Sopenharmony_ci { 15962306a36Sopenharmony_ci .compatible = "starfive,jh7110-aon-pinctrl", 16062306a36Sopenharmony_ci .data = &jh7110_aon_pinctrl_info, 16162306a36Sopenharmony_ci }, 16262306a36Sopenharmony_ci { /* sentinel */ } 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, jh7110_aon_pinctrl_of_match); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic struct platform_driver jh7110_aon_pinctrl_driver = { 16762306a36Sopenharmony_ci .probe = jh7110_pinctrl_probe, 16862306a36Sopenharmony_ci .driver = { 16962306a36Sopenharmony_ci .name = "starfive-jh7110-aon-pinctrl", 17062306a36Sopenharmony_ci .of_match_table = jh7110_aon_pinctrl_of_match, 17162306a36Sopenharmony_ci .pm = pm_sleep_ptr(&jh7110_pinctrl_pm_ops), 17262306a36Sopenharmony_ci }, 17362306a36Sopenharmony_ci}; 17462306a36Sopenharmony_cimodule_platform_driver(jh7110_aon_pinctrl_driver); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciMODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC aon controller"); 17762306a36Sopenharmony_ciMODULE_AUTHOR("Jianlong Huang <jianlong.huang@starfivetech.com>"); 17862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 179