ARM: dts: npcm8xx: add npcm845 function node
[platform/kernel/u-boot.git] / drivers / gpio / ftgpio010.c
1 // 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
11 struct ftgpio010_regs {
12         u32 out;
13         u32 in;
14         u32 direction;  // 1 - output
15         u32 reserved;
16         u32 set;
17         u32 clear;
18 };
19
20 struct ftgpio010_plat {
21         struct ftgpio010_regs __iomem *regs;
22 };
23
24 static 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
33 static 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
46 static 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
54 static 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
63 static 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
73 static 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
82 static 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
90 static 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
98 static const struct udevice_id ftgpio010_ids[] = {
99         { .compatible = "faraday,ftgpio010" },
100         { }
101 };
102
103 U_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 };