From patchwork Wed Apr 3 19:25:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Daney X-Patchwork-Id: 233575 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 9A7BD2C010E for ; Thu, 4 Apr 2013 06:26:09 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1763300Ab3DCTZk (ORCPT ); Wed, 3 Apr 2013 15:25:40 -0400 Received: from mail-da0-f42.google.com ([209.85.210.42]:54676 "EHLO mail-da0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1763267Ab3DCTZh (ORCPT ); Wed, 3 Apr 2013 15:25:37 -0400 Received: by mail-da0-f42.google.com with SMTP id n15so797214dad.15 for ; Wed, 03 Apr 2013 12:25:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer; bh=HfjGeb0IE2U3E9EmEUy4ysDAJpqGnu57sEwl+K+3JE8=; b=cGBCaUNS/IOIpq+gP3lP/elTbuT3yyDI+3VZdVJ9hbB3+CY4xIpnFdV5x7cPj4J/J0 dPilyo5qpgCqUt3zLFyP1qYS8hsw6+SkCQidJ7CSjounx3QOQzhP3yBMnHiklXz1q1AW vhVKTLBgkeWc9P2iRgG4/V8QeTpJvkleWWPwFCc8XKLCUT9EgtX9vEYmMcXLLj4W0Qt4 wNlaXBBYOA7dNazHxdSd3UcHBJigySBoxpqysn4WZt1yYgWpnxRbS/G06Vrwm6bSXqB6 7eMnE644Arf3MzO550X2qjENYQuKLZ3oOgWJiaXBVb7Ff4nRZ6FPwjoNLdjTv0Xpyhci J45w== X-Received: by 10.66.255.99 with SMTP id ap3mr5250126pad.102.1365017137300; Wed, 03 Apr 2013 12:25:37 -0700 (PDT) Received: from dl.caveonetworks.com (64.2.3.195.ptr.us.xo.net. [64.2.3.195]) by mx.google.com with ESMTPS id yp2sm8082305pab.10.2013.04.03.12.25.35 (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 03 Apr 2013 12:25:36 -0700 (PDT) Received: from dl.caveonetworks.com (localhost.localdomain [127.0.0.1]) by dl.caveonetworks.com (8.14.5/8.14.5) with ESMTP id r33JPYdw006068; Wed, 3 Apr 2013 12:25:34 -0700 Received: (from ddaney@localhost) by dl.caveonetworks.com (8.14.5/8.14.5/Submit) id r33JPX69006067; Wed, 3 Apr 2013 12:25:33 -0700 From: David Daney To: "David S. Miller" , netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org, David Daney Subject: [PATCH v3] netdev/phy: Implement ieee802.3 clause 45 in mdio-octeon.c Date: Wed, 3 Apr 2013 12:25:32 -0700 Message-Id: <1365017132-6035-1-git-send-email-ddaney.cavm@gmail.com> X-Mailer: git-send-email 1.7.11.7 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Daney The Octeon SMI/MDIO interfaces can do clause 45 communications, so implement this in the driver. Also fix some comment formatting to make it consistent and to comply with the netdev style. Signed-off-by: David Daney --- v3: Remove now bogus comment noted by Ben Huchings v2: No code changes from v1, just fixed comment formatting snafu. Sorry for the spam. drivers/net/phy/mdio-octeon.c | 94 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/drivers/net/phy/mdio-octeon.c b/drivers/net/phy/mdio-octeon.c index c2c878d..b51fa1f 100644 --- a/drivers/net/phy/mdio-octeon.c +++ b/drivers/net/phy/mdio-octeon.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2009,2011 Cavium, Inc. + * Copyright (C) 2009-2012 Cavium, Inc. */ #include @@ -27,30 +27,98 @@ #define SMI_CLK 0x18 #define SMI_EN 0x20 +enum octeon_mdiobus_mode { + UNINIT = 0, + C22, + C45 +}; + struct octeon_mdiobus { struct mii_bus *mii_bus; u64 register_base; resource_size_t mdio_phys; resource_size_t regsize; + enum octeon_mdiobus_mode mode; int phy_irq[PHY_MAX_ADDR]; }; +static void octeon_mdiobus_set_mode(struct octeon_mdiobus *p, + enum octeon_mdiobus_mode m) +{ + union cvmx_smix_clk smi_clk; + + if (m == p->mode) + return; + + smi_clk.u64 = cvmx_read_csr(p->register_base + SMI_CLK); + smi_clk.s.mode = (m == C45) ? 1 : 0; + smi_clk.s.preamble = 1; + cvmx_write_csr(p->register_base + SMI_CLK, smi_clk.u64); + p->mode = m; +} + +static int octeon_mdiobus_c45_addr(struct octeon_mdiobus *p, + int phy_id, int regnum) +{ + union cvmx_smix_cmd smi_cmd; + union cvmx_smix_wr_dat smi_wr; + int timeout = 1000; + + octeon_mdiobus_set_mode(p, C45); + + smi_wr.u64 = 0; + smi_wr.s.dat = regnum & 0xffff; + cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64); + + regnum = (regnum >> 16) & 0x1f; + + smi_cmd.u64 = 0; + smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_45_ADDRESS */ + smi_cmd.s.phy_adr = phy_id; + smi_cmd.s.reg_adr = regnum; + cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); + + do { + /* Wait 1000 clocks so we don't saturate the RSL bus + * doing reads. + */ + __delay(1000); + smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT); + } while (smi_wr.s.pending && --timeout); + + if (timeout <= 0) + return -EIO; + return 0; +} + static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) { struct octeon_mdiobus *p = bus->priv; union cvmx_smix_cmd smi_cmd; union cvmx_smix_rd_dat smi_rd; + unsigned int op = 1; /* MDIO_CLAUSE_22_READ */ int timeout = 1000; + if (regnum & MII_ADDR_C45) { + int r = octeon_mdiobus_c45_addr(p, phy_id, regnum); + if (r < 0) + return r; + + regnum = (regnum >> 16) & 0x1f; + op = 3; /* MDIO_CLAUSE_45_READ */ + } else { + octeon_mdiobus_set_mode(p, C22); + } + + smi_cmd.u64 = 0; - smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */ + smi_cmd.s.phy_op = op; smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = regnum; cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); do { - /* - * Wait 1000 clocks so we don't saturate the RSL bus + /* Wait 1000 clocks so we don't saturate the RSL bus * doing reads. */ __delay(1000); @@ -69,21 +137,33 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id, struct octeon_mdiobus *p = bus->priv; union cvmx_smix_cmd smi_cmd; union cvmx_smix_wr_dat smi_wr; + unsigned int op = 0; /* MDIO_CLAUSE_22_WRITE */ int timeout = 1000; + + if (regnum & MII_ADDR_C45) { + int r = octeon_mdiobus_c45_addr(p, phy_id, regnum); + if (r < 0) + return r; + + regnum = (regnum >> 16) & 0x1f; + op = 1; /* MDIO_CLAUSE_45_WRITE */ + } else { + octeon_mdiobus_set_mode(p, C22); + } + smi_wr.u64 = 0; smi_wr.s.dat = val; cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64); smi_cmd.u64 = 0; - smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */ + smi_cmd.s.phy_op = op; smi_cmd.s.phy_adr = phy_id; smi_cmd.s.reg_adr = regnum; cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64); do { - /* - * Wait 1000 clocks so we don't saturate the RSL bus + /* Wait 1000 clocks so we don't saturate the RSL bus * doing reads. */ __delay(1000);