2 * Simple memory-mapped device MDIO MUX driver
4 * Author: Timur Tabi <timur@freescale.com>
6 * Copyright 2012 Freescale Semiconductor, Inc.
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
13 #include <linux/platform_device.h>
14 #include <linux/device.h>
15 #include <linux/of_address.h>
16 #include <linux/of_mdio.h>
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/phy.h>
20 #include <linux/mdio-mux.h>
22 struct mdio_mux_mmioreg_state
{
29 * MDIO multiplexing switch function
31 * This function is called by the mdio-mux layer when it thinks the mdio bus
32 * multiplexer needs to switch.
34 * 'current_child' is the current value of the mux register (masked via
37 * 'desired_child' is the value of the 'reg' property of the target child MDIO
40 * The first time this function is called, current_child == -1.
42 * If current_child == desired_child, then the mux is already set to the
45 static int mdio_mux_mmioreg_switch_fn(int current_child
, int desired_child
,
48 struct mdio_mux_mmioreg_state
*s
= data
;
50 if (current_child
^ desired_child
) {
51 void __iomem
*p
= ioremap(s
->phys
, 1);
58 y
= (x
& ~s
->mask
) | desired_child
;
60 iowrite8((x
& ~s
->mask
) | desired_child
, p
);
61 pr_debug("%s: %02x -> %02x\n", __func__
, x
, y
);
70 static int mdio_mux_mmioreg_probe(struct platform_device
*pdev
)
72 struct device_node
*np2
, *np
= pdev
->dev
.of_node
;
73 struct mdio_mux_mmioreg_state
*s
;
78 dev_dbg(&pdev
->dev
, "probing node %s\n", np
->full_name
);
80 s
= devm_kzalloc(&pdev
->dev
, sizeof(*s
), GFP_KERNEL
);
84 ret
= of_address_to_resource(np
, 0, &res
);
86 dev_err(&pdev
->dev
, "could not obtain memory map for node %s\n",
92 if (resource_size(&res
) != sizeof(uint8_t)) {
93 dev_err(&pdev
->dev
, "only 8-bit registers are supported\n");
97 iprop
= of_get_property(np
, "mux-mask", &len
);
98 if (!iprop
|| len
!= sizeof(uint32_t)) {
99 dev_err(&pdev
->dev
, "missing or invalid mux-mask property\n");
102 if (be32_to_cpup(iprop
) > 255) {
103 dev_err(&pdev
->dev
, "only 8-bit registers are supported\n");
106 s
->mask
= be32_to_cpup(iprop
);
109 * Verify that the 'reg' property of each child MDIO bus does not
110 * set any bits outside of the 'mask'.
112 for_each_available_child_of_node(np
, np2
) {
113 iprop
= of_get_property(np2
, "reg", &len
);
114 if (!iprop
|| len
!= sizeof(uint32_t)) {
115 dev_err(&pdev
->dev
, "mdio-mux child node %s is "
116 "missing a 'reg' property\n", np2
->full_name
);
119 if (be32_to_cpup(iprop
) & ~s
->mask
) {
120 dev_err(&pdev
->dev
, "mdio-mux child node %s has "
121 "a 'reg' value with unmasked bits\n",
127 ret
= mdio_mux_init(&pdev
->dev
, mdio_mux_mmioreg_switch_fn
,
130 dev_err(&pdev
->dev
, "failed to register mdio-mux bus %s\n",
135 pdev
->dev
.platform_data
= s
;
140 static int mdio_mux_mmioreg_remove(struct platform_device
*pdev
)
142 struct mdio_mux_mmioreg_state
*s
= dev_get_platdata(&pdev
->dev
);
144 mdio_mux_uninit(s
->mux_handle
);
149 static struct of_device_id mdio_mux_mmioreg_match
[] = {
151 .compatible
= "mdio-mux-mmioreg",
155 MODULE_DEVICE_TABLE(of
, mdio_mux_mmioreg_match
);
157 static struct platform_driver mdio_mux_mmioreg_driver
= {
159 .name
= "mdio-mux-mmioreg",
160 .owner
= THIS_MODULE
,
161 .of_match_table
= mdio_mux_mmioreg_match
,
163 .probe
= mdio_mux_mmioreg_probe
,
164 .remove
= mdio_mux_mmioreg_remove
,
167 module_platform_driver(mdio_mux_mmioreg_driver
);
169 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
170 MODULE_DESCRIPTION("Memory-mapped device MDIO MUX driver");
171 MODULE_LICENSE("GPL v2");