aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2012-10-25 12:23:53 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-11-16 03:28:27 -0500
commit9b7a0c40de6c5c04371f8cdb9153a0a5a0af5243 (patch)
tree02a02f2c3b38e8504d58a2eb4e4fa815804faf78
parent29fb08c300b5cb626b8a803440aab25d0983cab7 (diff)
i2c: mux: Add dt support to i2c-mux-gpio driver
Allow the i2c-mux-gpio to be used by a device tree enabled device. The bindings are inspired by the one found in the i2c-mux-pinctrl driver. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Reviewed-by: Stephen Warren <swarren@nvidia.com> Acked-by: Peter Korsgaard <peter.korsgaard@barco.com> [wsa: fixed some whitespace] Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt81
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c145
2 files changed, 195 insertions, 31 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
new file mode 100644
index 00000000000..66709a82554
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
@@ -0,0 +1,81 @@
1GPIO-based I2C Bus Mux
2
3This binding describes an I2C bus multiplexer that uses GPIOs to
4route the I2C signals.
5
6 +-----+ +-----+
7 | dev | | dev |
8 +------------+ +-----+ +-----+
9 | SoC | | |
10 | | /--------+--------+
11 | +------+ | +------+ child bus A, on GPIO value set to 0
12 | | I2C |-|--| Mux |
13 | +------+ | +--+---+ child bus B, on GPIO value set to 1
14 | | | \----------+--------+--------+
15 | +------+ | | | | |
16 | | GPIO |-|-----+ +-----+ +-----+ +-----+
17 | +------+ | | dev | | dev | | dev |
18 +------------+ +-----+ +-----+ +-----+
19
20Required properties:
21- compatible: i2c-mux-gpio
22- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
23 port is connected to.
24- mux-gpios: list of gpios used to control the muxer
25* Standard I2C mux properties. See mux.txt in this directory.
26* I2C child bus nodes. See mux.txt in this directory.
27
28Optional properties:
29- idle-state: value to set the muxer to when idle. When no value is
30 given, it defaults to the last value used.
31
32For each i2c child node, an I2C child bus will be created. They will
33be numbered based on their order in the device tree.
34
35Whenever an access is made to a device on a child bus, the value set
36in the revelant node's reg property will be output using the list of
37GPIOs, the first in the list holding the least-significant value.
38
39If an idle state is defined, using the idle-state (optional) property,
40whenever an access is not being made to a device on a child bus, the
41GPIOs will be set according to the idle value.
42
43If an idle state is not defined, the most recently used value will be
44left programmed into hardware whenever no access is being made to a
45device on a child bus.
46
47Example:
48 i2cmux {
49 compatible = "i2c-mux-gpio";
50 #address-cells = <1>;
51 #size-cells = <0>;
52 mux-gpios = <&gpio1 22 0 &gpio1 23 0>;
53 i2c-parent = <&i2c1>;
54
55 i2c@1 {
56 reg = <1>;
57 #address-cells = <1>;
58 #size-cells = <0>;
59
60 ssd1307: oled@3c {
61 compatible = "solomon,ssd1307fb-i2c";
62 reg = <0x3c>;
63 pwms = <&pwm 4 3000>;
64 reset-gpios = <&gpio2 7 1>;
65 reset-active-low;
66 };
67 };
68
69 i2c@3 {
70 reg = <3>;
71 #address-cells = <1>;
72 #size-cells = <0>;
73
74 pca9555: pca9555@20 {
75 compatible = "nxp,pca9555";
76 gpio-controller;
77 #gpio-cells = <2>;
78 reg = <0x20>;
79 };
80 };
81 };
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 566a6757a33..3b7bc06fe8a 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -16,6 +16,8 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/gpio.h> 18#include <linux/gpio.h>
19#include <linux/of_i2c.h>
20#include <linux/of_gpio.h>
19 21
20struct gpiomux { 22struct gpiomux {
21 struct i2c_adapter *parent; 23 struct i2c_adapter *parent;
@@ -57,29 +59,110 @@ static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
57 return !strcmp(chip->label, data); 59 return !strcmp(chip->label, data);
58} 60}
59 61
62#ifdef CONFIG_OF
63static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
64 struct platform_device *pdev)
65{
66 struct device_node *np = pdev->dev.of_node;
67 struct device_node *adapter_np, *child;
68 struct i2c_adapter *adapter;
69 unsigned *values, *gpios;
70 int i = 0;
71
72 if (!np)
73 return -ENODEV;
74
75 adapter_np = of_parse_phandle(np, "i2c-parent", 0);
76 if (!adapter_np) {
77 dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
78 return -ENODEV;
79 }
80 adapter = of_find_i2c_adapter_by_node(adapter_np);
81 if (!adapter) {
82 dev_err(&pdev->dev, "Cannot find parent bus\n");
83 return -ENODEV;
84 }
85 mux->data.parent = i2c_adapter_id(adapter);
86 put_device(&adapter->dev);
87
88 mux->data.n_values = of_get_child_count(np);
89
90 values = devm_kzalloc(&pdev->dev,
91 sizeof(*mux->data.values) * mux->data.n_values,
92 GFP_KERNEL);
93 if (!values) {
94 dev_err(&pdev->dev, "Cannot allocate values array");
95 return -ENOMEM;
96 }
97
98 for_each_child_of_node(np, child) {
99 of_property_read_u32(child, "reg", values + i);
100 i++;
101 }
102 mux->data.values = values;
103
104 if (of_property_read_u32(np, "idle-state", &mux->data.idle))
105 mux->data.idle = I2C_MUX_GPIO_NO_IDLE;
106
107 mux->data.n_gpios = of_gpio_named_count(np, "mux-gpios");
108 if (mux->data.n_gpios < 0) {
109 dev_err(&pdev->dev, "Missing mux-gpios property in the DT.\n");
110 return -EINVAL;
111 }
112
113 gpios = devm_kzalloc(&pdev->dev,
114 sizeof(*mux->data.gpios) * mux->data.n_gpios, GFP_KERNEL);
115 if (!gpios) {
116 dev_err(&pdev->dev, "Cannot allocate gpios array");
117 return -ENOMEM;
118 }
119
120 for (i = 0; i < mux->data.n_gpios; i++)
121 gpios[i] = of_get_named_gpio(np, "mux-gpios", i);
122
123 mux->data.gpios = gpios;
124
125 return 0;
126}
127#else
128static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
129 struct platform_device *pdev)
130{
131 return 0;
132}
133#endif
134
60static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev) 135static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
61{ 136{
62 struct gpiomux *mux; 137 struct gpiomux *mux;
63 struct i2c_mux_gpio_platform_data *pdata;
64 struct i2c_adapter *parent; 138 struct i2c_adapter *parent;
65 int (*deselect) (struct i2c_adapter *, void *, u32); 139 int (*deselect) (struct i2c_adapter *, void *, u32);
66 unsigned initial_state, gpio_base; 140 unsigned initial_state, gpio_base;
67 int i, ret; 141 int i, ret;
68 142
69 pdata = pdev->dev.platform_data; 143 mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
70 if (!pdata) { 144 if (!mux) {
71 dev_err(&pdev->dev, "Missing platform data\n"); 145 dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
72 return -ENODEV; 146 return -ENOMEM;
73 } 147 }
74 148
149 platform_set_drvdata(pdev, mux);
150
151 if (!pdev->dev.platform_data) {
152 ret = i2c_mux_gpio_probe_dt(mux, pdev);
153 if (ret < 0)
154 return ret;
155 } else
156 memcpy(&mux->data, pdev->dev.platform_data, sizeof(mux->data));
157
75 /* 158 /*
76 * If a GPIO chip name is provided, the GPIO pin numbers provided are 159 * If a GPIO chip name is provided, the GPIO pin numbers provided are
77 * relative to its base GPIO number. Otherwise they are absolute. 160 * relative to its base GPIO number. Otherwise they are absolute.
78 */ 161 */
79 if (pdata->gpio_chip) { 162 if (mux->data.gpio_chip) {
80 struct gpio_chip *gpio; 163 struct gpio_chip *gpio;
81 164
82 gpio = gpiochip_find(pdata->gpio_chip, 165 gpio = gpiochip_find(mux->data.gpio_chip,
83 match_gpio_chip_by_label); 166 match_gpio_chip_by_label);
84 if (!gpio) 167 if (!gpio)
85 return -EPROBE_DEFER; 168 return -EPROBE_DEFER;
@@ -89,49 +172,44 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
89 gpio_base = 0; 172 gpio_base = 0;
90 } 173 }
91 174
92 parent = i2c_get_adapter(pdata->parent); 175 parent = i2c_get_adapter(mux->data.parent);
93 if (!parent) { 176 if (!parent) {
94 dev_err(&pdev->dev, "Parent adapter (%d) not found\n", 177 dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
95 pdata->parent); 178 mux->data.parent);
96 return -ENODEV; 179 return -ENODEV;
97 } 180 }
98 181
99 mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
100 if (!mux) {
101 ret = -ENOMEM;
102 goto alloc_failed;
103 }
104
105 mux->parent = parent; 182 mux->parent = parent;
106 mux->data = *pdata;
107 mux->gpio_base = gpio_base; 183 mux->gpio_base = gpio_base;
184
108 mux->adap = devm_kzalloc(&pdev->dev, 185 mux->adap = devm_kzalloc(&pdev->dev,
109 sizeof(*mux->adap) * pdata->n_values, 186 sizeof(*mux->adap) * mux->data.n_values,
110 GFP_KERNEL); 187 GFP_KERNEL);
111 if (!mux->adap) { 188 if (!mux->adap) {
189 dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
112 ret = -ENOMEM; 190 ret = -ENOMEM;
113 goto alloc_failed; 191 goto alloc_failed;
114 } 192 }
115 193
116 if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) { 194 if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
117 initial_state = pdata->idle; 195 initial_state = mux->data.idle;
118 deselect = i2c_mux_gpio_deselect; 196 deselect = i2c_mux_gpio_deselect;
119 } else { 197 } else {
120 initial_state = pdata->values[0]; 198 initial_state = mux->data.values[0];
121 deselect = NULL; 199 deselect = NULL;
122 } 200 }
123 201
124 for (i = 0; i < pdata->n_gpios; i++) { 202 for (i = 0; i < mux->data.n_gpios; i++) {
125 ret = gpio_request(gpio_base + pdata->gpios[i], "i2c-mux-gpio"); 203 ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
126 if (ret) 204 if (ret)
127 goto err_request_gpio; 205 goto err_request_gpio;
128 gpio_direction_output(gpio_base + pdata->gpios[i], 206 gpio_direction_output(gpio_base + mux->data.gpios[i],
129 initial_state & (1 << i)); 207 initial_state & (1 << i));
130 } 208 }
131 209
132 for (i = 0; i < pdata->n_values; i++) { 210 for (i = 0; i < mux->data.n_values; i++) {
133 u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; 211 u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
134 unsigned int class = pdata->classes ? pdata->classes[i] : 0; 212 unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
135 213
136 mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, 214 mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
137 i, class, 215 i, class,
@@ -144,19 +222,17 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
144 } 222 }
145 223
146 dev_info(&pdev->dev, "%d port mux on %s adapter\n", 224 dev_info(&pdev->dev, "%d port mux on %s adapter\n",
147 pdata->n_values, parent->name); 225 mux->data.n_values, parent->name);
148
149 platform_set_drvdata(pdev, mux);
150 226
151 return 0; 227 return 0;
152 228
153add_adapter_failed: 229add_adapter_failed:
154 for (; i > 0; i--) 230 for (; i > 0; i--)
155 i2c_del_mux_adapter(mux->adap[i - 1]); 231 i2c_del_mux_adapter(mux->adap[i - 1]);
156 i = pdata->n_gpios; 232 i = mux->data.n_gpios;
157err_request_gpio: 233err_request_gpio:
158 for (; i > 0; i--) 234 for (; i > 0; i--)
159 gpio_free(gpio_base + pdata->gpios[i - 1]); 235 gpio_free(gpio_base + mux->data.gpios[i - 1]);
160alloc_failed: 236alloc_failed:
161 i2c_put_adapter(parent); 237 i2c_put_adapter(parent);
162 238
@@ -180,12 +256,19 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
180 return 0; 256 return 0;
181} 257}
182 258
259static const struct of_device_id i2c_mux_gpio_of_match[] __devinitconst = {
260 { .compatible = "i2c-mux-gpio", },
261 {},
262};
263MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match);
264
183static struct platform_driver i2c_mux_gpio_driver = { 265static struct platform_driver i2c_mux_gpio_driver = {
184 .probe = i2c_mux_gpio_probe, 266 .probe = i2c_mux_gpio_probe,
185 .remove = __devexit_p(i2c_mux_gpio_remove), 267 .remove = __devexit_p(i2c_mux_gpio_remove),
186 .driver = { 268 .driver = {
187 .owner = THIS_MODULE, 269 .owner = THIS_MODULE,
188 .name = "i2c-mux-gpio", 270 .name = "i2c-mux-gpio",
271 .of_match_table = of_match_ptr(i2c_mux_gpio_of_match),
189 }, 272 },
190}; 273};
191 274