cregit-Linux how code gets into the kernel

Release 4.7 drivers/net/phy/mdio-sun4i.c

Directory: drivers/net/phy
/*
 * Allwinner EMAC MDIO interface driver
 *
 * Copyright 2012-2013 Stefan Roese <sr@denx.de>
 * Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
 *
 * Based on the Linux driver provided by Allwinner:
 * Copyright (C) 1997  Sten Wang
 *
 * 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 <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_address.h>
#include <linux/of_mdio.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>


#define EMAC_MAC_MCMD_REG	(0x00)

#define EMAC_MAC_MADR_REG	(0x04)

#define EMAC_MAC_MWTD_REG	(0x08)

#define EMAC_MAC_MRDD_REG	(0x0c)

#define EMAC_MAC_MIND_REG	(0x10)

#define EMAC_MAC_SSRR_REG	(0x14)


#define MDIO_TIMEOUT		(msecs_to_jiffies(100))


struct sun4i_mdio_data {
	
void __iomem		*membase;
	
struct regulator	*regulator;
};


static int sun4i_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct sun4i_mdio_data *data = bus->priv; unsigned long timeout_jiffies; int value; /* issue the phy address and reg */ writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG); /* pull up the phy io line */ writel(0x1, data->membase + EMAC_MAC_MCMD_REG); /* Wait read complete */ timeout_jiffies = jiffies + MDIO_TIMEOUT; while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { if (time_is_before_jiffies(timeout_jiffies)) return -ETIMEDOUT; msleep(1); } /* push down the phy io line */ writel(0x0, data->membase + EMAC_MAC_MCMD_REG); /* and read data */ value = readl(data->membase + EMAC_MAC_MRDD_REG); return value; }

Contributors

PersonTokensPropCommitsCommitProp
maxime ripardmaxime ripard12295.31%150.00%
emilio lopezemilio lopez64.69%150.00%
Total128100.00%2100.00%


static int sun4i_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { struct sun4i_mdio_data *data = bus->priv; unsigned long timeout_jiffies; /* issue the phy address and reg */ writel((mii_id << 8) | regnum, data->membase + EMAC_MAC_MADR_REG); /* pull up the phy io line */ writel(0x1, data->membase + EMAC_MAC_MCMD_REG); /* Wait read complete */ timeout_jiffies = jiffies + MDIO_TIMEOUT; while (readl(data->membase + EMAC_MAC_MIND_REG) & 0x1) { if (time_is_before_jiffies(timeout_jiffies)) return -ETIMEDOUT; msleep(1); } /* push down the phy io line */ writel(0x0, data->membase + EMAC_MAC_MCMD_REG); /* and write data */ writel(value, data->membase + EMAC_MAC_MWTD_REG); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
maxime ripardmaxime ripard12295.31%150.00%
emilio lopezemilio lopez64.69%150.00%
Total128100.00%2100.00%


static int sun4i_mdio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mii_bus *bus; struct sun4i_mdio_data *data; struct resource *res; int ret; bus = mdiobus_alloc_size(sizeof(*data)); if (!bus) return -ENOMEM; bus->name = "sun4i_mii_bus"; bus->read = &sun4i_mdio_read; bus->write = &sun4i_mdio_write; snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); bus->parent = &pdev->dev; data = bus->priv; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); data->membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(data->membase)) { ret = PTR_ERR(data->membase); goto err_out_free_mdiobus; } data->regulator = devm_regulator_get(&pdev->dev, "phy"); if (IS_ERR(data->regulator)) { if (PTR_ERR(data->regulator) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_info(&pdev->dev, "no regulator found\n"); data->regulator = NULL; } else { ret = regulator_enable(data->regulator); if (ret) goto err_out_free_mdiobus; } ret = of_mdiobus_register(bus, np); if (ret < 0) goto err_out_disable_regulator; platform_set_drvdata(pdev, bus); return 0; err_out_disable_regulator: if (data->regulator) regulator_disable(data->regulator); err_out_free_mdiobus: mdiobus_free(bus); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
maxime ripardmaxime ripard24684.54%133.33%
jisheng zhangjisheng zhang3311.34%133.33%
dan carpenterdan carpenter124.12%133.33%
Total291100.00%3100.00%


static int sun4i_mdio_remove(struct platform_device *pdev) { struct mii_bus *bus = platform_get_drvdata(pdev); mdiobus_unregister(bus); mdiobus_free(bus); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
maxime ripardmaxime ripard34100.00%1100.00%
Total34100.00%1100.00%

static const struct of_device_id sun4i_mdio_dt_ids[] = { { .compatible = "allwinner,sun4i-a10-mdio" }, /* Deprecated */ { .compatible = "allwinner,sun4i-mdio" }, { } }; MODULE_DEVICE_TABLE(of, sun4i_mdio_dt_ids); static struct platform_driver sun4i_mdio_driver = { .probe = sun4i_mdio_probe, .remove = sun4i_mdio_remove, .driver = { .name = "sun4i-mdio", .of_match_table = sun4i_mdio_dt_ids, }, }; module_platform_driver(sun4i_mdio_driver); MODULE_DESCRIPTION("Allwinner EMAC MDIO interface driver"); MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
maxime ripardmaxime ripard68092.27%240.00%
jisheng zhangjisheng zhang334.48%120.00%
emilio lopezemilio lopez121.63%120.00%
dan carpenterdan carpenter121.63%120.00%
Total737100.00%5100.00%
Directory: drivers/net/phy
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}