blob: d1e1009d51afe5e0de6a7ff58b37f89a2d6e7e6f [file] [log] [blame]
Andrew Lunn8bbe8332019-01-21 19:34:53 +01001// SPDX-License-Identifier: GPL-2.0
David Daney25d967b2009-10-14 12:04:38 -07002/*
David Daney1eefee92016-03-11 09:53:10 -08003 * Copyright (C) 2009-2015 Cavium, Inc.
David Daney25d967b2009-10-14 12:04:38 -07004 */
5
David Daney25d967b2009-10-14 12:04:38 -07006#include <linux/platform_device.h>
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -07007#include <linux/of_address.h>
David Daney2fd46f42012-07-05 18:12:39 +02008#include <linux/of_mdio.h>
David Daney2fd46f42012-07-05 18:12:39 +02009#include <linux/module.h>
David Daney2fd46f42012-07-05 18:12:39 +020010#include <linux/gfp.h>
David Daney25d967b2009-10-14 12:04:38 -070011#include <linux/phy.h>
David Daney2fd46f42012-07-05 18:12:39 +020012#include <linux/io.h>
David Daney25d967b2009-10-14 12:04:38 -070013
David Daney1eefee92016-03-11 09:53:10 -080014#include "mdio-cavium.h"
David Daney25d967b2009-10-14 12:04:38 -070015
Bill Pemberton633d1592012-12-03 09:24:14 -050016static int octeon_mdiobus_probe(struct platform_device *pdev)
David Daney25d967b2009-10-14 12:04:38 -070017{
David Daney1eefee92016-03-11 09:53:10 -080018 struct cavium_mdiobus *bus;
Andrew Lunn35d2aea2016-01-06 20:11:14 +010019 struct mii_bus *mii_bus;
David Daney2fd46f42012-07-05 18:12:39 +020020 struct resource *res_mem;
David Daney1eefee92016-03-11 09:53:10 -080021 resource_size_t mdio_phys;
22 resource_size_t regsize;
David Daney6c178122010-04-01 18:17:54 -070023 union cvmx_smix_en smi_en;
David Daney25d967b2009-10-14 12:04:38 -070024 int err = -ENOENT;
25
Andrew Lunn35d2aea2016-01-06 20:11:14 +010026 mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus));
27 if (!mii_bus)
David Daney25d967b2009-10-14 12:04:38 -070028 return -ENOMEM;
29
David Daney2fd46f42012-07-05 18:12:39 +020030 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
David Daney2fd46f42012-07-05 18:12:39 +020031 if (res_mem == NULL) {
32 dev_err(&pdev->dev, "found no memory resource\n");
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070033 return -ENXIO;
David Daney2fd46f42012-07-05 18:12:39 +020034 }
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070035
Andrew Lunn35d2aea2016-01-06 20:11:14 +010036 bus = mii_bus->priv;
37 bus->mii_bus = mii_bus;
David Daney1eefee92016-03-11 09:53:10 -080038 mdio_phys = res_mem->start;
39 regsize = resource_size(res_mem);
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070040
David Daney1eefee92016-03-11 09:53:10 -080041 if (!devm_request_mem_region(&pdev->dev, mdio_phys, regsize,
David Daney2fd46f42012-07-05 18:12:39 +020042 res_mem->name)) {
43 dev_err(&pdev->dev, "request_mem_region failed\n");
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070044 return -ENXIO;
David Daney2fd46f42012-07-05 18:12:39 +020045 }
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070046
Andrew Lunnc7b04d12020-07-07 03:49:38 +020047 bus->register_base = devm_ioremap(&pdev->dev, mdio_phys, regsize);
Radha Mohan Chintakuntlade9e3972015-07-28 15:12:12 -070048 if (!bus->register_base) {
49 dev_err(&pdev->dev, "dev_ioremap failed\n");
50 return -ENOMEM;
51 }
David Daney25d967b2009-10-14 12:04:38 -070052
David Daney6c178122010-04-01 18:17:54 -070053 smi_en.u64 = 0;
54 smi_en.s.en = 1;
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -070055 oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
David Daney25d967b2009-10-14 12:04:38 -070056
David Daney1eefee92016-03-11 09:53:10 -080057 bus->mii_bus->name = KBUILD_MODNAME;
Andrew Lunnc7b04d12020-07-07 03:49:38 +020058 snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%px", bus->register_base);
David Daney25d967b2009-10-14 12:04:38 -070059 bus->mii_bus->parent = &pdev->dev;
60
David Daney1eefee92016-03-11 09:53:10 -080061 bus->mii_bus->read = cavium_mdiobus_read;
62 bus->mii_bus->write = cavium_mdiobus_write;
David Daney25d967b2009-10-14 12:04:38 -070063
Libo Chenf8825662013-08-21 18:15:15 +080064 platform_set_drvdata(pdev, bus);
David Daney25d967b2009-10-14 12:04:38 -070065
David Daney2fd46f42012-07-05 18:12:39 +020066 err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
David Daney25d967b2009-10-14 12:04:38 -070067 if (err)
David Daney2fd46f42012-07-05 18:12:39 +020068 goto fail_register;
David Daney25d967b2009-10-14 12:04:38 -070069
David Daney1eefee92016-03-11 09:53:10 -080070 dev_info(&pdev->dev, "Probed\n");
David Daney25d967b2009-10-14 12:04:38 -070071
72 return 0;
David Daney2fd46f42012-07-05 18:12:39 +020073fail_register:
David Daney25d967b2009-10-14 12:04:38 -070074 mdiobus_free(bus->mii_bus);
David Daney6c178122010-04-01 18:17:54 -070075 smi_en.u64 = 0;
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -070076 oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
David Daney25d967b2009-10-14 12:04:38 -070077 return err;
78}
79
Bill Pemberton633d1592012-12-03 09:24:14 -050080static int octeon_mdiobus_remove(struct platform_device *pdev)
David Daney25d967b2009-10-14 12:04:38 -070081{
David Daney1eefee92016-03-11 09:53:10 -080082 struct cavium_mdiobus *bus;
David Daney6c178122010-04-01 18:17:54 -070083 union cvmx_smix_en smi_en;
David Daney25d967b2009-10-14 12:04:38 -070084
Jingoo Han2c0c4fb2013-09-02 17:10:09 +090085 bus = platform_get_drvdata(pdev);
David Daney25d967b2009-10-14 12:04:38 -070086
87 mdiobus_unregister(bus->mii_bus);
88 mdiobus_free(bus->mii_bus);
David Daney6c178122010-04-01 18:17:54 -070089 smi_en.u64 = 0;
Radha Mohan Chintakuntlaa6d67862015-07-28 15:12:11 -070090 oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
David Daney25d967b2009-10-14 12:04:38 -070091 return 0;
92}
93
Fabian Frederickd8a7dad2015-03-17 19:40:23 +010094static const struct of_device_id octeon_mdiobus_match[] = {
David Daney2fd46f42012-07-05 18:12:39 +020095 {
96 .compatible = "cavium,octeon-3860-mdio",
97 },
98 {},
99};
100MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
101
David Daney25d967b2009-10-14 12:04:38 -0700102static struct platform_driver octeon_mdiobus_driver = {
103 .driver = {
David Daney1eefee92016-03-11 09:53:10 -0800104 .name = KBUILD_MODNAME,
David Daney2fd46f42012-07-05 18:12:39 +0200105 .of_match_table = octeon_mdiobus_match,
David Daney25d967b2009-10-14 12:04:38 -0700106 },
107 .probe = octeon_mdiobus_probe,
Bill Pemberton633d1592012-12-03 09:24:14 -0500108 .remove = octeon_mdiobus_remove,
David Daney25d967b2009-10-14 12:04:38 -0700109};
110
Sachin Kamat9fad0c92013-03-20 01:41:32 +0000111module_platform_driver(octeon_mdiobus_driver);
David Daney25d967b2009-10-14 12:04:38 -0700112
David Daney1eefee92016-03-11 09:53:10 -0800113MODULE_DESCRIPTION("Cavium OCTEON MDIO bus driver");
David Daney25d967b2009-10-14 12:04:38 -0700114MODULE_AUTHOR("David Daney");
Andrew Lunn8bbe8332019-01-21 19:34:53 +0100115MODULE_LICENSE("GPL v2");