]> Git Repo - J-u-boot.git/blob - drivers/gpio/sl28cpld-gpio.c
net: mediatek: fix gmac2 usability for mt7629
[J-u-boot.git] / drivers / gpio / sl28cpld-gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * GPIO driver for the sl28cpld
4  *
5  * Copyright (c) 2021 Michael Walle <[email protected]>
6  */
7
8 #include <dm.h>
9 #include <asm/gpio.h>
10 #include <sl28cpld.h>
11
12 /* GPIO flavor */
13 #define SL28CPLD_GPIO_DIR       0x00
14 #define SL28CPLD_GPIO_OUT       0x01
15 #define SL28CPLD_GPIO_IN        0x02
16
17 /* input-only flavor */
18 #define SL28CPLD_GPI_IN         0x00
19
20 /* output-only flavor */
21 #define SL28CPLD_GPO_OUT        0x00
22
23 enum {
24         SL28CPLD_GPIO,
25         SL28CPLD_GPI,
26         SL28CPLD_GPO,
27 };
28
29 static int sl28cpld_gpio_get_value(struct udevice *dev, unsigned int gpio)
30 {
31         ulong type = dev_get_driver_data(dev);
32         int val, reg;
33
34         switch (type) {
35         case SL28CPLD_GPIO:
36                 reg = SL28CPLD_GPIO_IN;
37                 break;
38         case SL28CPLD_GPI:
39                 reg = SL28CPLD_GPI_IN;
40                 break;
41         case SL28CPLD_GPO:
42                 /* we are output only, thus just return the output value */
43                 reg = SL28CPLD_GPO_OUT;
44                 break;
45         default:
46                 return -EINVAL;
47         }
48
49         val = sl28cpld_read(dev, reg);
50
51         return val < 0 ? val : !!(val & BIT(gpio));
52 }
53
54 static int sl28cpld_gpio_set_value(struct udevice *dev, unsigned int gpio,
55                                    int value)
56 {
57         ulong type = dev_get_driver_data(dev);
58         uint reg;
59
60         switch (type) {
61         case SL28CPLD_GPIO:
62                 reg = SL28CPLD_GPIO_OUT;
63                 break;
64         case SL28CPLD_GPO:
65                 reg = SL28CPLD_GPO_OUT;
66                 break;
67         case SL28CPLD_GPI:
68         default:
69                 return -EINVAL;
70         }
71
72         if (value)
73                 return sl28cpld_update(dev, reg, 0, BIT(gpio));
74         else
75                 return sl28cpld_update(dev, reg, BIT(gpio), 0);
76 }
77
78 static int sl28cpld_gpio_direction_input(struct udevice *dev, unsigned int gpio)
79 {
80         ulong type = dev_get_driver_data(dev);
81
82         switch (type) {
83         case SL28CPLD_GPI:
84                 return 0;
85         case SL28CPLD_GPIO:
86                 return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, BIT(gpio), 0);
87         case SL28CPLD_GPO:
88         default:
89                 return -EINVAL;
90         }
91 }
92
93 static int sl28cpld_gpio_direction_output(struct udevice *dev,
94                                           unsigned int gpio, int value)
95 {
96         ulong type = dev_get_driver_data(dev);
97         int ret;
98
99         /* set_value() will report an error if we are input-only */
100         ret = sl28cpld_gpio_set_value(dev, gpio, value);
101         if (ret)
102                 return ret;
103
104         if (type == SL28CPLD_GPIO)
105                 return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, 0, BIT(gpio));
106
107         return 0;
108 }
109
110 static int sl28cpld_gpio_get_function(struct udevice *dev, unsigned int gpio)
111 {
112         ulong type = dev_get_driver_data(dev);
113         int val;
114
115         switch (type) {
116         case SL28CPLD_GPIO:
117                 val = sl28cpld_read(dev, SL28CPLD_GPIO_DIR);
118                 if (val < 0)
119                         return val;
120                 if (val & BIT(gpio))
121                         return GPIOF_OUTPUT;
122                 else
123                         return GPIOF_INPUT;
124         case SL28CPLD_GPI:
125                 return GPIOF_INPUT;
126         case SL28CPLD_GPO:
127                 return GPIOF_OUTPUT;
128         default:
129                 return -EINVAL;
130         }
131 }
132
133 static const struct dm_gpio_ops sl28cpld_gpio_ops = {
134         .direction_input = sl28cpld_gpio_direction_input,
135         .direction_output = sl28cpld_gpio_direction_output,
136         .get_value = sl28cpld_gpio_get_value,
137         .set_value = sl28cpld_gpio_set_value,
138         .get_function = sl28cpld_gpio_get_function,
139 };
140
141 static int sl28cpld_gpio_probe(struct udevice *dev)
142 {
143         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
144
145         uc_priv->gpio_count = 8;
146         uc_priv->bank_name = dev_read_name(dev);
147
148         return 0;
149 }
150
151 static const struct udevice_id sl28cpld_gpio_ids[] = {
152         { .compatible = "kontron,sl28cpld-gpio", .data = SL28CPLD_GPIO},
153         { .compatible = "kontron,sl28cpld-gpo", .data = SL28CPLD_GPO},
154         { .compatible = "kontron,sl28cpld-gpi", .data = SL28CPLD_GPI},
155         { }
156 };
157
158 U_BOOT_DRIVER(sl28cpld_gpio) = {
159         .name   = "sl28cpld_gpio",
160         .id     = UCLASS_GPIO,
161         .of_match = sl28cpld_gpio_ids,
162         .probe  = sl28cpld_gpio_probe,
163         .ops    = &sl28cpld_gpio_ops,
164 };
This page took 0.035624 seconds and 4 git commands to generate.