1*cd33f216SAsmaa Mnebhi // SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause 2*cd33f216SAsmaa Mnebhi /* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */ 3*cd33f216SAsmaa Mnebhi 4*cd33f216SAsmaa Mnebhi #include <linux/bitfield.h> 5*cd33f216SAsmaa Mnebhi #include <linux/bitops.h> 6*cd33f216SAsmaa Mnebhi #include <linux/device.h> 7*cd33f216SAsmaa Mnebhi #include <linux/err.h> 8*cd33f216SAsmaa Mnebhi #include <linux/gpio/driver.h> 9*cd33f216SAsmaa Mnebhi #include <linux/interrupt.h> 10*cd33f216SAsmaa Mnebhi #include <linux/io.h> 11*cd33f216SAsmaa Mnebhi #include <linux/module.h> 12*cd33f216SAsmaa Mnebhi #include <linux/platform_device.h> 13*cd33f216SAsmaa Mnebhi #include <linux/spinlock.h> 14*cd33f216SAsmaa Mnebhi #include <linux/types.h> 15*cd33f216SAsmaa Mnebhi 16*cd33f216SAsmaa Mnebhi /* 17*cd33f216SAsmaa Mnebhi * There are 2 YU GPIO blocks: 18*cd33f216SAsmaa Mnebhi * gpio[0]: HOST_GPIO0->HOST_GPIO31 19*cd33f216SAsmaa Mnebhi * gpio[1]: HOST_GPIO32->HOST_GPIO55 20*cd33f216SAsmaa Mnebhi */ 21*cd33f216SAsmaa Mnebhi #define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32 22*cd33f216SAsmaa Mnebhi 23*cd33f216SAsmaa Mnebhi /* 24*cd33f216SAsmaa Mnebhi * fw_gpio[x] block registers and their offset 25*cd33f216SAsmaa Mnebhi */ 26*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_OUTPUT_ENABLE_SET 0x00 27*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_DATA_OUT_SET 0x04 28*cd33f216SAsmaa Mnebhi 29*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x00 30*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_DATA_OUT_CLEAR 0x04 31*cd33f216SAsmaa Mnebhi 32*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_RISE_EN 0x00 33*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_FALL_EN 0x04 34*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_READ_DATA_IN 0x08 35*cd33f216SAsmaa Mnebhi 36*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x00 37*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_OR_EVTEN0 0x14 38*cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_OR_CLRCAUSE 0x18 39*cd33f216SAsmaa Mnebhi 40*cd33f216SAsmaa Mnebhi struct mlxbf3_gpio_context { 41*cd33f216SAsmaa Mnebhi struct gpio_chip gc; 42*cd33f216SAsmaa Mnebhi 43*cd33f216SAsmaa Mnebhi /* YU GPIO block address */ 44*cd33f216SAsmaa Mnebhi void __iomem *gpio_set_io; 45*cd33f216SAsmaa Mnebhi void __iomem *gpio_clr_io; 46*cd33f216SAsmaa Mnebhi void __iomem *gpio_io; 47*cd33f216SAsmaa Mnebhi 48*cd33f216SAsmaa Mnebhi /* YU GPIO cause block address */ 49*cd33f216SAsmaa Mnebhi void __iomem *gpio_cause_io; 50*cd33f216SAsmaa Mnebhi }; 51*cd33f216SAsmaa Mnebhi 52*cd33f216SAsmaa Mnebhi static void mlxbf3_gpio_irq_enable(struct irq_data *irqd) 53*cd33f216SAsmaa Mnebhi { 54*cd33f216SAsmaa Mnebhi struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 55*cd33f216SAsmaa Mnebhi struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 56*cd33f216SAsmaa Mnebhi irq_hw_number_t offset = irqd_to_hwirq(irqd); 57*cd33f216SAsmaa Mnebhi unsigned long flags; 58*cd33f216SAsmaa Mnebhi u32 val; 59*cd33f216SAsmaa Mnebhi 60*cd33f216SAsmaa Mnebhi gpiochip_enable_irq(gc, offset); 61*cd33f216SAsmaa Mnebhi 62*cd33f216SAsmaa Mnebhi raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 63*cd33f216SAsmaa Mnebhi writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); 64*cd33f216SAsmaa Mnebhi 65*cd33f216SAsmaa Mnebhi val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 66*cd33f216SAsmaa Mnebhi val |= BIT(offset); 67*cd33f216SAsmaa Mnebhi writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 68*cd33f216SAsmaa Mnebhi raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 69*cd33f216SAsmaa Mnebhi } 70*cd33f216SAsmaa Mnebhi 71*cd33f216SAsmaa Mnebhi static void mlxbf3_gpio_irq_disable(struct irq_data *irqd) 72*cd33f216SAsmaa Mnebhi { 73*cd33f216SAsmaa Mnebhi struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 74*cd33f216SAsmaa Mnebhi struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 75*cd33f216SAsmaa Mnebhi irq_hw_number_t offset = irqd_to_hwirq(irqd); 76*cd33f216SAsmaa Mnebhi unsigned long flags; 77*cd33f216SAsmaa Mnebhi u32 val; 78*cd33f216SAsmaa Mnebhi 79*cd33f216SAsmaa Mnebhi raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 80*cd33f216SAsmaa Mnebhi val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 81*cd33f216SAsmaa Mnebhi val &= ~BIT(offset); 82*cd33f216SAsmaa Mnebhi writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0); 83*cd33f216SAsmaa Mnebhi raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 84*cd33f216SAsmaa Mnebhi 85*cd33f216SAsmaa Mnebhi gpiochip_disable_irq(gc, offset); 86*cd33f216SAsmaa Mnebhi } 87*cd33f216SAsmaa Mnebhi 88*cd33f216SAsmaa Mnebhi static irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr) 89*cd33f216SAsmaa Mnebhi { 90*cd33f216SAsmaa Mnebhi struct mlxbf3_gpio_context *gs = ptr; 91*cd33f216SAsmaa Mnebhi struct gpio_chip *gc = &gs->gc; 92*cd33f216SAsmaa Mnebhi unsigned long pending; 93*cd33f216SAsmaa Mnebhi u32 level; 94*cd33f216SAsmaa Mnebhi 95*cd33f216SAsmaa Mnebhi pending = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0); 96*cd33f216SAsmaa Mnebhi writel(pending, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE); 97*cd33f216SAsmaa Mnebhi 98*cd33f216SAsmaa Mnebhi for_each_set_bit(level, &pending, gc->ngpio) 99*cd33f216SAsmaa Mnebhi generic_handle_domain_irq(gc->irq.domain, level); 100*cd33f216SAsmaa Mnebhi 101*cd33f216SAsmaa Mnebhi return IRQ_RETVAL(pending); 102*cd33f216SAsmaa Mnebhi } 103*cd33f216SAsmaa Mnebhi 104*cd33f216SAsmaa Mnebhi static int 105*cd33f216SAsmaa Mnebhi mlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) 106*cd33f216SAsmaa Mnebhi { 107*cd33f216SAsmaa Mnebhi struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd); 108*cd33f216SAsmaa Mnebhi struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc); 109*cd33f216SAsmaa Mnebhi irq_hw_number_t offset = irqd_to_hwirq(irqd); 110*cd33f216SAsmaa Mnebhi unsigned long flags; 111*cd33f216SAsmaa Mnebhi u32 val; 112*cd33f216SAsmaa Mnebhi 113*cd33f216SAsmaa Mnebhi raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags); 114*cd33f216SAsmaa Mnebhi 115*cd33f216SAsmaa Mnebhi switch (type & IRQ_TYPE_SENSE_MASK) { 116*cd33f216SAsmaa Mnebhi case IRQ_TYPE_EDGE_BOTH: 117*cd33f216SAsmaa Mnebhi val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 118*cd33f216SAsmaa Mnebhi val |= BIT(offset); 119*cd33f216SAsmaa Mnebhi writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 120*cd33f216SAsmaa Mnebhi val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 121*cd33f216SAsmaa Mnebhi val |= BIT(offset); 122*cd33f216SAsmaa Mnebhi writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 123*cd33f216SAsmaa Mnebhi break; 124*cd33f216SAsmaa Mnebhi case IRQ_TYPE_EDGE_RISING: 125*cd33f216SAsmaa Mnebhi val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 126*cd33f216SAsmaa Mnebhi val |= BIT(offset); 127*cd33f216SAsmaa Mnebhi writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN); 128*cd33f216SAsmaa Mnebhi break; 129*cd33f216SAsmaa Mnebhi case IRQ_TYPE_EDGE_FALLING: 130*cd33f216SAsmaa Mnebhi val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 131*cd33f216SAsmaa Mnebhi val |= BIT(offset); 132*cd33f216SAsmaa Mnebhi writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN); 133*cd33f216SAsmaa Mnebhi break; 134*cd33f216SAsmaa Mnebhi default: 135*cd33f216SAsmaa Mnebhi raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 136*cd33f216SAsmaa Mnebhi return -EINVAL; 137*cd33f216SAsmaa Mnebhi } 138*cd33f216SAsmaa Mnebhi 139*cd33f216SAsmaa Mnebhi raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); 140*cd33f216SAsmaa Mnebhi 141*cd33f216SAsmaa Mnebhi irq_set_handler_locked(irqd, handle_edge_irq); 142*cd33f216SAsmaa Mnebhi 143*cd33f216SAsmaa Mnebhi return 0; 144*cd33f216SAsmaa Mnebhi } 145*cd33f216SAsmaa Mnebhi 146*cd33f216SAsmaa Mnebhi /* This function needs to be defined for handle_edge_irq() */ 147*cd33f216SAsmaa Mnebhi static void mlxbf3_gpio_irq_ack(struct irq_data *data) 148*cd33f216SAsmaa Mnebhi { 149*cd33f216SAsmaa Mnebhi } 150*cd33f216SAsmaa Mnebhi 151*cd33f216SAsmaa Mnebhi static const struct irq_chip gpio_mlxbf3_irqchip = { 152*cd33f216SAsmaa Mnebhi .name = "MLNXBF33", 153*cd33f216SAsmaa Mnebhi .irq_ack = mlxbf3_gpio_irq_ack, 154*cd33f216SAsmaa Mnebhi .irq_set_type = mlxbf3_gpio_irq_set_type, 155*cd33f216SAsmaa Mnebhi .irq_enable = mlxbf3_gpio_irq_enable, 156*cd33f216SAsmaa Mnebhi .irq_disable = mlxbf3_gpio_irq_disable, 157*cd33f216SAsmaa Mnebhi .flags = IRQCHIP_IMMUTABLE, 158*cd33f216SAsmaa Mnebhi GPIOCHIP_IRQ_RESOURCE_HELPERS, 159*cd33f216SAsmaa Mnebhi }; 160*cd33f216SAsmaa Mnebhi 161*cd33f216SAsmaa Mnebhi static int mlxbf3_gpio_probe(struct platform_device *pdev) 162*cd33f216SAsmaa Mnebhi { 163*cd33f216SAsmaa Mnebhi struct device *dev = &pdev->dev; 164*cd33f216SAsmaa Mnebhi struct mlxbf3_gpio_context *gs; 165*cd33f216SAsmaa Mnebhi struct gpio_irq_chip *girq; 166*cd33f216SAsmaa Mnebhi struct gpio_chip *gc; 167*cd33f216SAsmaa Mnebhi int ret, irq; 168*cd33f216SAsmaa Mnebhi 169*cd33f216SAsmaa Mnebhi gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); 170*cd33f216SAsmaa Mnebhi if (!gs) 171*cd33f216SAsmaa Mnebhi return -ENOMEM; 172*cd33f216SAsmaa Mnebhi 173*cd33f216SAsmaa Mnebhi gs->gpio_io = devm_platform_ioremap_resource(pdev, 0); 174*cd33f216SAsmaa Mnebhi if (IS_ERR(gs->gpio_io)) 175*cd33f216SAsmaa Mnebhi return PTR_ERR(gs->gpio_io); 176*cd33f216SAsmaa Mnebhi 177*cd33f216SAsmaa Mnebhi gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1); 178*cd33f216SAsmaa Mnebhi if (IS_ERR(gs->gpio_cause_io)) 179*cd33f216SAsmaa Mnebhi return PTR_ERR(gs->gpio_cause_io); 180*cd33f216SAsmaa Mnebhi 181*cd33f216SAsmaa Mnebhi gs->gpio_set_io = devm_platform_ioremap_resource(pdev, 2); 182*cd33f216SAsmaa Mnebhi if (IS_ERR(gs->gpio_set_io)) 183*cd33f216SAsmaa Mnebhi return PTR_ERR(gs->gpio_set_io); 184*cd33f216SAsmaa Mnebhi 185*cd33f216SAsmaa Mnebhi gs->gpio_clr_io = devm_platform_ioremap_resource(pdev, 3); 186*cd33f216SAsmaa Mnebhi if (IS_ERR(gs->gpio_clr_io)) 187*cd33f216SAsmaa Mnebhi return PTR_ERR(gs->gpio_clr_io); 188*cd33f216SAsmaa Mnebhi gc = &gs->gc; 189*cd33f216SAsmaa Mnebhi 190*cd33f216SAsmaa Mnebhi ret = bgpio_init(gc, dev, 4, 191*cd33f216SAsmaa Mnebhi gs->gpio_io + MLXBF_GPIO_READ_DATA_IN, 192*cd33f216SAsmaa Mnebhi gs->gpio_set_io + MLXBF_GPIO_FW_DATA_OUT_SET, 193*cd33f216SAsmaa Mnebhi gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR, 194*cd33f216SAsmaa Mnebhi gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET, 195*cd33f216SAsmaa Mnebhi gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0); 196*cd33f216SAsmaa Mnebhi 197*cd33f216SAsmaa Mnebhi gc->request = gpiochip_generic_request; 198*cd33f216SAsmaa Mnebhi gc->free = gpiochip_generic_free; 199*cd33f216SAsmaa Mnebhi gc->owner = THIS_MODULE; 200*cd33f216SAsmaa Mnebhi 201*cd33f216SAsmaa Mnebhi irq = platform_get_irq(pdev, 0); 202*cd33f216SAsmaa Mnebhi if (irq >= 0) { 203*cd33f216SAsmaa Mnebhi girq = &gs->gc.irq; 204*cd33f216SAsmaa Mnebhi gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip); 205*cd33f216SAsmaa Mnebhi girq->default_type = IRQ_TYPE_NONE; 206*cd33f216SAsmaa Mnebhi /* This will let us handle the parent IRQ in the driver */ 207*cd33f216SAsmaa Mnebhi girq->num_parents = 0; 208*cd33f216SAsmaa Mnebhi girq->parents = NULL; 209*cd33f216SAsmaa Mnebhi girq->parent_handler = NULL; 210*cd33f216SAsmaa Mnebhi girq->handler = handle_bad_irq; 211*cd33f216SAsmaa Mnebhi 212*cd33f216SAsmaa Mnebhi /* 213*cd33f216SAsmaa Mnebhi * Directly request the irq here instead of passing 214*cd33f216SAsmaa Mnebhi * a flow-handler because the irq is shared. 215*cd33f216SAsmaa Mnebhi */ 216*cd33f216SAsmaa Mnebhi ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler, 217*cd33f216SAsmaa Mnebhi IRQF_SHARED, dev_name(dev), gs); 218*cd33f216SAsmaa Mnebhi if (ret) 219*cd33f216SAsmaa Mnebhi return dev_err_probe(dev, ret, "failed to request IRQ"); 220*cd33f216SAsmaa Mnebhi } 221*cd33f216SAsmaa Mnebhi 222*cd33f216SAsmaa Mnebhi platform_set_drvdata(pdev, gs); 223*cd33f216SAsmaa Mnebhi 224*cd33f216SAsmaa Mnebhi ret = devm_gpiochip_add_data(dev, &gs->gc, gs); 225*cd33f216SAsmaa Mnebhi if (ret) 226*cd33f216SAsmaa Mnebhi dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n"); 227*cd33f216SAsmaa Mnebhi 228*cd33f216SAsmaa Mnebhi return 0; 229*cd33f216SAsmaa Mnebhi } 230*cd33f216SAsmaa Mnebhi 231*cd33f216SAsmaa Mnebhi static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = { 232*cd33f216SAsmaa Mnebhi { "MLNXBF33", 0 }, 233*cd33f216SAsmaa Mnebhi {} 234*cd33f216SAsmaa Mnebhi }; 235*cd33f216SAsmaa Mnebhi MODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match); 236*cd33f216SAsmaa Mnebhi 237*cd33f216SAsmaa Mnebhi static struct platform_driver mlxbf3_gpio_driver = { 238*cd33f216SAsmaa Mnebhi .driver = { 239*cd33f216SAsmaa Mnebhi .name = "mlxbf3_gpio", 240*cd33f216SAsmaa Mnebhi .acpi_match_table = mlxbf3_gpio_acpi_match, 241*cd33f216SAsmaa Mnebhi }, 242*cd33f216SAsmaa Mnebhi .probe = mlxbf3_gpio_probe, 243*cd33f216SAsmaa Mnebhi }; 244*cd33f216SAsmaa Mnebhi module_platform_driver(mlxbf3_gpio_driver); 245*cd33f216SAsmaa Mnebhi 246*cd33f216SAsmaa Mnebhi MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver"); 247*cd33f216SAsmaa Mnebhi MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>"); 248*cd33f216SAsmaa Mnebhi MODULE_LICENSE("Dual BSD/GPL"); 249