brintos

brintos / linux-shallow public Read only

0
0
Text · 11.7 KiB · 6abe01b Raw
479 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/*4 * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES5 */6 7#include <linux/bitfield.h>8#include <linux/bitops.h>9#include <linux/device.h>10#include <linux/gpio/driver.h>11#include <linux/interrupt.h>12#include <linux/io.h>13#include <linux/ioport.h>14#include <linux/kernel.h>15#include <linux/mod_devicetable.h>16#include <linux/module.h>17#include <linux/platform_device.h>18#include <linux/pm.h>19#include <linux/resource.h>20#include <linux/seq_file.h>21#include <linux/spinlock.h>22#include <linux/types.h>23 24/*25 * There are 3 YU GPIO blocks:26 * gpio[0]: HOST_GPIO0->HOST_GPIO3127 * gpio[1]: HOST_GPIO32->HOST_GPIO6328 * gpio[2]: HOST_GPIO64->HOST_GPIO6929 */30#define MLXBF2_GPIO_MAX_PINS_PER_BLOCK 3231 32/*33 * arm_gpio_lock register:34 * bit[31]	lock status: active if set35 * bit[15:0]	set lock36 * The lock is enabled only if 0xd42f is written to this field37 */38#define YU_ARM_GPIO_LOCK_ADDR		0x280108839#define YU_ARM_GPIO_LOCK_SIZE		0x840#define YU_LOCK_ACTIVE_BIT(val)		(val >> 31)41#define YU_ARM_GPIO_LOCK_ACQUIRE	0xd42f42#define YU_ARM_GPIO_LOCK_RELEASE	0x043 44/*45 * gpio[x] block registers and their offset46 */47#define YU_GPIO_DATAIN			0x0448#define YU_GPIO_MODE1			0x0849#define YU_GPIO_MODE0			0x0c50#define YU_GPIO_DATASET			0x1451#define YU_GPIO_DATACLEAR		0x1852#define YU_GPIO_CAUSE_RISE_EN		0x4453#define YU_GPIO_CAUSE_FALL_EN		0x4854#define YU_GPIO_MODE1_CLEAR		0x5055#define YU_GPIO_MODE0_SET		0x5456#define YU_GPIO_MODE0_CLEAR		0x5857#define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0	0x8058#define YU_GPIO_CAUSE_OR_EVTEN0		0x9459#define YU_GPIO_CAUSE_OR_CLRCAUSE	0x9860 61struct mlxbf2_gpio_context_save_regs {62	u32 gpio_mode0;63	u32 gpio_mode1;64};65 66/* BlueField-2 gpio block context structure. */67struct mlxbf2_gpio_context {68	struct gpio_chip gc;69 70	/* YU GPIO blocks address */71	void __iomem *gpio_io;72	struct device *dev;73 74	struct mlxbf2_gpio_context_save_regs *csave_regs;75};76 77/* BlueField-2 gpio shared structure. */78struct mlxbf2_gpio_param {79	void __iomem *io;80	struct resource *res;81	struct mutex *lock;82};83 84static struct resource yu_arm_gpio_lock_res =85	DEFINE_RES_MEM_NAMED(YU_ARM_GPIO_LOCK_ADDR, YU_ARM_GPIO_LOCK_SIZE, "YU_ARM_GPIO_LOCK");86 87static DEFINE_MUTEX(yu_arm_gpio_lock_mutex);88 89static struct mlxbf2_gpio_param yu_arm_gpio_lock_param = {90	.res = &yu_arm_gpio_lock_res,91	.lock = &yu_arm_gpio_lock_mutex,92};93 94/* Request memory region and map yu_arm_gpio_lock resource */95static int mlxbf2_gpio_get_lock_res(struct platform_device *pdev)96{97	struct device *dev = &pdev->dev;98	struct resource *res;99	resource_size_t size;100	int ret = 0;101 102	mutex_lock(yu_arm_gpio_lock_param.lock);103 104	/* Check if the memory map already exists */105	if (yu_arm_gpio_lock_param.io)106		goto exit;107 108	res = yu_arm_gpio_lock_param.res;109	size = resource_size(res);110 111	if (!devm_request_mem_region(dev, res->start, size, res->name)) {112		ret = -EFAULT;113		goto exit;114	}115 116	yu_arm_gpio_lock_param.io = devm_ioremap(dev, res->start, size);117	if (!yu_arm_gpio_lock_param.io)118		ret = -ENOMEM;119 120exit:121	mutex_unlock(yu_arm_gpio_lock_param.lock);122 123	return ret;124}125 126/*127 * Acquire the YU arm_gpio_lock to be able to change the direction128 * mode. If the lock_active bit is already set, return an error.129 */130static int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs)131{132	u32 arm_gpio_lock_val;133 134	mutex_lock(yu_arm_gpio_lock_param.lock);135	raw_spin_lock(&gs->gc.bgpio_lock);136 137	arm_gpio_lock_val = readl(yu_arm_gpio_lock_param.io);138 139	/*140	 * When lock active bit[31] is set, ModeX is write enabled141	 */142	if (YU_LOCK_ACTIVE_BIT(arm_gpio_lock_val)) {143		raw_spin_unlock(&gs->gc.bgpio_lock);144		mutex_unlock(yu_arm_gpio_lock_param.lock);145		return -EINVAL;146	}147 148	writel(YU_ARM_GPIO_LOCK_ACQUIRE, yu_arm_gpio_lock_param.io);149 150	return 0;151}152 153/*154 * Release the YU arm_gpio_lock after changing the direction mode.155 */156static void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs)157	__releases(&gs->gc.bgpio_lock)158	__releases(yu_arm_gpio_lock_param.lock)159{160	writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io);161	raw_spin_unlock(&gs->gc.bgpio_lock);162	mutex_unlock(yu_arm_gpio_lock_param.lock);163}164 165/*166 * mode0 and mode1 are both locked by the gpio_lock field.167 *168 * Together, mode0 and mode1 define the gpio Mode dependeing also169 * on Reg_DataOut.170 *171 * {mode1,mode0}:{Reg_DataOut=0,Reg_DataOut=1}->{DataOut=0,DataOut=1}172 *173 * {0,0}:Reg_DataOut{0,1}->{Z,Z} Input PAD174 * {0,1}:Reg_DataOut{0,1}->{0,1} Full drive Output PAD175 * {1,0}:Reg_DataOut{0,1}->{0,Z} 0-set PAD to low, 1-float176 * {1,1}:Reg_DataOut{0,1}->{Z,1} 0-float, 1-set PAD to high177 */178 179/*180 * Set input direction:181 * {mode1,mode0} = {0,0}182 */183static int mlxbf2_gpio_direction_input(struct gpio_chip *chip,184				       unsigned int offset)185{186	struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip);187	int ret;188 189	/*190	 * Although the arm_gpio_lock was set in the probe function, check again191	 * if it is still enabled to be able to write to the ModeX registers.192	 */193	ret = mlxbf2_gpio_lock_acquire(gs);194	if (ret < 0)195		return ret;196 197	writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_CLEAR);198	writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR);199 200	mlxbf2_gpio_lock_release(gs);201 202	return ret;203}204 205/*206 * Set output direction:207 * {mode1,mode0} = {0,1}208 */209static int mlxbf2_gpio_direction_output(struct gpio_chip *chip,210					unsigned int offset,211					int value)212{213	struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip);214	int ret = 0;215 216	/*217	 * Although the arm_gpio_lock was set in the probe function,218	 * check again it is still enabled to be able to write to the219	 * ModeX registers.220	 */221	ret = mlxbf2_gpio_lock_acquire(gs);222	if (ret < 0)223		return ret;224 225	writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR);226	writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_SET);227 228	mlxbf2_gpio_lock_release(gs);229 230	return ret;231}232 233static void mlxbf2_gpio_irq_enable(struct irq_data *irqd)234{235	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);236	struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);237	int offset = irqd_to_hwirq(irqd);238	unsigned long flags;239	u32 val;240 241	gpiochip_enable_irq(gc, irqd_to_hwirq(irqd));242	raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);243	val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE);244	val |= BIT(offset);245	writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE);246 247	val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);248	val |= BIT(offset);249	writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);250	raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);251}252 253static void mlxbf2_gpio_irq_disable(struct irq_data *irqd)254{255	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);256	struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);257	int offset = irqd_to_hwirq(irqd);258	unsigned long flags;259	u32 val;260 261	raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);262	val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);263	val &= ~BIT(offset);264	writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0);265	raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);266	gpiochip_disable_irq(gc, irqd_to_hwirq(irqd));267}268 269static irqreturn_t mlxbf2_gpio_irq_handler(int irq, void *ptr)270{271	struct mlxbf2_gpio_context *gs = ptr;272	struct gpio_chip *gc = &gs->gc;273	unsigned long pending;274	u32 level;275 276	pending = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0);277	writel(pending, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE);278 279	for_each_set_bit(level, &pending, gc->ngpio)280		generic_handle_domain_irq_safe(gc->irq.domain, level);281 282	return IRQ_RETVAL(pending);283}284 285static int286mlxbf2_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)287{288	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);289	struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);290	int offset = irqd_to_hwirq(irqd);291	unsigned long flags;292	bool fall = false;293	bool rise = false;294	u32 val;295 296	switch (type & IRQ_TYPE_SENSE_MASK) {297	case IRQ_TYPE_EDGE_BOTH:298		fall = true;299		rise = true;300		break;301	case IRQ_TYPE_EDGE_RISING:302		rise = true;303		break;304	case IRQ_TYPE_EDGE_FALLING:305		fall = true;306		break;307	default:308		return -EINVAL;309	}310 311	raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);312	if (fall) {313		val = readl(gs->gpio_io + YU_GPIO_CAUSE_FALL_EN);314		val |= BIT(offset);315		writel(val, gs->gpio_io + YU_GPIO_CAUSE_FALL_EN);316	}317 318	if (rise) {319		val = readl(gs->gpio_io + YU_GPIO_CAUSE_RISE_EN);320		val |= BIT(offset);321		writel(val, gs->gpio_io + YU_GPIO_CAUSE_RISE_EN);322	}323	raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);324 325	return 0;326}327 328static void mlxbf2_gpio_irq_print_chip(struct irq_data *irqd,329				       struct seq_file *p)330{331	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);332	struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);333 334	seq_printf(p, dev_name(gs->dev));335}336 337static const struct irq_chip mlxbf2_gpio_irq_chip = {338	.irq_set_type = mlxbf2_gpio_irq_set_type,339	.irq_enable = mlxbf2_gpio_irq_enable,340	.irq_disable = mlxbf2_gpio_irq_disable,341	.irq_print_chip = mlxbf2_gpio_irq_print_chip,342	.flags = IRQCHIP_IMMUTABLE,343	GPIOCHIP_IRQ_RESOURCE_HELPERS,344};345 346/* BlueField-2 GPIO driver initialization routine. */347static int348mlxbf2_gpio_probe(struct platform_device *pdev)349{350	struct mlxbf2_gpio_context *gs;351	struct device *dev = &pdev->dev;352	struct gpio_irq_chip *girq;353	struct gpio_chip *gc;354	unsigned int npins;355	const char *name;356	int ret, irq;357 358	name = dev_name(dev);359 360	gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL);361	if (!gs)362		return -ENOMEM;363 364	gs->dev = dev;365 366	/* YU GPIO block address */367	gs->gpio_io = devm_platform_ioremap_resource(pdev, 0);368	if (IS_ERR(gs->gpio_io))369		return PTR_ERR(gs->gpio_io);370 371	ret = mlxbf2_gpio_get_lock_res(pdev);372	if (ret) {373		dev_err(dev, "Failed to get yu_arm_gpio_lock resource\n");374		return ret;375	}376 377	if (device_property_read_u32(dev, "npins", &npins))378		npins = MLXBF2_GPIO_MAX_PINS_PER_BLOCK;379 380	gc = &gs->gc;381 382	ret = bgpio_init(gc, dev, 4,383			gs->gpio_io + YU_GPIO_DATAIN,384			gs->gpio_io + YU_GPIO_DATASET,385			gs->gpio_io + YU_GPIO_DATACLEAR,386			NULL,387			NULL,388			0);389 390	if (ret) {391		dev_err(dev, "bgpio_init failed\n");392		return ret;393	}394 395	gc->direction_input = mlxbf2_gpio_direction_input;396	gc->direction_output = mlxbf2_gpio_direction_output;397	gc->ngpio = npins;398	gc->owner = THIS_MODULE;399 400	irq = platform_get_irq(pdev, 0);401	if (irq >= 0) {402		girq = &gs->gc.irq;403		gpio_irq_chip_set_chip(girq, &mlxbf2_gpio_irq_chip);404		girq->handler = handle_simple_irq;405		girq->default_type = IRQ_TYPE_NONE;406		/* This will let us handle the parent IRQ in the driver */407		girq->num_parents = 0;408		girq->parents = NULL;409		girq->parent_handler = NULL;410 411		/*412		 * Directly request the irq here instead of passing413		 * a flow-handler because the irq is shared.414		 */415		ret = devm_request_irq(dev, irq, mlxbf2_gpio_irq_handler,416				       IRQF_SHARED, name, gs);417		if (ret) {418			dev_err(dev, "failed to request IRQ");419			return ret;420		}421	}422 423	platform_set_drvdata(pdev, gs);424 425	ret = devm_gpiochip_add_data(dev, &gs->gc, gs);426	if (ret) {427		dev_err(dev, "Failed adding memory mapped gpiochip\n");428		return ret;429	}430 431	return 0;432}433 434static int __maybe_unused mlxbf2_gpio_suspend(struct device *dev)435{436	struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);437 438	gs->csave_regs->gpio_mode0 = readl(gs->gpio_io +439		YU_GPIO_MODE0);440	gs->csave_regs->gpio_mode1 = readl(gs->gpio_io +441		YU_GPIO_MODE1);442 443	return 0;444}445 446static int __maybe_unused mlxbf2_gpio_resume(struct device *dev)447{448	struct mlxbf2_gpio_context *gs = dev_get_drvdata(dev);449 450	writel(gs->csave_regs->gpio_mode0, gs->gpio_io +451		YU_GPIO_MODE0);452	writel(gs->csave_regs->gpio_mode1, gs->gpio_io +453		YU_GPIO_MODE1);454 455	return 0;456}457static SIMPLE_DEV_PM_OPS(mlxbf2_pm_ops, mlxbf2_gpio_suspend, mlxbf2_gpio_resume);458 459static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = {460	{ "MLNXBF22", 0 },461	{},462};463MODULE_DEVICE_TABLE(acpi, mlxbf2_gpio_acpi_match);464 465static struct platform_driver mlxbf2_gpio_driver = {466	.driver = {467		.name = "mlxbf2_gpio",468		.acpi_match_table = mlxbf2_gpio_acpi_match,469		.pm = &mlxbf2_pm_ops,470	},471	.probe    = mlxbf2_gpio_probe,472};473 474module_platform_driver(mlxbf2_gpio_driver);475 476MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver");477MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");478MODULE_LICENSE("GPL v2");479