1198157Srrs/*- 2198157Srrs * Copyright (c) 2003-2009 RMI Corporation 3198157Srrs * All rights reserved. 4198157Srrs * 5198157Srrs * Redistribution and use in source and binary forms, with or without 6198157Srrs * modification, are permitted provided that the following conditions 7198157Srrs * are met: 8198157Srrs * 1. Redistributions of source code must retain the above copyright 9198157Srrs * notice, this list of conditions and the following disclaimer. 10198157Srrs * 2. Redistributions in binary form must reproduce the above copyright 11198157Srrs * notice, this list of conditions and the following disclaimer in the 12198157Srrs * documentation and/or other materials provided with the distribution. 13198157Srrs * 3. Neither the name of RMI Corporation, nor the names of its contributors, 14198157Srrs * may be used to endorse or promote products derived from this software 15198157Srrs * without specific prior written permission. 16198157Srrs * 17198157Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18198157Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19198157Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20198157Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21198157Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22198157Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23198157Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24198157Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25198157Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26198157Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27198157Srrs * SUCH DAMAGE. 28198157Srrs * 29202066Simp * RMI_BSD 30202066Simp */ 31198157Srrs 32202066Simp#include <sys/cdefs.h> 33202066Simp__FBSDID("$FreeBSD: stable/10/sys/mips/rmi/dev/xlr/rge.c 314667 2017-03-04 13:03:31Z avg $"); 34202066Simp 35198157Srrs#ifdef HAVE_KERNEL_OPTION_HEADERS 36198157Srrs#include "opt_device_polling.h" 37198157Srrs#endif 38198157Srrs 39198157Srrs#include <sys/types.h> 40198157Srrs#include <sys/endian.h> 41198157Srrs#include <sys/systm.h> 42198157Srrs#include <sys/sockio.h> 43198157Srrs#include <sys/param.h> 44198157Srrs#include <sys/lock.h> 45198157Srrs#include <sys/mutex.h> 46198157Srrs#include <sys/proc.h> 47198157Srrs#include <sys/limits.h> 48198157Srrs#include <sys/bus.h> 49198157Srrs#include <sys/mbuf.h> 50198157Srrs#include <sys/malloc.h> 51198157Srrs#include <sys/kernel.h> 52198157Srrs#include <sys/module.h> 53198157Srrs#include <sys/socket.h> 54198157Srrs#define __RMAN_RESOURCE_VISIBLE 55198157Srrs#include <sys/rman.h> 56198157Srrs#include <sys/taskqueue.h> 57208165Srrs#include <sys/smp.h> 58211994Sjchandra#include <sys/sysctl.h> 59198157Srrs 60198157Srrs#include <net/if.h> 61198157Srrs#include <net/if_arp.h> 62198157Srrs#include <net/ethernet.h> 63198157Srrs#include <net/if_dl.h> 64198157Srrs#include <net/if_media.h> 65198157Srrs 66198157Srrs#include <net/bpf.h> 67198157Srrs#include <net/if_types.h> 68198157Srrs#include <net/if_vlan_var.h> 69198157Srrs 70198157Srrs#include <netinet/in_systm.h> 71198157Srrs#include <netinet/in.h> 72198157Srrs#include <netinet/ip.h> 73198157Srrs 74198157Srrs#include <vm/vm.h> 75198157Srrs#include <vm/pmap.h> 76198157Srrs 77198157Srrs#include <machine/reg.h> 78198157Srrs#include <machine/cpu.h> 79198157Srrs#include <machine/mips_opcode.h> 80198157Srrs#include <machine/asm.h> 81198157Srrs 82198157Srrs#include <machine/param.h> 83198157Srrs#include <machine/intr_machdep.h> 84198157Srrs#include <machine/clock.h> /* for DELAY */ 85208165Srrs#include <machine/cpuregs.h> 86198626Srrs#include <machine/bus.h> /* */ 87198157Srrs#include <machine/resource.h> 88211994Sjchandra 89211994Sjchandra#include <dev/mii/mii.h> 90211994Sjchandra#include <dev/mii/miivar.h> 91211994Sjchandra#include <dev/mii/brgphyreg.h> 92211994Sjchandra 93198608Srrs#include <mips/rmi/interrupt.h> 94198608Srrs#include <mips/rmi/msgring.h> 95198608Srrs#include <mips/rmi/iomap.h> 96198608Srrs#include <mips/rmi/pic.h> 97211994Sjchandra#include <mips/rmi/rmi_mips_exts.h> 98211994Sjchandra#include <mips/rmi/rmi_boot_info.h> 99198608Srrs#include <mips/rmi/board.h> 100211996Sjchandra 101211996Sjchandra#include <mips/rmi/dev/xlr/debug.h> 102202066Simp#include <mips/rmi/dev/xlr/atx_cpld.h> 103202066Simp#include <mips/rmi/dev/xlr/xgmac_mdio.h> 104202092Simp#include <mips/rmi/dev/xlr/rge.h> 105198157Srrs 106198608Srrs#include "miibus_if.h" 107198608Srrs 108198157SrrsMODULE_DEPEND(rge, ether, 1, 1, 1); 109198157SrrsMODULE_DEPEND(rge, miibus, 1, 1, 1); 110198157Srrs 111198157Srrs/* #define DEBUG */ 112198157Srrs 113198157Srrs#define RGE_TX_THRESHOLD 1024 114198157Srrs#define RGE_TX_Q_SIZE 1024 115198157Srrs 116198157Srrs#ifdef DEBUG 117198157Srrs#undef dbg_msg 118198626Srrsint mac_debug = 1; 119198626Srrs 120198157Srrs#define dbg_msg(fmt, args...) \ 121198157Srrs do {\ 122198157Srrs if (mac_debug) {\ 123198157Srrs printf("[%s@%d|%s]: cpu_%d: " fmt, \ 124208369Sjchandra __FILE__, __LINE__, __FUNCTION__, xlr_cpu_id(), ##args);\ 125198157Srrs }\ 126198157Srrs } while(0); 127198157Srrs 128198157Srrs#define DUMP_PACKETS 129198157Srrs#else 130198157Srrs#undef dbg_msg 131198157Srrs#define dbg_msg(fmt, args...) 132198626Srrsint mac_debug = 0; 133198626Srrs 134198157Srrs#endif 135198157Srrs 136198157Srrs#define MAC_B2B_IPG 88 137198157Srrs 138198157Srrs/* frame sizes need to be cacheline aligned */ 139198157Srrs#define MAX_FRAME_SIZE 1536 140198157Srrs#define MAX_FRAME_SIZE_JUMBO 9216 141198157Srrs 142198157Srrs#define MAC_SKB_BACK_PTR_SIZE SMP_CACHE_BYTES 143198157Srrs#define MAC_PREPAD 0 144198157Srrs#define BYTE_OFFSET 2 145198157Srrs#define XLR_RX_BUF_SIZE (MAX_FRAME_SIZE+BYTE_OFFSET+MAC_PREPAD+MAC_SKB_BACK_PTR_SIZE+SMP_CACHE_BYTES) 146198157Srrs#define MAC_CRC_LEN 4 147198157Srrs#define MAX_NUM_MSGRNG_STN_CC 128 148198157Srrs 149198157Srrs#define MAX_NUM_DESC 1024 150198157Srrs#define MAX_SPILL_SIZE (MAX_NUM_DESC + 128) 151198157Srrs 152198157Srrs#define MAC_FRIN_TO_BE_SENT_THRESHOLD 16 153198157Srrs 154198157Srrs#define MAX_FRIN_SPILL (MAX_SPILL_SIZE << 2) 155198157Srrs#define MAX_FROUT_SPILL (MAX_SPILL_SIZE << 2) 156198157Srrs#define MAX_CLASS_0_SPILL (MAX_SPILL_SIZE << 2) 157198157Srrs#define MAX_CLASS_1_SPILL (MAX_SPILL_SIZE << 2) 158198157Srrs#define MAX_CLASS_2_SPILL (MAX_SPILL_SIZE << 2) 159198157Srrs#define MAX_CLASS_3_SPILL (MAX_SPILL_SIZE << 2) 160198157Srrs 161198157Srrs/***************************************************************** 162198157Srrs * Phoenix Generic Mac driver 163198157Srrs *****************************************************************/ 164198157Srrs 165198157Srrsextern uint32_t cpu_ltop_map[32]; 166198157Srrs 167198157Srrs#ifdef ENABLED_DEBUG 168198626Srrsstatic int port_counters[4][8] __aligned(XLR_CACHELINE_SIZE); 169198626Srrs 170198157Srrs#define port_inc_counter(port, counter) atomic_add_int(&port_counters[port][(counter)], 1) 171198157Srrs#else 172198626Srrs#define port_inc_counter(port, counter) /* Nothing */ 173198157Srrs#endif 174198157Srrs 175198157Srrsint xlr_rge_tx_prepend[MAXCPU]; 176198157Srrsint xlr_rge_tx_done[MAXCPU]; 177198157Srrsint xlr_rge_get_p2d_failed[MAXCPU]; 178198157Srrsint xlr_rge_msg_snd_failed[MAXCPU]; 179198157Srrsint xlr_rge_tx_ok_done[MAXCPU]; 180198157Srrsint xlr_rge_rx_done[MAXCPU]; 181198157Srrsint xlr_rge_repl_done[MAXCPU]; 182198157Srrs 183198157Srrs/* #define mac_stats_add(x, val) ({(x) += (val);}) */ 184212758Sjchandra#define mac_stats_add(x, val) xlr_ldaddwu(val, &x) 185198157Srrs 186198157Srrs#define XLR_MAX_CORE 8 187198157Srrs#define RGE_LOCK_INIT(_sc, _name) \ 188198157Srrs mtx_init(&(_sc)->rge_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) 189198157Srrs#define RGE_LOCK(_sc) mtx_lock(&(_sc)->rge_mtx) 190198157Srrs#define RGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->rge_mtx, MA_OWNED) 191198157Srrs#define RGE_UNLOCK(_sc) mtx_unlock(&(_sc)->rge_mtx) 192198157Srrs#define RGE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rge_mtx) 193198157Srrs 194198157Srrs#define XLR_MAX_MACS 8 195198157Srrs#define XLR_MAX_TX_FRAGS 14 196198626Srrs#define MAX_P2D_DESC_PER_PORT 512 197198157Srrsstruct p2d_tx_desc { 198198626Srrs uint64_t frag[XLR_MAX_TX_FRAGS + 2]; 199198157Srrs}; 200198626Srrs 201198157Srrs#define MAX_TX_RING_SIZE (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT * sizeof(struct p2d_tx_desc)) 202198157Srrs 203198157Srrsstruct rge_softc *dev_mac[XLR_MAX_MACS]; 204198626Srrsstatic int dev_mac_xgs0; 205198626Srrsstatic int dev_mac_gmac0; 206198157Srrs 207198626Srrsstatic int gmac_common_init_done; 208198157Srrs 209198157Srrs 210198626Srrsstatic int rge_probe(device_t); 211198626Srrsstatic int rge_attach(device_t); 212198626Srrsstatic int rge_detach(device_t); 213198626Srrsstatic int rge_suspend(device_t); 214198626Srrsstatic int rge_resume(device_t); 215198626Srrsstatic void rge_release_resources(struct rge_softc *); 216198626Srrsstatic void rge_rx(struct rge_softc *, vm_paddr_t paddr, int); 217198626Srrsstatic void rge_intr(void *); 218198626Srrsstatic void rge_start_locked(struct ifnet *, int); 219198626Srrsstatic void rge_start(struct ifnet *); 220198626Srrsstatic int rge_ioctl(struct ifnet *, u_long, caddr_t); 221198626Srrsstatic void rge_init(void *); 222198626Srrsstatic void rge_stop(struct rge_softc *); 223198626Srrsstatic int rge_shutdown(device_t); 224198626Srrsstatic void rge_reset(struct rge_softc *); 225198157Srrs 226198157Srrsstatic struct mbuf *get_mbuf(void); 227198626Srrsstatic void free_buf(vm_paddr_t paddr); 228198626Srrsstatic void *get_buf(void); 229198157Srrs 230198626Srrsstatic void xlr_mac_get_hwaddr(struct rge_softc *); 231198626Srrsstatic void xlr_mac_setup_hwaddr(struct driver_data *); 232198626Srrsstatic void rmi_xlr_mac_set_enable(struct driver_data *priv, int flag); 233198626Srrsstatic void rmi_xlr_xgmac_init(struct driver_data *priv); 234198626Srrsstatic void rmi_xlr_gmac_init(struct driver_data *priv); 235198626Srrsstatic void mac_common_init(void); 236198626Srrsstatic int rge_mii_write(device_t, int, int, int); 237198626Srrsstatic int rge_mii_read(device_t, int, int); 238198626Srrsstatic void rmi_xlr_mac_mii_statchg(device_t); 239198626Srrsstatic int rmi_xlr_mac_mediachange(struct ifnet *); 240198626Srrsstatic void rmi_xlr_mac_mediastatus(struct ifnet *, struct ifmediareq *); 241198626Srrsstatic void xlr_mac_set_rx_mode(struct rge_softc *sc); 242198626Srrsvoid 243198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code, 244198626Srrs int stid, struct msgrng_msg *msg, 245198626Srrs void *data); 246198626Srrsstatic void mac_frin_replenish(void *); 247198626Srrsstatic int rmi_xlr_mac_open(struct rge_softc *); 248198626Srrsstatic int rmi_xlr_mac_close(struct rge_softc *); 249198626Srrsstatic int 250198157Srrsmac_xmit(struct mbuf *, struct rge_softc *, 251198626Srrs struct driver_data *, int, struct p2d_tx_desc *); 252198626Srrsstatic int rmi_xlr_mac_xmit(struct mbuf *, struct rge_softc *, int, struct p2d_tx_desc *); 253198157Srrsstatic struct rge_softc_stats *rmi_xlr_mac_get_stats(struct rge_softc *sc); 254198626Srrsstatic void rmi_xlr_mac_set_multicast_list(struct rge_softc *sc); 255198626Srrsstatic int rmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu); 256198626Srrsstatic int rmi_xlr_mac_fill_rxfr(struct rge_softc *sc); 257198626Srrsstatic void rmi_xlr_config_spill_area(struct driver_data *priv); 258198626Srrsstatic int rmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed); 259198626Srrsstatic int 260198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s, 261198626Srrs xlr_mac_duplex_t duplex, xlr_mac_fc_t fc); 262198157Srrsstatic void serdes_regs_init(struct driver_data *priv); 263198157Srrsstatic int rmi_xlr_gmac_reset(struct driver_data *priv); 264198157Srrs 265198157Srrs/*Statistics...*/ 266198157Srrsstatic int get_p2d_desc_failed = 0; 267198626Srrsstatic int msg_snd_failed = 0; 268198157Srrs 269198157SrrsSYSCTL_INT(_hw, OID_AUTO, get_p2d_failed, CTLFLAG_RW, 270198626Srrs &get_p2d_desc_failed, 0, "p2d desc failed"); 271198157SrrsSYSCTL_INT(_hw, OID_AUTO, msg_snd_failed, CTLFLAG_RW, 272198626Srrs &msg_snd_failed, 0, "msg snd failed"); 273198157Srrs 274198626Srrsstruct callout xlr_tx_stop_bkp; 275198157Srrs 276198157Srrsstatic device_method_t rge_methods[] = { 277198157Srrs /* Device interface */ 278198157Srrs DEVMETHOD(device_probe, rge_probe), 279198157Srrs DEVMETHOD(device_attach, rge_attach), 280198157Srrs DEVMETHOD(device_detach, rge_detach), 281198157Srrs DEVMETHOD(device_shutdown, rge_shutdown), 282198157Srrs DEVMETHOD(device_suspend, rge_suspend), 283198157Srrs DEVMETHOD(device_resume, rge_resume), 284198157Srrs 285198157Srrs /* MII interface */ 286198157Srrs DEVMETHOD(miibus_readreg, rge_mii_read), 287198608Srrs DEVMETHOD(miibus_statchg, rmi_xlr_mac_mii_statchg), 288198157Srrs DEVMETHOD(miibus_writereg, rge_mii_write), 289198157Srrs {0, 0} 290198157Srrs}; 291198157Srrs 292198626Srrsstatic driver_t rge_driver = { 293198157Srrs "rge", 294198157Srrs rge_methods, 295198157Srrs sizeof(struct rge_softc) 296198157Srrs}; 297198157Srrs 298198157Srrsstatic devclass_t rge_devclass; 299198157Srrs 300198157SrrsDRIVER_MODULE(rge, iodi, rge_driver, rge_devclass, 0, 0); 301198157SrrsDRIVER_MODULE(miibus, rge, miibus_driver, miibus_devclass, 0, 0); 302198157Srrs 303198157Srrs#ifndef __STR 304198157Srrs#define __STR(x) #x 305198157Srrs#endif 306198157Srrs#ifndef STR 307198157Srrs#define STR(x) __STR(x) 308198157Srrs#endif 309198157Srrs 310198626Srrsvoid *xlr_tx_ring_mem; 311198157Srrs 312198157Srrsstruct tx_desc_node { 313198157Srrs struct p2d_tx_desc *ptr; 314198626Srrs TAILQ_ENTRY(tx_desc_node) list; 315198157Srrs}; 316198626Srrs 317198157Srrs#define XLR_MAX_TX_DESC_NODES (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT) 318198157Srrsstruct tx_desc_node tx_desc_nodes[XLR_MAX_TX_DESC_NODES]; 319198157Srrsstatic volatile int xlr_tot_avail_p2d[XLR_MAX_CORE]; 320198157Srrsstatic int xlr_total_active_core = 0; 321198157Srrs 322198157Srrs/* 323198157Srrs * This should contain the list of all free tx frag desc nodes pointing to tx 324198157Srrs * p2d arrays 325198157Srrs */ 326198626Srrsstatic 327198157SrrsTAILQ_HEAD(, tx_desc_node) tx_frag_desc[XLR_MAX_CORE] = 328198626Srrs{ 329198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[0]), 330198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[1]), 331198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[2]), 332198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[3]), 333198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[4]), 334198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[5]), 335198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[6]), 336198626Srrs TAILQ_HEAD_INITIALIZER(tx_frag_desc[7]), 337198626Srrs}; 338198157Srrs 339198157Srrs/* This contains a list of free tx frag node descriptors */ 340199139Srrsstatic 341198626SrrsTAILQ_HEAD(, tx_desc_node) free_tx_frag_desc[XLR_MAX_CORE] = 342198626Srrs{ 343198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[0]), 344198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[1]), 345198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[2]), 346198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[3]), 347198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[4]), 348198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[5]), 349198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[6]), 350198626Srrs TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[7]), 351198626Srrs}; 352198157Srrs 353198157Srrsstatic struct mtx tx_desc_lock[XLR_MAX_CORE]; 354198157Srrs 355198157Srrsstatic inline void 356198626Srrsmac_make_desc_rfr(struct msgrng_msg *msg, 357198626Srrs vm_paddr_t addr) 358198157Srrs{ 359198157Srrs msg->msg0 = (uint64_t) addr & 0xffffffffe0ULL; 360198157Srrs msg->msg1 = msg->msg2 = msg->msg3 = 0; 361198157Srrs} 362198157Srrs 363198157Srrs#define MAC_TX_DESC_ALIGNMENT (XLR_CACHELINE_SIZE - 1) 364198157Srrs 365198157Srrsstatic void 366198157Srrsinit_p2d_allocation(void) 367198157Srrs{ 368198626Srrs int active_core[8] = {0}; 369198626Srrs int i = 0; 370198157Srrs uint32_t cpumask; 371198157Srrs int cpu; 372198157Srrs 373208369Sjchandra cpumask = xlr_hw_thread_mask; 374198157Srrs 375198157Srrs for (i = 0; i < 32; i++) { 376198157Srrs if (cpumask & (1 << i)) { 377208165Srrs cpu = i; 378198626Srrs if (!active_core[cpu / 4]) { 379198626Srrs active_core[cpu / 4] = 1; 380198157Srrs xlr_total_active_core++; 381198157Srrs } 382198157Srrs } 383198157Srrs } 384198626Srrs for (i = 0; i < XLR_MAX_CORE; i++) { 385198626Srrs if (active_core[i]) 386198626Srrs xlr_tot_avail_p2d[i] = XLR_MAX_TX_DESC_NODES / xlr_total_active_core; 387198157Srrs } 388198626Srrs printf("Total Active Core %d\n", xlr_total_active_core); 389198157Srrs} 390198157Srrs 391198157Srrs 392198157Srrsstatic void 393198157Srrsinit_tx_ring(void) 394198157Srrs{ 395198626Srrs int i; 396198626Srrs int j = 0; 397198157Srrs struct tx_desc_node *start, *node; 398198157Srrs struct p2d_tx_desc *tx_desc; 399198626Srrs vm_paddr_t paddr; 400198626Srrs vm_offset_t unmapped_addr; 401198157Srrs 402198626Srrs for (i = 0; i < XLR_MAX_CORE; i++) 403198157Srrs mtx_init(&tx_desc_lock[i], "xlr tx_desc", NULL, MTX_SPIN); 404198157Srrs 405198157Srrs start = &tx_desc_nodes[0]; 406198157Srrs /* TODO: try to get this from KSEG0 */ 407198157Srrs xlr_tx_ring_mem = contigmalloc((MAX_TX_RING_SIZE + XLR_CACHELINE_SIZE), 408198626Srrs M_DEVBUF, M_NOWAIT | M_ZERO, 0, 409198626Srrs 0x10000000, XLR_CACHELINE_SIZE, 0); 410198157Srrs 411198157Srrs if (xlr_tx_ring_mem == NULL) { 412198157Srrs panic("TX ring memory allocation failed"); 413198157Srrs } 414198626Srrs paddr = vtophys((vm_offset_t)xlr_tx_ring_mem); 415198157Srrs 416198157Srrs unmapped_addr = MIPS_PHYS_TO_KSEG0(paddr); 417198157Srrs 418198157Srrs 419198157Srrs tx_desc = (struct p2d_tx_desc *)unmapped_addr; 420198157Srrs 421198157Srrs for (i = 0; i < XLR_MAX_TX_DESC_NODES; i++) { 422198157Srrs node = start + i; 423198157Srrs node->ptr = tx_desc; 424198157Srrs tx_desc++; 425198157Srrs TAILQ_INSERT_HEAD(&tx_frag_desc[j], node, list); 426198626Srrs j = (i / (XLR_MAX_TX_DESC_NODES / xlr_total_active_core)); 427198157Srrs } 428198157Srrs} 429198157Srrs 430198157Srrsstatic inline struct p2d_tx_desc * 431198157Srrsget_p2d_desc(void) 432198157Srrs{ 433198157Srrs struct tx_desc_node *node; 434198157Srrs struct p2d_tx_desc *tx_desc = NULL; 435208165Srrs int cpu = xlr_core_id(); 436198157Srrs 437198157Srrs mtx_lock_spin(&tx_desc_lock[cpu]); 438198157Srrs node = TAILQ_FIRST(&tx_frag_desc[cpu]); 439198157Srrs if (node) { 440198157Srrs xlr_tot_avail_p2d[cpu]--; 441198157Srrs TAILQ_REMOVE(&tx_frag_desc[cpu], node, list); 442198157Srrs tx_desc = node->ptr; 443198157Srrs TAILQ_INSERT_HEAD(&free_tx_frag_desc[cpu], node, list); 444198626Srrs } else { 445198626Srrs /* Increment p2d desc fail count */ 446198157Srrs get_p2d_desc_failed++; 447198157Srrs } 448198157Srrs mtx_unlock_spin(&tx_desc_lock[cpu]); 449198157Srrs return tx_desc; 450198157Srrs} 451198626Srrsstatic void 452198157Srrsfree_p2d_desc(struct p2d_tx_desc *tx_desc) 453198157Srrs{ 454198157Srrs struct tx_desc_node *node; 455208165Srrs int cpu = xlr_core_id(); 456198157Srrs 457198157Srrs mtx_lock_spin(&tx_desc_lock[cpu]); 458198157Srrs node = TAILQ_FIRST(&free_tx_frag_desc[cpu]); 459198157Srrs KASSERT((node != NULL), ("Free TX frag node list is empty\n")); 460198157Srrs 461198157Srrs TAILQ_REMOVE(&free_tx_frag_desc[cpu], node, list); 462198157Srrs node->ptr = tx_desc; 463198157Srrs TAILQ_INSERT_HEAD(&tx_frag_desc[cpu], node, list); 464198157Srrs xlr_tot_avail_p2d[cpu]++; 465198157Srrs mtx_unlock_spin(&tx_desc_lock[cpu]); 466198157Srrs 467198157Srrs} 468198157Srrs 469198626Srrsstatic int 470198157Srrsbuild_frag_list(struct mbuf *m_head, struct msgrng_msg *p2p_msg, struct p2d_tx_desc *tx_desc) 471198157Srrs{ 472198626Srrs struct mbuf *m; 473198626Srrs vm_paddr_t paddr; 474198626Srrs uint64_t p2d_len; 475198626Srrs int nfrag; 476198626Srrs vm_paddr_t p1, p2; 477198626Srrs uint32_t len1, len2; 478198626Srrs vm_offset_t taddr; 479198626Srrs uint64_t fr_stid; 480198626Srrs 481208165Srrs fr_stid = (xlr_core_id() << 3) + xlr_thr_id() + 4; 482198157Srrs 483198157Srrs if (tx_desc == NULL) 484198157Srrs return 1; 485198157Srrs 486198157Srrs nfrag = 0; 487198157Srrs for (m = m_head; m != NULL; m = m->m_next) { 488198157Srrs if ((nfrag + 1) >= XLR_MAX_TX_FRAGS) { 489198157Srrs free_p2d_desc(tx_desc); 490198157Srrs return 1; 491198157Srrs } 492198157Srrs if (m->m_len != 0) { 493198157Srrs paddr = vtophys(mtod(m, vm_offset_t)); 494198157Srrs p1 = paddr + m->m_len; 495198626Srrs p2 = vtophys(((vm_offset_t)m->m_data + m->m_len)); 496198157Srrs if (p1 != p2) { 497198157Srrs len1 = (uint32_t) 498198626Srrs (PAGE_SIZE - (paddr & PAGE_MASK)); 499198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 500198626Srrs ((uint64_t) len1 << 40) | paddr; 501198157Srrs nfrag++; 502198626Srrs taddr = (vm_offset_t)m->m_data + len1; 503198157Srrs p2 = vtophys(taddr); 504198157Srrs len2 = m->m_len - len1; 505203754Srrs if (len2 == 0) 506203754Srrs continue; 507198157Srrs if (nfrag >= XLR_MAX_TX_FRAGS) 508198157Srrs panic("TX frags exceeded"); 509198157Srrs 510198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 511198626Srrs ((uint64_t) len2 << 40) | p2; 512198157Srrs 513198157Srrs taddr += len2; 514198157Srrs p1 = vtophys(taddr); 515198157Srrs 516198157Srrs if ((p2 + len2) != p1) { 517198608Srrs printf("p1 = %p p2 = %p\n", (void *)p1, (void *)p2); 518198157Srrs printf("len1 = %x len2 = %x\n", len1, 519198626Srrs len2); 520198157Srrs printf("m_data %p\n", m->m_data); 521198157Srrs DELAY(1000000); 522198157Srrs panic("Multiple Mbuf segment discontiguous\n"); 523198157Srrs } 524198157Srrs } else { 525198157Srrs tx_desc->frag[nfrag] = (127ULL << 54) | 526198626Srrs ((uint64_t) m->m_len << 40) | paddr; 527198157Srrs } 528198157Srrs nfrag++; 529198157Srrs } 530198157Srrs } 531198157Srrs /* set eop in the last tx p2d desc */ 532198157Srrs tx_desc->frag[nfrag - 1] |= (1ULL << 63); 533198626Srrs paddr = vtophys((vm_offset_t)tx_desc); 534198157Srrs tx_desc->frag[nfrag] = (1ULL << 63) | (fr_stid << 54) | paddr; 535198157Srrs nfrag++; 536210630Sjchandra tx_desc->frag[XLR_MAX_TX_FRAGS] = (uint64_t)(intptr_t)tx_desc; 537210630Sjchandra tx_desc->frag[XLR_MAX_TX_FRAGS + 1] = (uint64_t)(intptr_t)m_head; 538198157Srrs 539198157Srrs p2d_len = (nfrag * 8); 540198157Srrs p2p_msg->msg0 = (1ULL << 63) | (1ULL << 62) | (127ULL << 54) | 541198626Srrs (p2d_len << 40) | paddr; 542198157Srrs 543198157Srrs return 0; 544198157Srrs} 545198626Srrsstatic void 546198157Srrsrelease_tx_desc(struct msgrng_msg *msg, int rel_buf) 547198157Srrs{ 548199139Srrs struct p2d_tx_desc *tx_desc, *chk_addr; 549198626Srrs struct mbuf *m; 550198157Srrs 551199139Srrs tx_desc = (struct p2d_tx_desc *)MIPS_PHYS_TO_KSEG0(msg->msg0); 552209808Sjchandra chk_addr = (struct p2d_tx_desc *)(intptr_t)tx_desc->frag[XLR_MAX_TX_FRAGS]; 553199139Srrs if (tx_desc != chk_addr) { 554199139Srrs printf("Address %p does not match with stored addr %p - we leaked a descriptor\n", 555199139Srrs tx_desc, chk_addr); 556199139Srrs return; 557199139Srrs } 558198157Srrs if (rel_buf) { 559209808Sjchandra m = (struct mbuf *)(intptr_t)tx_desc->frag[XLR_MAX_TX_FRAGS + 1]; 560198157Srrs m_freem(m); 561198157Srrs } 562198157Srrs free_p2d_desc(tx_desc); 563198157Srrs} 564198157Srrs 565198157Srrs 566198626Srrsstatic struct mbuf * 567198157Srrsget_mbuf(void) 568198157Srrs{ 569198626Srrs struct mbuf *m_new = NULL; 570198157Srrs 571243882Sglebius if ((m_new = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR)) == NULL) 572198157Srrs return NULL; 573198157Srrs 574198157Srrs m_new->m_len = MCLBYTES; 575198157Srrs m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 576198157Srrs return m_new; 577198157Srrs} 578198157Srrs 579198626Srrsstatic void 580198157Srrsfree_buf(vm_paddr_t paddr) 581198157Srrs{ 582198626Srrs struct mbuf *m; 583212758Sjchandra uint64_t mag; 584210630Sjchandra uint32_t sr; 585210630Sjchandra 586208165Srrs sr = xlr_enable_kx(); 587212758Sjchandra m = (struct mbuf *)(intptr_t)xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE); 588212758Sjchandra mag = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE + sizeof(uint64_t)); 589212758Sjchandra xlr_restore_kx(sr); 590199139Srrs if (mag != 0xf00bad) { 591212758Sjchandra printf("Something is wrong kseg:%lx found mag:%lx not 0xf00bad\n", 592212758Sjchandra (u_long)paddr, (u_long)mag); 593199139Srrs return; 594199139Srrs } 595198157Srrs if (m != NULL) 596198157Srrs m_freem(m); 597198157Srrs} 598198157Srrs 599198157Srrsstatic void * 600198157Srrsget_buf(void) 601198157Srrs{ 602198626Srrs struct mbuf *m_new = NULL; 603210630Sjchandra uint64_t *md; 604198157Srrs#ifdef INVARIANTS 605198626Srrs vm_paddr_t temp1, temp2; 606198157Srrs#endif 607198157Srrs 608198157Srrs m_new = get_mbuf(); 609198157Srrs if (m_new == NULL) 610198157Srrs return NULL; 611198157Srrs 612209808Sjchandra m_adj(m_new, XLR_CACHELINE_SIZE - ((uintptr_t)m_new->m_data & 0x1f)); 613210630Sjchandra md = (uint64_t *)m_new->m_data; 614209808Sjchandra md[0] = (uintptr_t)m_new; /* Back Ptr */ 615198157Srrs md[1] = 0xf00bad; 616198157Srrs m_adj(m_new, XLR_CACHELINE_SIZE); 617198157Srrs 618198157Srrs#ifdef INVARIANTS 619198626Srrs temp1 = vtophys((vm_offset_t)m_new->m_data); 620198626Srrs temp2 = vtophys((vm_offset_t)m_new->m_data + 1536); 621198157Srrs if ((temp1 + 1536) != temp2) 622198157Srrs panic("ALLOCED BUFFER IS NOT CONTIGUOUS\n"); 623198157Srrs#endif 624198157Srrs return (void *)m_new->m_data; 625198157Srrs} 626198157Srrs 627198157Srrs/********************************************************************** 628198157Srrs **********************************************************************/ 629198626Srrsstatic void 630198157Srrsrmi_xlr_mac_set_enable(struct driver_data *priv, int flag) 631198157Srrs{ 632198626Srrs uint32_t regval; 633198626Srrs int tx_threshold = 1518; 634198157Srrs 635198157Srrs if (flag) { 636198157Srrs regval = xlr_read_reg(priv->mmio, R_TX_CONTROL); 637198157Srrs regval |= (1 << O_TX_CONTROL__TxEnable) | 638198626Srrs (tx_threshold << O_TX_CONTROL__TxThreshold); 639198157Srrs 640198157Srrs xlr_write_reg(priv->mmio, R_TX_CONTROL, regval); 641198157Srrs 642198157Srrs regval = xlr_read_reg(priv->mmio, R_RX_CONTROL); 643198157Srrs regval |= 1 << O_RX_CONTROL__RxEnable; 644198157Srrs if (priv->mode == XLR_PORT0_RGMII) 645198157Srrs regval |= 1 << O_RX_CONTROL__RGMII; 646198157Srrs xlr_write_reg(priv->mmio, R_RX_CONTROL, regval); 647198157Srrs 648198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1); 649198157Srrs regval |= (O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen); 650198157Srrs xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval); 651198157Srrs } else { 652198157Srrs regval = xlr_read_reg(priv->mmio, R_TX_CONTROL); 653198157Srrs regval &= ~((1 << O_TX_CONTROL__TxEnable) | 654198626Srrs (tx_threshold << O_TX_CONTROL__TxThreshold)); 655198157Srrs 656198157Srrs xlr_write_reg(priv->mmio, R_TX_CONTROL, regval); 657198157Srrs 658198157Srrs regval = xlr_read_reg(priv->mmio, R_RX_CONTROL); 659198157Srrs regval &= ~(1 << O_RX_CONTROL__RxEnable); 660198157Srrs xlr_write_reg(priv->mmio, R_RX_CONTROL, regval); 661198157Srrs 662198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1); 663198157Srrs regval &= ~(O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen); 664198157Srrs xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval); 665198157Srrs } 666198157Srrs} 667198157Srrs 668198157Srrs/********************************************************************** 669198157Srrs **********************************************************************/ 670198626Srrsstatic __inline__ int 671198157Srrsxlr_mac_send_fr(struct driver_data *priv, 672198626Srrs vm_paddr_t addr, int len) 673198157Srrs{ 674212321Sjchandra struct msgrng_msg msg; 675198626Srrs int stid = priv->rfrbucket; 676212409Sjchandra int code, ret; 677212321Sjchandra uint32_t msgrng_flags; 678212409Sjchandra#ifdef INVARIANTS 679212409Sjchandra int i = 0; 680212409Sjchandra#endif 681198157Srrs 682198626Srrs mac_make_desc_rfr(&msg, addr); 683198157Srrs 684198157Srrs /* Send the packet to MAC */ 685208165Srrs dbg_msg("mac_%d: Sending free packet %lx to stid %d\n", 686208165Srrs priv->instance, (u_long)addr, stid); 687212321Sjchandra if (priv->type == XLR_XGMAC) 688212321Sjchandra code = MSGRNG_CODE_XGMAC; /* WHY? */ 689212321Sjchandra else 690212321Sjchandra code = MSGRNG_CODE_MAC; 691198157Srrs 692212321Sjchandra do { 693212321Sjchandra msgrng_flags = msgrng_access_enable(); 694212553Sjchandra ret = message_send(1, code, stid, &msg); 695212321Sjchandra msgrng_restore(msgrng_flags); 696212321Sjchandra KASSERT(i++ < 100000, ("Too many credit fails\n")); 697212321Sjchandra } while (ret != 0); 698212321Sjchandra 699198157Srrs return 0; 700198157Srrs} 701198157Srrs 702198157Srrs/**************************************************************/ 703198157Srrs 704198626Srrsstatic void 705198157Srrsxgmac_mdio_setup(volatile unsigned int *_mmio) 706198157Srrs{ 707198626Srrs int i; 708198626Srrs uint32_t rd_data; 709198626Srrs 710198157Srrs for (i = 0; i < 4; i++) { 711198157Srrs rd_data = xmdio_read(_mmio, 1, 0x8000 + i); 712198157Srrs rd_data = rd_data & 0xffffdfff; /* clear isolate bit */ 713198157Srrs xmdio_write(_mmio, 1, 0x8000 + i, rd_data); 714198157Srrs } 715198157Srrs} 716198157Srrs 717198157Srrs/********************************************************************** 718198157Srrs * Init MII interface 719198157Srrs * 720198157Srrs * Input parameters: 721198157Srrs * s - priv structure 722198157Srrs ********************************************************************* */ 723198157Srrs#define PHY_STATUS_RETRIES 25000 724198157Srrs 725198626Srrsstatic void 726198157Srrsrmi_xlr_mac_mii_init(struct driver_data *priv) 727198157Srrs{ 728198626Srrs xlr_reg_t *mii_mmio = priv->mii_mmio; 729198157Srrs 730198157Srrs /* use the lowest clock divisor - divisor 28 */ 731198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_CONFIG, 0x07); 732198157Srrs} 733198157Srrs 734198157Srrs/********************************************************************** 735198157Srrs * Read a PHY register. 736198157Srrs * 737198157Srrs * Input parameters: 738198157Srrs * s - priv structure 739198157Srrs * phyaddr - PHY's address 740198157Srrs * regidx = index of register to read 741198157Srrs * 742198157Srrs * Return value: 743198157Srrs * value read, or 0 if an error occurred. 744198157Srrs ********************************************************************* */ 745198157Srrs 746198626Srrsstatic int 747198626Srrsrge_mii_read_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx) 748198157Srrs{ 749198626Srrs int i = 0; 750198157Srrs 751198157Srrs /* setup the phy reg to be used */ 752198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS, 753198626Srrs (phyaddr << 8) | (regidx << 0)); 754198157Srrs /* Issue the read command */ 755198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND, 756198626Srrs (1 << O_MII_MGMT_COMMAND__rstat)); 757198157Srrs 758198157Srrs /* poll for the read cycle to complete */ 759198157Srrs for (i = 0; i < PHY_STATUS_RETRIES; i++) { 760198157Srrs if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0) 761198157Srrs break; 762198157Srrs } 763198157Srrs 764198157Srrs /* clear the read cycle */ 765198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND, 0); 766198157Srrs 767198157Srrs if (i == PHY_STATUS_RETRIES) { 768198157Srrs return 0xffffffff; 769198157Srrs } 770198157Srrs /* Read the data back */ 771198157Srrs return xlr_read_reg(mii_mmio, R_MII_MGMT_STATUS); 772198157Srrs} 773198157Srrs 774198626Srrsstatic int 775198608Srrsrge_mii_read(device_t dev, int phyaddr, int regidx) 776198157Srrs{ 777198157Srrs struct rge_softc *sc = device_get_softc(dev); 778198626Srrs 779198157Srrs return rge_mii_read_internal(sc->priv.mii_mmio, phyaddr, regidx); 780198157Srrs} 781198157Srrs 782198157Srrs/********************************************************************** 783198157Srrs * Set MII hooks to newly selected media 784198157Srrs * 785198157Srrs * Input parameters: 786198157Srrs * ifp - Interface Pointer 787198157Srrs * 788198157Srrs * Return value: 789198157Srrs * nothing 790198157Srrs ********************************************************************* */ 791198626Srrsstatic int 792198157Srrsrmi_xlr_mac_mediachange(struct ifnet *ifp) 793198157Srrs{ 794198157Srrs struct rge_softc *sc = ifp->if_softc; 795198157Srrs 796198157Srrs if (ifp->if_flags & IFF_UP) 797198157Srrs mii_mediachg(&sc->rge_mii); 798198157Srrs 799198157Srrs return 0; 800198157Srrs} 801198157Srrs 802198157Srrs/********************************************************************** 803198157Srrs * Get the current interface media status 804198157Srrs * 805198157Srrs * Input parameters: 806198157Srrs * ifp - Interface Pointer 807198157Srrs * ifmr - Interface media request ptr 808198157Srrs * 809198157Srrs * Return value: 810198157Srrs * nothing 811198157Srrs ********************************************************************* */ 812198157Srrsstatic void 813198157Srrsrmi_xlr_mac_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 814198157Srrs{ 815198157Srrs struct rge_softc *sc = ifp->if_softc; 816198157Srrs 817198626Srrs /* Check whether this is interface is active or not. */ 818198157Srrs ifmr->ifm_status = IFM_AVALID; 819198626Srrs if (sc->link_up) { 820198157Srrs ifmr->ifm_status |= IFM_ACTIVE; 821198626Srrs } else { 822198157Srrs ifmr->ifm_active = IFM_ETHER; 823198157Srrs } 824198157Srrs} 825198157Srrs 826198157Srrs/********************************************************************** 827198157Srrs * Write a value to a PHY register. 828198157Srrs * 829198157Srrs * Input parameters: 830198157Srrs * s - priv structure 831198157Srrs * phyaddr - PHY to use 832198157Srrs * regidx - register within the PHY 833198157Srrs * regval - data to write to register 834198157Srrs * 835198157Srrs * Return value: 836198157Srrs * nothing 837198157Srrs ********************************************************************* */ 838198608Srrsstatic void 839198626Srrsrge_mii_write_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx, int regval) 840198157Srrs{ 841198626Srrs int i = 0; 842198157Srrs 843198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS, 844198626Srrs (phyaddr << 8) | (regidx << 0)); 845198157Srrs 846198157Srrs /* Write the data which starts the write cycle */ 847198157Srrs xlr_write_reg(mii_mmio, R_MII_MGMT_WRITE_DATA, regval); 848198157Srrs 849198157Srrs /* poll for the write cycle to complete */ 850198157Srrs for (i = 0; i < PHY_STATUS_RETRIES; i++) { 851198157Srrs if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0) 852198157Srrs break; 853198157Srrs } 854198157Srrs 855198157Srrs return; 856198157Srrs} 857198157Srrs 858198608Srrsstatic int 859198608Srrsrge_mii_write(device_t dev, int phyaddr, int regidx, int regval) 860198157Srrs{ 861198157Srrs struct rge_softc *sc = device_get_softc(dev); 862198157Srrs 863198157Srrs rge_mii_write_internal(sc->priv.mii_mmio, phyaddr, regidx, regval); 864198608Srrs return (0); 865198157Srrs} 866198157Srrs 867198626Srrsstatic void 868198608Srrsrmi_xlr_mac_mii_statchg(struct device *dev) 869198157Srrs{ 870198157Srrs} 871198157Srrs 872198157Srrsstatic void 873198157Srrsserdes_regs_init(struct driver_data *priv) 874198157Srrs{ 875198626Srrs xlr_reg_t *mmio_gpio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GPIO_OFFSET); 876198157Srrs 877198157Srrs /* Initialize SERDES CONTROL Registers */ 878198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 0, 0x6DB0); 879198626Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 1, 0xFFFF); 880198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 2, 0xB6D0); 881198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 3, 0x00FF); 882198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 4, 0x0000); 883198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 5, 0x0000); 884198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 6, 0x0005); 885198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 7, 0x0001); 886198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 8, 0x0000); 887198157Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 9, 0x0000); 888198626Srrs rge_mii_write_internal(priv->serdes_mmio, 26, 10, 0x0000); 889198157Srrs 890198626Srrs /* 891209318Sjchandra * GPIO setting which affect the serdes - needs figuring out 892198157Srrs */ 893209318Sjchandra DELAY(100); 894209318Sjchandra xlr_write_reg(mmio_gpio, 0x20, 0x7e6802); 895209318Sjchandra xlr_write_reg(mmio_gpio, 0x10, 0x7104); 896209318Sjchandra DELAY(100); 897209318Sjchandra 898209318Sjchandra /* 899209318Sjchandra * This kludge is needed to setup serdes (?) clock correctly on some 900209318Sjchandra * XLS boards 901209318Sjchandra */ 902209318Sjchandra if ((xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI || 903209318Sjchandra xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XII) && 904209318Sjchandra xlr_boot1_info.board_minor_version == 4) { 905209318Sjchandra /* use 125 Mhz instead of 156.25Mhz ref clock */ 906209318Sjchandra DELAY(100); 907209318Sjchandra xlr_write_reg(mmio_gpio, 0x10, 0x7103); 908209318Sjchandra xlr_write_reg(mmio_gpio, 0x21, 0x7103); 909209318Sjchandra DELAY(100); 910198626Srrs } 911209318Sjchandra 912198157Srrs return; 913198626Srrs} 914198157Srrs 915199139Srrsstatic void 916198626Srrsserdes_autoconfig(struct driver_data *priv) 917198157Srrs{ 918198626Srrs int delay = 100000; 919198157Srrs 920198626Srrs /* Enable Auto negotiation in the PCS Layer */ 921198626Srrs rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x1000); 922198626Srrs DELAY(delay); 923198626Srrs rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x0200); 924198626Srrs DELAY(delay); 925198157Srrs 926198626Srrs rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x1000); 927198626Srrs DELAY(delay); 928198626Srrs rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x0200); 929198626Srrs DELAY(delay); 930198157Srrs 931198626Srrs rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x1000); 932198626Srrs DELAY(delay); 933198626Srrs rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x0200); 934198626Srrs DELAY(delay); 935198157Srrs 936198626Srrs rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x1000); 937198626Srrs DELAY(delay); 938198626Srrs rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x0200); 939198626Srrs DELAY(delay); 940198157Srrs 941198157Srrs} 942198157Srrs 943198157Srrs/***************************************************************** 944198157Srrs * Initialize GMAC 945198157Srrs *****************************************************************/ 946198626Srrsstatic void 947198157Srrsrmi_xlr_config_pde(struct driver_data *priv) 948198157Srrs{ 949198626Srrs int i = 0, cpu = 0, bucket = 0; 950198626Srrs uint64_t bucket_map = 0; 951198626Srrs 952198157Srrs /* uint32_t desc_pack_ctrl = 0; */ 953198626Srrs uint32_t cpumask; 954198157Srrs 955208369Sjchandra cpumask = 0x1; 956208165Srrs#ifdef SMP 957208165Srrs /* 958208165Srrs * rge may be called before SMP start in a BOOTP/NFSROOT 959208165Srrs * setup. we will distribute packets to other cpus only when 960208165Srrs * the SMP is started. 961208165Srrs */ 962208165Srrs if (smp_started) 963208369Sjchandra cpumask = xlr_hw_thread_mask; 964208165Srrs#endif 965198157Srrs 966208165Srrs for (i = 0; i < MAXCPU; i++) { 967198157Srrs if (cpumask & (1 << i)) { 968208165Srrs cpu = i; 969198626Srrs bucket = ((cpu >> 2) << 3); 970213377Sjchandra bucket_map |= (3ULL << bucket); 971198157Srrs } 972198157Srrs } 973209808Sjchandra printf("rmi_xlr_config_pde: bucket_map=%jx\n", (uintmax_t)bucket_map); 974198157Srrs 975198157Srrs /* bucket_map = 0x1; */ 976198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_0, (bucket_map & 0xffffffff)); 977198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_0 + 1, 978198626Srrs ((bucket_map >> 32) & 0xffffffff)); 979198157Srrs 980198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_1, (bucket_map & 0xffffffff)); 981198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_1 + 1, 982198626Srrs ((bucket_map >> 32) & 0xffffffff)); 983198157Srrs 984198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_2, (bucket_map & 0xffffffff)); 985198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_2 + 1, 986198626Srrs ((bucket_map >> 32) & 0xffffffff)); 987198157Srrs 988198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_3, (bucket_map & 0xffffffff)); 989198157Srrs xlr_write_reg(priv->mmio, R_PDE_CLASS_3 + 1, 990198626Srrs ((bucket_map >> 32) & 0xffffffff)); 991198157Srrs} 992198157Srrs 993198626Srrsstatic void 994208165Srrsrge_smp_update_pde(void *dummy __unused) 995208165Srrs{ 996208165Srrs int i; 997208165Srrs struct driver_data *priv; 998208165Srrs struct rge_softc *sc; 999208165Srrs 1000208165Srrs printf("Updating packet distribution for SMP\n"); 1001208165Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 1002208165Srrs sc = dev_mac[i]; 1003208165Srrs if (!sc) 1004208165Srrs continue; 1005208165Srrs priv = &(sc->priv); 1006208165Srrs rmi_xlr_mac_set_enable(priv, 0); 1007208165Srrs rmi_xlr_config_pde(priv); 1008208165Srrs rmi_xlr_mac_set_enable(priv, 1); 1009208165Srrs } 1010208165Srrs} 1011208165Srrs 1012208165SrrsSYSINIT(rge_smp_update_pde, SI_SUB_SMP, SI_ORDER_ANY, rge_smp_update_pde, NULL); 1013208165Srrs 1014208165Srrs 1015208165Srrsstatic void 1016198157Srrsrmi_xlr_config_parser(struct driver_data *priv) 1017198157Srrs{ 1018198157Srrs /* 1019198157Srrs * Mark it as no classification The parser extract is gauranteed to 1020198157Srrs * be zero with no classfication 1021198157Srrs */ 1022198157Srrs xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x00); 1023198157Srrs 1024198157Srrs xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x01); 1025198157Srrs 1026198157Srrs /* configure the parser : L2 Type is configured in the bootloader */ 1027198157Srrs /* extract IP: src, dest protocol */ 1028198157Srrs xlr_write_reg(priv->mmio, R_L3CTABLE, 1029198626Srrs (9 << 20) | (1 << 19) | (1 << 18) | (0x01 << 16) | 1030198626Srrs (0x0800 << 0)); 1031198157Srrs xlr_write_reg(priv->mmio, R_L3CTABLE + 1, 1032198626Srrs (12 << 25) | (4 << 21) | (16 << 14) | (4 << 10)); 1033198157Srrs 1034198157Srrs} 1035198157Srrs 1036198626Srrsstatic void 1037198157Srrsrmi_xlr_config_classifier(struct driver_data *priv) 1038198157Srrs{ 1039198626Srrs int i = 0; 1040198157Srrs 1041198157Srrs if (priv->type == XLR_XGMAC) { 1042198157Srrs /* xgmac translation table doesn't have sane values on reset */ 1043198157Srrs for (i = 0; i < 64; i++) 1044198157Srrs xlr_write_reg(priv->mmio, R_TRANSLATETABLE + i, 0x0); 1045198157Srrs 1046198157Srrs /* 1047198157Srrs * use upper 7 bits of the parser extract to index the 1048198157Srrs * translate table 1049198157Srrs */ 1050198157Srrs xlr_write_reg(priv->mmio, R_PARSERCONFIGREG, 0x0); 1051198157Srrs } 1052198157Srrs} 1053198157Srrs 1054198157Srrsenum { 1055198626Srrs SGMII_SPEED_10 = 0x00000000, 1056198626Srrs SGMII_SPEED_100 = 0x02000000, 1057198626Srrs SGMII_SPEED_1000 = 0x04000000, 1058198157Srrs}; 1059198157Srrs 1060198626Srrsstatic void 1061198157Srrsrmi_xlr_gmac_config_speed(struct driver_data *priv) 1062198157Srrs{ 1063198157Srrs int phy_addr = priv->phy_addr; 1064198626Srrs xlr_reg_t *mmio = priv->mmio; 1065198157Srrs struct rge_softc *sc = priv->sc; 1066198157Srrs 1067198157Srrs priv->speed = rge_mii_read_internal(priv->mii_mmio, phy_addr, 28); 1068198157Srrs priv->link = rge_mii_read_internal(priv->mii_mmio, phy_addr, 1) & 0x4; 1069198157Srrs priv->speed = (priv->speed >> 3) & 0x03; 1070198157Srrs 1071198157Srrs if (priv->speed == xlr_mac_speed_10) { 1072198157Srrs if (priv->mode != XLR_RGMII) 1073198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_10); 1074209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117); 1075198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x02); 1076198157Srrs printf("%s: [10Mbps]\n", device_get_nameunit(sc->rge_dev)); 1077198626Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1078198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1079198626Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX; 1080198157Srrs } else if (priv->speed == xlr_mac_speed_100) { 1081198157Srrs if (priv->mode != XLR_RGMII) 1082198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100); 1083209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117); 1084198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x01); 1085198157Srrs printf("%s: [100Mbps]\n", device_get_nameunit(sc->rge_dev)); 1086198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1087198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1088198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1089198157Srrs } else { 1090198157Srrs if (priv->speed != xlr_mac_speed_1000) { 1091198157Srrs if (priv->mode != XLR_RGMII) 1092198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100); 1093198157Srrs printf("PHY reported unknown MAC speed, defaulting to 100Mbps\n"); 1094209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117); 1095198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x01); 1096198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1097198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1098198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX; 1099198157Srrs } else { 1100198157Srrs if (priv->mode != XLR_RGMII) 1101198157Srrs xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_1000); 1102209318Sjchandra xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7217); 1103198157Srrs xlr_write_reg(mmio, R_CORECONTROL, 0x00); 1104198157Srrs printf("%s: [1000Mbps]\n", device_get_nameunit(sc->rge_dev)); 1105198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1106198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1107198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX; 1108198157Srrs } 1109198157Srrs } 1110198626Srrs 1111198157Srrs if (!priv->link) { 1112198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER; 1113198157Srrs sc->link_up = 0; 1114198157Srrs } else { 1115198157Srrs sc->link_up = 1; 1116198157Srrs } 1117198157Srrs} 1118198157Srrs 1119198157Srrs/***************************************************************** 1120198157Srrs * Initialize XGMAC 1121198157Srrs *****************************************************************/ 1122198626Srrsstatic void 1123198157Srrsrmi_xlr_xgmac_init(struct driver_data *priv) 1124198157Srrs{ 1125198626Srrs int i = 0; 1126198626Srrs xlr_reg_t *mmio = priv->mmio; 1127198626Srrs int id = priv->instance; 1128198157Srrs struct rge_softc *sc = priv->sc; 1129198157Srrs volatile unsigned short *cpld; 1130198157Srrs 1131198157Srrs cpld = (volatile unsigned short *)0xBD840000; 1132198157Srrs 1133198157Srrs xlr_write_reg(priv->mmio, R_DESC_PACK_CTRL, 1134198626Srrs (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize) | (4 << 20)); 1135198157Srrs xlr_write_reg(priv->mmio, R_BYTEOFFSET0, BYTE_OFFSET); 1136198157Srrs rmi_xlr_config_pde(priv); 1137198157Srrs rmi_xlr_config_parser(priv); 1138198157Srrs rmi_xlr_config_classifier(priv); 1139198157Srrs 1140198157Srrs xlr_write_reg(priv->mmio, R_MSG_TX_THRESHOLD, 1); 1141198157Srrs 1142198157Srrs /* configure the XGMAC Registers */ 1143198157Srrs xlr_write_reg(mmio, R_XGMAC_CONFIG_1, 0x50000026); 1144198157Srrs 1145198157Srrs /* configure the XGMAC_GLUE Registers */ 1146198157Srrs xlr_write_reg(mmio, R_DMACR0, 0xffffffff); 1147198157Srrs xlr_write_reg(mmio, R_DMACR1, 0xffffffff); 1148198157Srrs xlr_write_reg(mmio, R_DMACR2, 0xffffffff); 1149198157Srrs xlr_write_reg(mmio, R_DMACR3, 0xffffffff); 1150198157Srrs xlr_write_reg(mmio, R_STATCTRL, 0x04); 1151198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1152198157Srrs 1153198157Srrs xlr_write_reg(mmio, R_XGMACPADCALIBRATION, 0x030); 1154198157Srrs xlr_write_reg(mmio, R_EGRESSFIFOCARVINGSLOTS, 0x0f); 1155198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1156198157Srrs xlr_write_reg(mmio, R_XGMAC_MIIM_CONFIG, 0x3e); 1157198157Srrs 1158198157Srrs /* 1159198157Srrs * take XGMII phy out of reset 1160198157Srrs */ 1161198157Srrs /* 1162198157Srrs * we are pulling everything out of reset because writing a 0 would 1163198157Srrs * reset other devices on the chip 1164198157Srrs */ 1165198157Srrs cpld[ATX_CPLD_RESET_1] = 0xffff; 1166198157Srrs cpld[ATX_CPLD_MISC_CTRL] = 0xffff; 1167198157Srrs cpld[ATX_CPLD_RESET_2] = 0xffff; 1168198157Srrs 1169198157Srrs xgmac_mdio_setup(mmio); 1170198157Srrs 1171198157Srrs rmi_xlr_config_spill_area(priv); 1172198157Srrs 1173198157Srrs if (id == 0) { 1174198157Srrs for (i = 0; i < 16; i++) { 1175198157Srrs xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i, 1176198626Srrs bucket_sizes. 1177198626Srrs bucket[MSGRNG_STNID_XGS0_TX + i]); 1178198157Srrs } 1179198157Srrs 1180198157Srrs xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE, 1181198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC0JFR]); 1182198157Srrs xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE, 1183198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC0RFR]); 1184198157Srrs 1185198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1186198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1187198626Srrs cc_table_xgs_0. 1188198626Srrs counters[i >> 3][i & 0x07]); 1189198157Srrs } 1190198157Srrs } else if (id == 1) { 1191198157Srrs for (i = 0; i < 16; i++) { 1192198157Srrs xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i, 1193198626Srrs bucket_sizes. 1194198626Srrs bucket[MSGRNG_STNID_XGS1_TX + i]); 1195198157Srrs } 1196198157Srrs 1197198157Srrs xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE, 1198198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC1JFR]); 1199198157Srrs xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE, 1200198626Srrs bucket_sizes.bucket[MSGRNG_STNID_XMAC1RFR]); 1201198157Srrs 1202198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1203198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1204198626Srrs cc_table_xgs_1. 1205198626Srrs counters[i >> 3][i & 0x07]); 1206198157Srrs } 1207198157Srrs } 1208198157Srrs sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1209198157Srrs sc->rge_mii.mii_media.ifm_media |= (IFM_AVALID | IFM_ACTIVE); 1210198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1211198157Srrs sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX; 1212198157Srrs sc->rge_mii.mii_media.ifm_cur->ifm_media |= (IFM_AVALID | IFM_ACTIVE); 1213198157Srrs 1214198157Srrs priv->init_frin_desc = 1; 1215198157Srrs} 1216198157Srrs 1217198157Srrs/******************************************************* 1218198157Srrs * Initialization gmac 1219198157Srrs *******************************************************/ 1220198157Srrsstatic int 1221198157Srrsrmi_xlr_gmac_reset(struct driver_data *priv) 1222198157Srrs{ 1223198157Srrs volatile uint32_t val; 1224198157Srrs xlr_reg_t *mmio = priv->mmio; 1225198157Srrs int i, maxloops = 100; 1226198157Srrs 1227198626Srrs /* Disable MAC RX */ 1228198626Srrs val = xlr_read_reg(mmio, R_MAC_CONFIG_1); 1229198626Srrs val &= ~0x4; 1230198626Srrs xlr_write_reg(mmio, R_MAC_CONFIG_1, val); 1231198157Srrs 1232198626Srrs /* Disable Core RX */ 1233198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1234198626Srrs val &= ~0x1; 1235198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1236198157Srrs 1237198626Srrs /* wait for rx to halt */ 1238198626Srrs for (i = 0; i < maxloops; i++) { 1239198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1240198626Srrs if (val & 0x2) 1241198626Srrs break; 1242198626Srrs DELAY(1000); 1243198626Srrs } 1244198157Srrs if (i == maxloops) 1245198157Srrs return -1; 1246198157Srrs 1247198626Srrs /* Issue a soft reset */ 1248198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1249198626Srrs val |= 0x4; 1250198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1251198626Srrs 1252198626Srrs /* wait for reset to complete */ 1253198626Srrs for (i = 0; i < maxloops; i++) { 1254198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1255198626Srrs if (val & 0x8) 1256198626Srrs break; 1257198626Srrs DELAY(1000); 1258198626Srrs } 1259198157Srrs if (i == maxloops) 1260198157Srrs return -1; 1261198157Srrs 1262198626Srrs /* Clear the soft reset bit */ 1263198626Srrs val = xlr_read_reg(mmio, R_RX_CONTROL); 1264198626Srrs val &= ~0x4; 1265198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, val); 1266198157Srrs return 0; 1267198157Srrs} 1268198157Srrs 1269198626Srrsstatic void 1270198157Srrsrmi_xlr_gmac_init(struct driver_data *priv) 1271198157Srrs{ 1272198626Srrs int i = 0; 1273198626Srrs xlr_reg_t *mmio = priv->mmio; 1274198626Srrs int id = priv->instance; 1275198157Srrs struct stn_cc *gmac_cc_config; 1276198626Srrs uint32_t value = 0; 1277198626Srrs int blk = id / 4, port = id % 4; 1278198157Srrs 1279198157Srrs rmi_xlr_mac_set_enable(priv, 0); 1280198157Srrs 1281198157Srrs rmi_xlr_config_spill_area(priv); 1282198157Srrs 1283198157Srrs xlr_write_reg(mmio, R_DESC_PACK_CTRL, 1284198626Srrs (BYTE_OFFSET << O_DESC_PACK_CTRL__ByteOffset) | 1285198626Srrs (1 << O_DESC_PACK_CTRL__MaxEntry) | 1286198626Srrs (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize)); 1287198157Srrs 1288198157Srrs rmi_xlr_config_pde(priv); 1289198157Srrs rmi_xlr_config_parser(priv); 1290198157Srrs rmi_xlr_config_classifier(priv); 1291198157Srrs 1292198157Srrs xlr_write_reg(mmio, R_MSG_TX_THRESHOLD, 3); 1293198157Srrs xlr_write_reg(mmio, R_MAC_CONFIG_1, 0x35); 1294198626Srrs xlr_write_reg(mmio, R_RX_CONTROL, (0x7 << 6)); 1295198157Srrs 1296198626Srrs if (priv->mode == XLR_PORT0_RGMII) { 1297198157Srrs printf("Port 0 set in RGMII mode\n"); 1298198157Srrs value = xlr_read_reg(mmio, R_RX_CONTROL); 1299198157Srrs value |= 1 << O_RX_CONTROL__RGMII; 1300198157Srrs xlr_write_reg(mmio, R_RX_CONTROL, value); 1301198157Srrs } 1302198157Srrs rmi_xlr_mac_mii_init(priv); 1303198157Srrs 1304198626Srrs 1305198157Srrs#if 0 1306198157Srrs priv->advertising = ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half | 1307198626Srrs ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half | 1308198626Srrs ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | 1309198626Srrs ADVERTISED_MII; 1310198157Srrs#endif 1311198157Srrs 1312198157Srrs /* 1313198157Srrs * Enable all MDIO interrupts in the phy RX_ER bit seems to be get 1314198157Srrs * set about every 1 sec in GigE mode, ignore it for now... 1315198157Srrs */ 1316198157Srrs rge_mii_write_internal(priv->mii_mmio, priv->phy_addr, 25, 0xfffffffe); 1317198157Srrs 1318198626Srrs if (priv->mode != XLR_RGMII) { 1319198157Srrs serdes_regs_init(priv); 1320198157Srrs serdes_autoconfig(priv); 1321198157Srrs } 1322198626Srrs rmi_xlr_gmac_config_speed(priv); 1323198157Srrs 1324198157Srrs value = xlr_read_reg(mmio, R_IPG_IFG); 1325198157Srrs xlr_write_reg(mmio, R_IPG_IFG, ((value & ~0x7f) | MAC_B2B_IPG)); 1326198157Srrs xlr_write_reg(mmio, R_DMACR0, 0xffffffff); 1327198157Srrs xlr_write_reg(mmio, R_DMACR1, 0xffffffff); 1328198157Srrs xlr_write_reg(mmio, R_DMACR2, 0xffffffff); 1329198157Srrs xlr_write_reg(mmio, R_DMACR3, 0xffffffff); 1330198157Srrs xlr_write_reg(mmio, R_STATCTRL, 0x04); 1331198157Srrs xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff); 1332198157Srrs xlr_write_reg(mmio, R_INTMASK, 0); 1333198157Srrs xlr_write_reg(mmio, R_FREEQCARVE, 0); 1334198157Srrs 1335198157Srrs xlr_write_reg(mmio, R_GMAC_TX0_BUCKET_SIZE + port, 1336198626Srrs xlr_board_info.bucket_sizes->bucket[priv->txbucket]); 1337198157Srrs xlr_write_reg(mmio, R_GMAC_JFR0_BUCKET_SIZE, 1338198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_0]); 1339198157Srrs xlr_write_reg(mmio, R_GMAC_RFR0_BUCKET_SIZE, 1340198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_0]); 1341198157Srrs xlr_write_reg(mmio, R_GMAC_JFR1_BUCKET_SIZE, 1342198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_1]); 1343198157Srrs xlr_write_reg(mmio, R_GMAC_RFR1_BUCKET_SIZE, 1344198626Srrs xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_1]); 1345198157Srrs 1346198157Srrs dbg_msg("Programming credit counter %d : %d -> %d\n", blk, R_GMAC_TX0_BUCKET_SIZE + port, 1347198626Srrs xlr_board_info.bucket_sizes->bucket[priv->txbucket]); 1348198157Srrs 1349198157Srrs gmac_cc_config = xlr_board_info.gmac_block[blk].credit_config; 1350198157Srrs for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) { 1351198157Srrs xlr_write_reg(mmio, R_CC_CPU0_0 + i, 1352198626Srrs gmac_cc_config->counters[i >> 3][i & 0x07]); 1353198157Srrs dbg_msg("%d: %d -> %d\n", priv->instance, 1354198626Srrs R_CC_CPU0_0 + i, gmac_cc_config->counters[i >> 3][i & 0x07]); 1355198157Srrs } 1356198157Srrs priv->init_frin_desc = 1; 1357198157Srrs} 1358198157Srrs 1359198157Srrs/********************************************************************** 1360198157Srrs * Set promiscuous mode 1361198157Srrs **********************************************************************/ 1362198626Srrsstatic void 1363198157Srrsxlr_mac_set_rx_mode(struct rge_softc *sc) 1364198157Srrs{ 1365198157Srrs struct driver_data *priv = &(sc->priv); 1366198626Srrs uint32_t regval; 1367198157Srrs 1368198157Srrs regval = xlr_read_reg(priv->mmio, R_MAC_FILTER_CONFIG); 1369198626Srrs 1370198157Srrs if (sc->flags & IFF_PROMISC) { 1371198157Srrs regval |= (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) | 1372198626Srrs (1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) | 1373198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) | 1374198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN); 1375198157Srrs } else { 1376198157Srrs regval &= ~((1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) | 1377198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN)); 1378198157Srrs } 1379198157Srrs 1380198157Srrs xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG, regval); 1381198157Srrs} 1382198157Srrs 1383198157Srrs/********************************************************************** 1384198157Srrs * Configure LAN speed for the specified MAC. 1385198157Srrs ********************************************************************* */ 1386198626Srrsstatic int 1387198157Srrsrmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed) 1388198157Srrs{ 1389198157Srrs return 0; 1390198157Srrs} 1391198157Srrs 1392198157Srrs/********************************************************************** 1393198157Srrs * Set Ethernet duplex and flow control options for this MAC 1394198157Srrs ********************************************************************* */ 1395198626Srrsstatic int 1396198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s, 1397198626Srrs xlr_mac_duplex_t duplex, xlr_mac_fc_t fc) 1398198157Srrs{ 1399198157Srrs return 0; 1400198157Srrs} 1401198157Srrs 1402198157Srrs/***************************************************************** 1403198157Srrs * Kernel Net Stack <-> MAC Driver Interface 1404198157Srrs *****************************************************************/ 1405198157Srrs/********************************************************************** 1406198157Srrs **********************************************************************/ 1407198157Srrs#define MAC_TX_FAIL 2 1408198157Srrs#define MAC_TX_PASS 0 1409198157Srrs#define MAC_TX_RETRY 1 1410198157Srrs 1411198626Srrsint xlr_dev_queue_xmit_hack = 0; 1412198157Srrs 1413198626Srrsstatic int 1414198157Srrsmac_xmit(struct mbuf *m, struct rge_softc *sc, 1415198626Srrs struct driver_data *priv, int len, struct p2d_tx_desc *tx_desc) 1416198157Srrs{ 1417212321Sjchandra struct msgrng_msg msg = {0,0,0,0}; 1418198626Srrs int stid = priv->txbucket; 1419198626Srrs uint32_t tx_cycles = 0; 1420212321Sjchandra uint32_t mflags; 1421208369Sjchandra int vcpu = xlr_cpu_id(); 1422198157Srrs int rv; 1423198157Srrs 1424198157Srrs tx_cycles = mips_rd_count(); 1425198157Srrs 1426198157Srrs if (build_frag_list(m, &msg, tx_desc) != 0) 1427198157Srrs return MAC_TX_FAIL; 1428198157Srrs 1429198157Srrs else { 1430212321Sjchandra mflags = msgrng_access_enable(); 1431212553Sjchandra if ((rv = message_send(1, MSGRNG_CODE_MAC, stid, &msg)) != 0) { 1432198157Srrs msg_snd_failed++; 1433212321Sjchandra msgrng_restore(mflags); 1434198157Srrs release_tx_desc(&msg, 0); 1435198157Srrs xlr_rge_msg_snd_failed[vcpu]++; 1436209808Sjchandra dbg_msg("Failed packet to cpu %d, rv = %d, stid %d, msg0=%jx\n", 1437209808Sjchandra vcpu, rv, stid, (uintmax_t)msg.msg0); 1438198157Srrs return MAC_TX_FAIL; 1439198157Srrs } 1440212321Sjchandra msgrng_restore(mflags); 1441198157Srrs port_inc_counter(priv->instance, PORT_TX); 1442198157Srrs } 1443198157Srrs 1444198157Srrs /* Send the packet to MAC */ 1445209808Sjchandra dbg_msg("Sent tx packet to stid %d, msg0=%jx, msg1=%jx \n", stid, 1446209808Sjchandra (uintmax_t)msg.msg0, (uintmax_t)msg.msg1); 1447198157Srrs#ifdef DUMP_PACKETS 1448198157Srrs { 1449198626Srrs int i = 0; 1450198626Srrs unsigned char *buf = (char *)m->m_data; 1451198626Srrs 1452198157Srrs printf("Tx Packet: length=%d\n", len); 1453198157Srrs for (i = 0; i < 64; i++) { 1454198157Srrs if (i && (i % 16) == 0) 1455198157Srrs printf("\n"); 1456198157Srrs printf("%02x ", buf[i]); 1457198157Srrs } 1458198157Srrs printf("\n"); 1459198157Srrs } 1460198157Srrs#endif 1461198157Srrs xlr_inc_counter(NETIF_TX); 1462198157Srrs return MAC_TX_PASS; 1463198157Srrs} 1464198157Srrs 1465198626Srrsstatic int 1466198157Srrsrmi_xlr_mac_xmit(struct mbuf *m, struct rge_softc *sc, int len, struct p2d_tx_desc *tx_desc) 1467198157Srrs{ 1468198157Srrs struct driver_data *priv = &(sc->priv); 1469198626Srrs int ret = -ENOSPC; 1470198157Srrs 1471198157Srrs dbg_msg("IN\n"); 1472198157Srrs 1473198157Srrs xlr_inc_counter(NETIF_STACK_TX); 1474198157Srrs 1475198157Srrsretry: 1476198157Srrs ret = mac_xmit(m, sc, priv, len, tx_desc); 1477198157Srrs 1478198157Srrs if (ret == MAC_TX_RETRY) 1479198157Srrs goto retry; 1480198157Srrs 1481198157Srrs dbg_msg("OUT, ret = %d\n", ret); 1482198157Srrs if (ret == MAC_TX_FAIL) { 1483198157Srrs /* FULL */ 1484198157Srrs dbg_msg("Msg Ring Full. Stopping upper layer Q\n"); 1485198157Srrs port_inc_counter(priv->instance, PORT_STOPQ); 1486198157Srrs } 1487198157Srrs return ret; 1488198157Srrs} 1489198157Srrs 1490198626Srrsstatic void 1491198157Srrsmac_frin_replenish(void *args /* ignored */ ) 1492198157Srrs{ 1493208165Srrs int cpu = xlr_core_id(); 1494198626Srrs int done = 0; 1495198626Srrs int i = 0; 1496198157Srrs 1497198157Srrs xlr_inc_counter(REPLENISH_ENTER); 1498198157Srrs /* 1499198157Srrs * xlr_set_counter(REPLENISH_ENTER_COUNT, 1500198157Srrs * atomic_read(frin_to_be_sent)); 1501198157Srrs */ 1502198157Srrs xlr_set_counter(REPLENISH_CPU, PCPU_GET(cpuid)); 1503198157Srrs 1504198157Srrs for (;;) { 1505198157Srrs 1506198157Srrs done = 0; 1507198157Srrs 1508198157Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 1509198157Srrs /* int offset = 0; */ 1510198626Srrs void *m; 1511198626Srrs uint32_t cycles; 1512198157Srrs struct rge_softc *sc; 1513198157Srrs struct driver_data *priv; 1514198626Srrs int frin_to_be_sent; 1515198157Srrs 1516198157Srrs sc = dev_mac[i]; 1517198157Srrs if (!sc) 1518198157Srrs goto skip; 1519198157Srrs 1520198157Srrs priv = &(sc->priv); 1521198157Srrs frin_to_be_sent = priv->frin_to_be_sent[cpu]; 1522198157Srrs 1523198157Srrs /* if (atomic_read(frin_to_be_sent) < 0) */ 1524198157Srrs if (frin_to_be_sent < 0) { 1525198626Srrs panic("BUG?: [%s]: gmac_%d illegal value for frin_to_be_sent=%d\n", 1526198626Srrs __FUNCTION__, i, 1527198626Srrs frin_to_be_sent); 1528198157Srrs } 1529198157Srrs /* if (!atomic_read(frin_to_be_sent)) */ 1530198157Srrs if (!frin_to_be_sent) 1531198157Srrs goto skip; 1532198157Srrs 1533198157Srrs cycles = mips_rd_count(); 1534198157Srrs { 1535198157Srrs m = get_buf(); 1536198157Srrs if (!m) { 1537198157Srrs device_printf(sc->rge_dev, "No buffer\n"); 1538198157Srrs goto skip; 1539198157Srrs } 1540198157Srrs } 1541198157Srrs xlr_inc_counter(REPLENISH_FRIN); 1542198157Srrs if (xlr_mac_send_fr(priv, vtophys(m), MAX_FRAME_SIZE)) { 1543198157Srrs free_buf(vtophys(m)); 1544198157Srrs printf("[%s]: rx free message_send failed!\n", __FUNCTION__); 1545198157Srrs break; 1546198157Srrs } 1547198157Srrs xlr_set_counter(REPLENISH_CYCLES, 1548198626Srrs (read_c0_count() - cycles)); 1549198157Srrs atomic_subtract_int((&priv->frin_to_be_sent[cpu]), 1); 1550198157Srrs 1551198157Srrs continue; 1552198157Srrs skip: 1553198157Srrs done++; 1554198157Srrs } 1555198157Srrs if (done == XLR_MAX_MACS) 1556198157Srrs break; 1557198157Srrs } 1558198157Srrs} 1559198157Srrs 1560203010Srrsstatic volatile uint32_t g_tx_frm_tx_ok=0; 1561198157Srrs 1562198626Srrsstatic void 1563198157Srrsrge_tx_bkp_func(void *arg, int npending) 1564198157Srrs{ 1565198626Srrs int i = 0; 1566198626Srrs 1567198626Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 1568198157Srrs if (!dev_mac[i] || !dev_mac[i]->active) 1569198157Srrs continue; 1570198157Srrs rge_start_locked(dev_mac[i]->rge_ifp, RGE_TX_THRESHOLD); 1571198157Srrs } 1572198157Srrs atomic_subtract_int(&g_tx_frm_tx_ok, 1); 1573198157Srrs} 1574198157Srrs 1575198157Srrs/* This function is called from an interrupt handler */ 1576198626Srrsvoid 1577198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code, 1578198626Srrs int stid, struct msgrng_msg *msg, 1579198626Srrs void *data /* ignored */ ) 1580198157Srrs{ 1581198626Srrs uint64_t phys_addr = 0; 1582198626Srrs unsigned long addr = 0; 1583198626Srrs uint32_t length = 0; 1584198626Srrs int ctrl = 0, port = 0; 1585198157Srrs struct rge_softc *sc = NULL; 1586198157Srrs struct driver_data *priv = 0; 1587198626Srrs struct ifnet *ifp; 1588208165Srrs int vcpu = xlr_cpu_id(); 1589208165Srrs int cpu = xlr_core_id(); 1590198157Srrs 1591209808Sjchandra dbg_msg("mac: bucket=%d, size=%d, code=%d, stid=%d, msg0=%jx msg1=%jx\n", 1592209808Sjchandra bucket, size, code, stid, (uintmax_t)msg->msg0, (uintmax_t)msg->msg1); 1593198157Srrs 1594198157Srrs phys_addr = (uint64_t) (msg->msg0 & 0xffffffffe0ULL); 1595198157Srrs length = (msg->msg0 >> 40) & 0x3fff; 1596198157Srrs if (length == 0) { 1597198157Srrs ctrl = CTRL_REG_FREE; 1598198157Srrs port = (msg->msg0 >> 54) & 0x0f; 1599198157Srrs addr = 0; 1600198157Srrs } else { 1601198157Srrs ctrl = CTRL_SNGL; 1602198157Srrs length = length - BYTE_OFFSET - MAC_CRC_LEN; 1603198157Srrs port = msg->msg0 & 0x0f; 1604198157Srrs addr = 0; 1605198157Srrs } 1606198157Srrs 1607198157Srrs if (xlr_board_info.is_xls) { 1608198157Srrs if (stid == MSGRNG_STNID_GMAC1) 1609198157Srrs port += 4; 1610198157Srrs sc = dev_mac[dev_mac_gmac0 + port]; 1611198157Srrs } else { 1612198157Srrs if (stid == MSGRNG_STNID_XGS0FR) 1613198157Srrs sc = dev_mac[dev_mac_xgs0]; 1614198157Srrs else if (stid == MSGRNG_STNID_XGS1FR) 1615198157Srrs sc = dev_mac[dev_mac_xgs0 + 1]; 1616198626Srrs else 1617198157Srrs sc = dev_mac[dev_mac_gmac0 + port]; 1618198157Srrs } 1619198157Srrs if (sc == NULL) 1620198157Srrs return; 1621198157Srrs priv = &(sc->priv); 1622198157Srrs 1623209808Sjchandra dbg_msg("msg0 = %jx, stid = %d, port = %d, addr=%lx, length=%d, ctrl=%d\n", 1624209808Sjchandra (uintmax_t)msg->msg0, stid, port, addr, length, ctrl); 1625198157Srrs 1626198157Srrs if (ctrl == CTRL_REG_FREE || ctrl == CTRL_JUMBO_FREE) { 1627198157Srrs xlr_rge_tx_ok_done[vcpu]++; 1628198157Srrs release_tx_desc(msg, 1); 1629198157Srrs ifp = sc->rge_ifp; 1630198626Srrs if (ifp->if_drv_flags & IFF_DRV_OACTIVE) { 1631198157Srrs ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1632198157Srrs } 1633198626Srrs if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1)) 1634198626Srrs rge_tx_bkp_func(NULL, 0); 1635198157Srrs xlr_set_counter(NETIF_TX_COMPLETE_CYCLES, 1636198626Srrs (read_c0_count() - msgrng_msg_cycles)); 1637198157Srrs } else if (ctrl == CTRL_SNGL || ctrl == CTRL_START) { 1638198157Srrs /* Rx Packet */ 1639198157Srrs /* struct mbuf *m = 0; */ 1640198157Srrs /* int logical_cpu = 0; */ 1641198157Srrs 1642198157Srrs dbg_msg("Received packet, port = %d\n", port); 1643198157Srrs /* 1644198157Srrs * if num frins to be sent exceeds threshold, wake up the 1645198157Srrs * helper thread 1646198157Srrs */ 1647198157Srrs atomic_add_int(&(priv->frin_to_be_sent[cpu]), 1); 1648198157Srrs if ((priv->frin_to_be_sent[cpu]) > MAC_FRIN_TO_BE_SENT_THRESHOLD) { 1649198157Srrs mac_frin_replenish(NULL); 1650198157Srrs } 1651209808Sjchandra dbg_msg("gmac_%d: rx packet: phys_addr = %jx, length = %x\n", 1652209808Sjchandra priv->instance, (uintmax_t)phys_addr, length); 1653198157Srrs mac_stats_add(priv->stats.rx_packets, 1); 1654198157Srrs mac_stats_add(priv->stats.rx_bytes, length); 1655198157Srrs xlr_inc_counter(NETIF_RX); 1656198157Srrs xlr_set_counter(NETIF_RX_CYCLES, 1657198626Srrs (read_c0_count() - msgrng_msg_cycles)); 1658198157Srrs rge_rx(sc, phys_addr, length); 1659198157Srrs xlr_rge_rx_done[vcpu]++; 1660198157Srrs } else { 1661198157Srrs printf("[%s]: unrecognized ctrl=%d!\n", __FUNCTION__, ctrl); 1662198157Srrs } 1663198157Srrs 1664198157Srrs} 1665198157Srrs 1666198157Srrs/********************************************************************** 1667198157Srrs **********************************************************************/ 1668198157Srrsstatic int 1669198157Srrsrge_probe(dev) 1670198626Srrs device_t dev; 1671198157Srrs{ 1672208265Srpaulo device_set_desc(dev, "RMI Gigabit Ethernet"); 1673208265Srpaulo 1674198157Srrs /* Always return 0 */ 1675198157Srrs return 0; 1676198157Srrs} 1677198157Srrs 1678198157Srrsvolatile unsigned long xlr_debug_enabled; 1679198626Srrsstruct callout rge_dbg_count; 1680199139Srrsstatic void 1681198626Srrsxlr_debug_count(void *addr) 1682198157Srrs{ 1683198157Srrs struct driver_data *priv = &dev_mac[0]->priv; 1684198626Srrs 1685198626Srrs /* uint32_t crdt; */ 1686198626Srrs if (xlr_debug_enabled) { 1687198626Srrs printf("\nAvailRxIn %#x\n", xlr_read_reg(priv->mmio, 0x23e)); 1688198157Srrs } 1689198157Srrs callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL); 1690198157Srrs} 1691198157Srrs 1692198157Srrs 1693199139Srrsstatic void 1694198626Srrsxlr_tx_q_wakeup(void *addr) 1695198157Srrs{ 1696198626Srrs int i = 0; 1697198626Srrs int j = 0; 1698198626Srrs 1699198626Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 1700198157Srrs if (!dev_mac[i] || !dev_mac[i]->active) 1701198157Srrs continue; 1702198626Srrs if ((dev_mac[i]->rge_ifp->if_drv_flags) & IFF_DRV_OACTIVE) { 1703198626Srrs for (j = 0; j < XLR_MAX_CORE; j++) { 1704198626Srrs if (xlr_tot_avail_p2d[j]) { 1705198157Srrs dev_mac[i]->rge_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1706198157Srrs break; 1707198157Srrs } 1708198157Srrs } 1709198157Srrs } 1710198157Srrs } 1711203010Srrs if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1)) 1712203010Srrs rge_tx_bkp_func(NULL, 0); 1713198626Srrs callout_reset(&xlr_tx_stop_bkp, 5 * hz, xlr_tx_q_wakeup, NULL); 1714198157Srrs} 1715198157Srrs 1716198157Srrsstatic int 1717198608Srrsrge_attach(device_t dev) 1718198157Srrs{ 1719198626Srrs struct ifnet *ifp; 1720198157Srrs struct rge_softc *sc; 1721198157Srrs struct driver_data *priv = 0; 1722198626Srrs int ret = 0; 1723198157Srrs struct xlr_gmac_block_t *gmac_conf = device_get_ivars(dev); 1724198157Srrs 1725198157Srrs sc = device_get_softc(dev); 1726198157Srrs sc->rge_dev = dev; 1727198157Srrs 1728198157Srrs /* Initialize mac's */ 1729198157Srrs sc->unit = device_get_unit(dev); 1730198157Srrs 1731198157Srrs if (sc->unit > XLR_MAX_MACS) { 1732198157Srrs ret = ENXIO; 1733198157Srrs goto out; 1734198157Srrs } 1735198157Srrs RGE_LOCK_INIT(sc, device_get_nameunit(dev)); 1736198157Srrs 1737198157Srrs priv = &(sc->priv); 1738198157Srrs priv->sc = sc; 1739198157Srrs 1740198157Srrs sc->flags = 0; /* TODO : fix me up later */ 1741198157Srrs 1742198157Srrs priv->id = sc->unit; 1743198157Srrs if (gmac_conf->type == XLR_GMAC) { 1744198157Srrs priv->instance = priv->id; 1745198626Srrs priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr + 1746198626Srrs 0x1000 * (sc->unit % 4)); 1747198157Srrs if ((ret = rmi_xlr_gmac_reset(priv)) == -1) 1748198157Srrs goto out; 1749198157Srrs } else if (gmac_conf->type == XLR_XGMAC) { 1750198157Srrs priv->instance = priv->id - xlr_board_info.gmacports; 1751198157Srrs priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr); 1752198157Srrs } 1753209318Sjchandra if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI || 1754209318Sjchandra (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI && 1755209318Sjchandra priv->instance >=4)) { 1756198157Srrs dbg_msg("Arizona board - offset 4 \n"); 1757198626Srrs priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_4_OFFSET); 1758198157Srrs } else 1759198626Srrs priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET); 1760198157Srrs 1761198626Srrs priv->pcs_mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr); 1762198626Srrs priv->serdes_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET); 1763198157Srrs 1764198626Srrs sc->base_addr = (unsigned long)priv->mmio; 1765198626Srrs sc->mem_end = (unsigned long)priv->mmio + XLR_IO_SIZE - 1; 1766198157Srrs 1767198157Srrs sc->xmit = rge_start; 1768198157Srrs sc->stop = rge_stop; 1769198157Srrs sc->get_stats = rmi_xlr_mac_get_stats; 1770198157Srrs sc->ioctl = rge_ioctl; 1771198157Srrs 1772198157Srrs /* Initialize the device specific driver data */ 1773198157Srrs mtx_init(&priv->lock, "rge", NULL, MTX_SPIN); 1774198157Srrs 1775198157Srrs priv->type = gmac_conf->type; 1776198157Srrs 1777198157Srrs priv->mode = gmac_conf->mode; 1778198157Srrs if (xlr_board_info.is_xls == 0) { 1779209318Sjchandra /* TODO - check II and IIB boards */ 1780209318Sjchandra if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_II && 1781209318Sjchandra xlr_boot1_info.board_minor_version != 1) 1782198157Srrs priv->phy_addr = priv->instance - 2; 1783198157Srrs else 1784198157Srrs priv->phy_addr = priv->instance; 1785198157Srrs priv->mode = XLR_RGMII; 1786198626Srrs } else { 1787198157Srrs if (gmac_conf->mode == XLR_PORT0_RGMII && 1788198626Srrs priv->instance == 0) { 1789198626Srrs priv->mode = XLR_PORT0_RGMII; 1790198157Srrs priv->phy_addr = 0; 1791198626Srrs } else { 1792198626Srrs priv->mode = XLR_SGMII; 1793209318Sjchandra /* Board 11 has SGMII daughter cards with the XLS chips, in this case 1794209318Sjchandra the phy number is 0-3 for both GMAC blocks */ 1795209318Sjchandra if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI) 1796209318Sjchandra priv->phy_addr = priv->instance % 4 + 16; 1797209318Sjchandra else 1798209318Sjchandra priv->phy_addr = priv->instance + 16; 1799198157Srrs } 1800198157Srrs } 1801198157Srrs 1802198157Srrs priv->txbucket = gmac_conf->station_txbase + priv->instance % 4; 1803198626Srrs priv->rfrbucket = gmac_conf->station_rfr; 1804198157Srrs priv->spill_configured = 0; 1805198157Srrs 1806198157Srrs dbg_msg("priv->mmio=%p\n", priv->mmio); 1807198157Srrs 1808198157Srrs /* Set up ifnet structure */ 1809198157Srrs ifp = sc->rge_ifp = if_alloc(IFT_ETHER); 1810198157Srrs if (ifp == NULL) { 1811198157Srrs device_printf(sc->rge_dev, "failed to if_alloc()\n"); 1812198157Srrs rge_release_resources(sc); 1813198157Srrs ret = ENXIO; 1814198157Srrs RGE_LOCK_DESTROY(sc); 1815198157Srrs goto out; 1816198157Srrs } 1817198157Srrs ifp->if_softc = sc; 1818198157Srrs if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1819198157Srrs ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1820198157Srrs ifp->if_ioctl = rge_ioctl; 1821198157Srrs ifp->if_start = rge_start; 1822198157Srrs ifp->if_init = rge_init; 1823198157Srrs ifp->if_mtu = ETHERMTU; 1824198157Srrs ifp->if_snd.ifq_drv_maxlen = RGE_TX_Q_SIZE; 1825198157Srrs IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 1826198157Srrs IFQ_SET_READY(&ifp->if_snd); 1827198157Srrs sc->active = 1; 1828198626Srrs ifp->if_hwassist = 0; 1829198626Srrs ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING; 1830198157Srrs ifp->if_capenable = ifp->if_capabilities; 1831198157Srrs 1832198157Srrs /* Initialize the rge_softc */ 1833198157Srrs sc->irq = gmac_conf->baseirq + priv->instance % 4; 1834198157Srrs 1835198608Srrs /* Set the IRQ into the rid field */ 1836199139Srrs /* 1837199139Srrs * note this is a hack to pass the irq to the iodi interrupt setup 1838199139Srrs * routines 1839199139Srrs */ 1840209808Sjchandra sc->rge_irq.__r_i = (struct resource_i *)(intptr_t)sc->irq; 1841198608Srrs 1842217072Sjhb ret = bus_setup_intr(dev, &sc->rge_irq, INTR_TYPE_NET | INTR_MPSAFE, 1843198626Srrs NULL, rge_intr, sc, &sc->rge_intrhand); 1844198157Srrs 1845198157Srrs if (ret) { 1846198157Srrs rge_detach(dev); 1847198157Srrs device_printf(sc->rge_dev, "couldn't set up irq\n"); 1848198157Srrs RGE_LOCK_DESTROY(sc); 1849198157Srrs goto out; 1850198157Srrs } 1851198157Srrs xlr_mac_get_hwaddr(sc); 1852198157Srrs xlr_mac_setup_hwaddr(priv); 1853198157Srrs 1854198157Srrs dbg_msg("MMIO %08lx, MII %08lx, PCS %08lx, base %08lx PHY %d IRQ %d\n", 1855198626Srrs (u_long)priv->mmio, (u_long)priv->mii_mmio, (u_long)priv->pcs_mmio, 1856198626Srrs (u_long)sc->base_addr, priv->phy_addr, sc->irq); 1857198626Srrs dbg_msg("HWADDR %02x:%02x tx %d rfr %d\n", (u_int)sc->dev_addr[4], 1858198626Srrs (u_int)sc->dev_addr[5], priv->txbucket, priv->rfrbucket); 1859198157Srrs 1860198157Srrs /* 1861198157Srrs * Set up ifmedia support. 1862198157Srrs */ 1863198157Srrs /* 1864198157Srrs * Initialize MII/media info. 1865198157Srrs */ 1866198157Srrs sc->rge_mii.mii_ifp = ifp; 1867198157Srrs sc->rge_mii.mii_readreg = rge_mii_read; 1868198626Srrs sc->rge_mii.mii_writereg = (mii_writereg_t) rge_mii_write; 1869198157Srrs sc->rge_mii.mii_statchg = rmi_xlr_mac_mii_statchg; 1870198157Srrs ifmedia_init(&sc->rge_mii.mii_media, 0, rmi_xlr_mac_mediachange, 1871198626Srrs rmi_xlr_mac_mediastatus); 1872198157Srrs ifmedia_add(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL); 1873198157Srrs ifmedia_set(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO); 1874198157Srrs sc->rge_mii.mii_media.ifm_media = sc->rge_mii.mii_media.ifm_cur->ifm_media; 1875198157Srrs 1876198157Srrs /* 1877198157Srrs * Call MI attach routine. 1878198157Srrs */ 1879198157Srrs ether_ifattach(ifp, sc->dev_addr); 1880198157Srrs 1881198157Srrs if (priv->type == XLR_GMAC) { 1882198157Srrs rmi_xlr_gmac_init(priv); 1883198157Srrs } else if (priv->type == XLR_XGMAC) { 1884198157Srrs rmi_xlr_xgmac_init(priv); 1885198157Srrs } 1886198157Srrs dbg_msg("rge_%d: Phoenix Mac at 0x%p (mtu=%d)\n", 1887198626Srrs sc->unit, priv->mmio, sc->mtu); 1888198157Srrs dev_mac[sc->unit] = sc; 1889198157Srrs if (priv->type == XLR_XGMAC && priv->instance == 0) 1890198157Srrs dev_mac_xgs0 = sc->unit; 1891198157Srrs if (priv->type == XLR_GMAC && priv->instance == 0) 1892198157Srrs dev_mac_gmac0 = sc->unit; 1893198157Srrs 1894198626Srrs if (!gmac_common_init_done) { 1895198157Srrs mac_common_init(); 1896198157Srrs gmac_common_init_done = 1; 1897314667Savg callout_init(&xlr_tx_stop_bkp, 1); 1898198157Srrs callout_reset(&xlr_tx_stop_bkp, hz, xlr_tx_q_wakeup, NULL); 1899314667Savg callout_init(&rge_dbg_count, 1); 1900198626Srrs //callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL); 1901198157Srrs } 1902198157Srrs if ((ret = rmi_xlr_mac_open(sc)) == -1) { 1903198157Srrs RGE_LOCK_DESTROY(sc); 1904198157Srrs goto out; 1905198157Srrs } 1906198157Srrsout: 1907198157Srrs if (ret < 0) { 1908198157Srrs device_printf(dev, "error - skipping\n"); 1909198157Srrs } 1910198157Srrs return ret; 1911198157Srrs} 1912198157Srrs 1913198626Srrsstatic void 1914198157Srrsrge_reset(struct rge_softc *sc) 1915198157Srrs{ 1916198157Srrs} 1917198157Srrs 1918198157Srrsstatic int 1919198157Srrsrge_detach(dev) 1920198626Srrs device_t dev; 1921198157Srrs{ 1922198157Srrs#ifdef FREEBSD_MAC_NOT_YET 1923198157Srrs struct rge_softc *sc; 1924198626Srrs struct ifnet *ifp; 1925198157Srrs 1926198157Srrs sc = device_get_softc(dev); 1927198157Srrs ifp = sc->rge_ifp; 1928198157Srrs 1929198157Srrs RGE_LOCK(sc); 1930198157Srrs rge_stop(sc); 1931198157Srrs rge_reset(sc); 1932198157Srrs RGE_UNLOCK(sc); 1933198157Srrs 1934198157Srrs ether_ifdetach(ifp); 1935198157Srrs 1936198157Srrs if (sc->rge_tbi) { 1937198157Srrs ifmedia_removeall(&sc->rge_ifmedia); 1938198157Srrs } else { 1939198157Srrs bus_generic_detach(dev); 1940198157Srrs device_delete_child(dev, sc->rge_miibus); 1941198157Srrs } 1942198157Srrs 1943198157Srrs rge_release_resources(sc); 1944198157Srrs 1945198157Srrs#endif /* FREEBSD_MAC_NOT_YET */ 1946198157Srrs return (0); 1947198157Srrs} 1948198626Srrsstatic int 1949198157Srrsrge_suspend(device_t dev) 1950198157Srrs{ 1951198157Srrs struct rge_softc *sc; 1952198157Srrs 1953198157Srrs sc = device_get_softc(dev); 1954198157Srrs RGE_LOCK(sc); 1955198157Srrs rge_stop(sc); 1956198157Srrs RGE_UNLOCK(sc); 1957198157Srrs 1958198157Srrs return 0; 1959198157Srrs} 1960198157Srrs 1961198626Srrsstatic int 1962198157Srrsrge_resume(device_t dev) 1963198157Srrs{ 1964198157Srrs panic("rge_resume(): unimplemented\n"); 1965198157Srrs return 0; 1966198157Srrs} 1967198157Srrs 1968198626Srrsstatic void 1969198157Srrsrge_release_resources(struct rge_softc *sc) 1970198157Srrs{ 1971198157Srrs 1972198157Srrs if (sc->rge_ifp != NULL) 1973198157Srrs if_free(sc->rge_ifp); 1974198157Srrs 1975198157Srrs if (mtx_initialized(&sc->rge_mtx)) /* XXX */ 1976198157Srrs RGE_LOCK_DESTROY(sc); 1977198157Srrs} 1978198626Srrsuint32_t gmac_rx_fail[32]; 1979198626Srrsuint32_t gmac_rx_pass[32]; 1980198157Srrs 1981198626Srrsstatic void 1982198157Srrsrge_rx(struct rge_softc *sc, vm_paddr_t paddr, int len) 1983198157Srrs{ 1984198626Srrs struct mbuf *m; 1985198626Srrs struct ifnet *ifp = sc->rge_ifp; 1986212758Sjchandra uint64_t mag; 1987210630Sjchandra uint32_t sr; 1988210630Sjchandra /* 1989210630Sjchandra * On 32 bit machines we use XKPHYS to get the values stores with 1990210630Sjchandra * the mbuf, need to explicitly enable KX. Disable interrupts while 1991210630Sjchandra * KX is enabled to prevent this setting leaking to other code. 1992210630Sjchandra */ 1993208165Srrs sr = xlr_enable_kx(); 1994212758Sjchandra m = (struct mbuf *)(intptr_t)xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE); 1995212758Sjchandra mag = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE + sizeof(uint64_t)); 1996212758Sjchandra xlr_restore_kx(sr); 1997198157Srrs if (mag != 0xf00bad) { 1998198157Srrs /* somebody else packet Error - FIXME in intialization */ 1999210630Sjchandra printf("cpu %d: *ERROR* Not my packet paddr %p\n", 2000210630Sjchandra xlr_cpu_id(), (void *)paddr); 2001198157Srrs return; 2002198157Srrs } 2003198157Srrs /* align the data */ 2004198157Srrs m->m_data += BYTE_OFFSET; 2005198157Srrs m->m_pkthdr.len = m->m_len = len; 2006198157Srrs m->m_pkthdr.rcvif = ifp; 2007198157Srrs 2008198157Srrs#ifdef DUMP_PACKETS 2009198157Srrs { 2010198626Srrs int i = 0; 2011198626Srrs unsigned char *buf = (char *)m->m_data; 2012198626Srrs 2013198157Srrs printf("Rx Packet: length=%d\n", len); 2014198157Srrs for (i = 0; i < 64; i++) { 2015198157Srrs if (i && (i % 16) == 0) 2016198157Srrs printf("\n"); 2017198157Srrs printf("%02x ", buf[i]); 2018198157Srrs } 2019198157Srrs printf("\n"); 2020198157Srrs } 2021198157Srrs#endif 2022198157Srrs ifp->if_ipackets++; 2023198157Srrs (*ifp->if_input) (ifp, m); 2024198157Srrs} 2025198626Srrs 2026198626Srrsstatic void 2027198157Srrsrge_intr(void *arg) 2028198157Srrs{ 2029198157Srrs struct rge_softc *sc = (struct rge_softc *)arg; 2030198157Srrs struct driver_data *priv = &(sc->priv); 2031198626Srrs xlr_reg_t *mmio = priv->mmio; 2032198626Srrs uint32_t intreg = xlr_read_reg(mmio, R_INTREG); 2033198157Srrs 2034198157Srrs if (intreg & (1 << O_INTREG__MDInt)) { 2035198626Srrs uint32_t phy_int_status = 0; 2036198626Srrs int i = 0; 2037198157Srrs 2038198157Srrs for (i = 0; i < XLR_MAX_MACS; i++) { 2039198157Srrs struct rge_softc *phy_dev = 0; 2040198157Srrs struct driver_data *phy_priv = 0; 2041198157Srrs 2042198157Srrs phy_dev = dev_mac[i]; 2043198157Srrs if (phy_dev == NULL) 2044198157Srrs continue; 2045198157Srrs 2046198157Srrs phy_priv = &phy_dev->priv; 2047198157Srrs 2048198157Srrs if (phy_priv->type == XLR_XGMAC) 2049198157Srrs continue; 2050198157Srrs 2051198157Srrs phy_int_status = rge_mii_read_internal(phy_priv->mii_mmio, 2052198626Srrs phy_priv->phy_addr, 26); 2053198157Srrs printf("rge%d: Phy addr %d, MII MMIO %lx status %x\n", phy_priv->instance, 2054198626Srrs (int)phy_priv->phy_addr, (u_long)phy_priv->mii_mmio, phy_int_status); 2055198157Srrs rmi_xlr_gmac_config_speed(phy_priv); 2056198157Srrs } 2057198157Srrs } else { 2058198157Srrs printf("[%s]: mac type = %d, instance %d error " 2059198626Srrs "interrupt: INTREG = 0x%08x\n", 2060198626Srrs __FUNCTION__, priv->type, priv->instance, intreg); 2061198157Srrs } 2062198157Srrs 2063198157Srrs /* clear all interrupts and hope to make progress */ 2064198157Srrs xlr_write_reg(mmio, R_INTREG, 0xffffffff); 2065198157Srrs 2066209318Sjchandra /* (not yet) on A0 and B0, xgmac interrupts are routed only to xgs_1 irq */ 2067209318Sjchandra if ((xlr_revision() < 2) && (priv->type == XLR_XGMAC)) { 2068198157Srrs struct rge_softc *xgs0_dev = dev_mac[dev_mac_xgs0]; 2069198157Srrs struct driver_data *xgs0_priv = &xgs0_dev->priv; 2070198626Srrs xlr_reg_t *xgs0_mmio = xgs0_priv->mmio; 2071198626Srrs uint32_t xgs0_intreg = xlr_read_reg(xgs0_mmio, R_INTREG); 2072198157Srrs 2073198157Srrs if (xgs0_intreg) { 2074198157Srrs printf("[%s]: mac type = %d, instance %d error " 2075198626Srrs "interrupt: INTREG = 0x%08x\n", 2076198626Srrs __FUNCTION__, xgs0_priv->type, xgs0_priv->instance, xgs0_intreg); 2077198157Srrs 2078198157Srrs xlr_write_reg(xgs0_mmio, R_INTREG, 0xffffffff); 2079198157Srrs } 2080198157Srrs } 2081198157Srrs} 2082198157Srrs 2083198626Srrsstatic void 2084198157Srrsrge_start_locked(struct ifnet *ifp, int threshold) 2085198157Srrs{ 2086198157Srrs struct rge_softc *sc = ifp->if_softc; 2087198626Srrs struct mbuf *m = NULL; 2088198626Srrs int prepend_pkt = 0; 2089198626Srrs int i = 0; 2090198626Srrs struct p2d_tx_desc *tx_desc = NULL; 2091208165Srrs int cpu = xlr_core_id(); 2092208165Srrs uint32_t vcpu = xlr_cpu_id(); 2093198157Srrs 2094198157Srrs if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 2095198157Srrs return; 2096198157Srrs 2097198626Srrs for (i = 0; i < xlr_tot_avail_p2d[cpu]; i++) { 2098198157Srrs if (IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 2099198157Srrs return; 2100198157Srrs tx_desc = get_p2d_desc(); 2101198626Srrs if (!tx_desc) { 2102198157Srrs xlr_rge_get_p2d_failed[vcpu]++; 2103198157Srrs return; 2104198157Srrs } 2105198157Srrs /* Grab a packet off the queue. */ 2106198157Srrs IFQ_DEQUEUE(&ifp->if_snd, m); 2107198626Srrs if (m == NULL) { 2108198157Srrs free_p2d_desc(tx_desc); 2109198157Srrs return; 2110198157Srrs } 2111198157Srrs prepend_pkt = rmi_xlr_mac_xmit(m, sc, 0, tx_desc); 2112198157Srrs 2113198157Srrs if (prepend_pkt) { 2114198157Srrs xlr_rge_tx_prepend[vcpu]++; 2115198157Srrs IF_PREPEND(&ifp->if_snd, m); 2116198157Srrs ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2117198157Srrs return; 2118198157Srrs } else { 2119198157Srrs ifp->if_opackets++; 2120198157Srrs xlr_rge_tx_done[vcpu]++; 2121198157Srrs } 2122198157Srrs } 2123198157Srrs} 2124198157Srrs 2125198626Srrsstatic void 2126198157Srrsrge_start(struct ifnet *ifp) 2127198157Srrs{ 2128198157Srrs rge_start_locked(ifp, RGE_TX_Q_SIZE); 2129198157Srrs} 2130198157Srrs 2131198626Srrsstatic int 2132198157Srrsrge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 2133198157Srrs{ 2134198157Srrs struct rge_softc *sc = ifp->if_softc; 2135198626Srrs struct ifreq *ifr = (struct ifreq *)data; 2136198626Srrs int mask, error = 0; 2137198626Srrs 2138198157Srrs /* struct mii_data *mii; */ 2139198157Srrs switch (command) { 2140198157Srrs case SIOCSIFMTU: 2141198157Srrs ifp->if_mtu = ifr->ifr_mtu; 2142198157Srrs error = rmi_xlr_mac_change_mtu(sc, ifr->ifr_mtu); 2143198157Srrs break; 2144198157Srrs case SIOCSIFFLAGS: 2145198157Srrs 2146198157Srrs RGE_LOCK(sc); 2147198157Srrs if (ifp->if_flags & IFF_UP) { 2148198157Srrs /* 2149198157Srrs * If only the state of the PROMISC flag changed, 2150198157Srrs * then just use the 'set promisc mode' command 2151198157Srrs * instead of reinitializing the entire NIC. Doing a 2152198157Srrs * full re-init means reloading the firmware and 2153198157Srrs * waiting for it to start up, which may take a 2154198157Srrs * second or two. Similarly for ALLMULTI. 2155198157Srrs */ 2156198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2157198157Srrs ifp->if_flags & IFF_PROMISC && 2158198157Srrs !(sc->flags & IFF_PROMISC)) { 2159198157Srrs sc->flags |= IFF_PROMISC; 2160198157Srrs xlr_mac_set_rx_mode(sc); 2161198157Srrs } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2162198626Srrs !(ifp->if_flags & IFF_PROMISC) && 2163198626Srrs sc->flags & IFF_PROMISC) { 2164198157Srrs sc->flags &= IFF_PROMISC; 2165198157Srrs xlr_mac_set_rx_mode(sc); 2166198157Srrs } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && 2167198626Srrs (ifp->if_flags ^ sc->flags) & IFF_ALLMULTI) { 2168198157Srrs rmi_xlr_mac_set_multicast_list(sc); 2169198157Srrs } else 2170198157Srrs xlr_mac_set_rx_mode(sc); 2171198157Srrs } else { 2172198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2173198157Srrs xlr_mac_set_rx_mode(sc); 2174198157Srrs } 2175198157Srrs } 2176198157Srrs sc->flags = ifp->if_flags; 2177198157Srrs RGE_UNLOCK(sc); 2178198157Srrs error = 0; 2179198157Srrs break; 2180198157Srrs case SIOCADDMULTI: 2181198157Srrs case SIOCDELMULTI: 2182198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2183198157Srrs RGE_LOCK(sc); 2184198157Srrs rmi_xlr_mac_set_multicast_list(sc); 2185198157Srrs RGE_UNLOCK(sc); 2186198157Srrs error = 0; 2187198157Srrs } 2188198157Srrs break; 2189198157Srrs case SIOCSIFMEDIA: 2190198157Srrs case SIOCGIFMEDIA: 2191198157Srrs error = ifmedia_ioctl(ifp, ifr, 2192198626Srrs &sc->rge_mii.mii_media, command); 2193198157Srrs break; 2194198157Srrs case SIOCSIFCAP: 2195198157Srrs mask = ifr->ifr_reqcap ^ ifp->if_capenable; 2196198157Srrs ifp->if_hwassist = 0; 2197198157Srrs break; 2198198157Srrs default: 2199198157Srrs error = ether_ioctl(ifp, command, data); 2200198157Srrs break; 2201198157Srrs } 2202198157Srrs 2203198157Srrs return (error); 2204198157Srrs} 2205198157Srrs 2206198626Srrsstatic void 2207198157Srrsrge_init(void *addr) 2208198157Srrs{ 2209198157Srrs struct rge_softc *sc = (struct rge_softc *)addr; 2210198626Srrs struct ifnet *ifp; 2211198157Srrs struct driver_data *priv = &(sc->priv); 2212198157Srrs 2213198157Srrs ifp = sc->rge_ifp; 2214198157Srrs 2215198157Srrs if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2216198157Srrs return; 2217198157Srrs ifp->if_drv_flags |= IFF_DRV_RUNNING; 2218198157Srrs ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2219198157Srrs 2220198157Srrs rmi_xlr_mac_set_enable(priv, 1); 2221198157Srrs} 2222198157Srrs 2223198626Srrsstatic void 2224198157Srrsrge_stop(struct rge_softc *sc) 2225198157Srrs{ 2226198157Srrs rmi_xlr_mac_close(sc); 2227198157Srrs} 2228198157Srrs 2229198608Srrsstatic int 2230198157Srrsrge_shutdown(device_t dev) 2231198157Srrs{ 2232198157Srrs struct rge_softc *sc; 2233198626Srrs 2234198157Srrs sc = device_get_softc(dev); 2235198157Srrs 2236198157Srrs RGE_LOCK(sc); 2237198157Srrs rge_stop(sc); 2238198157Srrs rge_reset(sc); 2239198157Srrs RGE_UNLOCK(sc); 2240198157Srrs 2241198626Srrs return (0); 2242198157Srrs} 2243198157Srrs 2244198626Srrsstatic int 2245198157Srrsrmi_xlr_mac_open(struct rge_softc *sc) 2246198157Srrs{ 2247198157Srrs struct driver_data *priv = &(sc->priv); 2248198157Srrs int i; 2249198157Srrs 2250198157Srrs dbg_msg("IN\n"); 2251198157Srrs 2252198157Srrs if (rmi_xlr_mac_fill_rxfr(sc)) { 2253198157Srrs return -1; 2254198157Srrs } 2255198157Srrs mtx_lock_spin(&priv->lock); 2256198157Srrs 2257198157Srrs xlr_mac_set_rx_mode(sc); 2258198157Srrs 2259198157Srrs if (sc->unit == xlr_board_info.gmacports - 1) { 2260198157Srrs printf("Enabling MDIO interrupts\n"); 2261198157Srrs struct rge_softc *tmp = NULL; 2262198626Srrs 2263198157Srrs for (i = 0; i < xlr_board_info.gmacports; i++) { 2264198157Srrs tmp = dev_mac[i]; 2265198157Srrs if (tmp) 2266198157Srrs xlr_write_reg(tmp->priv.mmio, R_INTMASK, 2267198626Srrs ((tmp->priv.instance == 0) << O_INTMASK__MDInt)); 2268198157Srrs } 2269198157Srrs } 2270198157Srrs /* 2271198157Srrs * Configure the speed, duplex, and flow control 2272198157Srrs */ 2273198157Srrs rmi_xlr_mac_set_speed(priv, priv->speed); 2274198157Srrs rmi_xlr_mac_set_duplex(priv, priv->duplex, priv->flow_ctrl); 2275198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2276198157Srrs 2277198157Srrs mtx_unlock_spin(&priv->lock); 2278198157Srrs 2279198157Srrs for (i = 0; i < 8; i++) { 2280216408Savg priv->frin_to_be_sent[i] = 0; 2281198157Srrs } 2282198157Srrs 2283198157Srrs return 0; 2284198157Srrs} 2285198157Srrs 2286198157Srrs/********************************************************************** 2287198157Srrs **********************************************************************/ 2288198626Srrsstatic int 2289198157Srrsrmi_xlr_mac_close(struct rge_softc *sc) 2290198157Srrs{ 2291198157Srrs struct driver_data *priv = &(sc->priv); 2292198157Srrs 2293198157Srrs mtx_lock_spin(&priv->lock); 2294198157Srrs 2295198157Srrs /* 2296198157Srrs * There may have left over mbufs in the ring as well as in free in 2297198157Srrs * they will be reused next time open is called 2298198157Srrs */ 2299198157Srrs 2300198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2301198157Srrs 2302198157Srrs xlr_inc_counter(NETIF_STOP_Q); 2303198157Srrs port_inc_counter(priv->instance, PORT_STOPQ); 2304198157Srrs 2305198157Srrs mtx_unlock_spin(&priv->lock); 2306198157Srrs 2307198157Srrs return 0; 2308198157Srrs} 2309198157Srrs 2310198157Srrs/********************************************************************** 2311198157Srrs **********************************************************************/ 2312198157Srrsstatic struct rge_softc_stats * 2313198157Srrsrmi_xlr_mac_get_stats(struct rge_softc *sc) 2314198157Srrs{ 2315198157Srrs struct driver_data *priv = &(sc->priv); 2316198626Srrs 2317198157Srrs /* unsigned long flags; */ 2318198157Srrs 2319198157Srrs mtx_lock_spin(&priv->lock); 2320198157Srrs 2321198157Srrs /* XXX update other stats here */ 2322198157Srrs 2323198157Srrs mtx_unlock_spin(&priv->lock); 2324198157Srrs 2325198157Srrs return &priv->stats; 2326198157Srrs} 2327198157Srrs 2328198157Srrs/********************************************************************** 2329198157Srrs **********************************************************************/ 2330198626Srrsstatic void 2331198157Srrsrmi_xlr_mac_set_multicast_list(struct rge_softc *sc) 2332198157Srrs{ 2333198157Srrs} 2334198157Srrs 2335198157Srrs/********************************************************************** 2336198157Srrs **********************************************************************/ 2337198626Srrsstatic int 2338198157Srrsrmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu) 2339198157Srrs{ 2340198157Srrs struct driver_data *priv = &(sc->priv); 2341198157Srrs 2342198157Srrs if ((new_mtu > 9500) || (new_mtu < 64)) { 2343198157Srrs return -EINVAL; 2344198157Srrs } 2345198157Srrs mtx_lock_spin(&priv->lock); 2346198157Srrs 2347198157Srrs sc->mtu = new_mtu; 2348198157Srrs 2349198157Srrs /* Disable MAC TX/RX */ 2350198157Srrs rmi_xlr_mac_set_enable(priv, 0); 2351198157Srrs 2352198157Srrs /* Flush RX FR IN */ 2353198157Srrs /* Flush TX IN */ 2354198157Srrs rmi_xlr_mac_set_enable(priv, 1); 2355198157Srrs 2356198157Srrs mtx_unlock_spin(&priv->lock); 2357198157Srrs return 0; 2358198157Srrs} 2359198157Srrs 2360198157Srrs/********************************************************************** 2361198157Srrs **********************************************************************/ 2362198626Srrsstatic int 2363198157Srrsrmi_xlr_mac_fill_rxfr(struct rge_softc *sc) 2364198157Srrs{ 2365198157Srrs struct driver_data *priv = &(sc->priv); 2366198626Srrs int i; 2367198626Srrs int ret = 0; 2368198626Srrs void *ptr; 2369198157Srrs 2370198157Srrs dbg_msg("\n"); 2371198157Srrs if (!priv->init_frin_desc) 2372198157Srrs return ret; 2373198157Srrs priv->init_frin_desc = 0; 2374198157Srrs 2375198157Srrs dbg_msg("\n"); 2376198157Srrs for (i = 0; i < MAX_NUM_DESC; i++) { 2377198157Srrs ptr = get_buf(); 2378198157Srrs if (!ptr) { 2379198157Srrs ret = -ENOMEM; 2380198157Srrs break; 2381198157Srrs } 2382198157Srrs /* Send the free Rx desc to the MAC */ 2383198157Srrs xlr_mac_send_fr(priv, vtophys(ptr), MAX_FRAME_SIZE); 2384198157Srrs } 2385198157Srrs 2386198157Srrs return ret; 2387198157Srrs} 2388198157Srrs 2389198157Srrs/********************************************************************** 2390198157Srrs **********************************************************************/ 2391198157Srrsstatic __inline__ void * 2392198157Srrsrmi_xlr_config_spill(xlr_reg_t * mmio, 2393198626Srrs int reg_start_0, int reg_start_1, 2394198626Srrs int reg_size, int size) 2395198157Srrs{ 2396198626Srrs uint32_t spill_size = size; 2397198626Srrs void *spill = NULL; 2398198626Srrs uint64_t phys_addr = 0; 2399198157Srrs 2400198157Srrs 2401198157Srrs spill = contigmalloc((spill_size + XLR_CACHELINE_SIZE), M_DEVBUF, 2402198626Srrs M_NOWAIT | M_ZERO, 0, 0xffffffff, XLR_CACHELINE_SIZE, 0); 2403198626Srrs if (!spill || ((vm_offset_t)spill & (XLR_CACHELINE_SIZE - 1))) { 2404198157Srrs panic("Unable to allocate memory for spill area!\n"); 2405198157Srrs } 2406198157Srrs phys_addr = vtophys(spill); 2407209808Sjchandra dbg_msg("Allocate spill %d bytes at %jx\n", size, (uintmax_t)phys_addr); 2408198157Srrs xlr_write_reg(mmio, reg_start_0, (phys_addr >> 5) & 0xffffffff); 2409198157Srrs xlr_write_reg(mmio, reg_start_1, (phys_addr >> 37) & 0x07); 2410198157Srrs xlr_write_reg(mmio, reg_size, spill_size); 2411198157Srrs 2412198157Srrs return spill; 2413198157Srrs} 2414198157Srrs 2415198626Srrsstatic void 2416198157Srrsrmi_xlr_config_spill_area(struct driver_data *priv) 2417198157Srrs{ 2418198157Srrs /* 2419198157Srrs * if driver initialization is done parallely on multiple cpus 2420198157Srrs * spill_configured needs synchronization 2421198157Srrs */ 2422198157Srrs if (priv->spill_configured) 2423198157Srrs return; 2424198157Srrs 2425198157Srrs if (priv->type == XLR_GMAC && priv->instance % 4 != 0) { 2426198157Srrs priv->spill_configured = 1; 2427198157Srrs return; 2428198157Srrs } 2429198157Srrs priv->spill_configured = 1; 2430198157Srrs 2431198157Srrs priv->frin_spill = 2432198626Srrs rmi_xlr_config_spill(priv->mmio, 2433198626Srrs R_REG_FRIN_SPILL_MEM_START_0, 2434198626Srrs R_REG_FRIN_SPILL_MEM_START_1, 2435198626Srrs R_REG_FRIN_SPILL_MEM_SIZE, 2436198626Srrs MAX_FRIN_SPILL * 2437198626Srrs sizeof(struct fr_desc)); 2438198157Srrs 2439198157Srrs priv->class_0_spill = 2440198626Srrs rmi_xlr_config_spill(priv->mmio, 2441198626Srrs R_CLASS0_SPILL_MEM_START_0, 2442198626Srrs R_CLASS0_SPILL_MEM_START_1, 2443198626Srrs R_CLASS0_SPILL_MEM_SIZE, 2444198626Srrs MAX_CLASS_0_SPILL * 2445198626Srrs sizeof(union rx_tx_desc)); 2446198157Srrs priv->class_1_spill = 2447198626Srrs rmi_xlr_config_spill(priv->mmio, 2448198626Srrs R_CLASS1_SPILL_MEM_START_0, 2449198626Srrs R_CLASS1_SPILL_MEM_START_1, 2450198626Srrs R_CLASS1_SPILL_MEM_SIZE, 2451198626Srrs MAX_CLASS_1_SPILL * 2452198626Srrs sizeof(union rx_tx_desc)); 2453198157Srrs 2454198157Srrs priv->frout_spill = 2455198626Srrs rmi_xlr_config_spill(priv->mmio, R_FROUT_SPILL_MEM_START_0, 2456198626Srrs R_FROUT_SPILL_MEM_START_1, 2457198626Srrs R_FROUT_SPILL_MEM_SIZE, 2458198626Srrs MAX_FROUT_SPILL * 2459198626Srrs sizeof(struct fr_desc)); 2460198157Srrs 2461198157Srrs priv->class_2_spill = 2462198626Srrs rmi_xlr_config_spill(priv->mmio, 2463198626Srrs R_CLASS2_SPILL_MEM_START_0, 2464198626Srrs R_CLASS2_SPILL_MEM_START_1, 2465198626Srrs R_CLASS2_SPILL_MEM_SIZE, 2466198626Srrs MAX_CLASS_2_SPILL * 2467198626Srrs sizeof(union rx_tx_desc)); 2468198157Srrs priv->class_3_spill = 2469198626Srrs rmi_xlr_config_spill(priv->mmio, 2470198626Srrs R_CLASS3_SPILL_MEM_START_0, 2471198626Srrs R_CLASS3_SPILL_MEM_START_1, 2472198626Srrs R_CLASS3_SPILL_MEM_SIZE, 2473198626Srrs MAX_CLASS_3_SPILL * 2474198626Srrs sizeof(union rx_tx_desc)); 2475198157Srrs priv->spill_configured = 1; 2476198157Srrs} 2477198157Srrs 2478198157Srrs/***************************************************************** 2479198157Srrs * Write the MAC address to the XLR registers 2480198157Srrs * All 4 addresses are the same for now 2481198157Srrs *****************************************************************/ 2482198626Srrsstatic void 2483198157Srrsxlr_mac_setup_hwaddr(struct driver_data *priv) 2484198157Srrs{ 2485198157Srrs struct rge_softc *sc = priv->sc; 2486198157Srrs 2487198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR0, 2488198626Srrs ((sc->dev_addr[5] << 24) | (sc->dev_addr[4] << 16) 2489198626Srrs | (sc->dev_addr[3] << 8) | (sc->dev_addr[2])) 2490198626Srrs ); 2491198157Srrs 2492198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR0 + 1, 2493198626Srrs ((sc->dev_addr[1] << 24) | (sc-> 2494198626Srrs dev_addr[0] << 16))); 2495198157Srrs 2496198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2, 0xffffffff); 2497198157Srrs 2498198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2 + 1, 0xffffffff); 2499198157Srrs 2500198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3, 0xffffffff); 2501198157Srrs 2502198157Srrs xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3 + 1, 0xffffffff); 2503198157Srrs 2504198157Srrs xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG, 2505198626Srrs (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) | 2506198626Srrs (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) | 2507198626Srrs (1 << O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID) 2508198626Srrs ); 2509198157Srrs} 2510198157Srrs 2511198157Srrs/***************************************************************** 2512198157Srrs * Read the MAC address from the XLR registers 2513198157Srrs * All 4 addresses are the same for now 2514198157Srrs *****************************************************************/ 2515198626Srrsstatic void 2516198157Srrsxlr_mac_get_hwaddr(struct rge_softc *sc) 2517198157Srrs{ 2518198157Srrs struct driver_data *priv = &(sc->priv); 2519198157Srrs 2520198157Srrs sc->dev_addr[0] = (xlr_boot1_info.mac_addr >> 40) & 0xff; 2521198157Srrs sc->dev_addr[1] = (xlr_boot1_info.mac_addr >> 32) & 0xff; 2522198157Srrs sc->dev_addr[2] = (xlr_boot1_info.mac_addr >> 24) & 0xff; 2523198157Srrs sc->dev_addr[3] = (xlr_boot1_info.mac_addr >> 16) & 0xff; 2524198157Srrs sc->dev_addr[4] = (xlr_boot1_info.mac_addr >> 8) & 0xff; 2525198157Srrs sc->dev_addr[5] = ((xlr_boot1_info.mac_addr >> 0) & 0xff) + priv->instance; 2526198157Srrs} 2527198157Srrs 2528198157Srrs/***************************************************************** 2529198157Srrs * Mac Module Initialization 2530198157Srrs *****************************************************************/ 2531198626Srrsstatic void 2532198157Srrsmac_common_init(void) 2533198157Srrs{ 2534198157Srrs init_p2d_allocation(); 2535198157Srrs init_tx_ring(); 2536198157Srrs 2537198157Srrs if (xlr_board_info.is_xls) { 2538213377Sjchandra if (register_msgring_handler(MSGRNG_STNID_GMAC, 2539213377Sjchandra MSGRNG_STNID_GMAC + 1, rmi_xlr_mac_msgring_handler, 2540213377Sjchandra NULL)) { 2541198157Srrs panic("Couldn't register msgring handler\n"); 2542198157Srrs } 2543213377Sjchandra if (register_msgring_handler(MSGRNG_STNID_GMAC1, 2544213377Sjchandra MSGRNG_STNID_GMAC1 + 1, rmi_xlr_mac_msgring_handler, 2545213377Sjchandra NULL)) { 2546198157Srrs panic("Couldn't register msgring handler\n"); 2547198157Srrs } 2548198157Srrs } else { 2549213377Sjchandra if (register_msgring_handler(MSGRNG_STNID_GMAC, 2550213377Sjchandra MSGRNG_STNID_GMAC + 1, rmi_xlr_mac_msgring_handler, 2551213377Sjchandra NULL)) { 2552198157Srrs panic("Couldn't register msgring handler\n"); 2553198157Srrs } 2554198157Srrs } 2555198157Srrs 2556198626Srrs /* 2557198626Srrs * Not yet if (xlr_board_atx_ii()) { if (register_msgring_handler 2558198626Srrs * (TX_STN_XGS_0, rmi_xlr_mac_msgring_handler, NULL)) { 2559198626Srrs * panic("Couldn't register msgring handler for TX_STN_XGS_0\n"); } 2560198626Srrs * if (register_msgring_handler (TX_STN_XGS_1, 2561198626Srrs * rmi_xlr_mac_msgring_handler, NULL)) { panic("Couldn't register 2562198626Srrs * msgring handler for TX_STN_XGS_1\n"); } } 2563198626Srrs */ 2564198157Srrs} 2565