blob: f9d19869971426053373c3fba804734fdb333c34 [file] [log] [blame]
/******************************************************************************
* File Name : hwEthernetPhy.c
* Version : 1.0
* Device(s) : Renesas
* Tool-Chain : Renesas SH2A V9+
* OS : None
* H/W Platform : SH2A
* Description : Hardware driver for the LAN8700 PHY
*******************************************************************************
* History : DD.MM.YYYY Ver. Description
* : 01.08.2009 1.00 MAB First Release
******************************************************************************/
/******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Technology Corp. and is only
* intended for use with Renesas products. No other uses are authorized.
* This software is owned by Renesas Technology Corp. and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES
* REGARDING THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY
* DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* TECHNOLOGY CORP. NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
* FOR ANY REASON RELATED TO THE THIS SOFTWARE, EVEN IF RENESAS OR ITS
* AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this
* software and to discontinue the availability of this software.
* By using this software, you agree to the additional terms and
* conditions found by accessing the following link:
* http://www.renesas.com/disclaimer
******************************************************************************/
/* Copyright (C) 2008. Renesas Technology Corp., All Rights Reserved. */
/* Copyright (C) 2009. Renesas Technology Europe Ltd., All Rights Reserved. */
/*****************************************************************************/
/*****************************************************************************
System Includes
******************************************************************************/
#include <stdio.h>
/* Header file for sleep() and nop() functions */
#include <machine.h>
/*****************************************************************************
User Includes
******************************************************************************/
/* Defines for I/O registers */
#include "iodefine.h"
/* rsk7216def.h provides common defines for widely used items. */
#include "rsk7216def.h"
/* Physical layer functions */
#include "hwEthernetPhy.h"
#include "Trace.h"
#include "FreeRTOS.h"
#include "task.h"
/*****************************************************************************
Constant Macros
******************************************************************************/
/* Preamble */
#define PHY_ST 0x0001
/* Operation to be executed on PHY registers */
#define PHY_READ 0x0002
#define PHY_WRITE 0x0001
/* Physical address of PHY device */
#define PHY_ADDR 0x001F
/* Description of PHY data registers */
#define PHY_BASIC_MODE_CONTROL 0x0000
#define PHY_BASIC_MODE_STATUS 0x0001
#define PHY_IDENTIFIER1 0x0002
#define PHY_IDENTIFIER2 0x0003
#define PHY_AN_ADVERTISEMENT 0x0004
#define PHY_AN_LINK_PARTNER_ABILITY 0x0005
/* Definitions of some configuration bits */
#define PHY_RESET 0x8000
#define PHY_AN_ENABLE 0x1200
/* Bits for auto negotiation for 100, 10 half and full duplex set */
#define PHY_AN_10_100_F_H 0xDE1
/* Link partner ability register bits for establising the result of the
auto negotiation */
#define PHY_AN_100F BIT_8
#define PHY_AN_100H BIT_7
#define PHY_AN_10F BIT_6
#define PHY_AN_10H BIT_5
/*****************************************************************************
Function Prototypes
******************************************************************************/
static USHORT phyReadReg(USHORT usRegAddr);
static void phyWriteReg(USHORT usRegAddr, USHORT usData);
static void phyPreamble(void);
static void phyMiiWrite1(void);
static void phyMiiWrite0(void);
static void phyRegSet(USHORT usRegAddr, long lOption);
static void phyRegRead(PUSHORT pusData);
static void phyRegWrite(USHORT usData);
static void phyTaZ0(void);
static void phyTa10(void);
static void phyDelay(void);
/*****************************************************************************
Public Functions
******************************************************************************/
/*****************************************************************************
Function Name: phyReset
Description: Executes software reset of PHY and sets to auto negotiate link
Parameters: None
Return value: 0 for success -1 on error
******************************************************************************/
int phyReset(void)
{
/* One second of attempting to reset the PHY */
int iCount = 1000;
/* Set software reset */
phyWriteReg(PHY_BASIC_MODE_CONTROL, PHY_RESET);
while (iCount--)
{
USHORT usData;
vTaskDelay( 2 / portTICK_PERIOD_MS );
/* Read the status of the PHY */
usData = phyReadReg(PHY_BASIC_MODE_CONTROL);
/* Wait for the reset flag to be cleared */
if ((usData & PHY_RESET) == 0)
{
/* Set auto negoatiation for 10,100 full and half duplex */
phyWriteReg(PHY_AN_ADVERTISEMENT, PHY_AN_10_100_F_H);
/* Set auto negotiate and restart auto negotiate bits */
phyWriteReg(PHY_BASIC_MODE_CONTROL, PHY_AN_ENABLE);
/* Auto negotiation will now take place wait for two seconds */
vTaskDelay( 2000 / portTICK_PERIOD_MS );
/* Success */
return 0;
}
}
/* Phy did not respond to software reset */
return -1;
}
/*****************************************************************************
End of function phyReset
******************************************************************************/
/*****************************************************************************
Function Name: phyStatus
Description: Function to reurn the type of physical link
Parameters: none
Return value: The link type
*****************************************************************************/
NETLNK phyStatus(void)
{
/* The state of this flag depens on the hardware connection to the MAC */
if (!EtherC.PSR.BIT.LMON)
{
/* Read the auto negotiation link partner ability register to establish
the type of link */
USHORT usData = phyReadReg(PHY_AN_LINK_PARTNER_ABILITY);
if (usData & PHY_AN_100F)
{
return PHY_LINK_100F;
}
if (usData & PHY_AN_100H)
{
return PHY_LINK_100H;
}
if (usData & PHY_AN_10F)
{
return PHY_LINK_10F;
}
if (usData & PHY_AN_10H)
{
return PHY_LINK_10H;
}
}
return PHY_NO_LINK;
}
/*****************************************************************************
End of function phyStatus
******************************************************************************/
/*****************************************************************************
Private Functions
******************************************************************************/
/*****************************************************************************
Function Name: phyReadReg
Description: Reads data from a register with the address usRegAddr
Parameters: (USHORT) usRegAddr - address to be read;
Return value: (USHORT) - value from read register;
******************************************************************************/
static USHORT phyReadReg(USHORT usRegAddr)
{
USHORT usData;
phyPreamble();
phyRegSet(usRegAddr, PHY_READ);
phyTaZ0();
phyRegRead(&usData);
phyTaZ0();
return usData;
}
/*****************************************************************************
End of function phyReadReg
******************************************************************************/
/*****************************************************************************
Function Name: phyWriteReg
Description: Write data to register with the address usRegAddr
Parameters: (USHORT) usRegAddr - address of register where to be written;
(USHORT) usData - value to write;
Return value: None
******************************************************************************/
static void phyWriteReg(USHORT usRegAddr, USHORT usData)
{
phyPreamble();
phyRegSet(usRegAddr, PHY_WRITE);
phyTa10();
phyRegWrite(usData);
phyTaZ0();
}
/*****************************************************************************
End of function phyWriteReg
******************************************************************************/
/*****************************************************************************
Function Name: phyPreamble
Description: Writing 32 bits of '1'
Parameters: None
Return value: None
******************************************************************************/
static void phyPreamble(void)
{
int iCount = 32;
while (iCount--)
{
phyMiiWrite1();
}
}
/*****************************************************************************
End of function phyPreamble
******************************************************************************/
/*****************************************************************************
Function Name: phyRegSet
Description: Sets the address of register
Parameters: (USHORT) usRegAddr - address to be set;
(long) lOption - PHY_READ or PHY_WRITE;
Return value: None
******************************************************************************/
static void phyRegSet(USHORT usRegAddr, long lOption)
{
int iBit = 14;
USHORT usData;
/* Format of PHY Address Set Transmission */
/* ST R/W PAddress Address */
/* 1 10 11111 xxxx 00 */ //Read
/* 1 01 11111 xxxx 00 */ //Write
usData = 0;
/* ST code */
usData = (PHY_ST << 14);
if (lOption == PHY_READ)
{
/* Option code (RD) */
usData |= (PHY_READ << 12);
}
else
{
/* Option code (WT) */
usData |= (PHY_WRITE << 12);
}
/* PHY Address */
usData |= ((BYTE)PHY_ADDR << 7);
/* Reg Address */
usData |= (USHORT)(usRegAddr << 2);
while (iBit--)
{
if ((usData & 0x8000) == 0)
{
phyMiiWrite0();
}
else
{
phyMiiWrite1();
}
usData <<= 1;
}
}
/*****************************************************************************
End of function phyRegSet
******************************************************************************/
/*****************************************************************************
Function Name: phyRegRead
Description: Read data from register
Parameters: IN pusDest - value to be read;
Return value: None
******************************************************************************/
static void phyRegRead(PUSHORT pusDest)
{
USHORT usData = 0;
int iBit = 16;
while (iBit--)
{
EtherC.PIR.LONG = 0x00UL;
EtherC.PIR.LONG = 0x01UL;
usData <<= 1;
/* MDI read */
usData |= (USHORT)((EtherC.PIR.LONG & 0x08UL) >> 3);
EtherC.PIR.LONG = 0x01UL;
EtherC.PIR.LONG = 0x00UL;
}
*pusDest = usData;
}
/*****************************************************************************
End of function phyRegRead
******************************************************************************/
/*****************************************************************************
Function Name: phyRegWrite
Description: Write 2 bytes (16 bit) to MII
Parameters: IN usData - value to be written;
Return value: None
******************************************************************************/
static void phyRegWrite(USHORT usData)
{
int iBit = 16;
while (iBit--)
{
if ((usData & 0x8000) == 0)
{
phyMiiWrite0();
}
else
{
phyMiiWrite1();
}
usData <<= 1;
}
}
/*****************************************************************************
End of function phyRegWrite
******************************************************************************/
/*****************************************************************************
Function Name: phyTaZ0
Description: Set bus to high Z
Parameters: None
Return value: None
******************************************************************************/
static void phyTaZ0(void)
{
EtherC.PIR.LONG = 0x00UL;
EtherC.PIR.LONG = 0x01UL;
EtherC.PIR.LONG = 0x01UL;
EtherC.PIR.LONG = 0x00UL;
}
/*****************************************************************************
End of function phyTaZ0
******************************************************************************/
/*****************************************************************************
Function Name: phyTa10
Description: Set bus to output
Parameters: None
Return value: None
******************************************************************************/
static void phyTa10(void)
{
EtherC.PIR.LONG = 0x06UL;
EtherC.PIR.LONG = 0x07UL;
EtherC.PIR.LONG = 0x07UL;
EtherC.PIR.LONG = 0x06UL;
EtherC.PIR.LONG = 0x02UL;
EtherC.PIR.LONG = 0x03UL;
EtherC.PIR.LONG = 0x03UL;
EtherC.PIR.LONG = 0x02UL;
}
/*****************************************************************************
End of function phyTa10
******************************************************************************/
/*****************************************************************************
Function Name: phyMiiWrite1
Description: Write 1 to MII
Parameters: None
Return value: None
******************************************************************************/
static void phyMiiWrite1(void)
{
EtherC.PIR.LONG = 0x06UL;
EtherC.PIR.LONG = 0x07UL;
EtherC.PIR.LONG = 0x07UL;
EtherC.PIR.LONG = 0x06UL;
}
/*****************************************************************************
End of function phyMiiWrite1
******************************************************************************/
/*****************************************************************************
Function Name: phyMiiWrite0
Description: Write 0 to MII
Parameters: None
Return value: None
******************************************************************************/
static void phyMiiWrite0(void)
{
EtherC.PIR.LONG = 0x02UL;
EtherC.PIR.LONG = 0x03UL;
EtherC.PIR.LONG = 0x03UL;
EtherC.PIR.LONG = 0x02UL;
}
/*****************************************************************************
End of function phyMiiWrite0
******************************************************************************/
/*****************************************************************************
End Of File
******************************************************************************/