Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpio/gpio-amdpt.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* AMD Promontory GPIO driver
4
*
5
* Copyright (C) 2015 ASMedia Technology Inc.
6
* Author: YD Tseng <[email protected]>
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 8
17
#define PT_TOTAL_GPIO_EX 24
18
19
/* PCI-E MMIO register offsets */
20
#define PT_DIRECTION_REG 0x00
21
#define PT_INPUTDATA_REG 0x04
22
#define PT_OUTPUTDATA_REG 0x08
23
#define PT_CLOCKRATE_REG 0x0C
24
#define PT_SYNC_REG 0x28
25
26
struct pt_gpio_chip {
27
struct gpio_chip gc;
28
void __iomem *reg_base;
29
};
30
31
static 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
56
static 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
73
static 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 = devm_gpiochip_add_data(dev, &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
125
static const struct acpi_device_id pt_gpio_acpi_match[] = {
126
{ "AMDF030", PT_TOTAL_GPIO },
127
{ "AMDIF030", PT_TOTAL_GPIO },
128
{ "AMDIF031", PT_TOTAL_GPIO_EX },
129
{ },
130
};
131
MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match);
132
133
static struct platform_driver pt_gpio_driver = {
134
.driver = {
135
.name = "pt-gpio",
136
.acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),
137
},
138
.probe = pt_gpio_probe,
139
};
140
141
module_platform_driver(pt_gpio_driver);
142
143
MODULE_LICENSE("GPL");
144
MODULE_AUTHOR("YD Tseng <[email protected]>");
145
MODULE_DESCRIPTION("AMD Promontory GPIO Driver");
146
147