blob: ac6e68299e079beaf221a0136a24788d616a9c6b [file] [log] [blame]
Christophe Leroyd4f79cb2023-02-21 19:31:11 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2023 CR GROUP France
4 * Christophe Leroy <christophe.leroy@csgroup.eu>
5 */
6
Christophe Leroyd4f79cb2023-02-21 19:31:11 +01007#include <dm.h>
8#include <mapmem.h>
9#include <asm/gpio.h>
10#include <asm/immap_83xx.h>
11#include <asm/io.h>
12#include <dm/of_access.h>
13
14#define QE_DIR_NONE 0
15#define QE_DIR_OUT 1
16#define QE_DIR_IN 2
17#define QE_DIR_IN_OUT 3
18
19struct qe_gpio_data {
20 /* The bank's register base in memory */
21 struct gpio_n __iomem *base;
22 /* The address of the registers; used to identify the bank */
23 phys_addr_t addr;
24};
25
26static inline u32 gpio_mask(uint gpio)
27{
28 return 1U << (31 - (gpio));
29}
30
31static inline u32 gpio_mask2(uint gpio)
32{
33 return 1U << (30 - ((gpio & 15) << 1));
34}
35
36static int qe_gpio_direction_input(struct udevice *dev, uint gpio)
37{
38 struct qe_gpio_data *data = dev_get_priv(dev);
39 struct gpio_n __iomem *base = data->base;
40 u32 mask2 = gpio_mask2(gpio);
41
42 if (gpio < 16)
43 clrsetbits_be32(&base->dir1, mask2 * QE_DIR_OUT, mask2 * QE_DIR_IN);
44 else
45 clrsetbits_be32(&base->dir2, mask2 * QE_DIR_OUT, mask2 * QE_DIR_IN);
46
47 return 0;
48}
49
50static int qe_gpio_set_value(struct udevice *dev, uint gpio, int value)
51{
52 struct qe_gpio_data *data = dev_get_priv(dev);
53 struct gpio_n __iomem *base = data->base;
54 u32 mask = gpio_mask(gpio);
55 u32 mask2 = gpio_mask2(gpio);
56
57 if (gpio < 16)
58 clrsetbits_be32(&base->dir1, mask2 * QE_DIR_IN, mask2 * QE_DIR_OUT);
59 else
60 clrsetbits_be32(&base->dir2, mask2 * QE_DIR_IN, mask2 * QE_DIR_OUT);
61
62 if (value)
63 setbits_be32(&base->pdat, mask);
64 else
65 clrbits_be32(&base->pdat, mask);
66
67 return 0;
68}
69
70static int qe_gpio_get_value(struct udevice *dev, uint gpio)
71{
72 struct qe_gpio_data *data = dev_get_priv(dev);
73 struct gpio_n __iomem *base = data->base;
74 u32 mask = gpio_mask(gpio);
75
76 return !!(in_be32(&base->pdat) & mask);
77}
78
79static int qe_gpio_get_function(struct udevice *dev, uint gpio)
80{
81 struct qe_gpio_data *data = dev_get_priv(dev);
82 struct gpio_n __iomem *base = data->base;
83 u32 mask2 = gpio_mask2(gpio);
84 int dir;
85
86 if (gpio < 16)
87 dir = in_be32(&base->dir1);
88 else
89 dir = in_be32(&base->dir2);
90
91 if ((dir & (mask2 * QE_DIR_IN_OUT)) == (mask2 & QE_DIR_IN))
92 return GPIOF_INPUT;
93 else if ((dir & (mask2 * QE_DIR_IN_OUT)) == (mask2 & QE_DIR_OUT))
94 return GPIOF_OUTPUT;
95 else
96 return GPIOF_UNKNOWN;
97}
98
99static int qe_gpio_of_to_plat(struct udevice *dev)
100{
101 struct qe_gpio_plat *plat = dev_get_plat(dev);
102
103 plat->addr = dev_read_addr_size_index(dev, 0, (fdt_size_t *)&plat->size);
104
105 return 0;
106}
107
108static int qe_gpio_plat_to_priv(struct udevice *dev)
109{
110 struct qe_gpio_data *priv = dev_get_priv(dev);
111 struct qe_gpio_plat *plat = dev_get_plat(dev);
112 unsigned long size = plat->size;
113
114 if (size == 0)
115 size = sizeof(struct gpio_n);
116
117 priv->addr = plat->addr;
118 priv->base = (void __iomem *)plat->addr;
119
120 if (!priv->base)
121 return -ENOMEM;
122
123 return 0;
124}
125
126static int qe_gpio_probe(struct udevice *dev)
127{
128 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
129 struct qe_gpio_data *data = dev_get_priv(dev);
130 char name[32], *str;
131
132 qe_gpio_plat_to_priv(dev);
133
134 snprintf(name, sizeof(name), "QE@%.8llx",
135 (unsigned long long)data->addr);
136 str = strdup(name);
137
138 if (!str)
139 return -ENOMEM;
140
141 uc_priv->bank_name = str;
142 uc_priv->gpio_count = 32;
143
144 return 0;
145}
146
147static const struct dm_gpio_ops gpio_qe_ops = {
148 .direction_input = qe_gpio_direction_input,
149 .direction_output = qe_gpio_set_value,
150 .get_value = qe_gpio_get_value,
151 .set_value = qe_gpio_set_value,
152 .get_function = qe_gpio_get_function,
153};
154
155static const struct udevice_id qe_gpio_ids[] = {
156 { .compatible = "fsl,mpc8323-qe-pario-bank"},
157 { /* sentinel */ }
158};
159
160U_BOOT_DRIVER(gpio_qe) = {
161 .name = "gpio_qe",
162 .id = UCLASS_GPIO,
163 .ops = &gpio_qe_ops,
164 .of_to_plat = qe_gpio_of_to_plat,
165 .plat_auto = sizeof(struct qe_gpio_plat),
166 .of_match = qe_gpio_ids,
167 .probe = qe_gpio_probe,
168 .priv_auto = sizeof(struct qe_gpio_data),
169};