Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpio/gpio-amdpt.c
29269 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/gpio/generic.h>
13
#include <linux/spinlock.h>
14
#include <linux/acpi.h>
15
#include <linux/platform_device.h>
16
17
#define PT_TOTAL_GPIO 8
18
#define PT_TOTAL_GPIO_EX 24
19
20
/* PCI-E MMIO register offsets */
21
#define PT_DIRECTION_REG 0x00
22
#define PT_INPUTDATA_REG 0x04
23
#define PT_OUTPUTDATA_REG 0x08
24
#define PT_CLOCKRATE_REG 0x0C
25
#define PT_SYNC_REG 0x28
26
27
struct pt_gpio_chip {
28
struct gpio_generic_chip chip;
29
void __iomem *reg_base;
30
};
31
32
static int pt_gpio_request(struct gpio_chip *gc, unsigned offset)
33
{
34
struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
35
struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);
36
u32 using_pins;
37
38
dev_dbg(gc->parent, "pt_gpio_request offset=%x\n", offset);
39
40
guard(gpio_generic_lock_irqsave)(gen_gc);
41
42
using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
43
if (using_pins & BIT(offset)) {
44
dev_warn(gc->parent, "PT GPIO pin %x reconfigured\n",
45
offset);
46
return -EINVAL;
47
}
48
49
writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG);
50
51
return 0;
52
}
53
54
static void pt_gpio_free(struct gpio_chip *gc, unsigned offset)
55
{
56
struct gpio_generic_chip *gen_gc = to_gpio_generic_chip(gc);
57
struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);
58
u32 using_pins;
59
60
guard(gpio_generic_lock_irqsave)(gen_gc);
61
62
using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
63
using_pins &= ~BIT(offset);
64
writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG);
65
66
dev_dbg(gc->parent, "pt_gpio_free offset=%x\n", offset);
67
}
68
69
static int pt_gpio_probe(struct platform_device *pdev)
70
{
71
struct gpio_generic_chip_config config;
72
struct device *dev = &pdev->dev;
73
struct pt_gpio_chip *pt_gpio;
74
int ret = 0;
75
76
if (!ACPI_COMPANION(dev)) {
77
dev_err(dev, "PT GPIO device node not found\n");
78
return -ENODEV;
79
}
80
81
pt_gpio = devm_kzalloc(dev, sizeof(struct pt_gpio_chip), GFP_KERNEL);
82
if (!pt_gpio)
83
return -ENOMEM;
84
85
pt_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0);
86
if (IS_ERR(pt_gpio->reg_base)) {
87
dev_err(dev, "Failed to map MMIO resource for PT GPIO.\n");
88
return PTR_ERR(pt_gpio->reg_base);
89
}
90
91
config = (struct gpio_generic_chip_config) {
92
.dev = dev,
93
.sz = 4,
94
.dat = pt_gpio->reg_base + PT_INPUTDATA_REG,
95
.set = pt_gpio->reg_base + PT_OUTPUTDATA_REG,
96
.dirout = pt_gpio->reg_base + PT_DIRECTION_REG,
97
.flags = GPIO_GENERIC_READ_OUTPUT_REG_SET,
98
};
99
100
ret = gpio_generic_chip_init(&pt_gpio->chip, &config);
101
if (ret) {
102
dev_err(dev, "failed to initialize the generic GPIO chip\n");
103
return ret;
104
}
105
106
pt_gpio->chip.gc.owner = THIS_MODULE;
107
pt_gpio->chip.gc.request = pt_gpio_request;
108
pt_gpio->chip.gc.free = pt_gpio_free;
109
pt_gpio->chip.gc.ngpio = (uintptr_t)device_get_match_data(dev);
110
111
ret = devm_gpiochip_add_data(dev, &pt_gpio->chip.gc, pt_gpio);
112
if (ret) {
113
dev_err(dev, "Failed to register GPIO lib\n");
114
return ret;
115
}
116
117
platform_set_drvdata(pdev, pt_gpio);
118
119
/* initialize register setting */
120
writel(0, pt_gpio->reg_base + PT_SYNC_REG);
121
writel(0, pt_gpio->reg_base + PT_CLOCKRATE_REG);
122
123
dev_dbg(dev, "PT GPIO driver loaded\n");
124
return ret;
125
}
126
127
static const struct acpi_device_id pt_gpio_acpi_match[] = {
128
{ "AMDF030", PT_TOTAL_GPIO },
129
{ "AMDIF030", PT_TOTAL_GPIO },
130
{ "AMDIF031", PT_TOTAL_GPIO_EX },
131
{ },
132
};
133
MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match);
134
135
static struct platform_driver pt_gpio_driver = {
136
.driver = {
137
.name = "pt-gpio",
138
.acpi_match_table = ACPI_PTR(pt_gpio_acpi_match),
139
},
140
.probe = pt_gpio_probe,
141
};
142
143
module_platform_driver(pt_gpio_driver);
144
145
MODULE_LICENSE("GPL");
146
MODULE_AUTHOR("YD Tseng <[email protected]>");
147
MODULE_DESCRIPTION("AMD Promontory GPIO Driver");
148
149