blob: ab6914f8bd50f956efe1ce162a98b56469cbbe07 [file] [log] [blame]
David Daney25d967b2009-10-14 12:04:38 -07001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
David Daney1eefee92016-03-11 09:53:10 -08006 * Copyright (C) 2009-2015 Cavium, Inc.
David Daney25d967b2009-10-14 12:04:38 -07007 */
8
David Daney25d967b2009-10-14 12:04:38 -07009#include <linux/platform_device.h>
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -070010#include <linux/of_address.h>
David Daney2fd46f42012-07-05 18:12:39 +020011#include <linux/of_mdio.h>
David Daney2fd46f42012-07-05 18:12:39 +020012#include <linux/module.h>
David Daney2fd46f42012-07-05 18:12:39 +020013#include <linux/gfp.h>
David Daney25d967b2009-10-14 12:04:38 -070014#include <linux/phy.h>
David Daney2fd46f42012-07-05 18:12:39 +020015#include <linux/io.h>
David Daney25d967b2009-10-14 12:04:38 -070016
David Daney1eefee92016-03-11 09:53:10 -080017#include "mdio-cavium.h"
David Daney25d967b2009-10-14 12:04:38 -070018
Bill Pemberton633d1592012-12-03 09:24:14 -050019static int octeon_mdiobus_probe(struct platform_device *pdev)
David Daney25d967b2009-10-14 12:04:38 -070020{
David Daney1eefee92016-03-11 09:53:10 -080021 struct cavium_mdiobus *bus;
Andrew Lunn35d2aea2016-01-06 20:11:14 +010022 struct mii_bus *mii_bus;
David Daney2fd46f42012-07-05 18:12:39 +020023 struct resource *res_mem;
David Daney1eefee92016-03-11 09:53:10 -080024 resource_size_t mdio_phys;
25 resource_size_t regsize;
David Daney6c178122010-04-01 18:17:54 -070026 union cvmx_smix_en smi_en;
David Daney25d967b2009-10-14 12:04:38 -070027 int err = -ENOENT;
28
Andrew Lunn35d2aea2016-01-06 20:11:14 +010029 mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus));
30 if (!mii_bus)
David Daney25d967b2009-10-14 12:04:38 -070031 return -ENOMEM;
32
David Daney2fd46f42012-07-05 18:12:39 +020033 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
David Daney2fd46f42012-07-05 18:12:39 +020034 if (res_mem == NULL) {
35 dev_err(&pdev->dev, "found no memory resource\n");
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070036 return -ENXIO;
David Daney2fd46f42012-07-05 18:12:39 +020037 }
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070038
Andrew Lunn35d2aea2016-01-06 20:11:14 +010039 bus = mii_bus->priv;
40 bus->mii_bus = mii_bus;
David Daney1eefee92016-03-11 09:53:10 -080041 mdio_phys = res_mem->start;
42 regsize = resource_size(res_mem);
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070043
David Daney1eefee92016-03-11 09:53:10 -080044 if (!devm_request_mem_region(&pdev->dev, mdio_phys, regsize,
David Daney2fd46f42012-07-05 18:12:39 +020045 res_mem->name)) {
46 dev_err(&pdev->dev, "request_mem_region failed\n");
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070047 return -ENXIO;
David Daney2fd46f42012-07-05 18:12:39 +020048 }
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070049
David Daney2fd46f42012-07-05 18:12:39 +020050 bus->register_base =
David Daney1eefee92016-03-11 09:53:10 -080051 (u64)devm_ioremap(&pdev->dev, mdio_phys, regsize);
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070052 if (!bus->register_base) {
53 dev_err(&pdev->dev, "dev_ioremap failed\n");
54 return -ENOMEM;
55 }
David Daney25d967b2009-10-14 12:04:38 -070056
David Daney6c178122010-04-01 18:17:54 -070057 smi_en.u64 = 0;
58 smi_en.s.en = 1;
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -070059 oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
David Daney25d967b2009-10-14 12:04:38 -070060
David Daney1eefee92016-03-11 09:53:10 -080061 bus->mii_bus->name = KBUILD_MODNAME;
David Daney2fd46f42012-07-05 18:12:39 +020062 snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base);
David Daney25d967b2009-10-14 12:04:38 -070063 bus->mii_bus->parent = &pdev->dev;
64
David Daney1eefee92016-03-11 09:53:10 -080065 bus->mii_bus->read = cavium_mdiobus_read;
66 bus->mii_bus->write = cavium_mdiobus_write;
David Daney25d967b2009-10-14 12:04:38 -070067
Libo Chenf8825662013-08-21 18:15:15 +080068 platform_set_drvdata(pdev, bus);
David Daney25d967b2009-10-14 12:04:38 -070069
David Daney2fd46f42012-07-05 18:12:39 +020070 err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
David Daney25d967b2009-10-14 12:04:38 -070071 if (err)
David Daney2fd46f42012-07-05 18:12:39 +020072 goto fail_register;
David Daney25d967b2009-10-14 12:04:38 -070073
David Daney1eefee92016-03-11 09:53:10 -080074 dev_info(&pdev->dev, "Probed\n");
David Daney25d967b2009-10-14 12:04:38 -070075
76 return 0;
David Daney2fd46f42012-07-05 18:12:39 +020077fail_register:
David Daney25d967b2009-10-14 12:04:38 -070078 mdiobus_free(bus->mii_bus);
David Daney6c178122010-04-01 18:17:54 -070079 smi_en.u64 = 0;
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -070080 oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
David Daney25d967b2009-10-14 12:04:38 -070081 return err;
82}
83
Bill Pemberton633d1592012-12-03 09:24:14 -050084static int octeon_mdiobus_remove(struct platform_device *pdev)
David Daney25d967b2009-10-14 12:04:38 -070085{
David Daney1eefee92016-03-11 09:53:10 -080086 struct cavium_mdiobus *bus;
David Daney6c178122010-04-01 18:17:54 -070087 union cvmx_smix_en smi_en;
David Daney25d967b2009-10-14 12:04:38 -070088
Jingoo Han2c0c4fb2013-09-02 17:10:09 +090089 bus = platform_get_drvdata(pdev);
David Daney25d967b2009-10-14 12:04:38 -070090
91 mdiobus_unregister(bus->mii_bus);
92 mdiobus_free(bus->mii_bus);
David Daney6c178122010-04-01 18:17:54 -070093 smi_en.u64 = 0;
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -070094 oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
David Daney25d967b2009-10-14 12:04:38 -070095 return 0;
96}
97
Fabian Frederickd8a7dad2015-03-17 19:40:23 +010098static const struct of_device_id octeon_mdiobus_match[] = {
David Daney2fd46f42012-07-05 18:12:39 +020099 {
100 .compatible = "cavium,octeon-3860-mdio",
101 },
102 {},
103};
104MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
105
David Daney25d967b2009-10-14 12:04:38 -0700106static struct platform_driver octeon_mdiobus_driver = {
107 .driver = {
David Daney1eefee92016-03-11 09:53:10 -0800108 .name = KBUILD_MODNAME,
David Daney2fd46f42012-07-05 18:12:39 +0200109 .of_match_table = octeon_mdiobus_match,
David Daney25d967b2009-10-14 12:04:38 -0700110 },
111 .probe = octeon_mdiobus_probe,
Bill Pemberton633d1592012-12-03 09:24:14 -0500112 .remove = octeon_mdiobus_remove,
David Daney25d967b2009-10-14 12:04:38 -0700113};
114
115void octeon_mdiobus_force_mod_depencency(void)
116{
117 /* Let ethernet drivers force us to be loaded. */
118}
119EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency);
120
Sachin Kamat9fad0c92013-03-20 01:41:32 +0000121module_platform_driver(octeon_mdiobus_driver);
David Daney25d967b2009-10-14 12:04:38 -0700122
David Daney1eefee92016-03-11 09:53:10 -0800123MODULE_DESCRIPTION("Cavium OCTEON MDIO bus driver");
David Daney25d967b2009-10-14 12:04:38 -0700124MODULE_AUTHOR("David Daney");
125MODULE_LICENSE("GPL");