diff options
author | Maxime Ripard <maxime.ripard@free-electrons.com> | 2012-10-25 12:23:53 -0400 |
---|---|---|
committer | Wolfram Sang <w.sang@pengutronix.de> | 2012-11-16 03:28:27 -0500 |
commit | 9b7a0c40de6c5c04371f8cdb9153a0a5a0af5243 (patch) | |
tree | 02a02f2c3b38e8504d58a2eb4e4fa815804faf78 | |
parent | 29fb08c300b5cb626b8a803440aab25d0983cab7 (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.txt | 81 | ||||
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-gpio.c | 145 |
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 @@ | |||
1 | GPIO-based I2C Bus Mux | ||
2 | |||
3 | This binding describes an I2C bus multiplexer that uses GPIOs to | ||
4 | route 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 | |||
20 | Required 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 | |||
28 | Optional 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 | |||
32 | For each i2c child node, an I2C child bus will be created. They will | ||
33 | be numbered based on their order in the device tree. | ||
34 | |||
35 | Whenever an access is made to a device on a child bus, the value set | ||
36 | in the revelant node's reg property will be output using the list of | ||
37 | GPIOs, the first in the list holding the least-significant value. | ||
38 | |||
39 | If an idle state is defined, using the idle-state (optional) property, | ||
40 | whenever an access is not being made to a device on a child bus, the | ||
41 | GPIOs will be set according to the idle value. | ||
42 | |||
43 | If an idle state is not defined, the most recently used value will be | ||
44 | left programmed into hardware whenever no access is being made to a | ||
45 | device on a child bus. | ||
46 | |||
47 | Example: | ||
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 | ||
20 | struct gpiomux { | 22 | struct 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 | ||
63 | static 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 | ||
128 | static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux, | ||
129 | struct platform_device *pdev) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | #endif | ||
134 | |||
60 | static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev) | 135 | static 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 | ||
153 | add_adapter_failed: | 229 | add_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; |
157 | err_request_gpio: | 233 | err_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]); |
160 | alloc_failed: | 236 | alloc_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 | ||
259 | static const struct of_device_id i2c_mux_gpio_of_match[] __devinitconst = { | ||
260 | { .compatible = "i2c-mux-gpio", }, | ||
261 | {}, | ||
262 | }; | ||
263 | MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match); | ||
264 | |||
183 | static struct platform_driver i2c_mux_gpio_driver = { | 265 | static 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 | ||