ARM: dts: npcm8xx: add npcm845 function node
[platform/kernel/u-boot.git] / drivers / gpio / gpio_slg7xl45106.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * slg7xl45106_i2c_gpo driver
4  *
5  * Copyright (C) 2021 Xilinx, Inc.
6  */
7
8 #include <common.h>
9 #include <errno.h>
10 #include <asm/io.h>
11 #include <asm/gpio.h>
12 #include <dm.h>
13 #include <i2c.h>
14 #include <dt-bindings/gpio/gpio.h>
15 #include <asm/arch/hardware.h>
16
17 #define SLG7XL45106_REG         0xdb
18
19 static int slg7xl45106_i2c_gpo_direction_input(struct udevice *dev,
20                                                unsigned int offset)
21 {
22         return 0;
23 }
24
25 static int slg7xl45106_i2c_gpo_xlate(struct udevice *dev,
26                                      struct gpio_desc *desc,
27                                      struct ofnode_phandle_args *args)
28 {
29         desc->offset = (unsigned int)args->args[0];
30         desc->flags = (args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0);
31
32         return 0;
33 }
34
35 static int slg7xl45106_i2c_gpo_set_value(struct udevice *dev,
36                                          unsigned int offset, int value)
37 {
38         int ret;
39         u8 val;
40
41         ret = dm_i2c_read(dev, SLG7XL45106_REG, &val, 1);
42         if (ret)
43                 return ret;
44
45         if (value)
46                 val |= BIT(offset);
47         else
48                 val &= ~BIT(offset);
49
50         return dm_i2c_write(dev, SLG7XL45106_REG, &val, 1);
51 }
52
53 static int slg7xl45106_i2c_gpo_direction_output(struct udevice *dev,
54                                                 unsigned int offset, int value)
55 {
56         return slg7xl45106_i2c_gpo_set_value(dev, offset, value);
57 }
58
59 static int slg7xl45106_i2c_gpo_get_value(struct udevice *dev,
60                                          unsigned int offset)
61 {
62         int ret;
63         u8 val;
64
65         ret = dm_i2c_read(dev, SLG7XL45106_REG, &val, 1);
66         if (ret)
67                 return ret;
68
69         return !!(val & BIT(offset));
70 }
71
72 static int slg7xl45106_i2c_gpo_get_function(struct udevice *dev,
73                                             unsigned int offset)
74 {
75         return GPIOF_OUTPUT;
76 }
77
78 static const struct dm_gpio_ops slg7xl45106_i2c_gpo_ops = {
79         .direction_input = slg7xl45106_i2c_gpo_direction_input,
80         .direction_output = slg7xl45106_i2c_gpo_direction_output,
81         .get_value = slg7xl45106_i2c_gpo_get_value,
82         .set_value = slg7xl45106_i2c_gpo_set_value,
83         .get_function = slg7xl45106_i2c_gpo_get_function,
84         .xlate = slg7xl45106_i2c_gpo_xlate,
85 };
86
87 static int slg7xl45106_i2c_gpo_probe(struct udevice *dev)
88 {
89         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
90         const void *label_ptr;
91
92         label_ptr = dev_read_prop(dev, "label", NULL);
93         if (label_ptr) {
94                 uc_priv->bank_name = strdup(label_ptr);
95                 if (!uc_priv->bank_name)
96                         return -ENOMEM;
97         } else {
98                 uc_priv->bank_name = dev->name;
99         }
100
101         uc_priv->gpio_count = 8;
102
103         return 0;
104 }
105
106 static const struct udevice_id slg7xl45106_i2c_gpo_ids[] = {
107         { .compatible = "dlg,slg7xl45106",},
108         { }
109 };
110
111 U_BOOT_DRIVER(slg7xl45106_i2c_gpo) = {
112         .name = "slg7xl45106_i2c_gpo",
113         .id = UCLASS_GPIO,
114         .ops = &slg7xl45106_i2c_gpo_ops,
115         .of_match = slg7xl45106_i2c_gpo_ids,
116         .probe = slg7xl45106_i2c_gpo_probe,
117 };