2 * GPIO based MDIO bitbang driver.
3 * Supports OpenFirmware.
5 * Copyright (c) 2008 CSE Semaphore Belgium.
6 * by Laurent Pinchart <laurentp@cse-semaphore.com>
8 * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
10 * Based on earlier work by
12 * Copyright (c) 2003 Intracom S.A.
13 * by Pantelis Antoniou <panto@intracom.gr>
15 * 2005 (c) MontaVista Software, Inc.
16 * Vitaly Bordug <vbordug@ru.mvista.com>
18 * This file is licensed under the terms of the GNU General Public License
19 * version 2. This program is licensed "as is" without any warranty of any
20 * kind, whether express or implied.
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include <linux/interrupt.h>
26 #include <linux/platform_device.h>
27 #include <linux/gpio.h>
28 #include <linux/platform_data/mdio-gpio.h>
30 #include <linux/of_gpio.h>
31 #include <linux/of_mdio.h>
33 struct mdio_gpio_info
{
34 struct mdiobb_ctrl ctrl
;
35 struct gpio_desc
*mdc
, *mdio
, *mdo
;
38 static void *mdio_gpio_of_get_data(struct platform_device
*pdev
)
40 struct device_node
*np
= pdev
->dev
.of_node
;
41 struct mdio_gpio_platform_data
*pdata
;
42 enum of_gpio_flags flags
;
45 pdata
= devm_kzalloc(&pdev
->dev
, sizeof(*pdata
), GFP_KERNEL
);
49 ret
= of_get_gpio_flags(np
, 0, &flags
);
54 pdata
->mdc_active_low
= flags
& OF_GPIO_ACTIVE_LOW
;
56 ret
= of_get_gpio_flags(np
, 1, &flags
);
60 pdata
->mdio_active_low
= flags
& OF_GPIO_ACTIVE_LOW
;
62 ret
= of_get_gpio_flags(np
, 2, &flags
);
65 pdata
->mdo_active_low
= flags
& OF_GPIO_ACTIVE_LOW
;
71 static void mdio_dir(struct mdiobb_ctrl
*ctrl
, int dir
)
73 struct mdio_gpio_info
*bitbang
=
74 container_of(ctrl
, struct mdio_gpio_info
, ctrl
);
77 /* Separate output pin. Always set its value to high
78 * when changing direction. If direction is input,
79 * assume the pin serves as pull-up. If direction is
80 * output, the default value is high.
82 gpiod_set_value(bitbang
->mdo
, 1);
87 gpiod_direction_output(bitbang
->mdio
, 1);
89 gpiod_direction_input(bitbang
->mdio
);
92 static int mdio_get(struct mdiobb_ctrl
*ctrl
)
94 struct mdio_gpio_info
*bitbang
=
95 container_of(ctrl
, struct mdio_gpio_info
, ctrl
);
97 return gpiod_get_value(bitbang
->mdio
);
100 static void mdio_set(struct mdiobb_ctrl
*ctrl
, int what
)
102 struct mdio_gpio_info
*bitbang
=
103 container_of(ctrl
, struct mdio_gpio_info
, ctrl
);
106 gpiod_set_value(bitbang
->mdo
, what
);
108 gpiod_set_value(bitbang
->mdio
, what
);
111 static void mdc_set(struct mdiobb_ctrl
*ctrl
, int what
)
113 struct mdio_gpio_info
*bitbang
=
114 container_of(ctrl
, struct mdio_gpio_info
, ctrl
);
116 gpiod_set_value(bitbang
->mdc
, what
);
119 static struct mdiobb_ops mdio_gpio_ops
= {
120 .owner
= THIS_MODULE
,
122 .set_mdio_dir
= mdio_dir
,
123 .set_mdio_data
= mdio_set
,
124 .get_mdio_data
= mdio_get
,
127 static struct mii_bus
*mdio_gpio_bus_init(struct device
*dev
,
128 struct mdio_gpio_platform_data
*pdata
,
131 struct mii_bus
*new_bus
;
132 struct mdio_gpio_info
*bitbang
;
135 unsigned long mdc_flags
= GPIOF_OUT_INIT_LOW
;
136 unsigned long mdio_flags
= GPIOF_DIR_IN
;
137 unsigned long mdo_flags
= GPIOF_OUT_INIT_HIGH
;
139 bitbang
= devm_kzalloc(dev
, sizeof(*bitbang
), GFP_KERNEL
);
143 bitbang
->ctrl
.ops
= &mdio_gpio_ops
;
144 bitbang
->ctrl
.reset
= pdata
->reset
;
146 bitbang
->mdc
= gpio_to_desc(mdc
);
147 if (pdata
->mdc_active_low
)
148 mdc_flags
= GPIOF_OUT_INIT_HIGH
| GPIOF_ACTIVE_LOW
;
150 bitbang
->mdio
= gpio_to_desc(mdio
);
151 if (pdata
->mdio_active_low
)
152 mdio_flags
|= GPIOF_ACTIVE_LOW
;
155 bitbang
->mdo
= gpio_to_desc(mdo
);
156 if (pdata
->mdo_active_low
)
157 mdo_flags
= GPIOF_OUT_INIT_LOW
| GPIOF_ACTIVE_LOW
;
160 new_bus
= alloc_mdio_bitbang(&bitbang
->ctrl
);
164 new_bus
->name
= "GPIO Bitbanged MDIO",
166 new_bus
->phy_mask
= pdata
->phy_mask
;
167 new_bus
->phy_ignore_ta_mask
= pdata
->phy_ignore_ta_mask
;
168 memcpy(new_bus
->irq
, pdata
->irqs
, sizeof(new_bus
->irq
));
169 new_bus
->parent
= dev
;
171 if (new_bus
->phy_mask
== ~0)
174 for (i
= 0; i
< PHY_MAX_ADDR
; i
++)
175 if (!new_bus
->irq
[i
])
176 new_bus
->irq
[i
] = PHY_POLL
;
179 snprintf(new_bus
->id
, MII_BUS_ID_SIZE
, "gpio-%x", bus_id
);
181 strncpy(new_bus
->id
, "gpio", MII_BUS_ID_SIZE
);
183 if (devm_gpio_request_one(dev
, mdc
, mdc_flags
, "mdc"))
186 if (devm_gpio_request_one(dev
, mdio
, mdio_flags
, "mdio"))
189 if (mdo
&& devm_gpio_request_one(dev
, mdo
, mdo_flags
, "mdo"))
192 dev_set_drvdata(dev
, new_bus
);
197 free_mdio_bitbang(new_bus
);
202 static void mdio_gpio_bus_deinit(struct device
*dev
)
204 struct mii_bus
*bus
= dev_get_drvdata(dev
);
206 free_mdio_bitbang(bus
);
209 static void mdio_gpio_bus_destroy(struct device
*dev
)
211 struct mii_bus
*bus
= dev_get_drvdata(dev
);
213 mdiobus_unregister(bus
);
214 mdio_gpio_bus_deinit(dev
);
217 static int mdio_gpio_probe(struct platform_device
*pdev
)
219 struct mdio_gpio_platform_data
*pdata
;
220 struct mii_bus
*new_bus
;
223 if (pdev
->dev
.of_node
) {
224 pdata
= mdio_gpio_of_get_data(pdev
);
225 bus_id
= of_alias_get_id(pdev
->dev
.of_node
, "mdio-gpio");
227 dev_warn(&pdev
->dev
, "failed to get alias id\n");
231 pdata
= dev_get_platdata(&pdev
->dev
);
238 new_bus
= mdio_gpio_bus_init(&pdev
->dev
, pdata
, bus_id
);
242 if (pdev
->dev
.of_node
)
243 ret
= of_mdiobus_register(new_bus
, pdev
->dev
.of_node
);
245 ret
= mdiobus_register(new_bus
);
248 mdio_gpio_bus_deinit(&pdev
->dev
);
253 static int mdio_gpio_remove(struct platform_device
*pdev
)
255 mdio_gpio_bus_destroy(&pdev
->dev
);
260 static const struct of_device_id mdio_gpio_of_match
[] = {
261 { .compatible
= "virtual,mdio-gpio", },
264 MODULE_DEVICE_TABLE(of
, mdio_gpio_of_match
);
266 static struct platform_driver mdio_gpio_driver
= {
267 .probe
= mdio_gpio_probe
,
268 .remove
= mdio_gpio_remove
,
271 .of_match_table
= mdio_gpio_of_match
,
275 module_platform_driver(mdio_gpio_driver
);
277 MODULE_ALIAS("platform:mdio-gpio");
278 MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas");
279 MODULE_LICENSE("GPL");
280 MODULE_DESCRIPTION("Generic driver for MDIO bus emulation using GPIO");