aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/phy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 14:45:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 14:45:52 -0400
commit287dc4b7642df15fa6b9f286c812e79138acd698 (patch)
treec3ebe1caea100ff2b8f414619ec0a9dcd8a14547 /drivers/net/phy
parent720d85075b7ed3617de8ca8d9097390e303e9f60 (diff)
parent68d8848567ef03eb2c2303173934428d0bf0a531 (diff)
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: "More hardware support across the field including a bunch of device drivers. The highlight however really are further steps towards device tree. This has been sitting in -next for ages. All MIPS _defconfigs have been tested to boot or where I don't have hardware available, to at least build fine." * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (77 commits) MIPS: Loongson 1B: Add defconfig MIPS: Loongson 1B: Add board support MIPS: Netlogic: early console fix MIPS: Netlogic: Fix indentation of smpboot.S MIPS: Netlogic: remove cpu_has_dc_aliases define for XLP MIPS: Netlogic: Remove unused pcibios_fixups MIPS: Netlogic: Add XLP SoC devices in FDT MIPS: Netlogic: Add IRQ mappings for more devices MIPS: Netlogic: USB support for XLP MIPS: Netlogic: XLP PCIe controller support. MIPS: Netlogic: Platform changes for XLR/XLS I2C MIPS: Netlogic: Platform NAND/NOR flash support MIPS: Netlogic: Platform changes for XLS USB MIPS: Netlogic: Remove NETLOGIC_ prefix MIPS: Netlogic: SMP wakeup code update MIPS: Netlogic: Update comments in smpboot.S MIPS: BCM63XX: Add 96328avng reference board MIPS: Expose PCIe drivers for MIPS MIPS: BCM63XX: Add PCIe Support for BCM6328 MIPS: BCM63XX: Move the PCI initialization into its own function ...
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/mdio-octeon.c92
1 files changed, 58 insertions, 34 deletions
diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c
index 826d961f39f7..d4015aa663e6 100644
--- a/drivers/net/phy/mdio-octeon.c
+++ b/drivers/net/phy/mdio-octeon.c
@@ -3,14 +3,17 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 2009 Cavium Networks 6 * Copyright (C) 2009,2011 Cavium, Inc.
7 */ 7 */
8 8
9#include <linux/gfp.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/platform_device.h> 9#include <linux/platform_device.h>
10#include <linux/of_mdio.h>
11#include <linux/delay.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/gfp.h>
13#include <linux/phy.h> 15#include <linux/phy.h>
16#include <linux/io.h>
14 17
15#include <asm/octeon/octeon.h> 18#include <asm/octeon/octeon.h>
16#include <asm/octeon/cvmx-smix-defs.h> 19#include <asm/octeon/cvmx-smix-defs.h>
@@ -18,9 +21,17 @@
18#define DRV_VERSION "1.0" 21#define DRV_VERSION "1.0"
19#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver" 22#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
20 23
24#define SMI_CMD 0x0
25#define SMI_WR_DAT 0x8
26#define SMI_RD_DAT 0x10
27#define SMI_CLK 0x18
28#define SMI_EN 0x20
29
21struct octeon_mdiobus { 30struct octeon_mdiobus {
22 struct mii_bus *mii_bus; 31 struct mii_bus *mii_bus;
23 int unit; 32 u64 register_base;
33 resource_size_t mdio_phys;
34 resource_size_t regsize;
24 int phy_irq[PHY_MAX_ADDR]; 35 int phy_irq[PHY_MAX_ADDR];
25}; 36};
26 37
@@ -35,15 +46,15 @@ static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
35 smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */ 46 smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
36 smi_cmd.s.phy_adr = phy_id; 47 smi_cmd.s.phy_adr = phy_id;
37 smi_cmd.s.reg_adr = regnum; 48 smi_cmd.s.reg_adr = regnum;
38 cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); 49 cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
39 50
40 do { 51 do {
41 /* 52 /*
42 * Wait 1000 clocks so we don't saturate the RSL bus 53 * Wait 1000 clocks so we don't saturate the RSL bus
43 * doing reads. 54 * doing reads.
44 */ 55 */
45 cvmx_wait(1000); 56 __delay(1000);
46 smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit)); 57 smi_rd.u64 = cvmx_read_csr(p->register_base + SMI_RD_DAT);
47 } while (smi_rd.s.pending && --timeout); 58 } while (smi_rd.s.pending && --timeout);
48 59
49 if (smi_rd.s.val) 60 if (smi_rd.s.val)
@@ -62,21 +73,21 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
62 73
63 smi_wr.u64 = 0; 74 smi_wr.u64 = 0;
64 smi_wr.s.dat = val; 75 smi_wr.s.dat = val;
65 cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64); 76 cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64);
66 77
67 smi_cmd.u64 = 0; 78 smi_cmd.u64 = 0;
68 smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */ 79 smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
69 smi_cmd.s.phy_adr = phy_id; 80 smi_cmd.s.phy_adr = phy_id;
70 smi_cmd.s.reg_adr = regnum; 81 smi_cmd.s.reg_adr = regnum;
71 cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); 82 cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
72 83
73 do { 84 do {
74 /* 85 /*
75 * Wait 1000 clocks so we don't saturate the RSL bus 86 * Wait 1000 clocks so we don't saturate the RSL bus
76 * doing reads. 87 * doing reads.
77 */ 88 */
78 cvmx_wait(1000); 89 __delay(1000);
79 smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit)); 90 smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT);
80 } while (smi_wr.s.pending && --timeout); 91 } while (smi_wr.s.pending && --timeout);
81 92
82 if (timeout <= 0) 93 if (timeout <= 0)
@@ -88,38 +99,44 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
88static int __devinit octeon_mdiobus_probe(struct platform_device *pdev) 99static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
89{ 100{
90 struct octeon_mdiobus *bus; 101 struct octeon_mdiobus *bus;
102 struct resource *res_mem;
91 union cvmx_smix_en smi_en; 103 union cvmx_smix_en smi_en;
92 int i;
93 int err = -ENOENT; 104 int err = -ENOENT;
94 105
95 bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL); 106 bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
96 if (!bus) 107 if (!bus)
97 return -ENOMEM; 108 return -ENOMEM;
98 109
99 /* The platform_device id is our unit number. */ 110 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
100 bus->unit = pdev->id; 111
112 if (res_mem == NULL) {
113 dev_err(&pdev->dev, "found no memory resource\n");
114 err = -ENXIO;
115 goto fail;
116 }
117 bus->mdio_phys = res_mem->start;
118 bus->regsize = resource_size(res_mem);
119 if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize,
120 res_mem->name)) {
121 dev_err(&pdev->dev, "request_mem_region failed\n");
122 goto fail;
123 }
124 bus->register_base =
125 (u64)devm_ioremap(&pdev->dev, bus->mdio_phys, bus->regsize);
101 126
102 bus->mii_bus = mdiobus_alloc(); 127 bus->mii_bus = mdiobus_alloc();
103 128
104 if (!bus->mii_bus) 129 if (!bus->mii_bus)
105 goto err; 130 goto fail;
106 131
107 smi_en.u64 = 0; 132 smi_en.u64 = 0;
108 smi_en.s.en = 1; 133 smi_en.s.en = 1;
109 cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); 134 cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
110
111 /*
112 * Standard Octeon evaluation boards don't support phy
113 * interrupts, we need to poll.
114 */
115 for (i = 0; i < PHY_MAX_ADDR; i++)
116 bus->phy_irq[i] = PHY_POLL;
117 135
118 bus->mii_bus->priv = bus; 136 bus->mii_bus->priv = bus;
119 bus->mii_bus->irq = bus->phy_irq; 137 bus->mii_bus->irq = bus->phy_irq;
120 bus->mii_bus->name = "mdio-octeon"; 138 bus->mii_bus->name = "mdio-octeon";
121 snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", 139 snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base);
122 bus->mii_bus->name, bus->unit);
123 bus->mii_bus->parent = &pdev->dev; 140 bus->mii_bus->parent = &pdev->dev;
124 141
125 bus->mii_bus->read = octeon_mdiobus_read; 142 bus->mii_bus->read = octeon_mdiobus_read;
@@ -127,20 +144,18 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
127 144
128 dev_set_drvdata(&pdev->dev, bus); 145 dev_set_drvdata(&pdev->dev, bus);
129 146
130 err = mdiobus_register(bus->mii_bus); 147 err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
131 if (err) 148 if (err)
132 goto err_register; 149 goto fail_register;
133 150
134 dev_info(&pdev->dev, "Version " DRV_VERSION "\n"); 151 dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
135 152
136 return 0; 153 return 0;
137err_register: 154fail_register:
138 mdiobus_free(bus->mii_bus); 155 mdiobus_free(bus->mii_bus);
139 156fail:
140err:
141 devm_kfree(&pdev->dev, bus);
142 smi_en.u64 = 0; 157 smi_en.u64 = 0;
143 cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); 158 cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
144 return err; 159 return err;
145} 160}
146 161
@@ -154,14 +169,23 @@ static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
154 mdiobus_unregister(bus->mii_bus); 169 mdiobus_unregister(bus->mii_bus);
155 mdiobus_free(bus->mii_bus); 170 mdiobus_free(bus->mii_bus);
156 smi_en.u64 = 0; 171 smi_en.u64 = 0;
157 cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); 172 cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
158 return 0; 173 return 0;
159} 174}
160 175
176static struct of_device_id octeon_mdiobus_match[] = {
177 {
178 .compatible = "cavium,octeon-3860-mdio",
179 },
180 {},
181};
182MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
183
161static struct platform_driver octeon_mdiobus_driver = { 184static struct platform_driver octeon_mdiobus_driver = {
162 .driver = { 185 .driver = {
163 .name = "mdio-octeon", 186 .name = "mdio-octeon",
164 .owner = THIS_MODULE, 187 .owner = THIS_MODULE,
188 .of_match_table = octeon_mdiobus_match,
165 }, 189 },
166 .probe = octeon_mdiobus_probe, 190 .probe = octeon_mdiobus_probe,
167 .remove = __devexit_p(octeon_mdiobus_remove), 191 .remove = __devexit_p(octeon_mdiobus_remove),