Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'thunderx_octeon_mdio'

Radha Mohan Chintakuntla says:

====================
Add MDIO support to ThunderX NIC driver

This patch series adds MDIO support to ThunderX NIC driver by making use
of existing mdio-octeon driver. In the process modified the mdio-octeon
driver to work on both Octeon and ThunderX platforms.

* From v1:
- Removed default selection in Kconfig for MDIO_OCTEON
- Replace uint64 with u64 as suggested by David Daney
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+122 -26
+2
drivers/net/ethernet/cavium/Kconfig
··· 37 37 tristate "Thunder MAC interface driver (BGX)" 38 38 depends on 64BIT 39 39 default ARCH_THUNDER 40 + select PHYLIB 41 + select MDIO_OCTEON 40 42 ---help--- 41 43 This driver supports programming and controlling of MAC 42 44 interface from NIC physical function driver.
+5 -5
drivers/net/phy/Kconfig
··· 150 150 will be called mdio-gpio. 151 151 152 152 config MDIO_OCTEON 153 - tristate "Support for MDIO buses on Octeon SOCs" 154 - depends on CAVIUM_OCTEON_SOC 155 - default y 153 + tristate "Support for MDIO buses on Octeon and ThunderX SOCs" 154 + depends on 64BIT 156 155 help 157 156 158 - This module provides a driver for the Octeon MDIO busses. 159 - It is required by the Octeon Ethernet device drivers. 157 + This module provides a driver for the Octeon and ThunderX MDIO 158 + busses. It is required by the Octeon and ThunderX ethernet device 159 + drivers. 160 160 161 161 If in doubt, say Y. 162 162
+115 -21
drivers/net/phy/mdio-octeon.c
··· 7 7 */ 8 8 9 9 #include <linux/platform_device.h> 10 + #include <linux/of_address.h> 10 11 #include <linux/of_mdio.h> 11 12 #include <linux/delay.h> 12 13 #include <linux/module.h> ··· 15 14 #include <linux/phy.h> 16 15 #include <linux/io.h> 17 16 17 + #ifdef CONFIG_CAVIUM_OCTEON_SOC 18 18 #include <asm/octeon/octeon.h> 19 - #include <asm/octeon/cvmx-smix-defs.h> 19 + #endif 20 20 21 - #define DRV_VERSION "1.0" 22 - #define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver" 21 + #define DRV_VERSION "1.1" 22 + #define DRV_DESCRIPTION "Cavium Networks Octeon/ThunderX SMI/MDIO driver" 23 23 24 24 #define SMI_CMD 0x0 25 25 #define SMI_WR_DAT 0x8 26 26 #define SMI_RD_DAT 0x10 27 27 #define SMI_CLK 0x18 28 28 #define SMI_EN 0x20 29 + 30 + #ifdef __BIG_ENDIAN_BITFIELD 31 + #define OCT_MDIO_BITFIELD_FIELD(field, more) \ 32 + field; \ 33 + more 34 + 35 + #else 36 + #define OCT_MDIO_BITFIELD_FIELD(field, more) \ 37 + more \ 38 + field; 39 + 40 + #endif 41 + 42 + union cvmx_smix_clk { 43 + u64 u64; 44 + struct cvmx_smix_clk_s { 45 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_25_63:39, 46 + OCT_MDIO_BITFIELD_FIELD(u64 mode:1, 47 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_21_23:3, 48 + OCT_MDIO_BITFIELD_FIELD(u64 sample_hi:5, 49 + OCT_MDIO_BITFIELD_FIELD(u64 sample_mode:1, 50 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_14_14:1, 51 + OCT_MDIO_BITFIELD_FIELD(u64 clk_idle:1, 52 + OCT_MDIO_BITFIELD_FIELD(u64 preamble:1, 53 + OCT_MDIO_BITFIELD_FIELD(u64 sample:4, 54 + OCT_MDIO_BITFIELD_FIELD(u64 phase:8, 55 + ;)))))))))) 56 + } s; 57 + }; 58 + 59 + union cvmx_smix_cmd { 60 + u64 u64; 61 + struct cvmx_smix_cmd_s { 62 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46, 63 + OCT_MDIO_BITFIELD_FIELD(u64 phy_op:2, 64 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_13_15:3, 65 + OCT_MDIO_BITFIELD_FIELD(u64 phy_adr:5, 66 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_5_7:3, 67 + OCT_MDIO_BITFIELD_FIELD(u64 reg_adr:5, 68 + ;)))))) 69 + } s; 70 + }; 71 + 72 + union cvmx_smix_en { 73 + u64 u64; 74 + struct cvmx_smix_en_s { 75 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_1_63:63, 76 + OCT_MDIO_BITFIELD_FIELD(u64 en:1, 77 + ;)) 78 + } s; 79 + }; 80 + 81 + union cvmx_smix_rd_dat { 82 + u64 u64; 83 + struct cvmx_smix_rd_dat_s { 84 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46, 85 + OCT_MDIO_BITFIELD_FIELD(u64 pending:1, 86 + OCT_MDIO_BITFIELD_FIELD(u64 val:1, 87 + OCT_MDIO_BITFIELD_FIELD(u64 dat:16, 88 + ;)))) 89 + } s; 90 + }; 91 + 92 + union cvmx_smix_wr_dat { 93 + u64 u64; 94 + struct cvmx_smix_wr_dat_s { 95 + OCT_MDIO_BITFIELD_FIELD(u64 reserved_18_63:46, 96 + OCT_MDIO_BITFIELD_FIELD(u64 pending:1, 97 + OCT_MDIO_BITFIELD_FIELD(u64 val:1, 98 + OCT_MDIO_BITFIELD_FIELD(u64 dat:16, 99 + ;)))) 100 + } s; 101 + }; 29 102 30 103 enum octeon_mdiobus_mode { 31 104 UNINIT = 0, ··· 116 41 int phy_irq[PHY_MAX_ADDR]; 117 42 }; 118 43 44 + #ifdef CONFIG_CAVIUM_OCTEON_SOC 45 + static void oct_mdio_writeq(u64 val, u64 addr) 46 + { 47 + cvmx_write_csr(addr, val); 48 + } 49 + 50 + static u64 oct_mdio_readq(u64 addr) 51 + { 52 + return cvmx_read_csr(addr); 53 + } 54 + #else 55 + #define oct_mdio_writeq(val, addr) writeq_relaxed(val, (void *)addr) 56 + #define oct_mdio_readq(addr) readq_relaxed((void *)addr) 57 + #endif 58 + 119 59 static void octeon_mdiobus_set_mode(struct octeon_mdiobus *p, 120 60 enum octeon_mdiobus_mode m) 121 61 { ··· 139 49 if (m == p->mode) 140 50 return; 141 51 142 - smi_clk.u64 = cvmx_read_csr(p->register_base + SMI_CLK); 52 + smi_clk.u64 = oct_mdio_readq(p->register_base + SMI_CLK); 143 53 smi_clk.s.mode = (m == C45) ? 1 : 0; 144 54 smi_clk.s.preamble = 1; 145 - cvmx_write_csr(p->register_base + SMI_CLK, smi_clk.u64); 55 + oct_mdio_writeq(smi_clk.u64, p->register_base + SMI_CLK); 146 56 p->mode = m; 147 57 } 148 58 ··· 157 67 158 68 smi_wr.u64 = 0; 159 69 smi_wr.s.dat = regnum & 0xffff; 160 - cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64); 70 + oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT); 161 71 162 72 regnum = (regnum >> 16) & 0x1f; 163 73 ··· 165 75 smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_45_ADDRESS */ 166 76 smi_cmd.s.phy_adr = phy_id; 167 77 smi_cmd.s.reg_adr = regnum; 168 - cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); 78 + oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); 169 79 170 80 do { 171 81 /* Wait 1000 clocks so we don't saturate the RSL bus 172 82 * doing reads. 173 83 */ 174 84 __delay(1000); 175 - smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT); 85 + smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT); 176 86 } while (smi_wr.s.pending && --timeout); 177 87 178 88 if (timeout <= 0) ··· 204 114 smi_cmd.s.phy_op = op; 205 115 smi_cmd.s.phy_adr = phy_id; 206 116 smi_cmd.s.reg_adr = regnum; 207 - cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); 117 + oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); 208 118 209 119 do { 210 120 /* Wait 1000 clocks so we don't saturate the RSL bus 211 121 * doing reads. 212 122 */ 213 123 __delay(1000); 214 - smi_rd.u64 = cvmx_read_csr(p->register_base + SMI_RD_DAT); 124 + smi_rd.u64 = oct_mdio_readq(p->register_base + SMI_RD_DAT); 215 125 } while (smi_rd.s.pending && --timeout); 216 126 217 127 if (smi_rd.s.val) ··· 243 153 244 154 smi_wr.u64 = 0; 245 155 smi_wr.s.dat = val; 246 - cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64); 156 + oct_mdio_writeq(smi_wr.u64, p->register_base + SMI_WR_DAT); 247 157 248 158 smi_cmd.u64 = 0; 249 159 smi_cmd.s.phy_op = op; 250 160 smi_cmd.s.phy_adr = phy_id; 251 161 smi_cmd.s.reg_adr = regnum; 252 - cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); 162 + oct_mdio_writeq(smi_cmd.u64, p->register_base + SMI_CMD); 253 163 254 164 do { 255 165 /* Wait 1000 clocks so we don't saturate the RSL bus 256 166 * doing reads. 257 167 */ 258 168 __delay(1000); 259 - smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT); 169 + smi_wr.u64 = oct_mdio_readq(p->register_base + SMI_WR_DAT); 260 170 } while (smi_wr.s.pending && --timeout); 261 171 262 172 if (timeout <= 0) ··· 277 187 return -ENOMEM; 278 188 279 189 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 280 - 281 190 if (res_mem == NULL) { 282 191 dev_err(&pdev->dev, "found no memory resource\n"); 283 - err = -ENXIO; 284 - goto fail; 192 + return -ENXIO; 285 193 } 194 + 286 195 bus->mdio_phys = res_mem->start; 287 196 bus->regsize = resource_size(res_mem); 197 + 288 198 if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize, 289 199 res_mem->name)) { 290 200 dev_err(&pdev->dev, "request_mem_region failed\n"); 291 - goto fail; 201 + return -ENXIO; 292 202 } 203 + 293 204 bus->register_base = 294 205 (u64)devm_ioremap(&pdev->dev, bus->mdio_phys, bus->regsize); 206 + if (!bus->register_base) { 207 + dev_err(&pdev->dev, "dev_ioremap failed\n"); 208 + return -ENOMEM; 209 + } 295 210 296 211 bus->mii_bus = mdiobus_alloc(); 297 - 298 212 if (!bus->mii_bus) 299 213 goto fail; 300 214 301 215 smi_en.u64 = 0; 302 216 smi_en.s.en = 1; 303 - cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64); 217 + oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); 304 218 305 219 bus->mii_bus->priv = bus; 306 220 bus->mii_bus->irq = bus->phy_irq; ··· 328 234 mdiobus_free(bus->mii_bus); 329 235 fail: 330 236 smi_en.u64 = 0; 331 - cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64); 237 + oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); 332 238 return err; 333 239 } 334 240 ··· 342 248 mdiobus_unregister(bus->mii_bus); 343 249 mdiobus_free(bus->mii_bus); 344 250 smi_en.u64 = 0; 345 - cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64); 251 + oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN); 346 252 return 0; 347 253 } 348 254