From patchwork Mon Oct 27 10:53:22 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulius Zaleckas X-Patchwork-Id: 5887 X-Patchwork-Delegate: jgarzik@pobox.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 958A9DDDE0 for ; Mon, 27 Oct 2008 20:53:40 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752412AbYJ0Jx0 (ORCPT ); Mon, 27 Oct 2008 05:53:26 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751493AbYJ0Jx0 (ORCPT ); Mon, 27 Oct 2008 05:53:26 -0400 Received: from 81-7-68-229.static.zebra.lt ([81.7.68.229]:34365 "EHLO teltonika.lt" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752398AbYJ0JxY (ORCPT ); Mon, 27 Oct 2008 05:53:24 -0400 Received: (qmail 25113 invoked by uid 118); 27 Oct 2008 09:52:10 -0000 Received: from 82.135.208.232 by mailserver (envelope-from , uid 112) with qmail-scanner-1.25st (clamdscan: 0.90.1/8500. spamassassin: 3.1.7-deb. perlscan: 1.25st. Clear:RC:1(82.135.208.232):. Processed in 0.079124 secs); 27 Oct 2008 09:52:10 -0000 Received: from 82-135-208-232.static.zebra.lt (HELO Programuotojas.82-135-208-232.ip.zebra.lt) (paulius.zaleckas@[82.135.208.232]) (envelope-sender ) by teltonika.lt (qmail-ldap-1.03) with SMTP for ; 27 Oct 2008 09:52:10 -0000 From: Paulius Zaleckas Subject: [PATCH] phylib: add mdio-gpio bus driver (v2) To: netdev@vger.kernel.org Cc: linux-arm-kernel@lists.arm.linux.org.uk, linux-embedded@vger.kernel.org Date: Mon, 27 Oct 2008 12:53:22 +0200 Message-ID: <20081027105318.21923.24436.stgit@Programuotojas.82-135-208-232.ip.zebra.lt> User-Agent: StGIT/0.14.1 MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Useful for machines where PHY control is connected to GPIO. This driver also supports interrupts from PHY. Changes since v1: - fixed releasing of gpio (thanks to Sascha Hauer) - fixed compiling due to bus->dev to bus->parent change Signed-off-by: Paulius Zaleckas --- drivers/net/phy/Kconfig | 6 + drivers/net/phy/Makefile | 1 drivers/net/phy/mdio-gpio.c | 187 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mdio-gpio.h | 40 +++++++++ 4 files changed, 234 insertions(+), 0 deletions(-) create mode 100644 drivers/net/phy/mdio-gpio.c create mode 100644 include/linux/mdio-gpio.h -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index d55932a..b6a0350 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -84,6 +84,12 @@ config MDIO_BITBANG If in doubt, say N. +config MDIO_GPIO + tristate "Support for GPIO bitbanged MDIO buses" + depends on MDIO_BITBANG && GENERIC_GPIO + help + Supports MDIO busses connected to GPIO. + config MDIO_OF_GPIO tristate "Support for GPIO lib-based bitbanged MDIO buses" depends on MDIO_BITBANG && OF_GPIO diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index eee329f..8629b09 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -15,4 +15,5 @@ obj-$(CONFIG_ICPLUS_PHY) += icplus.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_FIXED_PHY) += fixed.o obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o +obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o obj-$(CONFIG_MDIO_OF_GPIO) += mdio-ofgpio.o diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c new file mode 100644 index 0000000..585897b --- /dev/null +++ b/drivers/net/phy/mdio-gpio.c @@ -0,0 +1,187 @@ +/* + * GPIO based MDIO bitbang driver. + * + * Copyright (C) 2008, Paulius Zaleckas + * + * Based on mdio-ofgpio.c: + * + * Copyright (c) 2008 CSE Semaphore Belgium. + * by Laurent Pinchart + * + * Copyright (c) 2003 Intracom S.A. + * by Pantelis Antoniou + * + * 2005 (c) MontaVista Software, Inc. + * Vitaly Bordug + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include + +struct mdio_gpio_info { + struct mdiobb_ctrl ctrl; + unsigned int mdc, mdio; +}; + +static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) +{ + struct mdio_gpio_info *bitbang = + container_of(ctrl, struct mdio_gpio_info, ctrl); + + if (dir) + gpio_direction_output(bitbang->mdio, 1); + else + gpio_direction_input(bitbang->mdio); +} + +static int mdio_read(struct mdiobb_ctrl *ctrl) +{ + struct mdio_gpio_info *bitbang = + container_of(ctrl, struct mdio_gpio_info, ctrl); + + return gpio_get_value(bitbang->mdio); +} + +static void mdio(struct mdiobb_ctrl *ctrl, int what) +{ + struct mdio_gpio_info *bitbang = + container_of(ctrl, struct mdio_gpio_info, ctrl); + + gpio_set_value(bitbang->mdio, what); +} + +static void mdc(struct mdiobb_ctrl *ctrl, int what) +{ + struct mdio_gpio_info *bitbang = + container_of(ctrl, struct mdio_gpio_info, ctrl); + + gpio_set_value(bitbang->mdc, what); +} + +static struct mdiobb_ops mdio_gpio_ops = { + .owner = THIS_MODULE, + .set_mdc = mdc, + .set_mdio_dir = mdio_dir, + .set_mdio_data = mdio, + .get_mdio_data = mdio_read, +}; + +static int __devinit mdio_gpio_probe(struct platform_device *pdev) +{ + struct mii_bus *new_bus; + struct mdio_gpio_info *bitbang; + struct mdio_gpio_platform_data *pdata; + int ret = -ENOMEM; + int i; + + pdata = pdev->dev.platform_data; + if (pdata == NULL) + goto out; + + bitbang = kzalloc(sizeof(struct mdio_gpio_info), GFP_KERNEL); + if (!bitbang) + goto out; + + bitbang->ctrl.ops = &mdio_gpio_ops; + bitbang->mdc = pdata->mdc; + bitbang->mdio = pdata->mdio; + + if (gpio_request(bitbang->mdc, "mdc")) + goto out_free_bitbang; + + if (gpio_request(bitbang->mdio, "mdio")) + goto out_free_mdc; + + new_bus = alloc_mdio_bitbang(&bitbang->ctrl); + if (!new_bus) + goto out_free_gpio; + + new_bus->name = "GPIO Bitbanged MII", + snprintf(new_bus->id, MII_BUS_ID_SIZE, "phy%i", pdev->id); + + new_bus->phy_mask = ~0; + new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!new_bus->irq) + goto out_free_bus; + + for (i = 0; i < PHY_MAX_ADDR; i++) + new_bus->irq[i] = PHY_POLL; + + for (i = 0; i < pdata->nr_phys; i++) { + unsigned int phy_addr = pdata->phys[i].addr; + + BUG_ON(phy_addr >= PHY_MAX_ADDR); + + new_bus->phy_mask &= ~(1 << phy_addr); + new_bus->irq[phy_addr] = pdata->phys[i].irq; + } + + new_bus->parent = &pdev->dev; + platform_set_drvdata(pdev, new_bus); + + ret = mdiobus_register(new_bus); + if (ret) + goto out_free_all; + + return 0; + +out_free_all: + platform_set_drvdata(pdev, NULL); + kfree(new_bus->irq); +out_free_bus: + free_mdio_bitbang(new_bus); +out_free_gpio: + gpio_free(bitbang->mdio); +out_free_mdc: + gpio_free(bitbang->mdc); +out_free_bitbang: + kfree(bitbang); +out: + return ret; +} + +static int __devexit mdio_gpio_remove(struct platform_device *pdev) +{ + struct mii_bus *bus = platform_get_drvdata(pdev); + struct mdio_gpio_info *bitbang = bus->priv; + + mdiobus_unregister(bus); + kfree(bus->irq); + free_mdio_bitbang(bus); + platform_set_drvdata(pdev, NULL); + gpio_free(bitbang->mdc); + gpio_free(bitbang->mdio); + kfree(bitbang); + + return 0; +} + +static struct platform_driver mdio_gpio_driver = { + .probe = mdio_gpio_probe, + .remove = __devexit_p(mdio_gpio_remove), + .driver = { + .name = "mdio-gpio", + .owner = THIS_MODULE, + }, +}; + +static int mdio_gpio_init(void) +{ + return platform_driver_register(&mdio_gpio_driver); +} + +static void mdio_gpio_exit(void) +{ + platform_driver_unregister(&mdio_gpio_driver); +} + +module_init(mdio_gpio_init); +module_exit(mdio_gpio_exit); diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h new file mode 100644 index 0000000..82d5fa4 --- /dev/null +++ b/include/linux/mdio-gpio.h @@ -0,0 +1,40 @@ +/* + * MDIO-GPIO bus platform data structures + * + * Copyright (C) 2008, Paulius Zaleckas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_MDIO_GPIO_H +#define __LINUX_MDIO_GPIO_H + +struct mdio_gpio_phy { + /* PHY address on MDIO bus */ + unsigned int addr; + /* preconfigured irq connected to PHY or -1 if no irq */ + int irq; +}; + +struct mdio_gpio_platform_data { + /* GPIO numbers for bus pins */ + unsigned int mdc; + unsigned int mdio; + + unsigned int nr_phys; + struct mdio_gpio_phy *phys; +}; + +#endif /* __LINUX_MDIO_GPIO_H */