brintos

brintos / linux-shallow public Read only

0
0
Text · 3.8 KiB · 0a2ea9d Raw
154 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * AMD Promontory GPIO driver4 *5 * Copyright (C) 2015 ASMedia Technology Inc.6 * Author: YD Tseng <yd_tseng@asmedia.com.tw>7 */8 9#include <linux/kernel.h>10#include <linux/module.h>11#include <linux/gpio/driver.h>12#include <linux/spinlock.h>13#include <linux/acpi.h>14#include <linux/platform_device.h>15 16#define PT_TOTAL_GPIO 817#define PT_TOTAL_GPIO_EX 2418 19/* PCI-E MMIO register offsets */20#define PT_DIRECTION_REG   0x0021#define PT_INPUTDATA_REG   0x0422#define PT_OUTPUTDATA_REG  0x0823#define PT_CLOCKRATE_REG   0x0C24#define PT_SYNC_REG        0x2825 26struct pt_gpio_chip {27	struct gpio_chip         gc;28	void __iomem             *reg_base;29};30 31static int pt_gpio_request(struct gpio_chip *gc, unsigned offset)32{33	struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);34	unsigned long flags;35	u32 using_pins;36 37	dev_dbg(gc->parent, "pt_gpio_request offset=%x\n", offset);38 39	raw_spin_lock_irqsave(&gc->bgpio_lock, flags);40 41	using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);42	if (using_pins & BIT(offset)) {43		dev_warn(gc->parent, "PT GPIO pin %x reconfigured\n",44			 offset);45		raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);46		return -EINVAL;47	}48 49	writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG);50 51	raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);52 53	return 0;54}55 56static void pt_gpio_free(struct gpio_chip *gc, unsigned offset)57{58	struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);59	unsigned long flags;60	u32 using_pins;61 62	raw_spin_lock_irqsave(&gc->bgpio_lock, flags);63 64	using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);65	using_pins &= ~BIT(offset);66	writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG);67 68	raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);69 70	dev_dbg(gc->parent, "pt_gpio_free offset=%x\n", offset);71}72 73static int pt_gpio_probe(struct platform_device *pdev)74{75	struct device *dev = &pdev->dev;76	struct pt_gpio_chip *pt_gpio;77	int ret = 0;78 79	if (!ACPI_COMPANION(dev)) {80		dev_err(dev, "PT GPIO device node not found\n");81		return -ENODEV;82	}83 84	pt_gpio = devm_kzalloc(dev, sizeof(struct pt_gpio_chip), GFP_KERNEL);85	if (!pt_gpio)86		return -ENOMEM;87 88	pt_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0);89	if (IS_ERR(pt_gpio->reg_base)) {90		dev_err(dev, "Failed to map MMIO resource for PT GPIO.\n");91		return PTR_ERR(pt_gpio->reg_base);92	}93 94	ret = bgpio_init(&pt_gpio->gc, dev, 4,95			 pt_gpio->reg_base + PT_INPUTDATA_REG,96			 pt_gpio->reg_base + PT_OUTPUTDATA_REG, NULL,97			 pt_gpio->reg_base + PT_DIRECTION_REG, NULL,98			 BGPIOF_READ_OUTPUT_REG_SET);99	if (ret) {100		dev_err(dev, "bgpio_init failed\n");101		return ret;102	}103 104	pt_gpio->gc.owner            = THIS_MODULE;105	pt_gpio->gc.request          = pt_gpio_request;106	pt_gpio->gc.free             = pt_gpio_free;107	pt_gpio->gc.ngpio            = (uintptr_t)device_get_match_data(dev);108 109	ret = gpiochip_add_data(&pt_gpio->gc, pt_gpio);110	if (ret) {111		dev_err(dev, "Failed to register GPIO lib\n");112		return ret;113	}114 115	platform_set_drvdata(pdev, pt_gpio);116 117	/* initialize register setting */118	writel(0, pt_gpio->reg_base + PT_SYNC_REG);119	writel(0, pt_gpio->reg_base + PT_CLOCKRATE_REG);120 121	dev_dbg(dev, "PT GPIO driver loaded\n");122	return ret;123}124 125static void pt_gpio_remove(struct platform_device *pdev)126{127	struct pt_gpio_chip *pt_gpio = platform_get_drvdata(pdev);128 129	gpiochip_remove(&pt_gpio->gc);130}131 132static const struct acpi_device_id pt_gpio_acpi_match[] = {133	{ "AMDF030", PT_TOTAL_GPIO },134	{ "AMDIF030", PT_TOTAL_GPIO },135	{ "AMDIF031", PT_TOTAL_GPIO_EX },136	{ },137};138MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match);139 140static struct platform_driver pt_gpio_driver = {141	.driver = {142		.name = "pt-gpio",143		.acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),144	},145	.probe = pt_gpio_probe,146	.remove_new = pt_gpio_remove,147};148 149module_platform_driver(pt_gpio_driver);150 151MODULE_LICENSE("GPL");152MODULE_AUTHOR("YD Tseng <yd_tseng@asmedia.com.tw>");153MODULE_DESCRIPTION("AMD Promontory GPIO Driver");154