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 /drivers/i2c | |
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>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-gpio.c | 145 |
1 files changed, 114 insertions, 31 deletions
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 566a6757a33d..3b7bc06fe8a6 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 | ||