1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) ASPEED Technology Inc.
* Billy Tsai <billy_tsai@aspeedtech.com>
*/
#include <asm/io.h>
#include <asm/gpio.h>
#include <config.h>
#include <clk.h>
#include <dm.h>
#include <asm/io.h>
#include <linux/bug.h>
#include <linux/sizes.h>
struct aspeed_gpio_priv {
void *regs;
};
#define GPIO_G7_IRQ_STS_BASE 0x100
#define GPIO_G7_IRQ_STS_OFFSET(x) (GPIO_G7_IRQ_STS_BASE + (x) * 0x4)
#define GPIO_G7_CTRL_REG_BASE 0x180
#define GPIO_G7_CTRL_REG_OFFSET(x) (GPIO_G7_CTRL_REG_BASE + (x) * 0x4)
#define GPIO_G7_OUT_DATA BIT(0)
#define GPIO_G7_DIR BIT(1)
#define GPIO_G7_IRQ_EN BIT(2)
#define GPIO_G7_IRQ_TYPE0 BIT(3)
#define GPIO_G7_IRQ_TYPE1 BIT(4)
#define GPIO_G7_IRQ_TYPE2 BIT(5)
#define GPIO_G7_RST_TOLERANCE BIT(6)
#define GPIO_G7_DEBOUNCE_SEL GENMASK(8, 7)
#define GPIO_G7_INPUT_MASK BIT(9)
#define GPIO_G7_IRQ_STS BIT(12)
#define GPIO_G7_IN_DATA BIT(13)
/*
* The configuration of the following registers should be determined
* outside of the GPIO driver.
*/
#define GPIO_G7_PRIVILEGE_W_REG_BASE 0x810
#define GPIO_G7_PRIVILEGE_W_REG_OFFSET(x) (GPIO_G7_PRIVILEGE_W_REG_BASE + ((x) >> 2) * 0x4)
#define GPIO_G7_PRIVILEGE_R_REG_BASE 0x910
#define GPIO_G7_PRIVILEGE_R_REG_OFFSET(x) (GPIO_G7_PRIVILEGE_R_REG_BASE + ((x) >> 2) * 0x4)
#define GPIO_G7_IRQ_TARGET_REG_BASE 0xA10
#define GPIO_G7_IRQ_TARGET_REG_OFFSET(x) (GPIO_G7_IRQ_TARGET_REG_BASE + ((x) >> 2) * 0x4)
#define GPIO_G7_IRQ_TO_INTC2_18 BIT(0)
#define GPIO_G7_IRQ_TO_INTC2_19 BIT(1)
#define GPIO_G7_IRQ_TO_INTC2_20 BIT(2)
#define GPIO_G7_IRQ_TO_SIO BIT(3)
#define GPIO_G7_IRQ_TARGET_RESET_TOLERANCE BIT(6)
#define GPIO_G7_IRQ_TARGET_W_PROTECT BIT(7)
static int
aspeed_gpio_direction_input(struct udevice *dev, unsigned int offset)
{
struct aspeed_gpio_priv *priv = dev_get_priv(dev);
void __iomem *addr = priv->regs + GPIO_G7_CTRL_REG_OFFSET(offset);
u32 dir = readl(addr);
dir &= ~GPIO_G7_DIR;
writel(dir, addr);
return 0;
}
static int aspeed_gpio_direction_output(struct udevice *dev, unsigned int offset,
int value)
{
struct aspeed_gpio_priv *priv = dev_get_priv(dev);
void __iomem *addr = priv->regs + GPIO_G7_CTRL_REG_OFFSET(offset);
u32 data = readl(addr);
if (value)
data |= GPIO_G7_OUT_DATA;
else
data &= ~GPIO_G7_OUT_DATA;
writel(data, addr);
data |= GPIO_G7_DIR;
writel(data, addr);
return 0;
}
static int aspeed_gpio_get_value(struct udevice *dev, unsigned int offset)
{
struct aspeed_gpio_priv *priv = dev_get_priv(dev);
void __iomem *addr = priv->regs + GPIO_G7_CTRL_REG_OFFSET(offset);
return !!(readl(addr) & GPIO_G7_IN_DATA);
}
static int
aspeed_gpio_set_value(struct udevice *dev, unsigned int offset, int value)
{
struct aspeed_gpio_priv *priv = dev_get_priv(dev);
void __iomem *addr = priv->regs + GPIO_G7_CTRL_REG_OFFSET(offset);
u32 data = readl(addr);
if (value)
data |= GPIO_G7_OUT_DATA;
else
data &= ~GPIO_G7_OUT_DATA;
writel(data, addr);
return 0;
}
static int aspeed_gpio_get_function(struct udevice *dev, unsigned int offset)
{
struct aspeed_gpio_priv *priv = dev_get_priv(dev);
void __iomem *addr = priv->regs + GPIO_G7_CTRL_REG_OFFSET(offset);
if (readl(addr) & GPIO_G7_DIR)
return GPIOF_OUTPUT;
return GPIOF_INPUT;
}
static const struct dm_gpio_ops aspeed_gpio_ops = {
.direction_input = aspeed_gpio_direction_input,
.direction_output = aspeed_gpio_direction_output,
.get_value = aspeed_gpio_get_value,
.set_value = aspeed_gpio_set_value,
.get_function = aspeed_gpio_get_function,
};
static int aspeed_gpio_probe(struct udevice *dev)
{
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct aspeed_gpio_priv *priv = dev_get_priv(dev);
uc_priv->bank_name = dev->name;
ofnode_read_u32(dev_ofnode(dev), "ngpios", &uc_priv->gpio_count);
priv->regs = devfdt_get_addr_ptr(dev);
return 0;
}
static const struct udevice_id aspeed_gpio_ids[] = {
{ .compatible = "aspeed,ast2700-gpio", },
{ }
};
U_BOOT_DRIVER(gpio_aspeed) = {
.name = "gpio-aspeed",
.id = UCLASS_GPIO,
.of_match = aspeed_gpio_ids,
.ops = &aspeed_gpio_ops,
.probe = aspeed_gpio_probe,
.priv_auto = sizeof(struct aspeed_gpio_priv),
};
|