198944Sobrien// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause 298944Sobrien/* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */ 398944Sobrien 498944Sobrien#include <linux/bitfield.h> 598944Sobrien#include <linux/bitops.h> 698944Sobrien#include <linux/device.h> 798944Sobrien#include <linux/err.h> 898944Sobrien#include <linux/gpio/driver.h> 998944Sobrien#include <linux/interrupt.h> 1098944Sobrien#include <linux/io.h> 1198944Sobrien#include <linux/module.h> 1298944Sobrien#include <linux/platform_device.h> 1398944Sobrien#include <linux/spinlock.h> 1498944Sobrien#include <linux/types.h> 1598944Sobrien 1698944Sobrien/* 1798944Sobrien * There are 2 YU GPIO blocks: 1898944Sobrien * gpio[0]: HOST_GPIO0->HOST_GPIO31 1998944Sobrien * gpio[1]: HOST_GPIO32->HOST_GPIO55 2098944Sobrien */ 2198944Sobrien#define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32 2298944Sobrien#define MLXBF3_GPIO_MAX_PINS_BLOCK0 32 2398944Sobrien#define MLXBF3_GPIO_MAX_PINS_BLOCK1 24 2498944Sobrien 2598944Sobrien/* 2698944Sobrien * fw_gpio[x] block registers and their offset 2798944Sobrien */ 2898944Sobrien#define MLXBF_GPIO_FW_OUTPUT_ENABLE_SET 0x00 2998944Sobrien#define MLXBF_GPIO_FW_DATA_OUT_SET 0x04 3098944Sobrien 3198944Sobrien#define MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x00 3298944Sobrien#define MLXBF_GPIO_FW_DATA_OUT_CLEAR 0x04 3398944Sobrien 3498944Sobrien#define MLXBF_GPIO_CAUSE_RISE_EN 0x00 3598944Sobrien#define MLXBF_GPIO_CAUSE_FALL_EN 0x04 3698944Sobrien#define MLXBF_GPIO_READ_DATA_IN 0x08 3798944Sobrien 3898944Sobrien#define MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x00 3998944Sobrien#define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14 4098944Sobrien#define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18 4198944Sobrien 4298944Sobrienstruct mlxbf3_gpio_context { 4398944Sobrien struct gpio_chip gc; 4498944Sobrien 4598944Sobrien /* YU GPIO block address */ 4698944Sobrien void __iomem *gpio_set_io; 4798944Sobrien void __iomem *gpio_clr_io; 4898944Sobrien void __iomem *gpio_io; 4998944Sobrien 5098944Sobrien /* YU GPIO cause block address */ 5198944Sobrien void __iomem *gpio_cause_io; 5298944Sobrien}; 5398944Sobrien 5498944Sobrienstatic void mlxbf3_gpio_irq_enable(struct irq_data *irqd) 5598944Sobrien{ 5698944Sobrien struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 5798944Sobrien struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 5898944Sobrien irq_hw_number_t offset = irqd_to_hwirq(irqd); 5998944Sobrien unsigned long flags; 6098944Sobrien u32 val; 6198944Sobrien 6298944Sobrien gpiochip_enable_irq(gc, offset); 6398944Sobrien 6498944Sobrien raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 6598944Sobrien writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); 6698944Sobrien 6798944Sobrien val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 6898944Sobrien val |= BIT(offset); 6998944Sobrien writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 7098944Sobrien raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 7198944Sobrien} 7298944Sobrien 7398944Sobrienstatic void mlxbf3_gpio_irq_disable(struct irq_data *irqd) 7498944Sobrien{ 7598944Sobrien struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 7698944Sobrien struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 7798944Sobrien irq_hw_number_t offset = irqd_to_hwirq(irqd); 7898944Sobrien unsigned long flags; 7998944Sobrien u32 val; 8098944Sobrien 8198944Sobrien raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 8298944Sobrien val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 8398944Sobrien val &= ~BIT(offset); 8498944Sobrien writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 8598944Sobrien raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 8698944Sobrien 8798944Sobrien gpiochip_disable_irq(gc, offset); 8898944Sobrien} 8998944Sobrien 9098944Sobrienstatic irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr) 9198944Sobrien{ 9298944Sobrien struct mlxbf3_gpio_context *gs = ptr; 9398944Sobrien struct gpio_chip *gc = &gs->gc; 9498944Sobrien unsigned long pending; 9598944Sobrien u32 level; 9698944Sobrien 9798944Sobrien pending = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0); 9898944Sobrien writel(pending, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); 9998944Sobrien 10098944Sobrien for_each_set_bit(level, &pending, gc->ngpio) 10198944Sobrien generic_handle_domain_irq(gc->irq.domain, level); 10298944Sobrien 10398944Sobrien return IRQ_RETVAL(pending); 10498944Sobrien} 10598944Sobrien 10698944Sobrienstatic int 10798944Sobrienmlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) 10898944Sobrien{ 10998944Sobrien struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 11098944Sobrien struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 11198944Sobrien irq_hw_number_t offset = irqd_to_hwirq(irqd); 11298944Sobrien unsigned long flags; 11398944Sobrien u32 val; 11498944Sobrien 11598944Sobrien raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 11698944Sobrien 11798944Sobrien switch (type & IRQ_TYPE_SENSE_MASK) { 11898944Sobrien case IRQ_TYPE_EDGE_BOTH: 11998944Sobrien val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 12098944Sobrien val |= BIT(offset); 12198944Sobrien writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 12298944Sobrien val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 12398944Sobrien val |= BIT(offset); 12498944Sobrien writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 12598944Sobrien break; 12698944Sobrien case IRQ_TYPE_EDGE_RISING: 12798944Sobrien val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 12898944Sobrien val |= BIT(offset); 12998944Sobrien writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 13098944Sobrien break; 13198944Sobrien case IRQ_TYPE_EDGE_FALLING: 13298944Sobrien val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 13398944Sobrien val |= BIT(offset); 13498944Sobrien writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 13598944Sobrien break; 13698944Sobrien default: 13798944Sobrien raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 13898944Sobrien return -EINVAL; 13998944Sobrien } 14098944Sobrien 14198944Sobrien raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 14298944Sobrien 14398944Sobrien irq_set_handler_locked(irqd, handle_edge_irq); 14498944Sobrien 14598944Sobrien return 0; 14698944Sobrien} 14798944Sobrien 14898944Sobrien/* This function needs to be defined for handle_edge_irq() */ 14998944Sobrienstatic void mlxbf3_gpio_irq_ack(struct irq_data *data) 15098944Sobrien{ 15198944Sobrien} 15298944Sobrien 15398944Sobrienstatic const struct irq_chip gpio_mlxbf3_irqchip = { 15498944Sobrien .name = "MLNXBF33", 15598944Sobrien .irq_ack = mlxbf3_gpio_irq_ack, 15698944Sobrien .irq_set_type = mlxbf3_gpio_irq_set_type, 15798944Sobrien .irq_enable = mlxbf3_gpio_irq_enable, 15898944Sobrien .irq_disable = mlxbf3_gpio_irq_disable, 15998944Sobrien .flags = IRQCHIP_IMMUTABLE, 16098944Sobrien GPIOCHIP_IRQ_RESOURCE_HELPERS, 16198944Sobrien}; 16298944Sobrien 16398944Sobrienstatic int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip) 16498944Sobrien{ 16598944Sobrien unsigned int id; 16698944Sobrien 16798944Sobrien switch(chip->ngpio) { 16898944Sobrien case MLXBF3_GPIO_MAX_PINS_BLOCK0: 16998944Sobrien id = 0; 17098944Sobrien break; 17198944Sobrien case MLXBF3_GPIO_MAX_PINS_BLOCK1: 17298944Sobrien id = 1; 17398944Sobrien break; 17498944Sobrien default: 17598944Sobrien return -EINVAL; 17698944Sobrien } 17798944Sobrien 17898944Sobrien return gpiochip_add_pin_range(chip, "MLNXBF34:00", 17998944Sobrien chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK, 18098944Sobrien chip->ngpio); 18198944Sobrien} 18298944Sobrien 18398944Sobrienstatic int mlxbf3_gpio_probe(struct platform_device *pdev) 18498944Sobrien{ 18598944Sobrien struct device *dev = &pdev->dev; 18698944Sobrien struct mlxbf3_gpio_context *gs; 18798944Sobrien struct gpio_irq_chip *girq; 18898944Sobrien struct gpio_chip *gc; 18998944Sobrien int ret, irq; 19098944Sobrien 19198944Sobrien gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); 19298944Sobrien if (!gs) 19398944Sobrien return -ENOMEM; 19498944Sobrien 19598944Sobrien gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); 19698944Sobrien if (IS_ERR(gs->gpio_io)) 19798944Sobrien return PTR_ERR(gs->gpio_io); 19898944Sobrien 19998944Sobrien gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1); 20098944Sobrien if (IS_ERR(gs->gpio_cause_io)) 20198944Sobrien return PTR_ERR(gs->gpio_cause_io); 20298944Sobrien 20398944Sobrien gs->gpio_set_io = devm_platform_ioremap_resource(pdev, 2); 20498944Sobrien if (IS_ERR(gs->gpio_set_io)) 20598944Sobrien return PTR_ERR(gs->gpio_set_io); 20698944Sobrien 20798944Sobrien gs->gpio_clr_io = devm_platform_ioremap_resource(pdev, 3); 20898944Sobrien if (IS_ERR(gs->gpio_clr_io)) 20998944Sobrien return PTR_ERR(gs->gpio_clr_io); 21098944Sobrien gc = &gs->gc; 21198944Sobrien 21298944Sobrien ret = bgpio_init(gc, dev, 4, 21398944Sobrien gs->gpio_io + MLXBF_GPIO_READ_DATA_IN, 21498944Sobrien gs->gpio_set_io + MLXBF_GPIO_FW_DATA_OUT_SET, 21598944Sobrien gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR, 21698944Sobrien gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET, 21798944Sobrien gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0); 21898944Sobrien if (ret) 21998944Sobrien return dev_err_probe(dev, ret, "%s: bgpio_init() failed", __func__); 22098944Sobrien 22198944Sobrien gc->request = gpiochip_generic_request; 22298944Sobrien gc->free = gpiochip_generic_free; 22398944Sobrien gc->owner = THIS_MODULE; 22498944Sobrien gc->add_pin_ranges = mlxbf3_gpio_add_pin_ranges; 22598944Sobrien 22698944Sobrien irq = platform_get_irq(pdev, 0); 22798944Sobrien if (irq >= 0) { 22898944Sobrien girq = &gs->gc.irq; 22998944Sobrien gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip); 23098944Sobrien girq->default_type = IRQ_TYPE_NONE; 23198944Sobrien /* This will let us handle the parent IRQ in the driver */ 23298944Sobrien girq->num_parents = 0; 23398944Sobrien girq->parents = NULL; 23498944Sobrien girq->parent_handler = NULL; 23598944Sobrien girq->handler = handle_bad_irq; 23698944Sobrien 23798944Sobrien /* 23898944Sobrien * Directly request the irq here instead of passing 23998944Sobrien * a flow-handler because the irq is shared. 24098944Sobrien */ 24198944Sobrien ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler, 24298944Sobrien IRQF_SHARED, dev_name(dev), gs); 24398944Sobrien if (ret) 24498944Sobrien return dev_err_probe(dev, ret, "failed to request IRQ"); 24598944Sobrien } 24698944Sobrien 24798944Sobrien platform_set_drvdata(pdev, gs); 24898944Sobrien 24998944Sobrien ret = devm_gpiochip_add_data(dev, &gs->gc, gs); 25098944Sobrien if (ret) 25198944Sobrien dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n"); 25298944Sobrien 25398944Sobrien return 0; 25498944Sobrien} 25598944Sobrien 25698944Sobrienstatic const struct acpi_device_id mlxbf3_gpio_acpi_match[] = { 25798944Sobrien { "MLNXBF33", 0 }, 25898944Sobrien {} 25998944Sobrien}; 26098944SobrienMODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match); 26198944Sobrien 26298944Sobrienstatic struct platform_driver mlxbf3_gpio_driver = { 26398944Sobrien .driver = { 26498944Sobrien .name = "mlxbf3_gpio", 26598944Sobrien .acpi_match_table = mlxbf3_gpio_acpi_match, 26698944Sobrien }, 26798944Sobrien .probe = mlxbf3_gpio_probe, 26898944Sobrien}; 26998944Sobrienmodule_platform_driver(mlxbf3_gpio_driver); 27098944Sobrien 27198944SobrienMODULE_SOFTDEP("pre: pinctrl-mlxbf3"); 27298944SobrienMODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver"); 27398944SobrienMODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>"); 27498944SobrienMODULE_LICENSE("Dual BSD/GPL"); 27598944Sobrien