]> git.sur5r.net Git - u-boot/blob - drivers/i2c/muxes/i2c-mux-gpio.c
SPDX: Convert a few files that were missed before
[u-boot] / drivers / i2c / muxes / i2c-mux-gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * I2C multiplexer using GPIO API
4  *
5  * Copyright 2017 NXP
6  *
7  * Peng Fan <peng.fan@nxp.com>
8  */
9
10 #include <asm/io.h>
11 #include <asm-generic/gpio.h>
12 #include <common.h>
13 #include <dm.h>
14 #include <dm/pinctrl.h>
15 #include <fdtdec.h>
16 #include <i2c.h>
17 #include <linux/errno.h>
18
19 DECLARE_GLOBAL_DATA_PTR;
20
21 /**
22  * struct i2c_mux_gpio_priv - private data for i2c mux gpio
23  *
24  * @values: the reg value of each child node
25  * @n_values: num of regs
26  * @gpios: the mux-gpios array
27  * @n_gpios: num of gpios in mux-gpios
28  * @idle: the value of idle-state
29  */
30 struct i2c_mux_gpio_priv {
31         u32 *values;
32         int n_values;
33         struct gpio_desc *gpios;
34         int n_gpios;
35         u32 idle;
36 };
37
38
39 static int i2c_mux_gpio_select(struct udevice *dev, struct udevice *bus,
40                                uint channel)
41 {
42         struct i2c_mux_gpio_priv *priv = dev_get_priv(dev);
43         int i, ret;
44
45         for (i = 0; i < priv->n_gpios; i++) {
46                 ret = dm_gpio_set_value(&priv->gpios[i], (channel >> i) & 1);
47                 if (ret)
48                         return ret;
49         }
50
51         return 0;
52 }
53
54 static int i2c_mux_gpio_deselect(struct udevice *dev, struct udevice *bus,
55                                  uint channel)
56 {
57         struct i2c_mux_gpio_priv *priv = dev_get_priv(dev);
58         int i, ret;
59
60         for (i = 0; i < priv->n_gpios; i++) {
61                 ret = dm_gpio_set_value(&priv->gpios[i], (priv->idle >> i) & 1);
62                 if (ret)
63                         return ret;
64         }
65
66         return 0;
67 }
68
69 static int i2c_mux_gpio_probe(struct udevice *dev)
70 {
71         const void *fdt = gd->fdt_blob;
72         int node = dev_of_offset(dev);
73         struct i2c_mux_gpio_priv *mux = dev_get_priv(dev);
74         struct gpio_desc *gpios;
75         u32 *values;
76         int i = 0, subnode, ret;
77
78         mux->n_values = fdtdec_get_child_count(fdt, node);
79         values = devm_kzalloc(dev, sizeof(*mux->values) * mux->n_values,
80                               GFP_KERNEL);
81         if (!values) {
82                 dev_err(dev, "Cannot alloc values array");
83                 return -ENOMEM;
84         }
85
86         fdt_for_each_subnode(subnode, fdt, node) {
87                 *(values + i) = fdtdec_get_uint(fdt, subnode, "reg", -1);
88                 i++;
89         }
90
91         mux->values = values;
92
93         mux->idle = fdtdec_get_uint(fdt, node, "idle-state", -1);
94
95         mux->n_gpios = gpio_get_list_count(dev, "mux-gpios");
96         if (mux->n_gpios < 0) {
97                 dev_err(dev, "Missing mux-gpios property\n");
98                 return -EINVAL;
99         }
100
101         gpios = devm_kzalloc(dev, sizeof(struct gpio_desc) * mux->n_gpios,
102                              GFP_KERNEL);
103         if (!gpios) {
104                 dev_err(dev, "Cannot allocate gpios array\n");
105                 return -ENOMEM;
106         }
107
108         ret = gpio_request_list_by_name(dev, "mux-gpios", gpios, mux->n_gpios,
109                                         GPIOD_IS_OUT_ACTIVE);
110         if (ret <= 0) {
111                 dev_err(dev, "Failed to request mux-gpios\n");
112                 return ret;
113         }
114
115         mux->gpios = gpios;
116
117         return 0;
118 }
119
120 static const struct i2c_mux_ops i2c_mux_gpio_ops = {
121         .select = i2c_mux_gpio_select,
122         .deselect = i2c_mux_gpio_deselect,
123 };
124
125 static const struct udevice_id i2c_mux_gpio_ids[] = {
126         { .compatible = "i2c-mux-gpio", },
127         {}
128 };
129
130 U_BOOT_DRIVER(i2c_mux_gpio) = {
131         .name = "i2c_mux_gpio",
132         .id = UCLASS_I2C_MUX,
133         .of_match = i2c_mux_gpio_ids,
134         .ops = &i2c_mux_gpio_ops,
135         .probe = i2c_mux_gpio_probe,
136         .priv_auto_alloc_size = sizeof(struct i2c_mux_gpio_priv),
137 };