2 * Pinctrl based I2C DeMultiplexer
4 * Copyright (C) 2015-16 by Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
5 * Copyright (C) 2015-16 by Renesas Electronics Corporation
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; version 2 of the License.
11 * See the bindings doc for DTS setup and the sysfs doc for usage information.
12 * (look for filenames containing 'i2c-demux-pinctrl' in Documentation/)
15 #include <linux/i2c.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
19 #include <linux/pinctrl/consumer.h>
20 #include <linux/platform_device.h>
21 #include <linux/slab.h>
22 #include <linux/sysfs.h>
24 struct i2c_demux_pinctrl_chan
{
25 struct device_node
*parent_np
;
26 struct i2c_adapter
*parent_adap
;
27 struct of_changeset chgset
;
30 struct i2c_demux_pinctrl_priv
{
35 struct i2c_adapter cur_adap
;
36 struct i2c_algorithm algo
;
37 struct i2c_demux_pinctrl_chan chan
[];
40 static struct property status_okay
= { .name
= "status", .length
= 3, .value
= "ok" };
42 static int i2c_demux_master_xfer(struct i2c_adapter
*adap
, struct i2c_msg msgs
[], int num
)
44 struct i2c_demux_pinctrl_priv
*priv
= adap
->algo_data
;
45 struct i2c_adapter
*parent
= priv
->chan
[priv
->cur_chan
].parent_adap
;
47 return __i2c_transfer(parent
, msgs
, num
);
50 static u32
i2c_demux_functionality(struct i2c_adapter
*adap
)
52 struct i2c_demux_pinctrl_priv
*priv
= adap
->algo_data
;
53 struct i2c_adapter
*parent
= priv
->chan
[priv
->cur_chan
].parent_adap
;
55 return parent
->algo
->functionality(parent
);
58 static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv
*priv
, u32 new_chan
)
60 struct i2c_adapter
*adap
;
64 ret
= of_changeset_apply(&priv
->chan
[new_chan
].chgset
);
68 adap
= of_find_i2c_adapter_by_node(priv
->chan
[new_chan
].parent_np
);
74 p
= devm_pinctrl_get_select(adap
->dev
.parent
, priv
->bus_name
);
80 priv
->chan
[new_chan
].parent_adap
= adap
;
81 priv
->cur_chan
= new_chan
;
83 /* Now fill out current adapter structure. cur_chan must be up to date */
84 priv
->algo
.master_xfer
= i2c_demux_master_xfer
;
85 priv
->algo
.functionality
= i2c_demux_functionality
;
87 snprintf(priv
->cur_adap
.name
, sizeof(priv
->cur_adap
.name
),
88 "i2c-demux (master i2c-%d)", i2c_adapter_id(adap
));
89 priv
->cur_adap
.owner
= THIS_MODULE
;
90 priv
->cur_adap
.algo
= &priv
->algo
;
91 priv
->cur_adap
.algo_data
= priv
;
92 priv
->cur_adap
.dev
.parent
= priv
->dev
;
93 priv
->cur_adap
.class = adap
->class;
94 priv
->cur_adap
.retries
= adap
->retries
;
95 priv
->cur_adap
.timeout
= adap
->timeout
;
96 priv
->cur_adap
.quirks
= adap
->quirks
;
97 priv
->cur_adap
.dev
.of_node
= priv
->dev
->of_node
;
98 ret
= i2c_add_adapter(&priv
->cur_adap
);
105 i2c_put_adapter(adap
);
107 dev_err(priv
->dev
, "failed to setup demux-adapter %d (%d)\n", new_chan
, ret
);
111 static int i2c_demux_deactivate_master(struct i2c_demux_pinctrl_priv
*priv
)
113 int ret
, cur
= priv
->cur_chan
;
118 i2c_del_adapter(&priv
->cur_adap
);
119 i2c_put_adapter(priv
->chan
[cur
].parent_adap
);
121 ret
= of_changeset_revert(&priv
->chan
[cur
].chgset
);
123 priv
->chan
[cur
].parent_adap
= NULL
;
124 priv
->cur_chan
= -EINVAL
;
129 static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv
*priv
, u32 new_chan
)
133 if (new_chan
== priv
->cur_chan
)
136 ret
= i2c_demux_deactivate_master(priv
);
140 return i2c_demux_activate_master(priv
, new_chan
);
143 static ssize_t
cur_master_show(struct device
*dev
, struct device_attribute
*attr
,
146 struct i2c_demux_pinctrl_priv
*priv
= dev_get_drvdata(dev
);
149 for (i
= 0; i
< priv
->num_chan
&& count
< PAGE_SIZE
; i
++)
150 count
+= scnprintf(buf
+ count
, PAGE_SIZE
- count
, "%c %d - %s\n",
151 i
== priv
->cur_chan
? '*' : ' ', i
,
152 priv
->chan
[i
].parent_np
->full_name
);
157 static ssize_t
cur_master_store(struct device
*dev
, struct device_attribute
*attr
,
158 const char *buf
, size_t count
)
160 struct i2c_demux_pinctrl_priv
*priv
= dev_get_drvdata(dev
);
164 ret
= kstrtouint(buf
, 0, &val
);
168 if (val
>= priv
->num_chan
)
171 ret
= i2c_demux_change_master(priv
, val
);
173 return ret
< 0 ? ret
: count
;
175 static DEVICE_ATTR_RW(cur_master
);
177 static int i2c_demux_pinctrl_probe(struct platform_device
*pdev
)
179 struct device_node
*np
= pdev
->dev
.of_node
;
180 struct i2c_demux_pinctrl_priv
*priv
;
181 int num_chan
, i
, j
, err
;
183 num_chan
= of_count_phandle_with_args(np
, "i2c-parent", NULL
);
185 dev_err(&pdev
->dev
, "Need at least two I2C masters to switch\n");
189 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
)
190 + num_chan
* sizeof(struct i2c_demux_pinctrl_chan
), GFP_KERNEL
);
194 err
= of_property_read_string(np
, "i2c-bus-name", &priv
->bus_name
);
198 for (i
= 0; i
< num_chan
; i
++) {
199 struct device_node
*adap_np
;
201 adap_np
= of_parse_phandle(np
, "i2c-parent", i
);
203 dev_err(&pdev
->dev
, "can't get phandle for parent %d\n", i
);
207 priv
->chan
[i
].parent_np
= adap_np
;
209 of_changeset_init(&priv
->chan
[i
].chgset
);
210 of_changeset_update_property(&priv
->chan
[i
].chgset
, adap_np
, &status_okay
);
213 priv
->num_chan
= num_chan
;
214 priv
->dev
= &pdev
->dev
;
216 platform_set_drvdata(pdev
, priv
);
218 /* switch to first parent as active master */
219 i2c_demux_activate_master(priv
, 0);
221 err
= device_create_file(&pdev
->dev
, &dev_attr_cur_master
);
228 for (j
= 0; j
< i
; j
++) {
229 of_node_put(priv
->chan
[j
].parent_np
);
230 of_changeset_destroy(&priv
->chan
[j
].chgset
);
236 static int i2c_demux_pinctrl_remove(struct platform_device
*pdev
)
238 struct i2c_demux_pinctrl_priv
*priv
= platform_get_drvdata(pdev
);
241 device_remove_file(&pdev
->dev
, &dev_attr_cur_master
);
243 i2c_demux_deactivate_master(priv
);
245 for (i
= 0; i
< priv
->num_chan
; i
++) {
246 of_node_put(priv
->chan
[i
].parent_np
);
247 of_changeset_destroy(&priv
->chan
[i
].chgset
);
253 static const struct of_device_id i2c_demux_pinctrl_of_match
[] = {
254 { .compatible
= "i2c-demux-pinctrl", },
257 MODULE_DEVICE_TABLE(of
, i2c_demux_pinctrl_of_match
);
259 static struct platform_driver i2c_demux_pinctrl_driver
= {
261 .name
= "i2c-demux-pinctrl",
262 .of_match_table
= i2c_demux_pinctrl_of_match
,
264 .probe
= i2c_demux_pinctrl_probe
,
265 .remove
= i2c_demux_pinctrl_remove
,
267 module_platform_driver(i2c_demux_pinctrl_driver
);
269 MODULE_DESCRIPTION("pinctrl-based I2C demux driver");
270 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
271 MODULE_LICENSE("GPL v2");
272 MODULE_ALIAS("platform:i2c-demux-pinctrl");