0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/gpio/consumer.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/mdio-bitbang.h>
0023 #include <linux/mdio-gpio.h>
0024 #include <linux/module.h>
0025 #include <linux/of_mdio.h>
0026 #include <linux/platform_data/mdio-gpio.h>
0027 #include <linux/platform_device.h>
0028 #include <linux/slab.h>
0029
0030 struct mdio_gpio_info {
0031 struct mdiobb_ctrl ctrl;
0032 struct gpio_desc *mdc, *mdio, *mdo;
0033 };
0034
0035 static int mdio_gpio_get_data(struct device *dev,
0036 struct mdio_gpio_info *bitbang)
0037 {
0038 bitbang->mdc = devm_gpiod_get_index(dev, NULL, MDIO_GPIO_MDC,
0039 GPIOD_OUT_LOW);
0040 if (IS_ERR(bitbang->mdc))
0041 return PTR_ERR(bitbang->mdc);
0042
0043 bitbang->mdio = devm_gpiod_get_index(dev, NULL, MDIO_GPIO_MDIO,
0044 GPIOD_IN);
0045 if (IS_ERR(bitbang->mdio))
0046 return PTR_ERR(bitbang->mdio);
0047
0048 bitbang->mdo = devm_gpiod_get_index_optional(dev, NULL, MDIO_GPIO_MDO,
0049 GPIOD_OUT_LOW);
0050 return PTR_ERR_OR_ZERO(bitbang->mdo);
0051 }
0052
0053 static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
0054 {
0055 struct mdio_gpio_info *bitbang =
0056 container_of(ctrl, struct mdio_gpio_info, ctrl);
0057
0058 if (bitbang->mdo) {
0059
0060
0061
0062
0063
0064 gpiod_set_value_cansleep(bitbang->mdo, 1);
0065 return;
0066 }
0067
0068 if (dir)
0069 gpiod_direction_output(bitbang->mdio, 1);
0070 else
0071 gpiod_direction_input(bitbang->mdio);
0072 }
0073
0074 static int mdio_get(struct mdiobb_ctrl *ctrl)
0075 {
0076 struct mdio_gpio_info *bitbang =
0077 container_of(ctrl, struct mdio_gpio_info, ctrl);
0078
0079 return gpiod_get_value_cansleep(bitbang->mdio);
0080 }
0081
0082 static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
0083 {
0084 struct mdio_gpio_info *bitbang =
0085 container_of(ctrl, struct mdio_gpio_info, ctrl);
0086
0087 if (bitbang->mdo)
0088 gpiod_set_value_cansleep(bitbang->mdo, what);
0089 else
0090 gpiod_set_value_cansleep(bitbang->mdio, what);
0091 }
0092
0093 static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
0094 {
0095 struct mdio_gpio_info *bitbang =
0096 container_of(ctrl, struct mdio_gpio_info, ctrl);
0097
0098 gpiod_set_value_cansleep(bitbang->mdc, what);
0099 }
0100
0101 static const struct mdiobb_ops mdio_gpio_ops = {
0102 .owner = THIS_MODULE,
0103 .set_mdc = mdc_set,
0104 .set_mdio_dir = mdio_dir,
0105 .set_mdio_data = mdio_set,
0106 .get_mdio_data = mdio_get,
0107 };
0108
0109 static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
0110 struct mdio_gpio_info *bitbang,
0111 int bus_id)
0112 {
0113 struct mdio_gpio_platform_data *pdata = dev_get_platdata(dev);
0114 struct mii_bus *new_bus;
0115
0116 bitbang->ctrl.ops = &mdio_gpio_ops;
0117
0118 new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
0119 if (!new_bus)
0120 return NULL;
0121
0122 new_bus->name = "GPIO Bitbanged MDIO";
0123 new_bus->parent = dev;
0124
0125 if (bus_id != -1)
0126 snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id);
0127 else
0128 strncpy(new_bus->id, "gpio", MII_BUS_ID_SIZE);
0129
0130 if (pdata) {
0131 new_bus->phy_mask = pdata->phy_mask;
0132 new_bus->phy_ignore_ta_mask = pdata->phy_ignore_ta_mask;
0133 }
0134
0135 if (dev->of_node &&
0136 of_device_is_compatible(dev->of_node, "microchip,mdio-smi0")) {
0137 bitbang->ctrl.op_c22_read = 0;
0138 bitbang->ctrl.op_c22_write = 0;
0139 bitbang->ctrl.override_op_c22 = 1;
0140 }
0141
0142 dev_set_drvdata(dev, new_bus);
0143
0144 return new_bus;
0145 }
0146
0147 static void mdio_gpio_bus_deinit(struct device *dev)
0148 {
0149 struct mii_bus *bus = dev_get_drvdata(dev);
0150
0151 free_mdio_bitbang(bus);
0152 }
0153
0154 static void mdio_gpio_bus_destroy(struct device *dev)
0155 {
0156 struct mii_bus *bus = dev_get_drvdata(dev);
0157
0158 mdiobus_unregister(bus);
0159 mdio_gpio_bus_deinit(dev);
0160 }
0161
0162 static int mdio_gpio_probe(struct platform_device *pdev)
0163 {
0164 struct mdio_gpio_info *bitbang;
0165 struct mii_bus *new_bus;
0166 int ret, bus_id;
0167
0168 bitbang = devm_kzalloc(&pdev->dev, sizeof(*bitbang), GFP_KERNEL);
0169 if (!bitbang)
0170 return -ENOMEM;
0171
0172 ret = mdio_gpio_get_data(&pdev->dev, bitbang);
0173 if (ret)
0174 return ret;
0175
0176 if (pdev->dev.of_node) {
0177 bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
0178 if (bus_id < 0) {
0179 dev_warn(&pdev->dev, "failed to get alias id\n");
0180 bus_id = 0;
0181 }
0182 } else {
0183 bus_id = pdev->id;
0184 }
0185
0186 new_bus = mdio_gpio_bus_init(&pdev->dev, bitbang, bus_id);
0187 if (!new_bus)
0188 return -ENODEV;
0189
0190 ret = of_mdiobus_register(new_bus, pdev->dev.of_node);
0191 if (ret)
0192 mdio_gpio_bus_deinit(&pdev->dev);
0193
0194 return ret;
0195 }
0196
0197 static int mdio_gpio_remove(struct platform_device *pdev)
0198 {
0199 mdio_gpio_bus_destroy(&pdev->dev);
0200
0201 return 0;
0202 }
0203
0204 static const struct of_device_id mdio_gpio_of_match[] = {
0205 { .compatible = "virtual,mdio-gpio", },
0206 { .compatible = "microchip,mdio-smi0" },
0207 { }
0208 };
0209 MODULE_DEVICE_TABLE(of, mdio_gpio_of_match);
0210
0211 static struct platform_driver mdio_gpio_driver = {
0212 .probe = mdio_gpio_probe,
0213 .remove = mdio_gpio_remove,
0214 .driver = {
0215 .name = "mdio-gpio",
0216 .of_match_table = mdio_gpio_of_match,
0217 },
0218 };
0219
0220 module_platform_driver(mdio_gpio_driver);
0221
0222 MODULE_ALIAS("platform:mdio-gpio");
0223 MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas");
0224 MODULE_LICENSE("GPL v2");
0225 MODULE_DESCRIPTION("Generic driver for MDIO bus emulation using GPIO");