ARM: dts: npcm8xx: add npcm845 function node
[platform/kernel/u-boot.git] / drivers / gpio / qcom_pmic_gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Qualcomm generic pmic gpio driver
4  *
5  * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
6  */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <log.h>
11 #include <power/pmic.h>
12 #include <spmi/spmi.h>
13 #include <asm/io.h>
14 #include <asm/gpio.h>
15 #include <linux/bitops.h>
16
17 /* Register offset for each gpio */
18 #define REG_OFFSET(x)          ((x) * 0x100)
19
20 /* Register maps */
21
22 /* Type and subtype are shared for all PMIC peripherals */
23 #define REG_TYPE               0x4
24 #define REG_SUBTYPE            0x5
25
26 /* GPIO peripheral type and subtype out_values */
27 #define REG_TYPE_VAL            0x10
28 #define REG_SUBTYPE_GPIO_4CH    0x1
29 #define REG_SUBTYPE_GPIOC_4CH   0x5
30 #define REG_SUBTYPE_GPIO_8CH    0x9
31 #define REG_SUBTYPE_GPIOC_8CH   0xd
32 #define REG_SUBTYPE_GPIO_LV     0x10
33 #define REG_SUBTYPE_GPIO_MV     0x11
34
35 #define REG_STATUS             0x08
36 #define REG_STATUS_VAL_MASK    0x1
37
38 /* MODE_CTL */
39 #define REG_CTL         0x40
40 #define REG_CTL_MODE_MASK       0x70
41 #define REG_CTL_MODE_INPUT      0x00
42 #define REG_CTL_MODE_INOUT      0x20
43 #define REG_CTL_MODE_OUTPUT     0x10
44 #define REG_CTL_OUTPUT_MASK     0x0F
45 #define REG_CTL_LV_MV_MODE_MASK         0x3
46 #define REG_CTL_LV_MV_MODE_INPUT        0x0
47 #define REG_CTL_LV_MV_MODE_INOUT        0x2
48 #define REG_CTL_LV_MV_MODE_OUTPUT       0x1
49
50 #define REG_DIG_VIN_CTL        0x41
51 #define REG_DIG_VIN_VIN0       0
52
53 #define REG_DIG_PULL_CTL       0x42
54 #define REG_DIG_PULL_NO_PU     0x5
55
56 #define REG_LV_MV_OUTPUT_CTL    0x44
57 #define REG_LV_MV_OUTPUT_CTL_MASK       0x80
58 #define REG_LV_MV_OUTPUT_CTL_SHIFT      7
59
60 #define REG_DIG_OUT_CTL        0x45
61 #define REG_DIG_OUT_CTL_CMOS   (0x0 << 4)
62 #define REG_DIG_OUT_CTL_DRIVE_L 0x1
63
64 #define REG_EN_CTL             0x46
65 #define REG_EN_CTL_ENABLE      (1 << 7)
66
67 struct qcom_gpio_bank {
68         uint32_t pid; /* Peripheral ID on SPMI bus */
69         bool     lv_mv_type; /* If subtype is GPIO_LV(0x10) or GPIO_MV(0x11) */
70 };
71
72 static int qcom_gpio_set_direction(struct udevice *dev, unsigned offset,
73                                    bool input, int value)
74 {
75         struct qcom_gpio_bank *priv = dev_get_priv(dev);
76         uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
77         uint32_t reg_ctl_val;
78         int ret;
79
80         /* Disable the GPIO */
81         ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL,
82                               REG_EN_CTL_ENABLE, 0);
83         if (ret < 0)
84                 return ret;
85
86         /* Select the mode and output */
87         if (priv->lv_mv_type) {
88                 if (input)
89                         reg_ctl_val = REG_CTL_LV_MV_MODE_INPUT;
90                 else
91                         reg_ctl_val = REG_CTL_LV_MV_MODE_INOUT;
92         } else {
93                 if (input)
94                         reg_ctl_val = REG_CTL_MODE_INPUT;
95                 else
96                         reg_ctl_val = REG_CTL_MODE_INOUT | !!value;
97         }
98
99         ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, reg_ctl_val);
100         if (ret < 0)
101                 return ret;
102
103         if (priv->lv_mv_type && !input) {
104                 ret = pmic_reg_write(dev->parent,
105                                      gpio_base + REG_LV_MV_OUTPUT_CTL,
106                                      !!value << REG_LV_MV_OUTPUT_CTL_SHIFT);
107                 if (ret < 0)
108                         return ret;
109         }
110
111         /* Set the right pull (no pull) */
112         ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_PULL_CTL,
113                              REG_DIG_PULL_NO_PU);
114         if (ret < 0)
115                 return ret;
116
117         /* Configure output pin drivers if needed */
118         if (!input) {
119                 /* Select the VIN - VIN0, pin is input so it doesn't matter */
120                 ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_VIN_CTL,
121                                      REG_DIG_VIN_VIN0);
122                 if (ret < 0)
123                         return ret;
124
125                 /* Set the right dig out control */
126                 ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_OUT_CTL,
127                                      REG_DIG_OUT_CTL_CMOS |
128                                      REG_DIG_OUT_CTL_DRIVE_L);
129                 if (ret < 0)
130                         return ret;
131         }
132
133         /* Enable the GPIO */
134         return pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, 0,
135                                REG_EN_CTL_ENABLE);
136 }
137
138 static int qcom_gpio_direction_input(struct udevice *dev, unsigned offset)
139 {
140         return qcom_gpio_set_direction(dev, offset, true, 0);
141 }
142
143 static int qcom_gpio_direction_output(struct udevice *dev, unsigned offset,
144                                       int value)
145 {
146         return qcom_gpio_set_direction(dev, offset, false, value);
147 }
148
149 static int qcom_gpio_get_function(struct udevice *dev, unsigned offset)
150 {
151         struct qcom_gpio_bank *priv = dev_get_priv(dev);
152         uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
153         int reg;
154
155         reg = pmic_reg_read(dev->parent, gpio_base + REG_CTL);
156         if (reg < 0)
157                 return reg;
158
159         if (priv->lv_mv_type) {
160                 switch (reg & REG_CTL_LV_MV_MODE_MASK) {
161                 case REG_CTL_LV_MV_MODE_INPUT:
162                         return GPIOF_INPUT;
163                 case REG_CTL_LV_MV_MODE_INOUT: /* Fallthrough */
164                 case REG_CTL_LV_MV_MODE_OUTPUT:
165                         return GPIOF_OUTPUT;
166                 default:
167                         return GPIOF_UNKNOWN;
168                 }
169         } else {
170                 switch (reg & REG_CTL_MODE_MASK) {
171                 case REG_CTL_MODE_INPUT:
172                         return GPIOF_INPUT;
173                 case REG_CTL_MODE_INOUT: /* Fallthrough */
174                 case REG_CTL_MODE_OUTPUT:
175                         return GPIOF_OUTPUT;
176                 default:
177                         return GPIOF_UNKNOWN;
178                 }
179         }
180 }
181
182 static int qcom_gpio_get_value(struct udevice *dev, unsigned offset)
183 {
184         struct qcom_gpio_bank *priv = dev_get_priv(dev);
185         uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
186         int reg;
187
188         reg = pmic_reg_read(dev->parent, gpio_base + REG_STATUS);
189         if (reg < 0)
190                 return reg;
191
192         return !!(reg & REG_STATUS_VAL_MASK);
193 }
194
195 static int qcom_gpio_set_value(struct udevice *dev, unsigned offset,
196                                int value)
197 {
198         struct qcom_gpio_bank *priv = dev_get_priv(dev);
199         uint32_t gpio_base = priv->pid + REG_OFFSET(offset);
200
201         /* Set the output value of the gpio */
202         if (priv->lv_mv_type)
203                 return pmic_clrsetbits(dev->parent,
204                                        gpio_base + REG_LV_MV_OUTPUT_CTL,
205                                        REG_LV_MV_OUTPUT_CTL_MASK,
206                                        !!value << REG_LV_MV_OUTPUT_CTL_SHIFT);
207         else
208                 return pmic_clrsetbits(dev->parent, gpio_base + REG_CTL,
209                                        REG_CTL_OUTPUT_MASK, !!value);
210 }
211
212 static const struct dm_gpio_ops qcom_gpio_ops = {
213         .direction_input        = qcom_gpio_direction_input,
214         .direction_output       = qcom_gpio_direction_output,
215         .get_value              = qcom_gpio_get_value,
216         .set_value              = qcom_gpio_set_value,
217         .get_function           = qcom_gpio_get_function,
218 };
219
220 static int qcom_gpio_probe(struct udevice *dev)
221 {
222         struct qcom_gpio_bank *priv = dev_get_priv(dev);
223         int reg;
224
225         priv->pid = dev_read_addr(dev);
226         if (priv->pid == FDT_ADDR_T_NONE)
227                 return log_msg_ret("bad address", -EINVAL);
228
229         /* Do a sanity check */
230         reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE);
231         if (reg != REG_TYPE_VAL)
232                 return log_msg_ret("bad type", -ENXIO);
233
234         reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE);
235         if (reg != REG_SUBTYPE_GPIO_4CH && reg != REG_SUBTYPE_GPIOC_4CH &&
236             reg != REG_SUBTYPE_GPIO_LV && reg != REG_SUBTYPE_GPIO_MV)
237                 return log_msg_ret("bad subtype", -ENXIO);
238
239         priv->lv_mv_type = reg == REG_SUBTYPE_GPIO_LV ||
240                            reg == REG_SUBTYPE_GPIO_MV;
241
242         return 0;
243 }
244
245 static int qcom_gpio_of_to_plat(struct udevice *dev)
246 {
247         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
248
249         uc_priv->gpio_count = dev_read_u32_default(dev, "gpio-count", 0);
250         uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
251         if (uc_priv->bank_name == NULL)
252                 uc_priv->bank_name = "qcom_pmic";
253
254         return 0;
255 }
256
257 static const struct udevice_id qcom_gpio_ids[] = {
258         { .compatible = "qcom,pm8916-gpio" },
259         { .compatible = "qcom,pm8994-gpio" },   /* 22 GPIO's */
260         { .compatible = "qcom,pm8998-gpio" },
261         { .compatible = "qcom,pms405-gpio" },
262         { }
263 };
264
265 U_BOOT_DRIVER(qcom_pmic_gpio) = {
266         .name   = "qcom_pmic_gpio",
267         .id     = UCLASS_GPIO,
268         .of_match = qcom_gpio_ids,
269         .of_to_plat = qcom_gpio_of_to_plat,
270         .probe  = qcom_gpio_probe,
271         .ops    = &qcom_gpio_ops,
272         .priv_auto      = sizeof(struct qcom_gpio_bank),
273 };
274
275
276 /* Add pmic buttons as GPIO as well - there is no generic way for now */
277 #define PON_INT_RT_STS                        0x10
278 #define KPDPWR_ON_INT_BIT                     0
279 #define RESIN_ON_INT_BIT                      1
280
281 static int qcom_pwrkey_get_function(struct udevice *dev, unsigned offset)
282 {
283         return GPIOF_INPUT;
284 }
285
286 static int qcom_pwrkey_get_value(struct udevice *dev, unsigned offset)
287 {
288         struct qcom_gpio_bank *priv = dev_get_priv(dev);
289
290         int reg = pmic_reg_read(dev->parent, priv->pid + PON_INT_RT_STS);
291
292         if (reg < 0)
293                 return 0;
294
295         switch (offset) {
296         case 0: /* Power button */
297                 return (reg & BIT(KPDPWR_ON_INT_BIT)) != 0;
298                 break;
299         case 1: /* Reset button */
300         default:
301                 return (reg & BIT(RESIN_ON_INT_BIT)) != 0;
302                 break;
303         }
304 }
305
306 static const struct dm_gpio_ops qcom_pwrkey_ops = {
307         .get_value              = qcom_pwrkey_get_value,
308         .get_function           = qcom_pwrkey_get_function,
309 };
310
311 static int qcom_pwrkey_probe(struct udevice *dev)
312 {
313         struct qcom_gpio_bank *priv = dev_get_priv(dev);
314         int reg;
315
316         priv->pid = dev_read_addr(dev);
317         if (priv->pid == FDT_ADDR_T_NONE)
318                 return log_msg_ret("bad address", -EINVAL);
319
320         /* Do a sanity check */
321         reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE);
322         if (reg != 0x1)
323                 return log_msg_ret("bad type", -ENXIO);
324
325         reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE);
326         if ((reg & 0x5) == 0)
327                 return log_msg_ret("bad subtype", -ENXIO);
328
329         return 0;
330 }
331
332 static int qcom_pwrkey_of_to_plat(struct udevice *dev)
333 {
334         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
335
336         uc_priv->gpio_count = 2;
337         uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name");
338         if (uc_priv->bank_name == NULL)
339                 uc_priv->bank_name = "pwkey_qcom";
340
341         return 0;
342 }
343
344 static const struct udevice_id qcom_pwrkey_ids[] = {
345         { .compatible = "qcom,pm8916-pwrkey" },
346         { .compatible = "qcom,pm8994-pwrkey" },
347         { .compatible = "qcom,pm8998-pwrkey" },
348         { }
349 };
350
351 U_BOOT_DRIVER(pwrkey_qcom) = {
352         .name   = "pwrkey_qcom",
353         .id     = UCLASS_GPIO,
354         .of_match = qcom_pwrkey_ids,
355         .of_to_plat = qcom_pwrkey_of_to_plat,
356         .probe  = qcom_pwrkey_probe,
357         .ops    = &qcom_pwrkey_ops,
358         .priv_auto      = sizeof(struct qcom_gpio_bank),
359 };