Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
6d54f144
Commit
6d54f144
authored
Aug 26, 2016
by
Wolfram Sang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'i2c-mux-dt-3' of
https://github.com/peda-r/i2c-mux
into i2c/for-4.9
Signed-off-by:
Wolfram Sang
<
wsa@the-dreams.de
>
parents
0317e6c0
8a191a7a
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
214 additions
and
35 deletions
+214
-35
Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
...tation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
+2
-6
Documentation/devicetree/bindings/i2c/i2c-arb.txt
Documentation/devicetree/bindings/i2c/i2c-arb.txt
+35
-0
Documentation/devicetree/bindings/i2c/i2c-gate.txt
Documentation/devicetree/bindings/i2c/i2c-gate.txt
+41
-0
Documentation/devicetree/bindings/i2c/i2c-mux.txt
Documentation/devicetree/bindings/i2c/i2c-mux.txt
+18
-5
Documentation/devicetree/bindings/i2c/nxp,pca9541.txt
Documentation/devicetree/bindings/i2c/nxp,pca9541.txt
+29
-0
MAINTAINERS
MAINTAINERS
+2
-0
drivers/i2c/i2c-mux.c
drivers/i2c/i2c-mux.c
+36
-8
drivers/i2c/muxes/i2c-arb-gpio-challenge.c
drivers/i2c/muxes/i2c-arb-gpio-challenge.c
+1
-1
drivers/i2c/muxes/i2c-mux-pca9541.c
drivers/i2c/muxes/i2c-mux-pca9541.c
+10
-1
drivers/i2c/muxes/i2c-mux-pca954x.c
drivers/i2c/muxes/i2c-mux-pca954x.c
+34
-12
include/linux/i2c-mux.h
include/linux/i2c-mux.h
+6
-2
No files found.
Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
View file @
6d54f144
...
...
@@ -44,8 +44,7 @@ Required properties:
- our-claim-gpio: The GPIO that we use to claim the bus.
- their-claim-gpios: The GPIOs that the other sides use to claim the bus.
Note that some implementations may only support a single other master.
- Standard I2C mux properties. See i2c-mux.txt in this directory.
- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory.
- I2C arbitration bus node. See i2c-arb.txt in this directory.
Optional properties:
- slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.
...
...
@@ -63,8 +62,6 @@ Example:
i2c-arbitrator {
compatible = "i2c-arb-gpio-challenge";
#address-cells = <1>;
#size-cells = <0>;
i2c-parent = <&{/i2c@12CA0000}>;
...
...
@@ -74,8 +71,7 @@ Example:
wait-retry-us = <3000>;
wait-free-us = <50000>;
i2c@0 {
reg = <0>;
i2c-arb {
#address-cells = <1>;
#size-cells = <0>;
...
...
Documentation/devicetree/bindings/i2c/i2c-arb.txt
0 → 100644
View file @
6d54f144
Common i2c arbitration bus properties.
- i2c-arb child node
Required properties for the i2c-arb child node:
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties for i2c-arb child node:
- Child nodes conforming to i2c bus binding
Example :
/*
An NXP pca9541 I2C bus master selector at address 0x74
with a NXP pca8574 GPIO expander attached.
*/
arb@74 {
compatible = "nxp,pca9541";
reg = <0x74>;
i2c-arb {
#address-cells = <1>;
#size-cells = <0>;
gpio@38 {
compatible = "nxp,pca8574";
reg = <0x38>;
#gpio-cells = <2>;
gpio-controller;
};
};
};
Documentation/devicetree/bindings/i2c/i2c-gate.txt
0 → 100644
View file @
6d54f144
An i2c gate is useful to e.g. reduce the digital noise for RF tuners connected
to the i2c bus. Gates are similar to arbitrators in that you need to perform
some kind of operation to access the i2c bus past the arbitrator/gate, but
there are no competing masters to consider for gates and therefore there is
no arbitration happening for gates.
Common i2c gate properties.
- i2c-gate child node
Required properties for the i2c-gate child node:
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties for i2c-gate child node:
- Child nodes conforming to i2c bus binding
Example :
/*
An Invensense mpu9150 at address 0x68 featuring an on-chip Asahi
Kasei ak8975 compass behind a gate.
*/
mpu9150@68 {
compatible = "invensense,mpu9150";
reg = <0x68>;
interrupt-parent = <&gpio1>;
interrupts = <18 1>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
ax8975@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};
Documentation/devicetree/bindings/i2c/i2c-mux.txt
View file @
6d54f144
...
...
@@ -2,19 +2,32 @@ Common i2c bus multiplexer/switch properties.
An i2c bus multiplexer/switch will have several child busses that are
numbered uniquely in a device dependent manner. The nodes for an i2c bus
multiplexer/switch will have one child node for each child
bus.
multiplexer/switch will have one child node for each child bus.
Required properties:
Optional properties:
- #address-cells = <1>;
This property is required is the i2c-mux child node does not exist.
- #size-cells = <0>;
This property is required is the i2c-mux child node does not exist.
- i2c-mux
For i2c multiplexers/switches that have child nodes that are a mixture
of both i2c child busses and other child nodes, the 'i2c-mux' subnode
can be used for populating the i2c child busses. If an 'i2c-mux'
subnode is present, only subnodes of this will be considered as i2c
child busses.
Required properties for the i2c-mux child node:
- #address-cells = <1>;
- #size-cells = <0>;
Required properties for
child
nodes:
Required properties for
i2c child bus
nodes:
- #address-cells = <1>;
- #size-cells = <0>;
- reg : The sub-bus number.
Optional properties for
child
nodes:
Optional properties for
i2c child bus
nodes:
- Other properties specific to the multiplexer/switch hardware.
- Child nodes conforming to i2c bus binding
...
...
Documentation/devicetree/bindings/i2c/nxp,pca9541.txt
0 → 100644
View file @
6d54f144
* NXP PCA9541 I2C bus master selector
Required Properties:
- compatible: Must be "nxp,pca9541"
- reg: The I2C address of the device.
The following required properties are defined externally:
- I2C arbitration bus node. See i2c-arb.txt in this directory.
Example:
i2c-arbitrator@74 {
compatible = "nxp,pca9541";
reg = <0x74>;
i2c-arb {
#address-cells = <1>;
#size-cells = <0>;
eeprom@54 {
compatible = "at,24c08";
reg = <0x54>;
};
};
};
MAINTAINERS
View file @
6d54f144
...
...
@@ -5675,6 +5675,8 @@ S: Maintained
F: Documentation/i2c/i2c-topology
F: Documentation/i2c/muxes/
F: Documentation/devicetree/bindings/i2c/i2c-mux*
F: Documentation/devicetree/bindings/i2c/i2c-arb*
F: Documentation/devicetree/bindings/i2c/i2c-gate*
F: drivers/i2c/i2c-mux.c
F: drivers/i2c/muxes/
F: include/linux/i2c-mux.h
...
...
drivers/i2c/i2c-mux.c
View file @
6d54f144
...
...
@@ -255,6 +255,10 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
muxc
->
dev
=
dev
;
if
(
flags
&
I2C_MUX_LOCKED
)
muxc
->
mux_locked
=
true
;
if
(
flags
&
I2C_MUX_ARBITRATOR
)
muxc
->
arbitrator
=
true
;
if
(
flags
&
I2C_MUX_GATE
)
muxc
->
gate
=
true
;
muxc
->
select
=
select
;
muxc
->
deselect
=
deselect
;
muxc
->
max_adapters
=
max_adapters
;
...
...
@@ -335,18 +339,42 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
* nothing if !CONFIG_OF.
*/
if
(
muxc
->
dev
->
of_node
)
{
struct
device_node
*
child
;
struct
device_node
*
dev_node
=
muxc
->
dev
->
of_node
;
struct
device_node
*
mux_node
,
*
child
=
NULL
;
u32
reg
;
for_each_child_of_node
(
muxc
->
dev
->
of_node
,
child
)
{
if
(
muxc
->
arbitrator
)
mux_node
=
of_get_child_by_name
(
dev_node
,
"i2c-arb"
);
else
if
(
muxc
->
gate
)
mux_node
=
of_get_child_by_name
(
dev_node
,
"i2c-gate"
);
else
mux_node
=
of_get_child_by_name
(
dev_node
,
"i2c-mux"
);
if
(
mux_node
)
{
/* A "reg" property indicates an old-style DT entry */
if
(
!
of_property_read_u32
(
mux_node
,
"reg"
,
&
reg
))
{
of_node_put
(
mux_node
);
mux_node
=
NULL
;
}
}
if
(
!
mux_node
)
mux_node
=
of_node_get
(
dev_node
);
else
if
(
muxc
->
arbitrator
||
muxc
->
gate
)
child
=
of_node_get
(
mux_node
);
if
(
!
child
)
{
for_each_child_of_node
(
mux_node
,
child
)
{
ret
=
of_property_read_u32
(
child
,
"reg"
,
&
reg
);
if
(
ret
)
continue
;
if
(
chan_id
==
reg
)
{
priv
->
adap
.
dev
.
of_node
=
child
;
if
(
chan_id
==
reg
)
break
;
}
}
priv
->
adap
.
dev
.
of_node
=
child
;
of_node_put
(
mux_node
);
}
/*
...
...
drivers/i2c/muxes/i2c-arb-gpio-challenge.c
View file @
6d54f144
...
...
@@ -130,7 +130,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
return
-
EINVAL
;
}
muxc
=
i2c_mux_alloc
(
NULL
,
dev
,
1
,
sizeof
(
*
arb
),
0
,
muxc
=
i2c_mux_alloc
(
NULL
,
dev
,
1
,
sizeof
(
*
arb
),
I2C_MUX_ARBITRATOR
,
i2c_arbitrator_select
,
i2c_arbitrator_deselect
);
if
(
!
muxc
)
return
-
ENOMEM
;
...
...
drivers/i2c/muxes/i2c-mux-pca9541.c
View file @
6d54f144
...
...
@@ -85,6 +85,13 @@ static const struct i2c_device_id pca9541_id[] = {
MODULE_DEVICE_TABLE
(
i2c
,
pca9541_id
);
#ifdef CONFIG_OF
static
const
struct
of_device_id
pca9541_of_match
[]
=
{
{
.
compatible
=
"nxp,pca9541"
},
{}
};
#endif
/*
* Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
* as they will try to lock the adapter a second time.
...
...
@@ -349,7 +356,8 @@ static int pca9541_probe(struct i2c_client *client,
force
=
0
;
if
(
pdata
)
force
=
pdata
->
modes
[
0
].
adap_id
;
muxc
=
i2c_mux_alloc
(
adap
,
&
client
->
dev
,
1
,
sizeof
(
*
data
),
0
,
muxc
=
i2c_mux_alloc
(
adap
,
&
client
->
dev
,
1
,
sizeof
(
*
data
),
I2C_MUX_ARBITRATOR
,
pca9541_select_chan
,
pca9541_release_chan
);
if
(
!
muxc
)
return
-
ENOMEM
;
...
...
@@ -382,6 +390,7 @@ static int pca9541_remove(struct i2c_client *client)
static
struct
i2c_driver
pca9541_driver
=
{
.
driver
=
{
.
name
=
"pca9541"
,
.
of_match_table
=
of_match_ptr
(
pca9541_of_match
),
},
.
probe
=
pca9541_probe
,
.
remove
=
pca9541_remove
,
...
...
drivers/i2c/muxes/i2c-mux-pca954x.c
View file @
6d54f144
...
...
@@ -42,6 +42,7 @@
#include <linux/i2c/pca954x.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
...
...
@@ -58,14 +59,6 @@ enum pca_type {
pca_9548
,
};
struct
pca954x
{
enum
pca_type
type
;
u8
last_chan
;
/* last register value */
u8
deselect
;
struct
i2c_client
*
client
;
};
struct
chip_desc
{
u8
nchans
;
u8
enable
;
/* used for muxes only */
...
...
@@ -75,6 +68,14 @@ struct chip_desc {
}
muxtype
;
};
struct
pca954x
{
const
struct
chip_desc
*
chip
;
u8
last_chan
;
/* last register value */
u8
deselect
;
struct
i2c_client
*
client
;
};
/* Provide specs for the PCA954x types we know about */
static
const
struct
chip_desc
chips
[]
=
{
[
pca_9540
]
=
{
...
...
@@ -119,6 +120,20 @@ static const struct i2c_device_id pca954x_id[] = {
};
MODULE_DEVICE_TABLE
(
i2c
,
pca954x_id
);
#ifdef CONFIG_OF
static
const
struct
of_device_id
pca954x_of_match
[]
=
{
{
.
compatible
=
"nxp,pca9540"
,
.
data
=
&
chips
[
pca_9540
]
},
{
.
compatible
=
"nxp,pca9542"
,
.
data
=
&
chips
[
pca_9542
]
},
{
.
compatible
=
"nxp,pca9543"
,
.
data
=
&
chips
[
pca_9543
]
},
{
.
compatible
=
"nxp,pca9544"
,
.
data
=
&
chips
[
pca_9544
]
},
{
.
compatible
=
"nxp,pca9545"
,
.
data
=
&
chips
[
pca_9545
]
},
{
.
compatible
=
"nxp,pca9546"
,
.
data
=
&
chips
[
pca_9546
]
},
{
.
compatible
=
"nxp,pca9547"
,
.
data
=
&
chips
[
pca_9547
]
},
{
.
compatible
=
"nxp,pca9548"
,
.
data
=
&
chips
[
pca_9548
]
},
{}
};
#endif
/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
for this as they will try to lock adapter a second time */
static
int
pca954x_reg_write
(
struct
i2c_adapter
*
adap
,
...
...
@@ -151,7 +166,7 @@ static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
{
struct
pca954x
*
data
=
i2c_mux_priv
(
muxc
);
struct
i2c_client
*
client
=
data
->
client
;
const
struct
chip_desc
*
chip
=
&
chips
[
data
->
type
]
;
const
struct
chip_desc
*
chip
=
data
->
chip
;
u8
regval
;
int
ret
=
0
;
...
...
@@ -197,6 +212,7 @@ static int pca954x_probe(struct i2c_client *client,
int
num
,
force
,
class
;
struct
i2c_mux_core
*
muxc
;
struct
pca954x
*
data
;
const
struct
of_device_id
*
match
;
int
ret
;
if
(
!
i2c_check_functionality
(
adap
,
I2C_FUNC_SMBUS_BYTE
))
...
...
@@ -226,14 +242,19 @@ static int pca954x_probe(struct i2c_client *client,
return
-
ENODEV
;
}
data
->
type
=
id
->
driver_data
;
match
=
of_match_device
(
of_match_ptr
(
pca954x_of_match
),
&
client
->
dev
);
if
(
match
)
data
->
chip
=
of_device_get_match_data
(
&
client
->
dev
);
else
data
->
chip
=
&
chips
[
id
->
driver_data
];
data
->
last_chan
=
0
;
/* force the first selection */
idle_disconnect_dt
=
of_node
&&
of_property_read_bool
(
of_node
,
"i2c-mux-idle-disconnect"
);
/* Now create an adapter for each channel */
for
(
num
=
0
;
num
<
chips
[
data
->
type
].
nchans
;
num
++
)
{
for
(
num
=
0
;
num
<
data
->
chip
->
nchans
;
num
++
)
{
bool
idle_disconnect_pd
=
false
;
force
=
0
;
/* dynamic adap number */
...
...
@@ -263,7 +284,7 @@ static int pca954x_probe(struct i2c_client *client,
dev_info
(
&
client
->
dev
,
"registered %d multiplexed busses for I2C %s %s
\n
"
,
num
,
chips
[
data
->
type
].
muxtype
==
pca954x_ismux
num
,
data
->
chip
->
muxtype
==
pca954x_ismux
?
"mux"
:
"switch"
,
client
->
name
);
return
0
;
...
...
@@ -299,6 +320,7 @@ static struct i2c_driver pca954x_driver = {
.
driver
=
{
.
name
=
"pca954x"
,
.
pm
=
&
pca954x_pm
,
.
of_match_table
=
of_match_ptr
(
pca954x_of_match
),
},
.
probe
=
pca954x_probe
,
.
remove
=
pca954x_remove
,
...
...
include/linux/i2c-mux.h
View file @
6d54f144
...
...
@@ -32,7 +32,9 @@
struct
i2c_mux_core
{
struct
i2c_adapter
*
parent
;
struct
device
*
dev
;
bool
mux_locked
;
unsigned
int
mux_locked
:
1
;
unsigned
int
arbitrator
:
1
;
unsigned
int
gate
:
1
;
void
*
priv
;
...
...
@@ -52,6 +54,8 @@ struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
/* flags for i2c_mux_alloc */
#define I2C_MUX_LOCKED BIT(0)
#define I2C_MUX_ARBITRATOR BIT(1)
#define I2C_MUX_GATE BIT(2)
static
inline
void
*
i2c_mux_priv
(
struct
i2c_mux_core
*
muxc
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment