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