Last active
August 29, 2015 13:56
-
-
Save ozaki-r/9182826 to your computer and use it in GitHub Desktop.
Patches for CKB-3352
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: sys/arch/arm/omap/if_cpsw.c | |
=================================================================== | |
RCS file: /cvs/cvsroot/src/sys/arch/arm/omap/if_cpsw.c,v | |
retrieving revision 1.4 | |
diff -u -r1.4 if_cpsw.c | |
--- sys/arch/arm/omap/if_cpsw.c 18 Dec 2013 12:53:26 -0000 1.4 | |
+++ sys/arch/arm/omap/if_cpsw.c 26 Feb 2014 02:44:33 -0000 | |
@@ -122,6 +122,7 @@ | |
bus_addr_t sc_rxdescs_pa; | |
struct ethercom sc_ec; | |
struct mii_data sc_mii; | |
+ bool sc_phy_has_1000t; | |
callout_t sc_tick_ch; | |
void *sc_ih; | |
struct cpsw_ring_data *sc_rdp; | |
@@ -163,6 +164,11 @@ | |
static int cpsw_txintr(void *); | |
static int cpsw_miscintr(void *); | |
+/* ALE support */ | |
+#define CPSW_MAX_ALE_ENTRIES 1024 | |
+ | |
+static int cpsw_ale_update_addresses(struct cpsw_softc *, int purge); | |
+ | |
CFATTACH_DECL_NEW(cpsw, sizeof(struct cpsw_softc), | |
cpsw_match, cpsw_attach, NULL, NULL); | |
@@ -318,6 +324,18 @@ | |
return 0; | |
} | |
+static bool | |
+cpsw_phy_has_1000t(struct cpsw_softc * const sc) | |
+{ | |
+ struct ifmedia_entry *ifm; | |
+ | |
+ TAILQ_FOREACH(ifm, &sc->sc_mii.mii_media.ifm_list, ifm_list) { | |
+ if (IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_T) | |
+ return true; | |
+ } | |
+ return false; | |
+} | |
+ | |
static void | |
cpsw_attach(device_t parent, device_t self, void *aux) | |
{ | |
@@ -469,13 +487,28 @@ | |
sc->sc_ec.ec_mii = &sc->sc_mii; | |
ifmedia_init(&sc->sc_mii.mii_media, 0, ether_mediachange, | |
ether_mediastatus); | |
+ | |
+ /* Initialize MDIO */ | |
+ cpsw_write_4(sc, MDIOCONTROL, MDIOCTL_ENABLE | MDIOCTL_FAULTENB | MDIOCTL_CLKDIV(0xff)); | |
+ /* Clear ALE */ | |
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, ALECTL_CLEAR_TABLE); | |
+ | |
mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, 0, 0); | |
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { | |
aprint_error_dev(self, "no PHY found!\n"); | |
+ sc->sc_phy_has_1000t = false; | |
ifmedia_add(&sc->sc_mii.mii_media, | |
IFM_ETHER|IFM_MANUAL, 0, NULL); | |
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_MANUAL); | |
} else { | |
+ sc->sc_phy_has_1000t = cpsw_phy_has_1000t(sc); | |
+ if (sc->sc_phy_has_1000t) { | |
+ aprint_normal_dev(sc->sc_dev, "1000baseT PHY found. setting RGMII Mode\n"); | |
+ /* Select the Interface RGMII Mode in the Control Module */ | |
+ sitara_cm_reg_write_4(CPSW_GMII_SEL, | |
+ GMIISEL_GMII2_SEL(RGMII_MODE) | GMIISEL_GMII1_SEL(RGMII_MODE)); | |
+ } | |
+ | |
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); | |
} | |
@@ -791,6 +824,8 @@ | |
/* Reset and init Sliver port 1 and 2 */ | |
for (i = 0; i < 2; i++) { | |
+ uint32_t macctl; | |
+ | |
/* Reset */ | |
cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1); | |
while(cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1); | |
@@ -805,9 +840,12 @@ | |
cpsw_write_4(sc, CPSW_PORT_P_SA_LO(i+1), | |
sc->sc_enaddr[4] | (sc->sc_enaddr[5] << 8)); | |
- /* Set MACCONTROL for ports 0,1: FULLDUPLEX(1), GMII_EN(5), | |
- IFCTL_A(15), IFCTL_B(16) FIXME */ | |
- cpsw_write_4(sc, CPSW_SL_MACCONTROL(i), 1 | (1<<5) | (1<<15)); | |
+ /* Set MACCONTROL for ports 0,1 */ | |
+ macctl = SLMACCTL_FULLDUPLEX | SLMACCTL_GMII_EN | | |
+ SLMACCTL_IFCTL_A; | |
+ if (sc->sc_phy_has_1000t) | |
+ macctl |= SLMACCTL_GIG; | |
+ cpsw_write_4(sc, CPSW_SL_MACCONTROL(i), macctl); | |
/* Set ALE port to forwarding(3) */ | |
cpsw_write_4(sc, CPSW_ALE_PORTCTL(i+1), 3); | |
@@ -820,6 +858,9 @@ | |
/* Set ALE port to forwarding(3) */ | |
cpsw_write_4(sc, CPSW_ALE_PORTCTL(0), 3); | |
+ /* Initialize addrs */ | |
+ cpsw_ale_update_addresses(sc, 1); | |
+ | |
cpsw_write_4(sc, CPSW_SS_PTYPE, 0); | |
cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7); | |
@@ -1242,3 +1283,194 @@ | |
return 1; | |
} | |
+ | |
+/* | |
+ * | |
+ * ALE support routines. | |
+ * | |
+ */ | |
+ | |
+static void | |
+cpsw_ale_entry_init(uint32_t *ale_entry) | |
+{ | |
+ ale_entry[0] = ale_entry[1] = ale_entry[2] = 0; | |
+} | |
+ | |
+static void | |
+cpsw_ale_entry_set_mac(uint32_t *ale_entry, const uint8_t *mac) | |
+{ | |
+ ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]; | |
+ ale_entry[1] = mac[0] << 8 | mac[1]; | |
+} | |
+ | |
+static void | |
+cpsw_ale_entry_set_bcast_mac(uint32_t *ale_entry) | |
+{ | |
+ ale_entry[0] = 0xffffffff; | |
+ ale_entry[1] = 0x0000ffff; | |
+} | |
+ | |
+static void | |
+cpsw_ale_entry_set(uint32_t *ale_entry, ale_entry_filed_t field, uint32_t val) | |
+{ | |
+ /* Entry type[61:60] is addr entry(1), Mcast fwd state[63:62] is fw(3)*/ | |
+ switch (field) { | |
+ case ALE_ENTRY_TYPE: | |
+ /* [61:60] */ | |
+ ale_entry[1] |= (val & 0x3) << 28; | |
+ break; | |
+ case ALE_MCAST_FWD_STATE: | |
+ /* [63:62] */ | |
+ ale_entry[1] |= (val & 0x3) << 30; | |
+ break; | |
+ case ALE_PORT_MASK: | |
+ /* [68:66] */ | |
+ ale_entry[2] |= (val & 0x7) << 2; | |
+ break; | |
+ case ALE_PORT_NUMBER: | |
+ /* [67:66] */ | |
+ ale_entry[2] |= (val & 0x3) << 2; | |
+ break; | |
+ default: | |
+ panic("Invalid ALE entry field: %d\n", field); | |
+ } | |
+ | |
+ return; | |
+} | |
+ | |
+static bool | |
+cpsw_ale_entry_mac_match(const uint32_t *ale_entry, const uint8_t *mac) | |
+{ | |
+ return (((ale_entry[1] >> 8) & 0xff) == mac[0]) && | |
+ (((ale_entry[1] >> 0) & 0xff) == mac[1]) && | |
+ (((ale_entry[0] >>24) & 0xff) == mac[2]) && | |
+ (((ale_entry[0] >>16) & 0xff) == mac[3]) && | |
+ (((ale_entry[0] >> 8) & 0xff) == mac[4]) && | |
+ (((ale_entry[0] >> 0) & 0xff) == mac[5]); | |
+} | |
+ | |
+static void | |
+cpsw_ale_set_outgoing_mac(struct cpsw_softc *sc, int port, const uint8_t *mac) | |
+{ | |
+ cpsw_write_4(sc, CPSW_PORT_P_SA_HI(port), | |
+ mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]); | |
+ cpsw_write_4(sc, CPSW_PORT_P_SA_LO(port), | |
+ mac[5] << 8 | mac[4]); | |
+} | |
+ | |
+static void | |
+cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry) | |
+{ | |
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, idx & 1023); | |
+ ale_entry[0] = cpsw_read_4(sc, CPSW_ALE_TBLW0); | |
+ ale_entry[1] = cpsw_read_4(sc, CPSW_ALE_TBLW1); | |
+ ale_entry[2] = cpsw_read_4(sc, CPSW_ALE_TBLW2); | |
+} | |
+ | |
+static void | |
+cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry) | |
+{ | |
+ cpsw_write_4(sc, CPSW_ALE_TBLW0, ale_entry[0]); | |
+ cpsw_write_4(sc, CPSW_ALE_TBLW1, ale_entry[1]); | |
+ cpsw_write_4(sc, CPSW_ALE_TBLW2, ale_entry[2]); | |
+ cpsw_write_4(sc, CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023)); | |
+} | |
+ | |
+static int | |
+cpsw_ale_remove_all_mc_entries(struct cpsw_softc *sc) | |
+{ | |
+ int i; | |
+ uint32_t ale_entry[3]; | |
+ | |
+ /* First two entries are link address and broadcast. */ | |
+ for (i = 2; i < CPSW_MAX_ALE_ENTRIES; i++) { | |
+ cpsw_ale_read_entry(sc, i, ale_entry); | |
+ if (((ale_entry[1] >> 28) & 3) == 1 && /* Address entry */ | |
+ ((ale_entry[1] >> 8) & 1) == 1) { /* MCast link addr */ | |
+ ale_entry[0] = ale_entry[1] = ale_entry[2] = 0; | |
+ cpsw_ale_write_entry(sc, i, ale_entry); | |
+ } | |
+ } | |
+ return CPSW_MAX_ALE_ENTRIES; | |
+} | |
+ | |
+static int | |
+cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmask, uint8_t *mac) | |
+{ | |
+ int free_index = -1, matching_index = -1, i; | |
+ uint32_t ale_entry[3]; | |
+ | |
+ /* Find a matching entry or a free entry. */ | |
+ for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) { | |
+ cpsw_ale_read_entry(sc, i, ale_entry); | |
+ | |
+ /* Entry Type[61:60] is 0 for free entry */ | |
+ if (free_index < 0 && ((ale_entry[1] >> 28) & 3) == 0) { | |
+ free_index = i; | |
+ } | |
+ | |
+ if (cpsw_ale_entry_mac_match(ale_entry, mac)) { | |
+ matching_index = i; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (matching_index < 0) { | |
+ if (free_index < 0) | |
+ return ENOMEM; | |
+ i = free_index; | |
+ } | |
+ | |
+ cpsw_ale_entry_init(ale_entry); | |
+ | |
+ cpsw_ale_entry_set_mac(ale_entry, mac); | |
+ cpsw_ale_entry_set(ale_entry, ALE_ENTRY_TYPE, ALE_TYPE_ADDRESS); | |
+ cpsw_ale_entry_set(ale_entry, ALE_MCAST_FWD_STATE, ALE_FWSTATE_FWONLY); | |
+ cpsw_ale_entry_set(ale_entry, ALE_PORT_MASK, portmask); | |
+ | |
+ cpsw_ale_write_entry(sc, i, ale_entry); | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int | |
+cpsw_ale_update_addresses(struct cpsw_softc *sc, int purge) | |
+{ | |
+ uint8_t *mac = sc->sc_enaddr; | |
+ uint32_t ale_entry[3]; | |
+ int i; | |
+ struct ethercom * const ec = &sc->sc_ec; | |
+ struct ether_multi *ifma; | |
+ | |
+ cpsw_ale_entry_init(ale_entry); | |
+ /* Route incoming packets for our MAC address to Port 0 (host). */ | |
+ /* For simplicity, keep this entry at table index 0 in the ALE. */ | |
+ cpsw_ale_entry_set_mac(ale_entry, mac); | |
+ cpsw_ale_entry_set(ale_entry, ALE_ENTRY_TYPE, ALE_TYPE_ADDRESS); | |
+ cpsw_ale_entry_set(ale_entry, ALE_PORT_NUMBER, 0); | |
+ cpsw_ale_write_entry(sc, 0, ale_entry); | |
+ | |
+ /* Set outgoing MAC Address for Ports 1 and 2. */ | |
+ for (i = 1; i < 3; ++i) | |
+ cpsw_ale_set_outgoing_mac(sc, i, mac); | |
+ | |
+ /* Keep the broadcast address at table entry 1. */ | |
+ cpsw_ale_entry_init(ale_entry); | |
+ cpsw_ale_entry_set_bcast_mac(ale_entry); | |
+ cpsw_ale_entry_set(ale_entry, ALE_ENTRY_TYPE, ALE_TYPE_ADDRESS); | |
+ cpsw_ale_entry_set(ale_entry, ALE_MCAST_FWD_STATE, ALE_FWSTATE_FWONLY); | |
+ cpsw_ale_entry_set(ale_entry, ALE_PORT_MASK, ALE_PORT_MASK_ALL); | |
+ cpsw_ale_write_entry(sc, 1, ale_entry); | |
+ | |
+ /* SIOCDELMULTI doesn't specify the particular address | |
+ being removed, so we have to remove all and rebuild. */ | |
+ if (purge) | |
+ cpsw_ale_remove_all_mc_entries(sc); | |
+ | |
+ /* Set other multicast addrs desired. */ | |
+ LIST_FOREACH(ifma, &ec->ec_multiaddrs, enm_list) { | |
+ cpsw_ale_mc_entry_set(sc, ALE_PORT_MASK_ALL, ifma->enm_addrlo); | |
+ } | |
+ | |
+ return 0; | |
+} | |
Index: sys/arch/arm/omap/if_cpswreg.h | |
=================================================================== | |
RCS file: /cvs/cvsroot/src/sys/arch/arm/omap/if_cpswreg.h,v | |
retrieving revision 1.1 | |
diff -u -r1.1 if_cpswreg.h | |
--- sys/arch/arm/omap/if_cpswreg.h 3 Jan 2013 21:13:26 -0000 1.1 | |
+++ sys/arch/arm/omap/if_cpswreg.h 26 Feb 2014 02:44:33 -0000 | |
@@ -34,6 +34,7 @@ | |
#define CPSW_SS_SOFT_RESET (CPSW_SS_OFFSET + 0x08) | |
#define CPSW_SS_STAT_PORT_EN (CPSW_SS_OFFSET + 0x0C) | |
#define CPSW_SS_PTYPE (CPSW_SS_OFFSET + 0x10) | |
+#define CPSW_SS_RGMII_CTL (CPSW_SS_OFFSET + 0x88) | |
#define CPSW_PORT_OFFSET 0x0100 | |
#define CPSW_PORT_P_TX_PRI_MAP(p) (CPSW_PORT_OFFSET + 0x118 + ((p-1) * 0x100)) | |
@@ -42,6 +43,8 @@ | |
#define CPSW_PORT_P_SA_LO(p) (CPSW_PORT_OFFSET + 0x120 + ((p-1) * 0x100)) | |
#define CPSW_PORT_P_SA_HI(p) (CPSW_PORT_OFFSET + 0x124 + ((p-1) * 0x100)) | |
+#define CPSW_GMII_SEL 0x0650 | |
+ | |
#define CPSW_CPDMA_OFFSET 0x0800 | |
#define CPSW_CPDMA_TX_CONTROL (CPSW_CPDMA_OFFSET + 0x04) | |
#define CPSW_CPDMA_TX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x08) | |
@@ -133,4 +136,82 @@ | |
#define CPSW_INTROFF_TX 2 | |
#define CPSW_INTROFF_MISC 3 | |
+/* MDIOCONTROL Register Field */ | |
+#define MDIOCTL_IDLE __BIT32(31) | |
+#define MDIOCTL_ENABLE __BIT32(30) | |
+#define MDIOCTL_HIGHEST_USER_CHANNEL(val) ((0xf & (val)) << 24) | |
+#define MDIOCTL_PREAMBLE __BIT32(20) | |
+#define MDIOCTL_FAULT __BIT32(19) | |
+#define MDIOCTL_FAULTENB __BIT32(18) | |
+#define MDIOCTL_INTTESTENB __BIT32(17) | |
+#define MDIOCTL_CLKDIV(val) (0xff & (val)) | |
+ | |
+/* ALE Control Register Field */ | |
+#define ALECTL_ENABLE_ALE __BIT32(31) | |
+#define ALECTL_CLEAR_TABLE __BIT32(30) | |
+#define ALECTL_AGE_OUT_NOW __BIT32(29) | |
+#define ALECTL_EN_P0_UNI_FLOOD __BIT32(8) | |
+#define ALECTL_LEARN_NO_VID __BIT32(7) | |
+#define ALECTL_EN_VID0_MODE __BIT32(6) | |
+#define ALECTL_ENABLE_OUI_DENY __BIT32(5) | |
+#define ALECTL_BYPASS __BIT32(4) | |
+#define ALECTL_RATE_LIMIT_TX __BIT32(3) | |
+#define ALECTL_VLAN_AWARE __BIT32(2) | |
+#define ALECTL_ENABLE_AUTH_MODE __BIT32(1) | |
+#define ALECTL_ENABLE_RATE_LIMIT __BIT32(0) | |
+ | |
+/* GMII_SEL Register Field */ | |
+#define GMIISEL_RMII2_IO_CLK_EN __BIT32(7) | |
+#define GMIISEL_RMII1_IO_CLK_EN __BIT32(6) | |
+#define GMIISEL_RGMII2_IDMODE __BIT32(5) | |
+#define GMIISEL_RGMII1_IDMODE __BIT32(4) | |
+#define GMIISEL_GMII2_SEL(val) ((0x3 & (val)) << 2) | |
+#define GMIISEL_GMII1_SEL(val) ((0x3 & (val)) << 0) | |
+#define GMII_MODE 0 | |
+#define RMII_MODE 1 | |
+#define RGMII_MODE 2 | |
+ | |
+/* Sliver MACCONTROL Register Field */ | |
+#define SLMACCTL_RX_CMF_EN __BIT32(24) | |
+#define SLMACCTL_RX_CSF_EN __BIT32(23) | |
+#define SLMACCTL_RX_CEF_EN __BIT32(22) | |
+#define SLMACCTL_TX_SHORT_GAP_LIM_EN __BIT32(21) | |
+#define SLMACCTL_EXT_EN __BIT32(18) | |
+#define SLMACCTL_GIG_FORCE __BIT32(17) | |
+#define SLMACCTL_IFCTL_B __BIT32(16) | |
+#define SLMACCTL_IFCTL_A __BIT32(15) | |
+#define SLMACCTL_CMD_IDLE __BIT32(11) | |
+#define SLMACCTL_TX_SHORT_GAP_EN __BIT32(10) | |
+#define SLMACCTL_GIG __BIT32(7) | |
+#define SLMACCTL_TX_PACE __BIT32(6) | |
+#define SLMACCTL_GMII_EN __BIT32(5) | |
+#define SLMACCTL_TX_FLOW_EN __BIT32(4) | |
+#define SLMACCTL_RX_FLOW_EN __BIT32(3) | |
+#define SLMACCTL_MTEST __BIT32(2) | |
+#define SLMACCTL_LOOPBACK __BIT32(1) | |
+#define SLMACCTL_FULLDUPLEX __BIT32(0) | |
+ | |
+/* ALE Address Table Entry Field */ | |
+typedef enum { | |
+ ALE_ENTRY_TYPE, | |
+ ALE_MCAST_FWD_STATE, | |
+ ALE_PORT_MASK, | |
+ ALE_PORT_NUMBER, | |
+} ale_entry_filed_t; | |
+ | |
+#define ALE_TYPE_FREE 0 | |
+#define ALE_TYPE_ADDRESS 1 | |
+#define ALE_TYPE_VLAN 2 | |
+#define ALE_TYPE_VLAN_ADDRESS 3 | |
+ | |
+/* | |
+ * The port state(s) required for the received port on a destination address lookup | |
+ * in order for the multicast packet to be forwarded to the transmit port(s) | |
+ */ | |
+#define ALE_FWSTATE_ALL 1 /* Blocking/Forwarding/Learning */ | |
+#define ALE_FWSTATE_NOBLOCK 2 /* Forwarding/Learning */ | |
+#define ALE_FWSTATE_FWONLY 3 /* Forwarding */ | |
+ | |
+#define ALE_PORT_MASK_ALL 7 | |
+ | |
#endif /*_IF_CPSWREG_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: sys/dev/mii/files.mii | |
=================================================================== | |
RCS file: /cvs/cvsroot/src/sys/dev/mii/files.mii,v | |
retrieving revision 1.48 | |
diff -u -r1.48 files.mii | |
--- sys/dev/mii/files.mii 26 Jan 2011 18:48:12 -0000 1.48 | |
+++ sys/dev/mii/files.mii 25 Feb 2014 10:52:05 -0000 | |
@@ -148,3 +148,7 @@ | |
device rdcphy: mii_phy | |
attach rdcphy at mii | |
file dev/mii/rdcphy.c rdcphy | |
+ | |
+device micphy: mii_phy, ukphy_subr | |
+attach micphy at mii | |
+file dev/mii/micphy.c micphy | |
Index: sys/dev/mii/micphy.c | |
=================================================================== | |
RCS file: sys/dev/mii/micphy.c | |
diff -N sys/dev/mii/micphy.c | |
--- /dev/null 1 Jan 1970 00:00:00 -0000 | |
+++ sys/dev/mii/micphy.c 25 Feb 2014 10:52:06 -0000 | |
@@ -0,0 +1,251 @@ | |
+/* $NetBSD$ */ | |
+ | |
+/*- | |
+ * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. | |
+ * All rights reserved. | |
+ * | |
+ * This code is derived from software contributed to The NetBSD Foundation | |
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
+ * NASA Ames Research Center, and by Frank van der Linden. | |
+ * | |
+ * Redistribution and use in source and binary forms, with or without | |
+ * modification, are permitted provided that the following conditions | |
+ * are met: | |
+ * 1. Redistributions of source code must retain the above copyright | |
+ * notice, this list of conditions and the following disclaimer. | |
+ * 2. Redistributions in binary form must reproduce the above copyright | |
+ * notice, this list of conditions and the following disclaimer in the | |
+ * documentation and/or other materials provided with the distribution. | |
+ * | |
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
+ * POSSIBILITY OF SUCH DAMAGE. | |
+ */ | |
+ | |
+/* | |
+ * Copyright (c) 1997 Manuel Bouyer. All rights reserved. | |
+ * | |
+ * Redistribution and use in source and binary forms, with or without | |
+ * modification, are permitted provided that the following conditions | |
+ * are met: | |
+ * 1. Redistributions of source code must retain the above copyright | |
+ * notice, this list of conditions and the following disclaimer. | |
+ * 2. Redistributions in binary form must reproduce the above copyright | |
+ * notice, this list of conditions and the following disclaimer in the | |
+ * documentation and/or other materials provided with the distribution. | |
+ * | |
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
+ */ | |
+ | |
+/* | |
+ * Driver for Micrel KSZ9021RN PHYs | |
+ */ | |
+ | |
+#include <sys/cdefs.h> | |
+__KERNEL_RCSID(0, "$NetBSD$"); | |
+ | |
+#include "opt_mii.h" | |
+ | |
+#include <sys/param.h> | |
+#include <sys/systm.h> | |
+#include <sys/kernel.h> | |
+#include <sys/device.h> | |
+#include <sys/socket.h> | |
+#include <sys/errno.h> | |
+ | |
+#include <net/if.h> | |
+#include <net/if_media.h> | |
+ | |
+#include <dev/mii/mii.h> | |
+#include <dev/mii/miivar.h> | |
+#include <dev/mii/miidevs.h> | |
+ | |
+static int micphymatch(device_t, cfdata_t, void *); | |
+static void micphyattach(device_t, device_t, void *); | |
+ | |
+CFATTACH_DECL3_NEW(micphy, sizeof(struct mii_softc), | |
+ micphymatch, micphyattach, mii_phy_detach, mii_phy_activate, NULL, NULL, | |
+ DVF_DETACH_SHUTDOWN); | |
+ | |
+static int micphy_service(struct mii_softc *, struct mii_data *, int); | |
+static void micphy_fixup(struct mii_softc *, int, int, device_t); | |
+ | |
+static const struct mii_phy_funcs micphy_funcs = { | |
+ micphy_service, ukphy_status, mii_phy_reset, | |
+}; | |
+ | |
+static const struct mii_phydesc micphys[] = { | |
+ { MII_OUI_MICREL, MII_MODEL_MICREL_KSZ9021RNI, | |
+ MII_STR_MICREL_KSZ9021RNI }, | |
+ | |
+ { 0, 0, | |
+ NULL }, | |
+}; | |
+ | |
+static int | |
+micphymatch(device_t parent, cfdata_t match, void *aux) | |
+{ | |
+ struct mii_attach_args *ma = aux; | |
+ | |
+ if (mii_phy_match(ma, micphys) != NULL) | |
+ return 10; | |
+ | |
+ return 1; | |
+} | |
+ | |
+static void | |
+micphyattach(device_t parent, device_t self, void *aux) | |
+{ | |
+ struct mii_softc *sc = device_private(self); | |
+ struct mii_attach_args *ma = aux; | |
+ struct mii_data *mii = ma->mii_data; | |
+ int model = MII_MODEL(ma->mii_id2); | |
+ int rev = MII_REV(ma->mii_id2); | |
+ const struct mii_phydesc *mpd; | |
+ | |
+ mpd = mii_phy_match(ma, micphys); | |
+ aprint_naive(": Media interface\n"); | |
+ aprint_normal(": %s, rev. %d\n", mpd->mpd_name, rev); | |
+ | |
+ sc->mii_dev = self; | |
+ sc->mii_inst = mii->mii_instance; | |
+ sc->mii_phy = ma->mii_phyno; | |
+ sc->mii_funcs = &micphy_funcs; | |
+ sc->mii_pdata = mii; | |
+ sc->mii_flags = ma->mii_flags; | |
+ sc->mii_anegticks = MII_ANEGTICKS; | |
+ | |
+ PHY_RESET(sc); | |
+ | |
+ micphy_fixup(sc, model, rev, parent); | |
+ | |
+ sc->mii_capabilities = | |
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask; | |
+ if (sc->mii_capabilities & BMSR_EXTSTAT) | |
+ sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); | |
+ aprint_normal_dev(self, ""); | |
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && | |
+ (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) | |
+ aprint_error("no media present"); | |
+ else | |
+ mii_phy_add_media(sc); | |
+ aprint_normal("\n"); | |
+} | |
+ | |
+static int | |
+micphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) | |
+{ | |
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur; | |
+ int reg; | |
+ | |
+ switch (cmd) { | |
+ case MII_POLLSTAT: | |
+ /* | |
+ * If we're not polling our PHY instance, just return. | |
+ */ | |
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) | |
+ return 0; | |
+ break; | |
+ | |
+ case MII_MEDIACHG: | |
+ /* | |
+ * If the media indicates a different PHY instance, | |
+ * isolate ourselves. | |
+ */ | |
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) { | |
+ reg = PHY_READ(sc, MII_BMCR); | |
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); | |
+ return 0; | |
+ } | |
+ | |
+ /* | |
+ * If the interface is not up, don't do anything. | |
+ */ | |
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0) | |
+ break; | |
+ | |
+ mii_phy_setmedia(sc); | |
+ break; | |
+ | |
+ case MII_TICK: | |
+ /* | |
+ * If we're not currently selected, just return. | |
+ */ | |
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) | |
+ return 0; | |
+ | |
+ if (mii_phy_tick(sc) == EJUSTRETURN) | |
+ return 0; | |
+ break; | |
+ | |
+ case MII_DOWN: | |
+ mii_phy_down(sc); | |
+ return 0; | |
+ } | |
+ | |
+ /* Update the media status. */ | |
+ mii_phy_status(sc); | |
+ | |
+ /* Callback if something changed. */ | |
+ mii_phy_update(sc, cmd); | |
+ return 0; | |
+} | |
+ | |
+#define XREG_CONTROL 0x0b | |
+#define XREG_WRITE 0x0c | |
+#define XREG_READ 0x0d | |
+#define XREG_CTL_SEL_READ 0x0000 | |
+#define XREG_CTL_SEL_WRITE 0x8000 | |
+ | |
+#define REG_RGMII_CLOCK_AND_CONTROL 0x104 | |
+#define REG_RGMII_RX_DATA 0x105 | |
+ | |
+static void micphy_writexreg(struct mii_softc *sc, uint32_t reg, uint32_t wval) | |
+{ | |
+ int rval; | |
+ | |
+ PHY_WRITE(sc, XREG_CONTROL, XREG_CTL_SEL_WRITE | reg); | |
+ PHY_WRITE(sc, XREG_WRITE, wval); | |
+ PHY_WRITE(sc, XREG_CONTROL, XREG_CTL_SEL_READ | reg); | |
+ rval = PHY_READ(sc, XREG_READ); | |
+ KDASSERT(wval == rval); | |
+} | |
+ | |
+static void | |
+micphy_fixup(struct mii_softc *sc, int model, int rev, device_t parent) | |
+{ | |
+ switch (model) { | |
+ case MII_MODEL_MICREL_KSZ9021RNI: | |
+ if (!device_is_a(parent, "cpsw")) | |
+ break; | |
+ | |
+ aprint_normal_dev(sc->mii_dev, "adjusting RGMII signal timing for cpsw\n"); | |
+ | |
+ // RGMII RX Data Pad Skew | |
+ micphy_writexreg(sc, REG_RGMII_RX_DATA, 0x0000); | |
+ | |
+ // RGMII Clock and Control Pad Skew | |
+ micphy_writexreg(sc, REG_RGMII_CLOCK_AND_CONTROL, 0x9090); | |
+ | |
+ break; | |
+ } | |
+ | |
+ return; | |
+} | |
Index: sys/dev/mii/miidevs | |
=================================================================== | |
RCS file: /cvs/cvsroot/src/sys/dev/mii/miidevs,v | |
retrieving revision 1.117 | |
diff -u -r1.117 miidevs | |
--- sys/dev/mii/miidevs 21 Dec 2013 15:16:23 -0000 1.117 | |
+++ sys/dev/mii/miidevs 25 Feb 2014 10:52:06 -0000 | |
@@ -66,6 +66,7 @@ | |
oui JMICRON 0x00d831 JMicron | |
oui LEVEL1 0x00207b Level 1 | |
oui MARVELL 0x005043 Marvell Semiconductor | |
+oui MICREL 0x0010a1 Micrel | |
oui MYSON 0x00c0b4 Myson Technology | |
oui NATSEMI 0x080017 National Semiconductor | |
oui PMCSIERRA 0x00e004 PMC-Sierra | |
@@ -260,6 +261,9 @@ | |
model xxMARVELL E1116R_29 0x0029 Marvell 88E1116R Gigabit PHY | |
model xxMARVELL E1543 0x002a Marvell 88E1543 Alaska Quad Port Gb PHY | |
+/* Micrel PHYs */ | |
+model MICREL KSZ9021RNI 0x0021 Micrel KSZ9021RNI 10/100/1000 PHY | |
+ | |
/* Myson Technology PHYs */ | |
model xxMYSON MTD972 0x0000 MTD972 10/100 media interface | |
model MYSON MTD803 0x0000 MTD803 3-in-1 media interface |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment