summaryrefslogtreecommitdiff
path: root/cpu/arm920t/at91rm9200/ks8721.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/arm920t/at91rm9200/ks8721.c')
-rw-r--r--cpu/arm920t/at91rm9200/ks8721.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/cpu/arm920t/at91rm9200/ks8721.c b/cpu/arm920t/at91rm9200/ks8721.c
new file mode 100644
index 0000000..9fe3793
--- /dev/null
+++ b/cpu/arm920t/at91rm9200/ks8721.c
@@ -0,0 +1,249 @@
+/*
+ * (C) Copyright 2006
+ * Author : Eric Benard (Eukrea Electromatique)
+ * based on dm9161.c which is :
+ * (C) Copyright 2003
+ * Author : Hamid Ikdoumi (Atmel)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <at91rm9200_net.h>
+#include <net.h>
+#include <ks8721.h>
+
+#ifdef CONFIG_DRIVER_ETHER
+
+#if defined(CONFIG_CMD_NET)
+
+/*
+ * Name:
+ * ks8721_isphyconnected
+ * Description:
+ * Reads the 2 PHY ID registers
+ * Arguments:
+ * p_mac - pointer to AT91S_EMAC struct
+ * Return value:
+ * 1 - if id read successfully
+ * 0 - if error
+ */
+unsigned int ks8721_isphyconnected(AT91PS_EMAC p_mac)
+{
+ unsigned short id1, id2;
+
+ at91rm9200_EmacEnableMDIO(p_mac);
+ at91rm9200_EmacReadPhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_PHYID1, &id1);
+ at91rm9200_EmacReadPhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_PHYID2, &id2);
+ at91rm9200_EmacDisableMDIO(p_mac);
+
+ if ((id1 == (KS8721_PHYID_OUI >> 6)) &&
+ ((id2 >> 10) == (KS8721_PHYID_OUI & KS8721_LSB_MASK))) {
+ if ((id2 & KS8721_MODELMASK) == KS8721BL_MODEL)
+ printf("Micrel KS8721bL PHY detected : ");
+ else
+ printf("Unknown Micrel PHY detected : ");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Name:
+ * ks8721_getlinkspeed
+ * Description:
+ * Link parallel detection status of MAC is checked and set in the
+ * MAC configuration registers
+ * Arguments:
+ * p_mac - pointer to MAC
+ * Return value:
+ * 1 - if link status set succesfully
+ * 0 - if link status not set
+ */
+unsigned char ks8721_getlinkspeed(AT91PS_EMAC p_mac)
+{
+ unsigned short stat1;
+
+ if (!at91rm9200_EmacReadPhy(p_mac, KS8721_BMSR, &stat1))
+ return 0;
+
+ if (!(stat1 & KS8721_LINK_STATUS)) {
+ /* link status up? */
+ printf("Link Down !\n");
+ return 0;
+ }
+
+ if (stat1 & KS8721_100BASE_TX_FD) {
+ /* set Emac for 100BaseTX and Full Duplex */
+ printf("100BT FD\n");
+ p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
+ return 1;
+ }
+
+ if (stat1 & KS8721_10BASE_T_FD) {
+ /* set MII for 10BaseT and Full Duplex */
+ printf("10BT FD\n");
+ p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
+ ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
+ | AT91C_EMAC_FD;
+ return 1;
+ }
+
+ if (stat1 & KS8721_100BASE_T4_HD) {
+ /* set MII for 100BaseTX and Half Duplex */
+ printf("100BT HD\n");
+ p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
+ ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
+ | AT91C_EMAC_SPD;
+ return 1;
+ }
+
+ if (stat1 & KS8721_10BASE_T_HD) {
+ /* set MII for 10BaseT and Half Duplex */
+ printf("10BT HD\n");
+ p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Name:
+ * ks8721_initphy
+ * Description:
+ * MAC starts checking its link by using parallel detection and
+ * Autonegotiation and the same is set in the MAC configuration registers
+ * Arguments:
+ * p_mac - pointer to struct AT91S_EMAC
+ * Return value:
+ * 1 - if link status set succesfully
+ * 0 - if link status not set
+ */
+unsigned char ks8721_initphy(AT91PS_EMAC p_mac)
+{
+ unsigned char ret = 1;
+ unsigned short intvalue;
+
+ at91rm9200_EmacEnableMDIO(p_mac);
+
+ /* Try another time */
+ if (!ks8721_getlinkspeed(p_mac))
+ ret = ks8721_getlinkspeed(p_mac);
+
+ /* Disable PHY Interrupts */
+ intvalue = 0;
+ at91rm9200_EmacWritePhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_MDINTR, &intvalue);
+ at91rm9200_EmacDisableMDIO(p_mac);
+
+ return ret;
+}
+
+/*
+ * Name:
+ * ks8721_autonegotiate
+ * Description:
+ * MAC Autonegotiates with the partner status of same is set in the
+ * MAC configuration registers
+ * Arguments:
+ * dev - pointer to struct net_device
+ * Return value:
+ * 1 - if link status set successfully
+ * 0 - if link status not set
+ */
+unsigned char ks8721_autonegotiate(AT91PS_EMAC p_mac, int *status)
+{
+ unsigned short value;
+ unsigned short phyanar;
+ unsigned short phyanalpar;
+
+ /* Set ks8721 control register */
+ if (!at91rm9200_EmacReadPhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_BMCR, &value))
+ return 0;
+
+ /* remove autonegotiation enable */
+ value &= ~KS8721_AUTONEG;
+ /* Electrically isolate PHY */
+ value |= KS8721_ISOLATE;
+ if (!at91rm9200_EmacWritePhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
+ return 0;
+ }
+ /*
+ * Set the Auto_negotiation Advertisement Register
+ * MII advertising for Next page, 100BaseTxFD and HD,
+ * 10BaseTFD and HD, IEEE 802.3
+ */
+ phyanar = KS8721_NP | KS8721_TX_FDX | KS8721_TX_HDX |
+ KS8721_10_FDX | KS8721_10_HDX | KS8721_AN_IEEE_802_3;
+ if (!at91rm9200_EmacWritePhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_ANAR, &phyanar)) {
+ return 0;
+ }
+ /* Read the Control Register */
+ if (!at91rm9200_EmacReadPhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
+ return 0;
+ }
+ value |= KS8721_SPEED_SELECT | KS8721_AUTONEG | KS8721_DUPLEX_MODE;
+ if (!at91rm9200_EmacWritePhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
+ return 0;
+ }
+ /* Restart Auto_negotiation */
+ value |= KS8721_RESTART_AUTONEG;
+ value &= ~KS8721_ISOLATE;
+ if (!at91rm9200_EmacWritePhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_BMCR, &value)) {
+ return 0;
+ }
+ /* Check AutoNegotiate complete */
+ udelay(10000);
+ at91rm9200_EmacReadPhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_BMSR, &value);
+ if (!(value & KS8721_AUTONEG_COMP))
+ return 0;
+
+ /* Get the AutoNeg Link partner base page */
+ if (!at91rm9200_EmacReadPhy(p_mac,
+ CONFIG_PHY_ADDRESS | KS8721_ANLPAR, &phyanalpar)) {
+ return 0;
+ }
+
+ if ((phyanar & KS8721_TX_FDX) && (phyanalpar & KS8721_TX_FDX)) {
+ /* Set MII for 100BaseTX and Full Duplex */
+ p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
+ return 1;
+ }
+
+ if ((phyanar & KS8721_10_FDX) && (phyanalpar & KS8721_10_FDX)) {
+ /* Set MII for 10BaseT and Full Duplex */
+ p_mac->EMAC_CFG = (p_mac->EMAC_CFG &
+ ~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
+ | AT91C_EMAC_FD;
+ return 1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_CMD_NET */
+
+#endif /* CONFIG_DRIVER_ETHER */