Commit | Line | Data |
---|---|---|
25d967b7 DD |
1 | /* |
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 | * | |
1eefee90 | 6 | * Copyright (C) 2009-2015 Cavium, Inc. |
25d967b7 DD |
7 | */ |
8 | ||
25d967b7 | 9 | #include <linux/platform_device.h> |
a6d67864 | 10 | #include <linux/of_address.h> |
2fd46f47 | 11 | #include <linux/of_mdio.h> |
2fd46f47 | 12 | #include <linux/module.h> |
2fd46f47 | 13 | #include <linux/gfp.h> |
25d967b7 | 14 | #include <linux/phy.h> |
2fd46f47 | 15 | #include <linux/io.h> |
25d967b7 | 16 | |
1eefee90 | 17 | #include "mdio-cavium.h" |
25d967b7 | 18 | |
633d1594 | 19 | static int octeon_mdiobus_probe(struct platform_device *pdev) |
25d967b7 | 20 | { |
1eefee90 | 21 | struct cavium_mdiobus *bus; |
35d2aeac | 22 | struct mii_bus *mii_bus; |
2fd46f47 | 23 | struct resource *res_mem; |
1eefee90 DD |
24 | resource_size_t mdio_phys; |
25 | resource_size_t regsize; | |
6c17812d | 26 | union cvmx_smix_en smi_en; |
25d967b7 DD |
27 | int err = -ENOENT; |
28 | ||
35d2aeac AL |
29 | mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus)); |
30 | if (!mii_bus) | |
25d967b7 DD |
31 | return -ENOMEM; |
32 | ||
2fd46f47 | 33 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2fd46f47 DD |
34 | if (res_mem == NULL) { |
35 | dev_err(&pdev->dev, "found no memory resource\n"); | |
de9e397e | 36 | return -ENXIO; |
2fd46f47 | 37 | } |
de9e397e | 38 | |
35d2aeac AL |
39 | bus = mii_bus->priv; |
40 | bus->mii_bus = mii_bus; | |
1eefee90 DD |
41 | mdio_phys = res_mem->start; |
42 | regsize = resource_size(res_mem); | |
de9e397e | 43 | |
1eefee90 | 44 | if (!devm_request_mem_region(&pdev->dev, mdio_phys, regsize, |
2fd46f47 DD |
45 | res_mem->name)) { |
46 | dev_err(&pdev->dev, "request_mem_region failed\n"); | |
de9e397e | 47 | return -ENXIO; |
2fd46f47 | 48 | } |
de9e397e | 49 | |
2fd46f47 | 50 | bus->register_base = |
1eefee90 | 51 | (u64)devm_ioremap(&pdev->dev, mdio_phys, regsize); |
de9e397e RMC |
52 | if (!bus->register_base) { |
53 | dev_err(&pdev->dev, "dev_ioremap failed\n"); | |
54 | return -ENOMEM; | |
55 | } | |
25d967b7 | 56 | |
6c17812d DD |
57 | smi_en.u64 = 0; |
58 | smi_en.s.en = 1; | |
a6d67864 | 59 | oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); |
25d967b7 | 60 | |
1eefee90 | 61 | bus->mii_bus->name = KBUILD_MODNAME; |
2fd46f47 | 62 | snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base); |
25d967b7 DD |
63 | bus->mii_bus->parent = &pdev->dev; |
64 | ||
1eefee90 DD |
65 | bus->mii_bus->read = cavium_mdiobus_read; |
66 | bus->mii_bus->write = cavium_mdiobus_write; | |
25d967b7 | 67 | |
f8825669 | 68 | platform_set_drvdata(pdev, bus); |
25d967b7 | 69 | |
2fd46f47 | 70 | err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node); |
25d967b7 | 71 | if (err) |
2fd46f47 | 72 | goto fail_register; |
25d967b7 | 73 | |
1eefee90 | 74 | dev_info(&pdev->dev, "Probed\n"); |
25d967b7 DD |
75 | |
76 | return 0; | |
2fd46f47 | 77 | fail_register: |
25d967b7 | 78 | mdiobus_free(bus->mii_bus); |
6c17812d | 79 | smi_en.u64 = 0; |
a6d67864 | 80 | oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); |
25d967b7 DD |
81 | return err; |
82 | } | |
83 | ||
633d1594 | 84 | static int octeon_mdiobus_remove(struct platform_device *pdev) |
25d967b7 | 85 | { |
1eefee90 | 86 | struct cavium_mdiobus *bus; |
6c17812d | 87 | union cvmx_smix_en smi_en; |
25d967b7 | 88 | |
2c0c4fbe | 89 | bus = platform_get_drvdata(pdev); |
25d967b7 DD |
90 | |
91 | mdiobus_unregister(bus->mii_bus); | |
92 | mdiobus_free(bus->mii_bus); | |
6c17812d | 93 | smi_en.u64 = 0; |
a6d67864 | 94 | oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); |
25d967b7 DD |
95 | return 0; |
96 | } | |
97 | ||
d8a7dadb | 98 | static const struct of_device_id octeon_mdiobus_match[] = { |
2fd46f47 DD |
99 | { |
100 | .compatible = "cavium,octeon-3860-mdio", | |
101 | }, | |
102 | {}, | |
103 | }; | |
104 | MODULE_DEVICE_TABLE(of, octeon_mdiobus_match); | |
105 | ||
25d967b7 DD |
106 | static struct platform_driver octeon_mdiobus_driver = { |
107 | .driver = { | |
1eefee90 | 108 | .name = KBUILD_MODNAME, |
2fd46f47 | 109 | .of_match_table = octeon_mdiobus_match, |
25d967b7 DD |
110 | }, |
111 | .probe = octeon_mdiobus_probe, | |
633d1594 | 112 | .remove = octeon_mdiobus_remove, |
25d967b7 DD |
113 | }; |
114 | ||
115 | void octeon_mdiobus_force_mod_depencency(void) | |
116 | { | |
117 | /* Let ethernet drivers force us to be loaded. */ | |
118 | } | |
119 | EXPORT_SYMBOL(octeon_mdiobus_force_mod_depencency); | |
120 | ||
9fad0c94 | 121 | module_platform_driver(octeon_mdiobus_driver); |
25d967b7 | 122 | |
1eefee90 | 123 | MODULE_DESCRIPTION("Cavium OCTEON MDIO bus driver"); |
25d967b7 DD |
124 | MODULE_AUTHOR("David Daney"); |
125 | MODULE_LICENSE("GPL"); |