blob: 6c091d4fd874bf5e93bda63e9f59894df95518e7 [file] [log] [blame]
Sergei Antonov03027a52022-09-12 13:09:15 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Faraday Technology's FTGPIO010 controller.
4 */
5
6#include <common.h>
7#include <dm.h>
8#include <asm/io.h>
9#include <asm/gpio.h>
10
11struct ftgpio010_regs {
12 u32 out;
13 u32 in;
14 u32 direction; // 1 - output
15 u32 reserved;
16 u32 set;
17 u32 clear;
18};
19
20struct ftgpio010_plat {
21 struct ftgpio010_regs __iomem *regs;
22};
23
24static int ftgpio010_direction_input(struct udevice *dev, unsigned int pin)
25{
26 struct ftgpio010_plat *plat = dev_get_plat(dev);
27 struct ftgpio010_regs *const regs = plat->regs;
28
29 clrbits_le32(&regs->direction, 1 << pin);
30 return 0;
31}
32
33static int ftgpio010_direction_output(struct udevice *dev, unsigned int pin,
34 int val)
35{
36 struct ftgpio010_plat *plat = dev_get_plat(dev);
37 struct ftgpio010_regs *const regs = plat->regs;
38
39 /* change the data first, then the direction. to avoid glitch */
40 out_le32(val ? &regs->set : &regs->clear, 1 << pin);
41 setbits_le32(&regs->direction, 1 << pin);
42
43 return 0;
44}
45
46static int ftgpio010_get_value(struct udevice *dev, unsigned int pin)
47{
48 struct ftgpio010_plat *plat = dev_get_plat(dev);
49 struct ftgpio010_regs *const regs = plat->regs;
50
51 return in_le32(&regs->in) >> pin & 1;
52}
53
54static int ftgpio010_set_value(struct udevice *dev, unsigned int pin, int val)
55{
56 struct ftgpio010_plat *plat = dev_get_plat(dev);
57 struct ftgpio010_regs *const regs = plat->regs;
58
59 out_le32(val ? &regs->set : &regs->clear, 1 << pin);
60 return 0;
61}
62
63static int ftgpio010_get_function(struct udevice *dev, unsigned int pin)
64{
65 struct ftgpio010_plat *plat = dev_get_plat(dev);
66 struct ftgpio010_regs *const regs = plat->regs;
67
68 if (in_le32(&regs->direction) >> pin & 1)
69 return GPIOF_OUTPUT;
70 return GPIOF_INPUT;
71}
72
73static int ftgpio010_probe(struct udevice *dev)
74{
75 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
76
77 uc_priv->gpio_count = ofnode_read_u32_default(dev_ofnode(dev),
78 "nr-gpios", 32);
79 return 0;
80}
81
82static int ftgpio010_of_to_plat(struct udevice *dev)
83{
84 struct ftgpio010_plat *plat = dev_get_plat(dev);
85
86 plat->regs = dev_read_addr_ptr(dev);
87 return 0;
88}
89
90static const struct dm_gpio_ops ftgpio010_ops = {
91 .direction_input = ftgpio010_direction_input,
92 .direction_output = ftgpio010_direction_output,
93 .get_value = ftgpio010_get_value,
94 .set_value = ftgpio010_set_value,
95 .get_function = ftgpio010_get_function,
96};
97
98static const struct udevice_id ftgpio010_ids[] = {
99 { .compatible = "faraday,ftgpio010" },
100 { }
101};
102
103U_BOOT_DRIVER(ftgpio010) = {
104 .name = "ftgpio010",
105 .id = UCLASS_GPIO,
106 .of_match = ftgpio010_ids,
107 .ops = &ftgpio010_ops,
108 .of_to_plat = ftgpio010_of_to_plat,
109 .plat_auto = sizeof(struct ftgpio010_plat),
110 .probe = ftgpio010_probe,
111};