if_smc.c (225354) | if_smc.c (226995) |
---|---|
1/*- 2 * Copyright (c) 2008 Benno Rice. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 9 unchanged lines hidden (view full) --- 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2008 Benno Rice. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 9 unchanged lines hidden (view full) --- 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25#include <sys/cdefs.h> |
26__FBSDID("$FreeBSD: head/sys/dev/smc/if_smc.c 225354 2011-09-02 20:35:22Z stas $"); | 26__FBSDID("$FreeBSD: head/sys/dev/smc/if_smc.c 226995 2011-11-01 16:13:59Z marius $"); |
27 28/* 29 * Driver for SMSC LAN91C111, may work for older variants. 30 */ 31 32#ifdef HAVE_KERNEL_OPTION_HEADERS 33#include "opt_device_polling.h" 34#endif --- 34 unchanged lines hidden (view full) --- 69 70#include <net/bpf.h> 71#include <net/bpfdesc.h> 72 73#include <dev/smc/if_smcreg.h> 74#include <dev/smc/if_smcvar.h> 75 76#include <dev/mii/mii.h> | 27 28/* 29 * Driver for SMSC LAN91C111, may work for older variants. 30 */ 31 32#ifdef HAVE_KERNEL_OPTION_HEADERS 33#include "opt_device_polling.h" 34#endif --- 34 unchanged lines hidden (view full) --- 69 70#include <net/bpf.h> 71#include <net/bpfdesc.h> 72 73#include <dev/smc/if_smcreg.h> 74#include <dev/smc/if_smcvar.h> 75 76#include <dev/mii/mii.h> |
77#include <dev/mii/mii_bitbang.h> |
|
77#include <dev/mii/miivar.h> 78 79#define SMC_LOCK(sc) mtx_lock(&(sc)->smc_mtx) 80#define SMC_UNLOCK(sc) mtx_unlock(&(sc)->smc_mtx) 81#define SMC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->smc_mtx, MA_OWNED) 82 83#define SMC_INTR_PRIORITY 0 84#define SMC_RX_PRIORITY 5 --- 33 unchanged lines hidden (view full) --- 118static void smc_task_tx(void *, int); 119 120static driver_filter_t smc_intr; 121static timeout_t smc_watchdog; 122#ifdef DEVICE_POLLING 123static poll_handler_t smc_poll; 124#endif 125 | 78#include <dev/mii/miivar.h> 79 80#define SMC_LOCK(sc) mtx_lock(&(sc)->smc_mtx) 81#define SMC_UNLOCK(sc) mtx_unlock(&(sc)->smc_mtx) 82#define SMC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->smc_mtx, MA_OWNED) 83 84#define SMC_INTR_PRIORITY 0 85#define SMC_RX_PRIORITY 5 --- 33 unchanged lines hidden (view full) --- 119static void smc_task_tx(void *, int); 120 121static driver_filter_t smc_intr; 122static timeout_t smc_watchdog; 123#ifdef DEVICE_POLLING 124static poll_handler_t smc_poll; 125#endif 126 |
127/* 128 * MII bit-bang glue 129 */ 130static uint32_t smc_mii_bitbang_read(device_t); 131static void smc_mii_bitbang_write(device_t, uint32_t); 132 133static const struct mii_bitbang_ops smc_mii_bitbang_ops = { 134 smc_mii_bitbang_read, 135 smc_mii_bitbang_write, 136 { 137 MGMT_MDO, /* MII_BIT_MDO */ 138 MGMT_MDI, /* MII_BIT_MDI */ 139 MGMT_MCLK, /* MII_BIT_MDC */ 140 MGMT_MDOE, /* MII_BIT_DIR_HOST_PHY */ 141 0, /* MII_BIT_DIR_PHY_HOST */ 142 } 143}; 144 |
|
126static __inline void 127smc_select_bank(struct smc_softc *sc, uint16_t bank) 128{ 129 | 145static __inline void 146smc_select_bank(struct smc_softc *sc, uint16_t bank) 147{ 148 |
149 bus_barrier(sc->smc_reg, BSR, 2, 150 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); |
|
130 bus_write_2(sc->smc_reg, BSR, bank & BSR_BANK_MASK); | 151 bus_write_2(sc->smc_reg, BSR, bank & BSR_BANK_MASK); |
152 bus_barrier(sc->smc_reg, BSR, 2, 153 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); |
|
131} 132 133/* Never call this when not in bank 2. */ 134static __inline void 135smc_mmu_wait(struct smc_softc *sc) 136{ 137 138 KASSERT((bus_read_2(sc->smc_reg, BSR) & 139 BSR_BANK_MASK) == 2, ("%s: smc_mmu_wait called when not in bank 2", 140 device_get_nameunit(sc->smc_dev))); 141 while (bus_read_2(sc->smc_reg, MMUCR) & MMUCR_BUSY) 142 ; 143} 144 145static __inline uint8_t | 154} 155 156/* Never call this when not in bank 2. */ 157static __inline void 158smc_mmu_wait(struct smc_softc *sc) 159{ 160 161 KASSERT((bus_read_2(sc->smc_reg, BSR) & 162 BSR_BANK_MASK) == 2, ("%s: smc_mmu_wait called when not in bank 2", 163 device_get_nameunit(sc->smc_dev))); 164 while (bus_read_2(sc->smc_reg, MMUCR) & MMUCR_BUSY) 165 ; 166} 167 168static __inline uint8_t |
146smc_read_1(struct smc_softc *sc, bus_addr_t offset) | 169smc_read_1(struct smc_softc *sc, bus_size_t offset) |
147{ 148 149 return (bus_read_1(sc->smc_reg, offset)); 150} 151 152static __inline void | 170{ 171 172 return (bus_read_1(sc->smc_reg, offset)); 173} 174 175static __inline void |
153smc_write_1(struct smc_softc *sc, bus_addr_t offset, uint8_t val) | 176smc_write_1(struct smc_softc *sc, bus_size_t offset, uint8_t val) |
154{ 155 156 bus_write_1(sc->smc_reg, offset, val); 157} 158 159static __inline uint16_t | 177{ 178 179 bus_write_1(sc->smc_reg, offset, val); 180} 181 182static __inline uint16_t |
160smc_read_2(struct smc_softc *sc, bus_addr_t offset) | 183smc_read_2(struct smc_softc *sc, bus_size_t offset) |
161{ 162 163 return (bus_read_2(sc->smc_reg, offset)); 164} 165 166static __inline void | 184{ 185 186 return (bus_read_2(sc->smc_reg, offset)); 187} 188 189static __inline void |
167smc_write_2(struct smc_softc *sc, bus_addr_t offset, uint16_t val) | 190smc_write_2(struct smc_softc *sc, bus_size_t offset, uint16_t val) |
168{ 169 170 bus_write_2(sc->smc_reg, offset, val); 171} 172 173static __inline void | 191{ 192 193 bus_write_2(sc->smc_reg, offset, val); 194} 195 196static __inline void |
174smc_read_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap, | 197smc_read_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap, |
175 bus_size_t count) 176{ 177 178 bus_read_multi_2(sc->smc_reg, offset, datap, count); 179} 180 181static __inline void | 198 bus_size_t count) 199{ 200 201 bus_read_multi_2(sc->smc_reg, offset, datap, count); 202} 203 204static __inline void |
182smc_write_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap, | 205smc_write_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap, |
183 bus_size_t count) 184{ 185 186 bus_write_multi_2(sc->smc_reg, offset, datap, count); 187} 188 | 206 bus_size_t count) 207{ 208 209 bus_write_multi_2(sc->smc_reg, offset, datap, count); 210} 211 |
212static __inline void 213smc_barrier(struct smc_softc *sc, bus_size_t offset, bus_size_t length, 214 int flags) 215{ 216 217 bus_barrier(sc->smc_reg, offset, length, flags); 218} 219 |
|
189int 190smc_probe(device_t dev) 191{ 192 int rid, type, error; 193 uint16_t val; 194 struct smc_softc *sc; 195 struct resource *reg; 196 --- 698 unchanged lines hidden (view full) --- 895 * Update the interrupt mask. 896 */ 897 if ((ifp->if_capenable & IFCAP_POLLING) == 0) 898 smc_write_1(sc, MSK, sc->smc_mask); 899 900 SMC_UNLOCK(sc); 901} 902 | 220int 221smc_probe(device_t dev) 222{ 223 int rid, type, error; 224 uint16_t val; 225 struct smc_softc *sc; 226 struct resource *reg; 227 --- 698 unchanged lines hidden (view full) --- 926 * Update the interrupt mask. 927 */ 928 if ((ifp->if_capenable & IFCAP_POLLING) == 0) 929 smc_write_1(sc, MSK, sc->smc_mask); 930 931 SMC_UNLOCK(sc); 932} 933 |
903static u_int 904smc_mii_readbits(struct smc_softc *sc, int nbits) | 934static uint32_t 935smc_mii_bitbang_read(device_t dev) |
905{ | 936{ |
906 u_int mgmt, mask, val; | 937 struct smc_softc *sc; 938 uint32_t val; |
907 | 939 |
940 sc = device_get_softc(dev); 941 |
|
908 SMC_ASSERT_LOCKED(sc); 909 KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3, | 942 SMC_ASSERT_LOCKED(sc); 943 KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3, |
910 ("%s: smc_mii_readbits called with bank %d (!= 3)", | 944 ("%s: smc_mii_bitbang_read called with bank %d (!= 3)", |
911 device_get_nameunit(sc->smc_dev), 912 smc_read_2(sc, BSR) & BSR_BANK_MASK)); 913 | 945 device_get_nameunit(sc->smc_dev), 946 smc_read_2(sc, BSR) & BSR_BANK_MASK)); 947 |
914 /* 915 * Set up the MGMT (aka MII) register. 916 */ 917 mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO); 918 smc_write_2(sc, MGMT, mgmt); | 948 val = smc_read_2(sc, MGMT); 949 smc_barrier(sc, MGMT, 2, 950 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); |
919 | 951 |
920 /* 921 * Read the bits in. 922 */ 923 for (mask = 1 << (nbits - 1), val = 0; mask; mask >>= 1) { 924 if (smc_read_2(sc, MGMT) & MGMT_MDI) 925 val |= mask; 926 927 smc_write_2(sc, MGMT, mgmt); 928 DELAY(1); 929 smc_write_2(sc, MGMT, mgmt | MGMT_MCLK); 930 DELAY(1); 931 } 932 | |
933 return (val); 934} 935 936static void | 952 return (val); 953} 954 955static void |
937smc_mii_writebits(struct smc_softc *sc, u_int val, int nbits) | 956smc_mii_bitbang_write(device_t dev, uint32_t val) |
938{ | 957{ |
939 u_int mgmt, mask; | 958 struct smc_softc *sc; |
940 | 959 |
960 sc = device_get_softc(dev); 961 |
|
941 SMC_ASSERT_LOCKED(sc); 942 KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3, | 962 SMC_ASSERT_LOCKED(sc); 963 KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3, |
943 ("%s: smc_mii_writebits called with bank %d (!= 3)", | 964 ("%s: smc_mii_bitbang_write called with bank %d (!= 3)", |
944 device_get_nameunit(sc->smc_dev), 945 smc_read_2(sc, BSR) & BSR_BANK_MASK)); 946 | 965 device_get_nameunit(sc->smc_dev), 966 smc_read_2(sc, BSR) & BSR_BANK_MASK)); 967 |
947 /* 948 * Set up the MGMT (aka MII) register). 949 */ 950 mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO); 951 mgmt |= MGMT_MDOE; 952 953 /* 954 * Push the bits out. 955 */ 956 for (mask = 1 << (nbits - 1); mask; mask >>= 1) { 957 if (val & mask) 958 mgmt |= MGMT_MDO; 959 else 960 mgmt &= ~MGMT_MDO; 961 962 smc_write_2(sc, MGMT, mgmt); 963 DELAY(1); 964 smc_write_2(sc, MGMT, mgmt | MGMT_MCLK); 965 DELAY(1); 966 } | 968 smc_write_2(sc, MGMT, val); 969 smc_barrier(sc, MGMT, 2, 970 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); |
967} 968 969int 970smc_miibus_readreg(device_t dev, int phy, int reg) 971{ 972 struct smc_softc *sc; 973 int val; 974 975 sc = device_get_softc(dev); 976 977 SMC_LOCK(sc); 978 979 smc_select_bank(sc, 3); 980 | 971} 972 973int 974smc_miibus_readreg(device_t dev, int phy, int reg) 975{ 976 struct smc_softc *sc; 977 int val; 978 979 sc = device_get_softc(dev); 980 981 SMC_LOCK(sc); 982 983 smc_select_bank(sc, 3); 984 |
981 /* 982 * Send out the idle pattern. 983 */ 984 smc_mii_writebits(sc, 0xffffffff, 32); | 985 val = mii_bitbang_readreg(dev, &smc_mii_bitbang_ops, phy, reg); |
985 | 986 |
986 /* 987 * Start code + read opcode + phy address + phy register 988 */ 989 smc_mii_writebits(sc, 6 << 10 | phy << 5 | reg, 14); 990 991 /* 992 * Turnaround + data 993 */ 994 val = smc_mii_readbits(sc, 18); 995 996 /* 997 * Reset the MDIO interface. 998 */ 999 smc_write_2(sc, MGMT, 1000 smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO)); 1001 | |
1002 SMC_UNLOCK(sc); 1003 return (val); 1004} 1005 1006int 1007smc_miibus_writereg(device_t dev, int phy, int reg, int data) 1008{ 1009 struct smc_softc *sc; 1010 1011 sc = device_get_softc(dev); 1012 1013 SMC_LOCK(sc); 1014 1015 smc_select_bank(sc, 3); 1016 | 987 SMC_UNLOCK(sc); 988 return (val); 989} 990 991int 992smc_miibus_writereg(device_t dev, int phy, int reg, int data) 993{ 994 struct smc_softc *sc; 995 996 sc = device_get_softc(dev); 997 998 SMC_LOCK(sc); 999 1000 smc_select_bank(sc, 3); 1001 |
1017 /* 1018 * Send idle pattern. 1019 */ 1020 smc_mii_writebits(sc, 0xffffffff, 32); | 1002 mii_bitbang_writereg(dev, &smc_mii_bitbang_ops, phy, reg, data); |
1021 | 1003 |
1022 /* 1023 * Start code + write opcode + phy address + phy register + turnaround 1024 * + data. 1025 */ 1026 smc_mii_writebits(sc, 5 << 28 | phy << 23 | reg << 18 | 2 << 16 | data, 1027 32); 1028 1029 /* 1030 * Reset MDIO interface. 1031 */ 1032 smc_write_2(sc, MGMT, 1033 smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO)); 1034 | |
1035 SMC_UNLOCK(sc); 1036 return (0); 1037} 1038 1039void 1040smc_miibus_statchg(device_t dev) 1041{ 1042 struct smc_softc *sc; --- 301 unchanged lines hidden --- | 1004 SMC_UNLOCK(sc); 1005 return (0); 1006} 1007 1008void 1009smc_miibus_statchg(device_t dev) 1010{ 1011 struct smc_softc *sc; --- 301 unchanged lines hidden --- |