Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 92 additions & 17 deletions ael2005_conf.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
/*******************************************************************************
*
* NetFPGA-10G http://www.netfpga.org
*
* File:
* ael2005_conf.c
*
* Project:
*
*
* Author:
* Hwanju Kim
* Marco Forconesi
*
* Description:
* Write magic registers for PHYs (AEL2005) configuration.
*
* TODO:
*
*
* This code is initially developed for the Network-as-a-Service (NaaS) project.
* (under development in https://github.com/NetFPGA-NewNIC/linux-driver)
*
*
* Copyright notice:
* Copyright (C) 2014 University of Cambridge
*
* Licence:
* This file is part of the NetFPGA 10G development base package.
*
* This file is free code: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 2.1 as
* published by the Free Software Foundation.
*
* This package is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the NetFPGA source package. If not, see
* http://www.gnu.org/licenses/.
*
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
Expand All @@ -8,6 +53,11 @@
#include "nf10.h"
#include "ael2005_conf.h"

static bool CF_PHY_NF0 = true;
static bool CF_PHY_NF1 = true;
static bool CF_PHY_NF2 = true;
static bool CF_PHY_NF3 = true;

irqreturn_t mdio_access_interrupt_handler(int irq, void *dev_id)
{
struct pci_dev *pdev = dev_id;
Expand All @@ -27,22 +77,48 @@ int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
u8 DEVAD;
u16 ADDR, WRITE_DATA;
int size, i;
int timeout = 0;
int timeout;
bool config_phy;

pr_info("PHY: AEL2005 Initialization Start...\n");
pr_info("PHY: AEL2005 configuration starts\n");

/* We only need interface 3 in this project
* don't forget that the nearest port to PCIe is hardwired to 0x2 */
for(PRTAD = 3; PRTAD < 4; PRTAD++) {
/* configure PHYs one at a time:
* Port Address (PRTAD) identifies each of the Ethernet
* interfaces on the board. The closest to the PCIe
* fingers has a PRTAD hard-wired to 0x02 and corresponds to
* nf0 in SW */
for(PRTAD = 0; PRTAD < 4; PRTAD++) {
DEVAD = MDIO_MMD_PMAPMD;
timeout = 0;

/* map nfx to PRTAD */
switch (PRTAD) {
case 0x02:
config_phy = CF_PHY_NF0;
break;
case 0x01:
config_phy = CF_PHY_NF1;
break;
case 0x00:
config_phy = CF_PHY_NF2;
break;
case 0x03:
config_phy = CF_PHY_NF3;
break;
default:
return -1;
}

if (!config_phy)
continue;

/* Step 1: write reset registers */
/* step 1: write reset registers */
size = sizeof(reset) / sizeof(u16);
for(i = 0; i < size; i += 2) {
/* MDIO clause 45 Set Address Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);

/* Send Memory Write Request TLP */
/* send Memory Write Request TLP */
OP_CODE = 0x0;
ADDR = reset[i];
*(((u32 *)adapter->bar0) + 4) =
Expand All @@ -54,16 +130,15 @@ int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
msleep(2);
timeout++;

/* if it takes too long,
* hw is not working properly */
/* no response from HW */
if (timeout > 20)
return ret;
} while (!atomic_read(&adapter->mdio_access_rdy));

/* MDIO clause 45 Write Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);

/* Send Memory Write Request TLP */
/* send Memory Write Request TLP */
OP_CODE = 0x1;
WRITE_DATA = reset[i+1];
*(((u32 *)adapter->bar0) + 4) =
Expand All @@ -76,14 +151,14 @@ int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
} while (!atomic_read(&adapter->mdio_access_rdy));
}

/* Step 2: write sr_edc or twinax_edc registers.
/* step 2: write sr_edc or twinax_edc registers.
* (depending on the sfp+ modules) */
size = sizeof(sr_edc) / sizeof(u16);
for (i = 0; i < size; i += 2) {
/* MDIO clause 45 Set Address Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);

/* Send Memory Write Request TLP */
/* send Memory Write Request TLP */
OP_CODE = 0x0;
ADDR = sr_edc[i];
*(((u32 *)adapter->bar0) + 4) =
Expand All @@ -98,7 +173,7 @@ int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
/* MDIO clause 45 Write Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);

/* Send Memory Write Request TLP */
/* send Memory Write Request TLP */
OP_CODE = 0x1;
WRITE_DATA = sr_edc[i+1];
*(((u32 *)adapter->bar0) + 4) =
Expand All @@ -111,13 +186,13 @@ int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
} while (!atomic_read(&adapter->mdio_access_rdy));
}

/* Step 1: write regs1 registers */
/* step 1: write regs1 registers */
size = sizeof(regs1) / sizeof(u16);
for(i = 0; i < size; i += 2) {
/* MDIO clause 45 Set Address Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);

/* Send Memory Write Request TLP */
/* send Memory Write Request TLP */
OP_CODE = 0x0;
ADDR = regs1[i];
*(((u32 *)adapter->bar0) + 4) =
Expand All @@ -132,7 +207,7 @@ int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
/* MDIO clause 45 Write Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);

/* Send Memory Write Request TLP */
/* send Memory Write Request TLP */
OP_CODE = 0x1;
WRITE_DATA = regs1[i+1];
*(((u32 *)adapter->bar0) + 4) =
Expand All @@ -145,7 +220,7 @@ int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
} while (!atomic_read(&adapter->mdio_access_rdy));
}
}
pr_info("PHY: AEL2005 Initialization Finished...\n");
pr_info("PHY: AEL2005 configuration finishes\n");

return 0;
}
1 change: 1 addition & 0 deletions ael2005_conf.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* Magic registers */
#ifndef _AEL2005_SIMPLE_CONF_H
#define _AEL2005_SIMPLE_CONF_H

Expand Down