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 int i2c_demux_master_xfer(struct i2c_adapter
*adap
, struct i2c_msg msgs
[], int num
)
42 struct i2c_demux_pinctrl_priv
*priv
= adap
->algo_data
;
43 struct i2c_adapter
*parent
= priv
->chan
[priv
->cur_chan
].parent_adap
;
45 return __i2c_transfer(parent
, msgs
, num
);
48 static u32
i2c_demux_functionality(struct i2c_adapter
*adap
)
50 struct i2c_demux_pinctrl_priv
*priv
= adap
->algo_data
;
51 struct i2c_adapter
*parent
= priv
->chan
[priv
->cur_chan
].parent_adap
;
53 return parent
->algo
->functionality(parent
);
56 static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv
*priv
, u32 new_chan
)
58 struct i2c_adapter
*adap
;
62 ret
= of_changeset_apply(&priv
->chan
[new_chan
].chgset
);
66 adap
= of_find_i2c_adapter_by_node(priv
->chan
[new_chan
].parent_np
);
72 p
= devm_pinctrl_get_select(adap
->dev
.parent
, priv
->bus_name
);
78 priv
->chan
[new_chan
].parent_adap
= adap
;
79 priv
->cur_chan
= new_chan
;
81 /* Now fill out current adapter structure. cur_chan must be up to date */
82 priv
->algo
.master_xfer
= i2c_demux_master_xfer
;
83 priv
->algo
.functionality
= i2c_demux_functionality
;
85 snprintf(priv
->cur_adap
.name
, sizeof(priv
->cur_adap
.name
),
86 "i2c-demux (master i2c-%d)", i2c_adapter_id(adap
));
87 priv
->cur_adap
.owner
= THIS_MODULE
;
88 priv
->cur_adap
.algo
= &priv
->algo
;
89 priv
->cur_adap
.algo_data
= priv
;
90 priv
->cur_adap
.dev
.parent
= priv
->dev
;
91 priv
->cur_adap
.class = adap
->class;
92 priv
->cur_adap
.retries
= adap
->retries
;
93 priv
->cur_adap
.timeout
= adap
->timeout
;
94 priv
->cur_adap
.quirks
= adap
->quirks
;
95 priv
->cur_adap
.dev
.of_node
= priv
->dev
->of_node
;
96 ret
= i2c_add_adapter(&priv
->cur_adap
);
103 i2c_put_adapter(adap
);
105 of_changeset_revert(&priv
->chan
[new_chan
].chgset
);
107 dev_err(priv
->dev
, "failed to setup demux-adapter %d (%d)\n", new_chan
, ret
);
108 priv
->cur_chan
= -EINVAL
;
112 static int i2c_demux_deactivate_master(struct i2c_demux_pinctrl_priv
*priv
)
114 int ret
, cur
= priv
->cur_chan
;
119 i2c_del_adapter(&priv
->cur_adap
);
120 i2c_put_adapter(priv
->chan
[cur
].parent_adap
);
122 ret
= of_changeset_revert(&priv
->chan
[cur
].chgset
);
124 priv
->chan
[cur
].parent_adap
= NULL
;
125 priv
->cur_chan
= -EINVAL
;
130 static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv
*priv
, u32 new_chan
)
134 if (new_chan
== priv
->cur_chan
)
137 ret
= i2c_demux_deactivate_master(priv
);
141 return i2c_demux_activate_master(priv
, new_chan
);
144 static ssize_t
available_masters_show(struct device
*dev
,
145 struct device_attribute
*attr
,
148 struct i2c_demux_pinctrl_priv
*priv
= dev_get_drvdata(dev
);
151 for (i
= 0; i
< priv
->num_chan
&& count
< PAGE_SIZE
; i
++)
152 count
+= scnprintf(buf
+ count
, PAGE_SIZE
- count
, "%d:%s%c",
153 i
, priv
->chan
[i
].parent_np
->full_name
,
154 i
== priv
->num_chan
- 1 ? '\n' : ' ');
158 static DEVICE_ATTR_RO(available_masters
);
160 static ssize_t
current_master_show(struct device
*dev
,
161 struct device_attribute
*attr
,
164 struct i2c_demux_pinctrl_priv
*priv
= dev_get_drvdata(dev
);
166 return sprintf(buf
, "%d\n", priv
->cur_chan
);
169 static ssize_t
current_master_store(struct device
*dev
,
170 struct device_attribute
*attr
,
171 const char *buf
, size_t count
)
173 struct i2c_demux_pinctrl_priv
*priv
= dev_get_drvdata(dev
);
177 ret
= kstrtouint(buf
, 0, &val
);
181 if (val
>= priv
->num_chan
)
184 ret
= i2c_demux_change_master(priv
, val
);
186 return ret
< 0 ? ret
: count
;
188 static DEVICE_ATTR_RW(current_master
);
190 static int i2c_demux_pinctrl_probe(struct platform_device
*pdev
)
192 struct device_node
*np
= pdev
->dev
.of_node
;
193 struct i2c_demux_pinctrl_priv
*priv
;
194 struct property
*props
;
195 int num_chan
, i
, j
, err
;
197 num_chan
= of_count_phandle_with_args(np
, "i2c-parent", NULL
);
199 dev_err(&pdev
->dev
, "Need at least two I2C masters to switch\n");
203 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
)
204 + num_chan
* sizeof(struct i2c_demux_pinctrl_chan
), GFP_KERNEL
);
206 props
= devm_kcalloc(&pdev
->dev
, num_chan
, sizeof(*props
), GFP_KERNEL
);
211 err
= of_property_read_string(np
, "i2c-bus-name", &priv
->bus_name
);
215 for (i
= 0; i
< num_chan
; i
++) {
216 struct device_node
*adap_np
;
218 adap_np
= of_parse_phandle(np
, "i2c-parent", i
);
220 dev_err(&pdev
->dev
, "can't get phandle for parent %d\n", i
);
224 priv
->chan
[i
].parent_np
= adap_np
;
226 props
[i
].name
= devm_kstrdup(&pdev
->dev
, "status", GFP_KERNEL
);
227 props
[i
].value
= devm_kstrdup(&pdev
->dev
, "ok", GFP_KERNEL
);
230 of_changeset_init(&priv
->chan
[i
].chgset
);
231 of_changeset_update_property(&priv
->chan
[i
].chgset
, adap_np
, &props
[i
]);
234 priv
->num_chan
= num_chan
;
235 priv
->dev
= &pdev
->dev
;
237 platform_set_drvdata(pdev
, priv
);
239 /* switch to first parent as active master */
240 i2c_demux_activate_master(priv
, 0);
242 err
= device_create_file(&pdev
->dev
, &dev_attr_available_masters
);
246 err
= device_create_file(&pdev
->dev
, &dev_attr_current_master
);
248 goto err_rollback_available
;
252 err_rollback_available
:
253 device_remove_file(&pdev
->dev
, &dev_attr_available_masters
);
255 for (j
= 0; j
< i
; j
++) {
256 of_node_put(priv
->chan
[j
].parent_np
);
257 of_changeset_destroy(&priv
->chan
[j
].chgset
);
263 static int i2c_demux_pinctrl_remove(struct platform_device
*pdev
)
265 struct i2c_demux_pinctrl_priv
*priv
= platform_get_drvdata(pdev
);
268 device_remove_file(&pdev
->dev
, &dev_attr_current_master
);
269 device_remove_file(&pdev
->dev
, &dev_attr_available_masters
);
271 i2c_demux_deactivate_master(priv
);
273 for (i
= 0; i
< priv
->num_chan
; i
++) {
274 of_node_put(priv
->chan
[i
].parent_np
);
275 of_changeset_destroy(&priv
->chan
[i
].chgset
);
281 static const struct of_device_id i2c_demux_pinctrl_of_match
[] = {
282 { .compatible
= "i2c-demux-pinctrl", },
285 MODULE_DEVICE_TABLE(of
, i2c_demux_pinctrl_of_match
);
287 static struct platform_driver i2c_demux_pinctrl_driver
= {
289 .name
= "i2c-demux-pinctrl",
290 .of_match_table
= i2c_demux_pinctrl_of_match
,
292 .probe
= i2c_demux_pinctrl_probe
,
293 .remove
= i2c_demux_pinctrl_remove
,
295 module_platform_driver(i2c_demux_pinctrl_driver
);
297 MODULE_DESCRIPTION("pinctrl-based I2C demux driver");
298 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
299 MODULE_LICENSE("GPL v2");
300 MODULE_ALIAS("platform:i2c-demux-pinctrl");