Merge branch '2021-10-19-assorted-changes'
[platform/kernel/u-boot.git] / drivers / gpio / max7320_gpio.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * max7320 I2C GPIO EXPANDER DRIVER
4  *
5  * Copyright (C) 2021 Hannes Schmelzer <oe5hpm@oevsv.at>
6  * B&R Industrial Automation GmbH - http://www.br-automation.com
7  *
8  */
9
10 #include <common.h>
11 #include <dm.h>
12 #include <i2c.h>
13 #include <asm-generic/gpio.h>
14 #include <linux/bitops.h>
15
16 struct max7320_chip {
17         u32 outreg;
18 };
19
20 static int max7320_direction_output(struct udevice *dev,
21                                     unsigned int offset, int value)
22 {
23         struct max7320_chip *plat = dev_get_plat(dev);
24         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
25         struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
26
27         int ret;
28
29         if (value)
30                 plat->outreg |= BIT(offset);
31         else
32                 plat->outreg &= ~BIT(offset);
33
34         ret = dm_i2c_write(dev,
35                            plat->outreg & 0xff,
36                            (uint8_t *)&plat->outreg + 1,
37                            uc_priv->gpio_count > 8 ? 1 : 0);
38         if (ret)
39                 printf("%s i2c write failed to addr %x\n", __func__,
40                        chip->chip_addr);
41
42         return ret;
43 }
44
45 static int max7320_get_value(struct udevice *dev, unsigned int offset)
46 {
47         struct max7320_chip *plat = dev_get_plat(dev);
48
49         return (plat->outreg >> offset) & 0x1;
50 }
51
52 static int max7320_set_value(struct udevice *dev, unsigned int offset,
53                              int value)
54 {
55         return max7320_direction_output(dev, offset, value);
56 }
57
58 static int max7320_get_function(struct udevice *dev, unsigned int offset)
59 {
60         return GPIOF_OUTPUT;
61 }
62
63 static int max7320_ofdata_plat(struct udevice *dev)
64 {
65         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
66
67         uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", 8);
68         if (uc_priv->gpio_count > 16) {
69                 printf("%s: max7320 doesn't support more than 16 gpios!",
70                        __func__);
71                 return -EINVAL;
72         }
73
74         uc_priv->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
75                                          "gpio-bank-name", NULL);
76         if (!uc_priv->bank_name)
77                 uc_priv->bank_name = fdt_get_name(gd->fdt_blob,
78                                                   dev_of_offset(dev), NULL);
79
80         return 0;
81 }
82
83 static int max7320_gpio_probe(struct udevice  *dev)
84 {
85         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
86
87         debug("%s GPIO controller with %d gpios probed\n",
88               uc_priv->bank_name, uc_priv->gpio_count);
89
90         return 0;
91 }
92
93 static const struct dm_gpio_ops max7320_gpio_ops = {
94         .direction_output       = max7320_direction_output,
95         .set_value              = max7320_set_value,
96         .get_value              = max7320_get_value,
97         .get_function           = max7320_get_function,
98 };
99
100 static const struct udevice_id max7320_gpio_ids[] = {
101         { .compatible = "maxim,max7320" },
102         { }
103 };
104
105 U_BOOT_DRIVER(gpio_max7320) = {
106         .name           = "gpio_max7320",
107         .id             = UCLASS_GPIO,
108         .ops            = &max7320_gpio_ops,
109         .of_match       = max7320_gpio_ids,
110         .of_to_plat     = max7320_ofdata_plat,
111         .probe          = max7320_gpio_probe,
112         .plat_auto      = sizeof(struct max7320_chip),
113 };