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/phy.h>
19 #include <linux/mdio-mux.h>
21 struct mdio_mux_mmioreg_state
{
28 * MDIO multiplexing switch function
30 * This function is called by the mdio-mux layer when it thinks the mdio bus
31 * multiplexer needs to switch.
33 * 'current_child' is the current value of the mux register (masked via
36 * 'desired_child' is the value of the 'reg' property of the target child MDIO
39 * The first time this function is called, current_child == -1.
41 * If current_child == desired_child, then the mux is already set to the
44 static int mdio_mux_mmioreg_switch_fn(int current_child
, int desired_child
,
47 struct mdio_mux_mmioreg_state
*s
= data
;
49 if (current_child
^ desired_child
) {
50 void __iomem
*p
= ioremap(s
->phys
, 1);
57 y
= (x
& ~s
->mask
) | desired_child
;
59 iowrite8((x
& ~s
->mask
) | desired_child
, p
);
60 pr_debug("%s: %02x -> %02x\n", __func__
, x
, y
);
69 static int mdio_mux_mmioreg_probe(struct platform_device
*pdev
)
71 struct device_node
*np2
, *np
= pdev
->dev
.of_node
;
72 struct mdio_mux_mmioreg_state
*s
;
77 dev_dbg(&pdev
->dev
, "probing node %s\n", np
->full_name
);
79 s
= devm_kzalloc(&pdev
->dev
, sizeof(*s
), GFP_KERNEL
);
83 ret
= of_address_to_resource(np
, 0, &res
);
85 dev_err(&pdev
->dev
, "could not obtain memory map for node %s\n",
91 if (resource_size(&res
) != sizeof(uint8_t)) {
92 dev_err(&pdev
->dev
, "only 8-bit registers are supported\n");
96 iprop
= of_get_property(np
, "mux-mask", &len
);
97 if (!iprop
|| len
!= sizeof(uint32_t)) {
98 dev_err(&pdev
->dev
, "missing or invalid mux-mask property\n");
101 if (be32_to_cpup(iprop
) > 255) {
102 dev_err(&pdev
->dev
, "only 8-bit registers are supported\n");
105 s
->mask
= be32_to_cpup(iprop
);
108 * Verify that the 'reg' property of each child MDIO bus does not
109 * set any bits outside of the 'mask'.
111 for_each_available_child_of_node(np
, np2
) {
112 iprop
= of_get_property(np2
, "reg", &len
);
113 if (!iprop
|| len
!= sizeof(uint32_t)) {
114 dev_err(&pdev
->dev
, "mdio-mux child node %s is "
115 "missing a 'reg' property\n", np2
->full_name
);
118 if (be32_to_cpup(iprop
) & ~s
->mask
) {
119 dev_err(&pdev
->dev
, "mdio-mux child node %s has "
120 "a 'reg' value with unmasked bits\n",
126 ret
= mdio_mux_init(&pdev
->dev
, mdio_mux_mmioreg_switch_fn
,
129 dev_err(&pdev
->dev
, "failed to register mdio-mux bus %s\n",
134 pdev
->dev
.platform_data
= s
;
139 static int mdio_mux_mmioreg_remove(struct platform_device
*pdev
)
141 struct mdio_mux_mmioreg_state
*s
= dev_get_platdata(&pdev
->dev
);
143 mdio_mux_uninit(s
->mux_handle
);
148 static struct of_device_id mdio_mux_mmioreg_match
[] = {
150 .compatible
= "mdio-mux-mmioreg",
154 MODULE_DEVICE_TABLE(of
, mdio_mux_mmioreg_match
);
156 static struct platform_driver mdio_mux_mmioreg_driver
= {
158 .name
= "mdio-mux-mmioreg",
159 .owner
= THIS_MODULE
,
160 .of_match_table
= mdio_mux_mmioreg_match
,
162 .probe
= mdio_mux_mmioreg_probe
,
163 .remove
= mdio_mux_mmioreg_remove
,
166 module_platform_driver(mdio_mux_mmioreg_driver
);
168 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
169 MODULE_DESCRIPTION("Memory-mapped device MDIO MUX driver");
170 MODULE_LICENSE("GPL v2");