Merge git://git.denx.de/u-boot-socfpga
[platform/kernel/u-boot.git] / drivers / power / pmic / as3722_gpio.c
1 /*
2  * Copyright (C) 2014 NVIDIA Corporation
3  *
4  * SPDX-License-Identifier: GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <asm/gpio.h>
10 #include <power/as3722.h>
11 #include <power/pmic.h>
12
13 #define NUM_GPIOS       8
14
15 int as3722_gpio_configure(struct udevice *pmic, unsigned int gpio,
16                           unsigned long flags)
17 {
18         u8 value = 0;
19         int err;
20
21         if (flags & AS3722_GPIO_OUTPUT_VDDH)
22                 value |= AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
23
24         if (flags & AS3722_GPIO_INVERT)
25                 value |= AS3722_GPIO_CONTROL_INVERT;
26
27         err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
28         if (err) {
29                 error("failed to configure GPIO#%u: %d", gpio, err);
30                 return err;
31         }
32
33         return 0;
34 }
35
36 static int as3722_gpio_set_value(struct udevice *dev, unsigned int gpio,
37                                  int level)
38 {
39         struct udevice *pmic = dev_get_parent(dev);
40         const char *l;
41         u8 value;
42         int err;
43
44         if (gpio >= NUM_GPIOS)
45                 return -EINVAL;
46
47         err = pmic_reg_read(pmic, AS3722_GPIO_SIGNAL_OUT);
48         if (err < 0) {
49                 error("failed to read GPIO signal out register: %d", err);
50                 return err;
51         }
52         value = err;
53
54         if (level == 0) {
55                 value &= ~(1 << gpio);
56                 l = "low";
57         } else {
58                 value |= 1 << gpio;
59                 l = "high";
60         }
61
62         err = pmic_reg_write(pmic, AS3722_GPIO_SIGNAL_OUT, value);
63         if (err) {
64                 error("failed to set GPIO#%u %s: %d", gpio, l, err);
65                 return err;
66         }
67
68         return 0;
69 }
70
71 int as3722_gpio_direction_output(struct udevice *dev, unsigned int gpio,
72                                  int value)
73 {
74         struct udevice *pmic = dev_get_parent(dev);
75         int err;
76
77         if (gpio > 7)
78                 return -EINVAL;
79
80         if (value == 0)
81                 value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDL;
82         else
83                 value = AS3722_GPIO_CONTROL_MODE_OUTPUT_VDDH;
84
85         err = pmic_reg_write(pmic, AS3722_GPIO_CONTROL(gpio), value);
86         if (err) {
87                 error("failed to configure GPIO#%u as output: %d", gpio, err);
88                 return err;
89         }
90
91         err = as3722_gpio_set_value(pmic, gpio, value);
92         if (err < 0) {
93                 error("failed to set GPIO#%u high: %d", gpio, err);
94                 return err;
95         }
96
97         return 0;
98 }
99
100 static int as3722_gpio_probe(struct udevice *dev)
101 {
102         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
103
104         uc_priv->gpio_count = NUM_GPIOS;
105         uc_priv->bank_name = "as3722_";
106
107         return 0;
108 }
109
110 static const struct dm_gpio_ops gpio_as3722_ops = {
111         .direction_output       = as3722_gpio_direction_output,
112         .set_value              = as3722_gpio_set_value,
113 };
114
115 U_BOOT_DRIVER(gpio_as3722) = {
116         .name   = "gpio_as3722",
117         .id     = UCLASS_GPIO,
118         .ops    = &gpio_as3722_ops,
119         .probe  = as3722_gpio_probe,
120 };