lpc_eth.c revision cdaf0b835df04177397b90214f8b457fd23b67e0
1b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 2b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * drivers/net/ethernet/nxp/lpc_eth.c 3b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * 4b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Author: Kevin Wells <kevin.wells@nxp.com> 5b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * 6b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Copyright (C) 2010 NXP Semiconductors 7b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Copyright (C) 2012 Roland Stigge <stigge@antcom.de> 8b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * 9b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * This program is free software; you can redistribute it and/or modify 10b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * it under the terms of the GNU General Public License as published by 11b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * the Free Software Foundation; either version 2 of the License, or 12b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * (at your option) any later version. 13b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * 14b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * This program is distributed in the hope that it will be useful, 15b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * but WITHOUT ANY WARRANTY; without even the implied warranty of 16b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * GNU General Public License for more details. 18b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 19b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 20b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 21b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 22b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/init.h> 23b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/module.h> 24b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/kernel.h> 25b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/sched.h> 26b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/slab.h> 27b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/delay.h> 28b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/interrupt.h> 29b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/errno.h> 30b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/ioport.h> 31b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/crc32.h> 32b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/platform_device.h> 33b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/spinlock.h> 34b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/ethtool.h> 35b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/mii.h> 36b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/clk.h> 37b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/workqueue.h> 38b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/netdevice.h> 39b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/etherdevice.h> 40b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/skbuff.h> 41b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/phy.h> 42b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/dma-mapping.h> 43b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/of_net.h> 44b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/types.h> 45b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 46b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/delay.h> 47b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <linux/io.h> 48b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <mach/board.h> 49b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <mach/platform.h> 50b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#include <mach/hardware.h> 51b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 52b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define MODNAME "lpc-eth" 53b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define DRV_VERSION "1.00" 54b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define PHYDEF_ADDR 0x00 55b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 56b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define ENET_MAXF_SIZE 1536 57b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define ENET_RX_DESC 48 58b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define ENET_TX_DESC 16 59b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 60b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define NAPI_WEIGHT 16 61b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 62b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 63b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Ethernet MAC controller Register offsets 64b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 65b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MAC1(x) (x + 0x000) 66b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MAC2(x) (x + 0x004) 67b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_IPGT(x) (x + 0x008) 68b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_IPGR(x) (x + 0x00C) 69b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_CLRT(x) (x + 0x010) 70b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MAXF(x) (x + 0x014) 71b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_SUPP(x) (x + 0x018) 72b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TEST(x) (x + 0x01C) 73b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MCFG(x) (x + 0x020) 74b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MCMD(x) (x + 0x024) 75b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MADR(x) (x + 0x028) 76b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MWTD(x) (x + 0x02C) 77b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MRDD(x) (x + 0x030) 78b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_MIND(x) (x + 0x034) 79b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_SA0(x) (x + 0x040) 80b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_SA1(x) (x + 0x044) 81b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_SA2(x) (x + 0x048) 82b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_COMMAND(x) (x + 0x100) 83b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_STATUS(x) (x + 0x104) 84b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXDESCRIPTOR(x) (x + 0x108) 85b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXSTATUS(x) (x + 0x10C) 86b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXDESCRIPTORNUMBER(x) (x + 0x110) 87b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXPRODUCEINDEX(x) (x + 0x114) 88b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXCONSUMEINDEX(x) (x + 0x118) 89b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TXDESCRIPTOR(x) (x + 0x11C) 90b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TXSTATUS(x) (x + 0x120) 91b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TXDESCRIPTORNUMBER(x) (x + 0x124) 92b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TXPRODUCEINDEX(x) (x + 0x128) 93b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TXCONSUMEINDEX(x) (x + 0x12C) 94b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TSV0(x) (x + 0x158) 95b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_TSV1(x) (x + 0x15C) 96b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RSV(x) (x + 0x160) 97b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_FLOWCONTROLCOUNTER(x) (x + 0x170) 98b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_FLOWCONTROLSTATUS(x) (x + 0x174) 99b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXFILTER_CTRL(x) (x + 0x200) 100b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXFILTERWOLSTATUS(x) (x + 0x204) 101b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_RXFILTERWOLCLEAR(x) (x + 0x208) 102b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_HASHFILTERL(x) (x + 0x210) 103b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_HASHFILTERH(x) (x + 0x214) 104b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_INTSTATUS(x) (x + 0xFE0) 105b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_INTENABLE(x) (x + 0xFE4) 106b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_INTCLEAR(x) (x + 0xFE8) 107b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_INTSET(x) (x + 0xFEC) 108b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_ENET_POWERDOWN(x) (x + 0xFF4) 109b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 110b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 111b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * mac1 register definitions 112b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 113b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_RECV_ENABLE (1 << 0) 114b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_PASS_ALL_RX_FRAMES (1 << 1) 115b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_RX_FLOW_CONTROL (1 << 2) 116b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_TX_FLOW_CONTROL (1 << 3) 117b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_LOOPBACK (1 << 4) 118b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_RESET_TX (1 << 8) 119b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_RESET_MCS_TX (1 << 9) 120b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_RESET_RX (1 << 10) 121b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_RESET_MCS_RX (1 << 11) 122b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_SIMULATION_RESET (1 << 14) 123b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC1_SOFT_RESET (1 << 15) 124b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 125b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 126b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * mac2 register definitions 127b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 128b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_FULL_DUPLEX (1 << 0) 129b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_FRAME_LENGTH_CHECKING (1 << 1) 130b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_HUGH_LENGTH_CHECKING (1 << 2) 131b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_DELAYED_CRC (1 << 3) 132b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_CRC_ENABLE (1 << 4) 133b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_PAD_CRC_ENABLE (1 << 5) 134b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_VLAN_PAD_ENABLE (1 << 6) 135b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_AUTO_DETECT_PAD_ENABLE (1 << 7) 136b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_PURE_PREAMBLE_ENFORCEMENT (1 << 8) 137b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_LONG_PREAMBLE_ENFORCEMENT (1 << 9) 138b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_NO_BACKOFF (1 << 12) 139b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_BACK_PRESSURE (1 << 13) 140b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAC2_EXCESS_DEFER (1 << 14) 141b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 142b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 143b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * ipgt register definitions 144b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 145b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_IPGT_LOAD(n) ((n) & 0x7F) 146b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 147b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 148b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * ipgr register definitions 149b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 150b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_IPGR_LOAD_PART2(n) ((n) & 0x7F) 151b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_IPGR_LOAD_PART1(n) (((n) & 0x7F) << 8) 152b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 153b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 154b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * clrt register definitions 155b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 156b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_CLRT_LOAD_RETRY_MAX(n) ((n) & 0xF) 157b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_CLRT_LOAD_COLLISION_WINDOW(n) (((n) & 0x3F) << 8) 158b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 159b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 160b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * maxf register definitions 161b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 162b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MAXF_LOAD_MAX_FRAME_LEN(n) ((n) & 0xFFFF) 163b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 164b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 165b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * supp register definitions 166b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 167b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_SUPP_SPEED (1 << 8) 168b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_SUPP_RESET_RMII (1 << 11) 169b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 170b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 171b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * test register definitions 172b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 173b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TEST_SHORTCUT_PAUSE_QUANTA (1 << 0) 174b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TEST_PAUSE (1 << 1) 175b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TEST_BACKPRESSURE (1 << 2) 176b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 177b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 178b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * mcfg register definitions 179b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 180b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_SCAN_INCREMENT (1 << 0) 181b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_SUPPRESS_PREAMBLE (1 << 1) 182b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_SELECT(n) (((n) & 0x7) << 2) 183b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_HOST_DIV_4 0 184b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_HOST_DIV_6 2 185b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_HOST_DIV_8 3 186b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_HOST_DIV_10 4 187b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_HOST_DIV_14 5 188b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_HOST_DIV_20 6 189b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_CLOCK_HOST_DIV_28 7 190b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCFG_RESET_MII_MGMT (1 << 15) 191b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 192b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 193b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * mcmd register definitions 194b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 195b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCMD_READ (1 << 0) 196b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MCMD_SCAN (1 << 1) 197b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 198b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 199b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * madr register definitions 200b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 201b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MADR_REGISTER_ADDRESS(n) ((n) & 0x1F) 202b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MADR_PHY_0ADDRESS(n) (((n) & 0x1F) << 8) 203b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 204b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 205b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * mwtd register definitions 206b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 207b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MWDT_WRITE(n) ((n) & 0xFFFF) 208b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 209b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 210b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * mrdd register definitions 211b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 212b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MRDD_READ_MASK 0xFFFF 213b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 214b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 215b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * mind register definitions 216b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 217b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MIND_BUSY (1 << 0) 218b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MIND_SCANNING (1 << 1) 219b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MIND_NOT_VALID (1 << 2) 220b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MIND_MII_LINK_FAIL (1 << 3) 221b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 222b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 223b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * command register definitions 224b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 225b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_RXENABLE (1 << 0) 226b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_TXENABLE (1 << 1) 227b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_REG_RESET (1 << 3) 228b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_TXRESET (1 << 4) 229b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_RXRESET (1 << 5) 230b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_PASSRUNTFRAME (1 << 6) 231b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_PASSRXFILTER (1 << 7) 232b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_TXFLOWCONTROL (1 << 8) 233b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_RMII (1 << 9) 234b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_COMMAND_FULLDUPLEX (1 << 10) 235b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 236b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 237b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * status register definitions 238b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 239b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_STATUS_RXACTIVE (1 << 0) 240b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_STATUS_TXACTIVE (1 << 1) 241b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 242b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 243b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * tsv0 register definitions 244b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 245b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_CRC_ERROR (1 << 0) 246b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_LENGTH_CHECK_ERROR (1 << 1) 247b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_LENGTH_OUT_OF_RANGE (1 << 2) 248b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_DONE (1 << 3) 249b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_MULTICAST (1 << 4) 250b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_BROADCAST (1 << 5) 251b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_PACKET_DEFER (1 << 6) 252b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_ESCESSIVE_DEFER (1 << 7) 253b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_ESCESSIVE_COLLISION (1 << 8) 254b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_LATE_COLLISION (1 << 9) 255b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_GIANT (1 << 10) 256b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_UNDERRUN (1 << 11) 257b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_TOTAL_BYTES(n) (((n) >> 12) & 0xFFFF) 258b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_CONTROL_FRAME (1 << 28) 259b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_PAUSE (1 << 29) 260b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_BACKPRESSURE (1 << 30) 261b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV0_VLAN (1 << 31) 262b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 263b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 264b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * tsv1 register definitions 265b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 266b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV1_TRANSMIT_BYTE_COUNT(n) ((n) & 0xFFFF) 267b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_TSV1_COLLISION_COUNT(n) (((n) >> 16) & 0xF) 268b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 269b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 270b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * rsv register definitions 271b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 272b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_RECEIVED_BYTE_COUNT(n) ((n) & 0xFFFF) 273b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_RXDV_EVENT_IGNORED (1 << 16) 274b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_RXDV_EVENT_PREVIOUSLY_SEEN (1 << 17) 275b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_CARRIER_EVNT_PREVIOUS_SEEN (1 << 18) 276b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_RECEIVE_CODE_VIOLATION (1 << 19) 277b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_CRC_ERROR (1 << 20) 278b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_LENGTH_CHECK_ERROR (1 << 21) 279b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_LENGTH_OUT_OF_RANGE (1 << 22) 280b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_RECEIVE_OK (1 << 23) 281b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_MULTICAST (1 << 24) 282b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_BROADCAST (1 << 25) 283b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_DRIBBLE_NIBBLE (1 << 26) 284b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_CONTROL_FRAME (1 << 27) 285b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_PAUSE (1 << 28) 286b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_UNSUPPORTED_OPCODE (1 << 29) 287b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RSV_VLAN (1 << 30) 288b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 289b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 290b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * flowcontrolcounter register definitions 291b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 292b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_FCCR_MIRRORCOUNTER(n) ((n) & 0xFFFF) 293b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_FCCR_PAUSETIMER(n) (((n) >> 16) & 0xFFFF) 294b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 295b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 296b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * flowcontrolstatus register definitions 297b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 298b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_FCCR_MIRRORCOUNTERCURRENT(n) ((n) & 0xFFFF) 299b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 300b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 301b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * rxfliterctrl, rxfilterwolstatus, and rxfilterwolclear shared 302b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * register definitions 303b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 304b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRW_ACCEPTUNICAST (1 << 0) 305b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRW_ACCEPTUBROADCAST (1 << 1) 306b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRW_ACCEPTUMULTICAST (1 << 2) 307b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRW_ACCEPTUNICASTHASH (1 << 3) 308b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRW_ACCEPTUMULTICASTHASH (1 << 4) 309b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRW_ACCEPTPERFECT (1 << 5) 310b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 311b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 312b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * rxfliterctrl register definitions 313b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 314b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRWSTS_MAGICPACKETENWOL (1 << 12) 315b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRWSTS_RXFILTERENWOL (1 << 13) 316b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 317b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 318b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * rxfilterwolstatus/rxfilterwolclear register definitions 319b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 320b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRWSTS_RXFILTERWOL (1 << 7) 321b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_RXFLTRWSTS_MAGICPACKETWOL (1 << 8) 322b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 323b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 324b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * intstatus, intenable, intclear, and Intset shared register 325b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * definitions 326b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 327b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_RXOVERRUNINTEN (1 << 0) 328b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_RXERRORONINT (1 << 1) 329b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_RXFINISHEDINTEN (1 << 2) 330b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_RXDONEINTEN (1 << 3) 331b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_TXUNDERRUNINTEN (1 << 4) 332b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_TXERRORINTEN (1 << 5) 333b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_TXFINISHEDINTEN (1 << 6) 334b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_TXDONEINTEN (1 << 7) 335b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_SOFTINTEN (1 << 12) 336b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_MACINT_WAKEUPINTEN (1 << 13) 337b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 338b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 339b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * powerdown register definitions 340b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 341b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define LPC_POWERDOWN_MACAHB (1 << 31) 342b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 343b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* Upon the upcoming introduction of device tree usage in LPC32xx, 344b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * lpc_phy_interface_mode() and use_iram_for_net() will be extended with a 345b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * device parameter for access to device tree information at runtime, instead 346b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * of defining the values at compile time 347b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 348b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic inline phy_interface_t lpc_phy_interface_mode(void) 349b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 350b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT 351b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return PHY_INTERFACE_MODE_MII; 352b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#else 353b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return PHY_INTERFACE_MODE_RMII; 354b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#endif 355b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 356b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 357b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic inline int use_iram_for_net(void) 358b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 359b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET 360b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 1; 361b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#else 362b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 363b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#endif 364b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 365b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 366b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* Receive Status information word */ 367b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_SIZE 0x000007FF 368b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_CONTROL (1 << 18) 369b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_VLAN (1 << 19) 370b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_FILTER (1 << 20) 371b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_MULTICAST (1 << 21) 372b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_BROADCAST (1 << 22) 373b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_CRC (1 << 23) 374b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_SYMBOL (1 << 24) 375b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_LENGTH (1 << 25) 376b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_RANGE (1 << 26) 377b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_ALIGN (1 << 27) 378b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_OVERRUN (1 << 28) 379b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_NODESC (1 << 29) 380b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_LAST (1 << 30) 381b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_ERROR (1 << 31) 382b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 383b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXSTATUS_STATUS_ERROR \ 384b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de (RXSTATUS_NODESC | RXSTATUS_OVERRUN | RXSTATUS_ALIGN | \ 385b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de RXSTATUS_RANGE | RXSTATUS_LENGTH | RXSTATUS_SYMBOL | RXSTATUS_CRC) 386b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 387b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* Receive Descriptor control word */ 388b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXDESC_CONTROL_SIZE 0x000007FF 389b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define RXDESC_CONTROL_INT (1 << 31) 390b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 391b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* Transmit Status information word */ 392b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_COLLISIONS_GET(x) (((x) >> 21) & 0xF) 393b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_DEFER (1 << 25) 394b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_EXCESSDEFER (1 << 26) 395b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_EXCESSCOLL (1 << 27) 396b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_LATECOLL (1 << 28) 397b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_UNDERRUN (1 << 29) 398b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_NODESC (1 << 30) 399b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXSTATUS_ERROR (1 << 31) 400b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 401b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* Transmit Descriptor control word */ 402b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXDESC_CONTROL_SIZE 0x000007FF 403b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXDESC_CONTROL_OVERRIDE (1 << 26) 404b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXDESC_CONTROL_HUGE (1 << 27) 405b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXDESC_CONTROL_PAD (1 << 28) 406b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXDESC_CONTROL_CRC (1 << 29) 407b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXDESC_CONTROL_LAST (1 << 30) 408b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#define TXDESC_CONTROL_INT (1 << 31) 409b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 410b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_hard_start_xmit(struct sk_buff *skb, 411b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev); 412b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 413b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 414b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Structure of a TX/RX descriptors and RX status 415b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 416b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destruct txrx_desc_t { 417b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __le32 packet; 418b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __le32 control; 419b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de}; 420b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destruct rx_status_t { 421b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __le32 statusinfo; 422b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __le32 statushashcrc; 423b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de}; 424b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 425b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 426b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Device driver data structure 427b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 428b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destruct netdata_local { 429b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct platform_device *pdev; 430b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev; 431b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spinlock_t lock; 432b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de void __iomem *net_base; 433b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 msg_enable; 434b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct sk_buff *skb[ENET_TX_DESC]; 435b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned int last_tx_idx; 436b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned int num_used_tx_buffs; 437b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct mii_bus *mii_bus; 438b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct phy_device *phy_dev; 439b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct clk *clk; 440b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dma_addr_t dma_buff_base_p; 441b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de void *dma_buff_base_v; 442b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de size_t dma_buff_size; 443b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct txrx_desc_t *tx_desc_v; 444b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 *tx_stat_v; 445b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de void *tx_buff_v; 446b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct txrx_desc_t *rx_desc_v; 447b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct rx_status_t *rx_stat_v; 448b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de void *rx_buff_v; 449b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int link; 450b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int speed; 451b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int duplex; 452b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct napi_struct napi; 453b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de}; 454b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 455b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 456b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * MAC support functions 457b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 458b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_set_mac(struct netdata_local *pldat, u8 *mac) 459b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 460b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 tmp; 461b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 462b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Set station address */ 463b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = mac[0] | ((u32)mac[1] << 8); 464b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_SA2(pldat->net_base)); 465b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = mac[2] | ((u32)mac[3] << 8); 466b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_SA1(pldat->net_base)); 467b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = mac[4] | ((u32)mac[5] << 8); 468b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_SA0(pldat->net_base)); 469b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 470b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_dbg(pldat->ndev, "Ethernet MAC address %pM\n", mac); 471b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 472b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 473b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_get_mac(struct netdata_local *pldat, u8 *mac) 474b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 475b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 tmp; 476b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 477b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get station address */ 478b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_SA2(pldat->net_base)); 479b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mac[0] = tmp & 0xFF; 480b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mac[1] = tmp >> 8; 481b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_SA1(pldat->net_base)); 482b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mac[2] = tmp & 0xFF; 483b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mac[3] = tmp >> 8; 484b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_SA0(pldat->net_base)); 485b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mac[4] = tmp & 0xFF; 486b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mac[5] = tmp >> 8; 487b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 488b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 489b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_eth_clock_enable(struct netdata_local *pldat, 490b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de bool enable) 491b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 492b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (enable) 493b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_enable(pldat->clk); 494b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else 495b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_disable(pldat->clk); 496b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 497b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 498b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_params_setup(struct netdata_local *pldat) 499b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 500b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 tmp; 501b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 502b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->duplex == DUPLEX_FULL) { 503b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_MAC2(pldat->net_base)); 504b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp |= LPC_MAC2_FULL_DUPLEX; 505b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_MAC2(pldat->net_base)); 506b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_COMMAND(pldat->net_base)); 507b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp |= LPC_COMMAND_FULLDUPLEX; 508b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_COMMAND(pldat->net_base)); 509b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_IPGT_LOAD(0x15), LPC_ENET_IPGT(pldat->net_base)); 510b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } else { 511b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_MAC2(pldat->net_base)); 512b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp &= ~LPC_MAC2_FULL_DUPLEX; 513b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_MAC2(pldat->net_base)); 514b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_COMMAND(pldat->net_base)); 515b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp &= ~LPC_COMMAND_FULLDUPLEX; 516b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_COMMAND(pldat->net_base)); 517b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_IPGT_LOAD(0x12), LPC_ENET_IPGT(pldat->net_base)); 518b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 519b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 520b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->speed == SPEED_100) 521b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_SUPP_SPEED, LPC_ENET_SUPP(pldat->net_base)); 522b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else 523b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0, LPC_ENET_SUPP(pldat->net_base)); 524b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 525b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 526b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_eth_reset(struct netdata_local *pldat) 527b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 528b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Reset all MAC logic */ 529b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_MAC1_RESET_TX | LPC_MAC1_RESET_MCS_TX | LPC_MAC1_RESET_RX | 530b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_MAC1_RESET_MCS_RX | LPC_MAC1_SIMULATION_RESET | 531b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_MAC1_SOFT_RESET), LPC_ENET_MAC1(pldat->net_base)); 532b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_COMMAND_REG_RESET | LPC_COMMAND_TXRESET | 533b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_COMMAND_RXRESET), LPC_ENET_COMMAND(pldat->net_base)); 534b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 535b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 536b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int __lpc_mii_mngt_reset(struct netdata_local *pldat) 537b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 538b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Reset MII management hardware */ 539b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_MCFG_RESET_MII_MGMT, LPC_ENET_MCFG(pldat->net_base)); 540b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 541b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup MII clock to slowest rate with a /28 divider */ 542b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_MCFG_CLOCK_SELECT(LPC_MCFG_CLOCK_HOST_DIV_28), 543b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_MCFG(pldat->net_base)); 544b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 545b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 546b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 547b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 548b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic inline phys_addr_t __va_to_pa(void *addr, struct netdata_local *pldat) 549b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 550b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phys_addr_t phaddr; 551b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 552b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phaddr = addr - pldat->dma_buff_base_v; 553b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phaddr += pldat->dma_buff_base_p; 554b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 555b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return phaddr; 556b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 557b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 558b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void lpc_eth_enable_int(void __iomem *regbase) 559b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 560b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_MACINT_RXDONEINTEN | LPC_MACINT_TXDONEINTEN), 561b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_INTENABLE(regbase)); 562b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 563b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 564b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void lpc_eth_disable_int(void __iomem *regbase) 565b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 566b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0, LPC_ENET_INTENABLE(regbase)); 567b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 568b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 569b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* Setup TX/RX descriptors */ 570b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_txrx_desc_setup(struct netdata_local *pldat) 571b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 572b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 *ptxstat; 573b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de void *tbuff; 574b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int i; 575b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct txrx_desc_t *ptxrxdesc; 576b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct rx_status_t *prxstat; 577b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 578b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff = PTR_ALIGN(pldat->dma_buff_base_v, 16); 579b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 580b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup TX descriptors, status, and buffers */ 581b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->tx_desc_v = tbuff; 582b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff += sizeof(struct txrx_desc_t) * ENET_TX_DESC; 583b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 584b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->tx_stat_v = tbuff; 585b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff += sizeof(u32) * ENET_TX_DESC; 586b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 587b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff = PTR_ALIGN(tbuff, 16); 588b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->tx_buff_v = tbuff; 589b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff += ENET_MAXF_SIZE * ENET_TX_DESC; 590b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 591b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup RX descriptors, status, and buffers */ 592b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->rx_desc_v = tbuff; 593b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff += sizeof(struct txrx_desc_t) * ENET_RX_DESC; 594b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 595b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff = PTR_ALIGN(tbuff, 16); 596b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->rx_stat_v = tbuff; 597b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff += sizeof(struct rx_status_t) * ENET_RX_DESC; 598b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 599b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff = PTR_ALIGN(tbuff, 16); 600b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->rx_buff_v = tbuff; 601b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tbuff += ENET_MAXF_SIZE * ENET_RX_DESC; 602b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 603b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Map the TX descriptors to the TX buffers in hardware */ 604b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de for (i = 0; i < ENET_TX_DESC; i++) { 605b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxstat = &pldat->tx_stat_v[i]; 606b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc = &pldat->tx_desc_v[i]; 607b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 608b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc->packet = __va_to_pa( 609b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->tx_buff_v + i * ENET_MAXF_SIZE, pldat); 610b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc->control = 0; 611b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de *ptxstat = 0; 612b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 613b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 614b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Map the RX descriptors to the RX buffers in hardware */ 615b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de for (i = 0; i < ENET_RX_DESC; i++) { 616b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de prxstat = &pldat->rx_stat_v[i]; 617b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc = &pldat->rx_desc_v[i]; 618b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 619b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc->packet = __va_to_pa( 620b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->rx_buff_v + i * ENET_MAXF_SIZE, pldat); 621b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc->control = RXDESC_CONTROL_INT | (ENET_MAXF_SIZE - 1); 622b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de prxstat->statusinfo = 0; 623b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de prxstat->statushashcrc = 0; 624b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 625b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 626b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup base addresses in hardware to point to buffers and 627b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * descriptors 628b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 629b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((ENET_TX_DESC - 1), 630b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_TXDESCRIPTORNUMBER(pldat->net_base)); 631b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(__va_to_pa(pldat->tx_desc_v, pldat), 632b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_TXDESCRIPTOR(pldat->net_base)); 633b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(__va_to_pa(pldat->tx_stat_v, pldat), 634b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_TXSTATUS(pldat->net_base)); 635b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((ENET_RX_DESC - 1), 636b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_RXDESCRIPTORNUMBER(pldat->net_base)); 637b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(__va_to_pa(pldat->rx_desc_v, pldat), 638b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_RXDESCRIPTOR(pldat->net_base)); 639b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(__va_to_pa(pldat->rx_stat_v, pldat), 640b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_RXSTATUS(pldat->net_base)); 641b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 642b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 643b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_eth_init(struct netdata_local *pldat) 644b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 645b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 tmp; 646b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 647b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Disable controller and reset */ 648b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_COMMAND(pldat->net_base)); 649b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp &= ~LPC_COMMAND_RXENABLE | LPC_COMMAND_TXENABLE; 650b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_COMMAND(pldat->net_base)); 651b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_MAC1(pldat->net_base)); 652b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp &= ~LPC_MAC1_RECV_ENABLE; 653b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_MAC1(pldat->net_base)); 654b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 655b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Initial MAC setup */ 656b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_MAC1_PASS_ALL_RX_FRAMES, LPC_ENET_MAC1(pldat->net_base)); 657b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_MAC2_PAD_CRC_ENABLE | LPC_MAC2_CRC_ENABLE), 658b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_MAC2(pldat->net_base)); 659b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(ENET_MAXF_SIZE, LPC_ENET_MAXF(pldat->net_base)); 660b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 661b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Collision window, gap */ 662b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_CLRT_LOAD_RETRY_MAX(0xF) | 663b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_CLRT_LOAD_COLLISION_WINDOW(0x37)), 664b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_CLRT(pldat->net_base)); 665b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_IPGR_LOAD_PART2(0x12), LPC_ENET_IPGR(pldat->net_base)); 666b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 667b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) 668b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_COMMAND_PASSRUNTFRAME, 669b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_COMMAND(pldat->net_base)); 670b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else { 671b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_COMMAND_PASSRUNTFRAME | LPC_COMMAND_RMII), 672b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_COMMAND(pldat->net_base)); 673b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_SUPP_RESET_RMII, LPC_ENET_SUPP(pldat->net_base)); 674b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 675b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 676b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_params_setup(pldat); 677b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 678b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup TX and RX descriptors */ 679b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_txrx_desc_setup(pldat); 680b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 681b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup packet filtering */ 682b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_RXFLTRW_ACCEPTUBROADCAST | LPC_RXFLTRW_ACCEPTPERFECT), 683b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_RXFILTER_CTRL(pldat->net_base)); 684b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 685b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get the next TX buffer output index */ 686b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->num_used_tx_buffs = 0; 687b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->last_tx_idx = 688b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); 689b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 690b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Clear and enable interrupts */ 691b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0xFFFF, LPC_ENET_INTCLEAR(pldat->net_base)); 692b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de smp_wmb(); 693b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de lpc_eth_enable_int(pldat->net_base); 694b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 695b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Enable controller */ 696b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_COMMAND(pldat->net_base)); 697b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp |= LPC_COMMAND_RXENABLE | LPC_COMMAND_TXENABLE; 698b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_COMMAND(pldat->net_base)); 699b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_MAC1(pldat->net_base)); 700b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp |= LPC_MAC1_RECV_ENABLE; 701b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_MAC1(pldat->net_base)); 702b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 703b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 704b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_eth_shutdown(struct netdata_local *pldat) 705b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 706b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Reset ethernet and power down PHY */ 707b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_reset(pldat); 708b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0, LPC_ENET_MAC1(pldat->net_base)); 709b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0, LPC_ENET_MAC2(pldat->net_base)); 710b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 711b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 712b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 713b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * MAC<--->PHY support functions 714b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 715b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_mdio_read(struct mii_bus *bus, int phy_id, int phyreg) 716b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 717b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = bus->priv; 718b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned long timeout = jiffies + msecs_to_jiffies(100); 719b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int lps; 720b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 721b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(((phy_id << 8) | phyreg), LPC_ENET_MADR(pldat->net_base)); 722b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_MCMD_READ, LPC_ENET_MCMD(pldat->net_base)); 723b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 724b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Wait for unbusy status */ 725b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de while (readl(LPC_ENET_MIND(pldat->net_base)) & LPC_MIND_BUSY) { 726b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (time_after(jiffies, timeout)) 727b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -EIO; 728b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de cpu_relax(); 729b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 730b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 731b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de lps = readl(LPC_ENET_MRDD(pldat->net_base)); 732b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0, LPC_ENET_MCMD(pldat->net_base)); 733b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 734b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return lps; 735b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 736b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 737b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_mdio_write(struct mii_bus *bus, int phy_id, int phyreg, 738b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u16 phydata) 739b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 740b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = bus->priv; 741b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned long timeout = jiffies + msecs_to_jiffies(100); 742b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 743b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(((phy_id << 8) | phyreg), LPC_ENET_MADR(pldat->net_base)); 744b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(phydata, LPC_ENET_MWTD(pldat->net_base)); 745b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 746b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Wait for completion */ 747b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de while (readl(LPC_ENET_MIND(pldat->net_base)) & LPC_MIND_BUSY) { 748b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (time_after(jiffies, timeout)) 749b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -EIO; 750b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de cpu_relax(); 751b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 752b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 753b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 754b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 755b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 756b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_mdio_reset(struct mii_bus *bus) 757b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 758b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return __lpc_mii_mngt_reset((struct netdata_local *)bus->priv); 759b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 760b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 761b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void lpc_handle_link_change(struct net_device *ndev) 762b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 763b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 764b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct phy_device *phydev = pldat->phy_dev; 765b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned long flags; 766b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 767b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de bool status_change = false; 768b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 769b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_lock_irqsave(&pldat->lock, flags); 770b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 771b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (phydev->link) { 772b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if ((pldat->speed != phydev->speed) || 773b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de (pldat->duplex != phydev->duplex)) { 774b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->speed = phydev->speed; 775b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->duplex = phydev->duplex; 776b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de status_change = true; 777b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 778b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 779b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 780b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (phydev->link != pldat->link) { 781b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!phydev->link) { 782b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->speed = 0; 783b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->duplex = -1; 784b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 785b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->link = phydev->link; 786b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 787b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de status_change = true; 788b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 789b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 790b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_unlock_irqrestore(&pldat->lock, flags); 791b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 792b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (status_change) 793b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_params_setup(pldat); 794b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 795b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 796b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_mii_probe(struct net_device *ndev) 797b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 798b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 799b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct phy_device *phydev = phy_find_first(pldat->mii_bus); 800b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 801b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!phydev) { 802b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_err(ndev, "no PHY found\n"); 803b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -ENODEV; 804b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 805b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 806b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Attach to the PHY */ 807b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) 808b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_info(ndev, "using MII interface\n"); 809b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else 810b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_info(ndev, "using RMII interface\n"); 811b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phydev = phy_connect(ndev, dev_name(&phydev->dev), 812b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de &lpc_handle_link_change, 0, lpc_phy_interface_mode()); 813b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 814b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (IS_ERR(phydev)) { 815b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_err(ndev, "Could not attach to PHY\n"); 816b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return PTR_ERR(phydev); 817b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 818b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 819b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* mask with MAC supported features */ 820b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phydev->supported &= PHY_BASIC_FEATURES; 821b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 822b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phydev->advertising = phydev->supported; 823b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 824b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->link = 0; 825b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->speed = 0; 826b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->duplex = -1; 827b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->phy_dev = phydev; 828b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 829b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_info(ndev, 830b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", 831b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phydev->drv->name, dev_name(&phydev->dev), phydev->irq); 832b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 833b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 834b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 835b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_mii_init(struct netdata_local *pldat) 836b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 837b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int err = -ENXIO, i; 838b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 839b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus = mdiobus_alloc(); 840b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!pldat->mii_bus) { 841b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de err = -ENOMEM; 842b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out; 843b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 844b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 845b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup MII mode */ 846b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (lpc_phy_interface_mode() == PHY_INTERFACE_MODE_MII) 847b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_COMMAND_PASSRUNTFRAME, 848b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_COMMAND(pldat->net_base)); 849b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else { 850b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel((LPC_COMMAND_PASSRUNTFRAME | LPC_COMMAND_RMII), 851b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_COMMAND(pldat->net_base)); 852b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(LPC_SUPP_RESET_RMII, LPC_ENET_SUPP(pldat->net_base)); 853b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 854b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 855b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->name = "lpc_mii_bus"; 856b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->read = &lpc_mdio_read; 857b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->write = &lpc_mdio_write; 858b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->reset = &lpc_mdio_reset; 859b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de snprintf(pldat->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", 860b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->pdev->name, pldat->pdev->id); 861b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->priv = pldat; 862b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->parent = &pldat->pdev->dev; 863b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 864b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); 865b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!pldat->mii_bus->irq) { 866b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de err = -ENOMEM; 867b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_1; 868b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 869b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 870b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de for (i = 0; i < PHY_MAX_ADDR; i++) 871b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->mii_bus->irq[i] = PHY_POLL; 872b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 873b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de platform_set_drvdata(pldat->pdev, pldat->mii_bus); 874b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 875b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (mdiobus_register(pldat->mii_bus)) 876b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_free_mdio_irq; 877b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 878b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (lpc_mii_probe(pldat->ndev) != 0) 879b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_unregister_bus; 880b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 881b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 882b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 883b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_unregister_bus: 884b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mdiobus_unregister(pldat->mii_bus); 885b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_free_mdio_irq: 886b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de kfree(pldat->mii_bus->irq); 887b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_1: 888b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mdiobus_free(pldat->mii_bus); 889b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out: 890b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return err; 891b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 892b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 893b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void __lpc_handle_xmit(struct net_device *ndev) 894b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 895b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 896b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct sk_buff *skb; 897b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 txcidx, *ptxstat, txstat; 898b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 899b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); 900b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de while (pldat->last_tx_idx != txcidx) { 901b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de skb = pldat->skb[pldat->last_tx_idx]; 902b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 903b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* A buffer is available, get buffer status */ 904b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxstat = &pldat->tx_stat_v[pldat->last_tx_idx]; 905b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de txstat = *ptxstat; 906b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 907b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Next buffer and decrement used buffer counter */ 908b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->num_used_tx_buffs--; 909b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->last_tx_idx++; 910b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->last_tx_idx >= ENET_TX_DESC) 911b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->last_tx_idx = 0; 912b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 913b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Update collision counter */ 914b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.collisions += TXSTATUS_COLLISIONS_GET(txstat); 915b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 916b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Any errors occurred? */ 917b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (txstat & TXSTATUS_ERROR) { 918b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (txstat & TXSTATUS_UNDERRUN) { 919b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* FIFO underrun */ 920b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.tx_fifo_errors++; 921b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 922b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (txstat & TXSTATUS_LATECOLL) { 923b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Late collision */ 924b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.tx_aborted_errors++; 925b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 926b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (txstat & TXSTATUS_EXCESSCOLL) { 927b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Excessive collision */ 928b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.tx_aborted_errors++; 929b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 930b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (txstat & TXSTATUS_EXCESSDEFER) { 931b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Defer limit */ 932b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.tx_aborted_errors++; 933b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 934b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.tx_errors++; 935b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } else { 936b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Update stats */ 937b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.tx_packets++; 938b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.tx_bytes += skb->len; 939b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 940b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Free buffer */ 941b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_kfree_skb_irq(skb); 942b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 943b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 944b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); 945b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 946b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 947b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (netif_queue_stopped(ndev)) 948b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_wake_queue(ndev); 949b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 950b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 951b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int __lpc_handle_recv(struct net_device *ndev, int budget) 952b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 953b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 954b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct sk_buff *skb; 955b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 rxconsidx, len, ethst; 956b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct rx_status_t *prxstat; 957b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u8 *prdbuf; 958b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int rx_done = 0; 959b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 960b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get the current RX buffer indexes */ 961b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de rxconsidx = readl(LPC_ENET_RXCONSUMEINDEX(pldat->net_base)); 962b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de while (rx_done < budget && rxconsidx != 963b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de readl(LPC_ENET_RXPRODUCEINDEX(pldat->net_base))) { 964b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get pointer to receive status */ 965b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de prxstat = &pldat->rx_stat_v[rxconsidx]; 966b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de len = (prxstat->statusinfo & RXSTATUS_SIZE) + 1; 967b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 968b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Status error? */ 969b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ethst = prxstat->statusinfo; 970b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if ((ethst & (RXSTATUS_ERROR | RXSTATUS_STATUS_ERROR)) == 971b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de (RXSTATUS_ERROR | RXSTATUS_RANGE)) 972b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ethst &= ~RXSTATUS_ERROR; 973b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 974b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (ethst & RXSTATUS_ERROR) { 975b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int si = prxstat->statusinfo; 976b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Check statuses */ 977b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (si & RXSTATUS_OVERRUN) { 978b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Overrun error */ 979b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_fifo_errors++; 980b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } else if (si & RXSTATUS_CRC) { 981b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* CRC error */ 982b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_crc_errors++; 983b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } else if (si & RXSTATUS_LENGTH) { 984b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Length error */ 985b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_length_errors++; 986b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } else if (si & RXSTATUS_ERROR) { 987b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Other error */ 988b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_length_errors++; 989b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 990b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_errors++; 991b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } else { 992b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Packet is good */ 993b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de skb = dev_alloc_skb(len + 8); 994b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!skb) 995b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_dropped++; 996b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else { 997b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de prdbuf = skb_put(skb, len); 998b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 999b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Copy packet from buffer */ 1000b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de memcpy(prdbuf, pldat->rx_buff_v + 1001b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de rxconsidx * ENET_MAXF_SIZE, len); 1002b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1003b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Pass to upper layer */ 1004b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de skb->protocol = eth_type_trans(skb, ndev); 1005b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_receive_skb(skb); 1006b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_packets++; 1007b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->stats.rx_bytes += len; 1008b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1009b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1010b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1011b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Increment consume index */ 1012b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de rxconsidx = rxconsidx + 1; 1013b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (rxconsidx >= ENET_RX_DESC) 1014b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de rxconsidx = 0; 1015b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(rxconsidx, 1016b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_ENET_RXCONSUMEINDEX(pldat->net_base)); 1017b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de rx_done++; 1018b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1019b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1020b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return rx_done; 1021b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1022b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1023b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_poll(struct napi_struct *napi, int budget) 1024b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1025b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = container_of(napi, 1026b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local, napi); 1027b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev = pldat->ndev; 1028b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int rx_done = 0; 1029b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdev_queue *txq = netdev_get_tx_queue(ndev, 0); 1030b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1031b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __netif_tx_lock(txq, smp_processor_id()); 1032b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_handle_xmit(ndev); 1033b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __netif_tx_unlock(txq); 1034b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de rx_done = __lpc_handle_recv(ndev, budget); 1035b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1036b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (rx_done < budget) { 1037b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de napi_complete(napi); 1038b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de lpc_eth_enable_int(pldat->net_base); 1039b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1040b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1041b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return rx_done; 1042b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1043b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1044b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic irqreturn_t __lpc_eth_interrupt(int irq, void *dev_id) 1045b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1046b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev = dev_id; 1047b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1048b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 tmp; 1049b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1050b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_lock(&pldat->lock); 1051b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1052b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp = readl(LPC_ENET_INTSTATUS(pldat->net_base)); 1053b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Clear interrupts */ 1054b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp, LPC_ENET_INTCLEAR(pldat->net_base)); 1055b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1056b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de lpc_eth_disable_int(pldat->net_base); 1057b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (likely(napi_schedule_prep(&pldat->napi))) 1058b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __napi_schedule(&pldat->napi); 1059b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1060b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_unlock(&pldat->lock); 1061b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1062b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return IRQ_HANDLED; 1063b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1064b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1065b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_close(struct net_device *ndev) 1066b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1067b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned long flags; 1068b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1069b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1070b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (netif_msg_ifdown(pldat)) 1071b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_dbg(&pldat->pdev->dev, "shutting down %s\n", ndev->name); 1072b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1073b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de napi_disable(&pldat->napi); 1074b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_stop_queue(ndev); 1075b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1076b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->phy_dev) 1077b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phy_stop(pldat->phy_dev); 1078b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1079b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_lock_irqsave(&pldat->lock, flags); 1080b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_reset(pldat); 1081b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_carrier_off(ndev); 1082b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0, LPC_ENET_MAC1(pldat->net_base)); 1083b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(0, LPC_ENET_MAC2(pldat->net_base)); 1084b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_unlock_irqrestore(&pldat->lock, flags); 1085b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1086b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_clock_enable(pldat, false); 1087b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1088b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 1089b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1090b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1091b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) 1092b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1093b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1094b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 len, txidx; 1095b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 *ptxstat; 1096b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct txrx_desc_t *ptxrxdesc; 1097b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1098b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de len = skb->len; 1099b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1100b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_lock_irq(&pldat->lock); 1101b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1102b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->num_used_tx_buffs >= (ENET_TX_DESC - 1)) { 1103b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* This function should never be called when there are no 1104b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de buffers */ 1105b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_stop_queue(ndev); 1106b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_unlock_irq(&pldat->lock); 1107b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de WARN(1, "BUG! TX request when no free TX buffers!\n"); 1108b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return NETDEV_TX_BUSY; 1109b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1110b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1111b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get the next TX descriptor index */ 1112b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de txidx = readl(LPC_ENET_TXPRODUCEINDEX(pldat->net_base)); 1113b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1114b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup control for the transfer */ 1115b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxstat = &pldat->tx_stat_v[txidx]; 1116b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de *ptxstat = 0; 1117b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc = &pldat->tx_desc_v[txidx]; 1118b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ptxrxdesc->control = 1119b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de (len - 1) | TXDESC_CONTROL_LAST | TXDESC_CONTROL_INT; 1120b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1121b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Copy data to the DMA buffer */ 1122b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de memcpy(pldat->tx_buff_v + txidx * ENET_MAXF_SIZE, skb->data, len); 1123b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1124b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Save the buffer and increment the buffer counter */ 1125b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->skb[txidx] = skb; 1126b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->num_used_tx_buffs++; 1127b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1128b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Start transmit */ 1129b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de txidx++; 1130b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (txidx >= ENET_TX_DESC) 1131b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de txidx = 0; 1132b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(txidx, LPC_ENET_TXPRODUCEINDEX(pldat->net_base)); 1133b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1134b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Stop queue if no more TX buffers */ 1135b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->num_used_tx_buffs >= (ENET_TX_DESC - 1)) 1136b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_stop_queue(ndev); 1137b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1138b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_unlock_irq(&pldat->lock); 1139b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1140b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return NETDEV_TX_OK; 1141b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1142b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1143b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_set_mac_address(struct net_device *ndev, void *p) 1144b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1145b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct sockaddr *addr = p; 1146b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1147b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned long flags; 1148b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1149b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!is_valid_ether_addr(addr->sa_data)) 1150b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -EADDRNOTAVAIL; 1151b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de memcpy(ndev->dev_addr, addr->sa_data, ETH_ALEN); 1152b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1153b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_lock_irqsave(&pldat->lock, flags); 1154b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1155b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Set station address */ 1156b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_set_mac(pldat, ndev->dev_addr); 1157b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1158b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_unlock_irqrestore(&pldat->lock, flags); 1159b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1160b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 1161b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1162b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1163b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void lpc_eth_set_multicast_list(struct net_device *ndev) 1164b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1165b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1166b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdev_hw_addr_list *mcptr = &ndev->mc; 1167b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdev_hw_addr *ha; 1168b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de u32 tmp32, hash_val, hashlo, hashhi; 1169b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unsigned long flags; 1170b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1171b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_lock_irqsave(&pldat->lock, flags); 1172b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1173b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Set station address */ 1174b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_set_mac(pldat, ndev->dev_addr); 1175b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1176b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp32 = LPC_RXFLTRW_ACCEPTUBROADCAST | LPC_RXFLTRW_ACCEPTPERFECT; 1177b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1178b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (ndev->flags & IFF_PROMISC) 1179b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp32 |= LPC_RXFLTRW_ACCEPTUNICAST | 1180b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de LPC_RXFLTRW_ACCEPTUMULTICAST; 1181b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (ndev->flags & IFF_ALLMULTI) 1182b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp32 |= LPC_RXFLTRW_ACCEPTUMULTICAST; 1183b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1184b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (netdev_hw_addr_list_count(mcptr)) 1185b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de tmp32 |= LPC_RXFLTRW_ACCEPTUMULTICASTHASH; 1186b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1187b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(tmp32, LPC_ENET_RXFILTER_CTRL(pldat->net_base)); 1188b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1189b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1190b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Set initial hash table */ 1191b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de hashlo = 0x0; 1192b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de hashhi = 0x0; 1193b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1194b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* 64 bits : multicast address in hash table */ 1195b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_hw_addr_list_for_each(ha, mcptr) { 1196b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de hash_val = (ether_crc(6, ha->addr) >> 23) & 0x3F; 1197b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1198b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (hash_val >= 32) 1199b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de hashhi |= 1 << (hash_val - 32); 1200b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else 1201b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de hashlo |= 1 << hash_val; 1202b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1203b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1204b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(hashlo, LPC_ENET_HASHFILTERL(pldat->net_base)); 1205b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de writel(hashhi, LPC_ENET_HASHFILTERH(pldat->net_base)); 1206b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1207b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_unlock_irqrestore(&pldat->lock, flags); 1208b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1209b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1210b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) 1211b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1212b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1213b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct phy_device *phydev = pldat->phy_dev; 1214b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1215b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!netif_running(ndev)) 1216b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -EINVAL; 1217b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1218b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!phydev) 1219b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -ENODEV; 1220b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1221b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return phy_mii_ioctl(phydev, req, cmd); 1222b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1223b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1224b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_open(struct net_device *ndev) 1225b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1226b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1227b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1228b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (netif_msg_ifup(pldat)) 1229b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_dbg(&pldat->pdev->dev, "enabling %s\n", ndev->name); 1230b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1231b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!is_valid_ether_addr(ndev->dev_addr)) 1232b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -EADDRNOTAVAIL; 1233b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1234b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_clock_enable(pldat, true); 1235b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1236b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Reset and initialize */ 1237b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_reset(pldat); 1238b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_init(pldat); 1239b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1240b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* schedule a link state check */ 1241b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phy_start(pldat->phy_dev); 1242b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_start_queue(ndev); 1243b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de napi_enable(&pldat->napi); 1244b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1245b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 1246b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1247b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1248b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de/* 1249b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Ethtool ops 1250b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 1251b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void lpc_eth_ethtool_getdrvinfo(struct net_device *ndev, 1252b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct ethtool_drvinfo *info) 1253b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1254b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de strcpy(info->driver, MODNAME); 1255b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de strcpy(info->version, DRV_VERSION); 1256b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de strcpy(info->bus_info, dev_name(ndev->dev.parent)); 1257b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1258b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1259b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic u32 lpc_eth_ethtool_getmsglevel(struct net_device *ndev) 1260b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1261b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1262b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1263b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return pldat->msg_enable; 1264b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1265b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1266b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic void lpc_eth_ethtool_setmsglevel(struct net_device *ndev, u32 level) 1267b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1268b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1269b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1270b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->msg_enable = level; 1271b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1272b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1273b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_ethtool_getsettings(struct net_device *ndev, 1274b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct ethtool_cmd *cmd) 1275b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1276b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1277b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct phy_device *phydev = pldat->phy_dev; 1278b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1279b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!phydev) 1280b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -EOPNOTSUPP; 1281b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1282b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return phy_ethtool_gset(phydev, cmd); 1283b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1284b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1285b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_ethtool_setsettings(struct net_device *ndev, 1286b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct ethtool_cmd *cmd) 1287b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1288b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1289b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct phy_device *phydev = pldat->phy_dev; 1290b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1291b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!phydev) 1292b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return -EOPNOTSUPP; 1293b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1294b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return phy_ethtool_sset(phydev, cmd); 1295b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1296b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1297b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic const struct ethtool_ops lpc_eth_ethtool_ops = { 1298b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .get_drvinfo = lpc_eth_ethtool_getdrvinfo, 1299b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .get_settings = lpc_eth_ethtool_getsettings, 1300b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .set_settings = lpc_eth_ethtool_setsettings, 1301b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .get_msglevel = lpc_eth_ethtool_getmsglevel, 1302b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .set_msglevel = lpc_eth_ethtool_setmsglevel, 1303b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .get_link = ethtool_op_get_link, 1304b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de}; 1305b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1306b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic const struct net_device_ops lpc_netdev_ops = { 1307b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .ndo_open = lpc_eth_open, 1308b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .ndo_stop = lpc_eth_close, 1309b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .ndo_start_xmit = lpc_eth_hard_start_xmit, 1310b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .ndo_set_rx_mode = lpc_eth_set_multicast_list, 1311b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .ndo_do_ioctl = lpc_eth_ioctl, 1312b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .ndo_set_mac_address = lpc_set_mac_address, 1313b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de}; 1314b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1315b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_drv_probe(struct platform_device *pdev) 1316b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1317b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct resource *res; 1318b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct resource *dma_res; 1319b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev; 1320b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat; 1321b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct phy_device *phydev; 1322b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dma_addr_t dma_handle; 1323b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de int irq, ret; 1324b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1325b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get platform resources */ 1326b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1327b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1328b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de irq = platform_get_irq(pdev, 0); 1329b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if ((!res) || (!dma_res) || (irq < 0) || (irq >= NR_IRQS)) { 1330b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_err(&pdev->dev, "error getting resources.\n"); 1331b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ret = -ENXIO; 1332b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_exit; 1333b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1334b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1335b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Allocate net driver data structure */ 1336b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev = alloc_etherdev(sizeof(struct netdata_local)); 1337b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!ndev) { 1338b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_err(&pdev->dev, "could not allocate device.\n"); 1339b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ret = -ENOMEM; 1340b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_exit; 1341b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1342b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1343b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de SET_NETDEV_DEV(ndev, &pdev->dev); 1344b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1345b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat = netdev_priv(ndev); 1346b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->pdev = pdev; 1347b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->ndev = ndev; 1348b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1349b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de spin_lock_init(&pldat->lock); 1350b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1351b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Save resources */ 1352b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->irq = irq; 1353b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1354b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get clock for the device */ 1355b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->clk = clk_get(&pdev->dev, NULL); 1356b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (IS_ERR(pldat->clk)) { 1357b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_err(&pdev->dev, "error getting clock.\n"); 1358b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ret = PTR_ERR(pldat->clk); 1359b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_free_dev; 1360b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1361b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1362b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Enable network clock */ 1363b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_clock_enable(pldat, true); 1364b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1365b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Map IO space */ 1366b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->net_base = ioremap(res->start, res->end - res->start + 1); 1367b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!pldat->net_base) { 1368b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_err(&pdev->dev, "failed to map registers\n"); 1369b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ret = -ENOMEM; 1370b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_disable_clocks; 1371b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1372b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ret = request_irq(ndev->irq, __lpc_eth_interrupt, 0, 1373b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->name, ndev); 1374b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (ret) { 1375b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_err(&pdev->dev, "error requesting interrupt.\n"); 1376b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_iounmap; 1377b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1378b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1379b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Fill in the fields of the device structure with ethernet values. */ 1380b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ether_setup(ndev); 1381b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1382b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Setup driver functions */ 1383b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->netdev_ops = &lpc_netdev_ops; 1384b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->ethtool_ops = &lpc_eth_ethtool_ops; 1385b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ndev->watchdog_timeo = msecs_to_jiffies(2500); 1386b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1387b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get size of DMA buffers/descriptors region */ 1388b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_size = (ENET_TX_DESC + ENET_RX_DESC) * (ENET_MAXF_SIZE + 1389b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de sizeof(struct txrx_desc_t) + sizeof(struct rx_status_t)); 1390b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_v = 0; 1391b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1392b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (use_iram_for_net()) { 1393b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dma_handle = dma_res->start; 1394b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->dma_buff_size <= lpc32xx_return_iram_size()) 1395b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_v = 1396b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de io_p2v(dma_res->start); 1397b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de else 1398b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_err(ndev, 1399b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de "IRAM not big enough for net buffers, using SDRAM instead.\n"); 1400b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1401b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1402b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->dma_buff_base_v == 0) { 1403b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_size = PAGE_ALIGN(pldat->dma_buff_size); 1404b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1405b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Allocate a chunk of memory for the DMA ethernet buffers 1406b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de and descriptors */ 1407b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_v = 1408b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dma_alloc_coherent(&pldat->pdev->dev, 1409b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_size, &dma_handle, 1410b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de GFP_KERNEL); 1411b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1412b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (pldat->dma_buff_base_v == NULL) { 1413b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_err(&pdev->dev, "error getting DMA region.\n"); 1414b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ret = -ENOMEM; 1415b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_free_irq; 1416b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1417b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1418b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_p = dma_handle; 1419b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1420b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_dbg(ndev, "IO address start :0x%08x\n", 1421b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de res->start); 1422b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_dbg(ndev, "IO address size :%d\n", 1423b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de res->end - res->start + 1); 1424b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_err(ndev, "IO address (mapped) :0x%p\n", 1425b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->net_base); 1426b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_dbg(ndev, "IRQ number :%d\n", ndev->irq); 1427b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_dbg(ndev, "DMA buffer size :%d\n", pldat->dma_buff_size); 1428b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_dbg(ndev, "DMA buffer P address :0x%08x\n", 1429b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_p); 1430b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_dbg(ndev, "DMA buffer V address :0x%p\n", 1431b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_v); 1432b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1433b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Get MAC address from current HW setting (POR state is all zeros) */ 1434b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_get_mac(pldat, ndev->dev_addr); 1435b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1436b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#ifdef CONFIG_OF_NET 1437b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!is_valid_ether_addr(ndev->dev_addr)) { 1438b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de const char *macaddr = of_get_mac_address(pdev->dev.of_node); 1439b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (macaddr) 1440b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de memcpy(ndev->dev_addr, macaddr, ETH_ALEN); 1441b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1442b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#endif 1443b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!is_valid_ether_addr(ndev->dev_addr)) 1444cdaf0b835df04177397b90214f8b457fd23b67e0stigge@antcom.de eth_hw_addr_random(ndev); 1445b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1446b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Reset the ethernet controller */ 1447b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_reset(pldat); 1448b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1449b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* then shut everything down to save power */ 1450b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_shutdown(pldat); 1451b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1452b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Set default parameters */ 1453b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->msg_enable = NETIF_MSG_LINK; 1454b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1455b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Force an MII interface reset and clock setup */ 1456b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_mii_mngt_reset(pldat); 1457b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1458b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Force default PHY interface setup in chip, this will probably be 1459b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de changed by the PHY driver */ 1460b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->link = 0; 1461b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->speed = 100; 1462b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->duplex = DUPLEX_FULL; 1463b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_params_setup(pldat); 1464b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1465b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_napi_add(ndev, &pldat->napi, lpc_eth_poll, NAPI_WEIGHT); 1466b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1467b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de ret = register_netdev(ndev); 1468b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (ret) { 1469b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); 1470b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_dma_unmap; 1471b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1472b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de platform_set_drvdata(pdev, ndev); 1473b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1474b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (lpc_mii_init(pldat) != 0) 1475b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de goto err_out_unregister_netdev; 1476b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1477b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netdev_info(ndev, "LPC mac at 0x%08x irq %d\n", 1478b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de res->start, ndev->irq); 1479b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1480b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de phydev = pldat->phy_dev; 1481b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1482b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de device_init_wakeup(&pdev->dev, 1); 1483b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de device_set_wakeup_enable(&pdev->dev, 0); 1484b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1485b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 1486b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1487b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_unregister_netdev: 1488b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de platform_set_drvdata(pdev, NULL); 1489b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unregister_netdev(ndev); 1490b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_dma_unmap: 1491b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!use_iram_for_net() || 1492b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_size > lpc32xx_return_iram_size()) 1493b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, 1494b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_v, 1495b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_p); 1496b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_free_irq: 1497b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de free_irq(ndev->irq, ndev); 1498b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_iounmap: 1499b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de iounmap(pldat->net_base); 1500b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_disable_clocks: 1501b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_disable(pldat->clk); 1502b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_put(pldat->clk); 1503b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_out_free_dev: 1504b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de free_netdev(ndev); 1505b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deerr_exit: 1506b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pr_err("%s: not found (%d).\n", MODNAME, ret); 1507b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return ret; 1508b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1509b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1510b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_drv_remove(struct platform_device *pdev) 1511b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1512b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev = platform_get_drvdata(pdev); 1513b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1514b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1515b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de unregister_netdev(ndev); 1516b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de platform_set_drvdata(pdev, NULL); 1517b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1518b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (!use_iram_for_net() || 1519b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_size > lpc32xx_return_iram_size()) 1520b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de dma_free_coherent(&pldat->pdev->dev, pldat->dma_buff_size, 1521b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_v, 1522b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat->dma_buff_base_p); 1523b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de free_irq(ndev->irq, ndev); 1524b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de iounmap(pldat->net_base); 1525b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de mdiobus_free(pldat->mii_bus); 1526b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_disable(pldat->clk); 1527b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_put(pldat->clk); 1528b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de free_netdev(ndev); 1529b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1530b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 1531b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1532b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1533b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#ifdef CONFIG_PM 1534b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_drv_suspend(struct platform_device *pdev, 1535b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pm_message_t state) 1536b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1537b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev = platform_get_drvdata(pdev); 1538b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat = netdev_priv(ndev); 1539b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1540b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (device_may_wakeup(&pdev->dev)) 1541b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de enable_irq_wake(ndev->irq); 1542b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1543b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (ndev) { 1544b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (netif_running(ndev)) { 1545b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_device_detach(ndev); 1546b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_shutdown(pldat); 1547b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_disable(pldat->clk); 1548b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1549b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* 1550b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * Reset again now clock is disable to be sure 1551b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de * EMC_MDC is down 1552b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de */ 1553b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_reset(pldat); 1554b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1555b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1556b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1557b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 1558b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1559b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1560b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic int lpc_eth_drv_resume(struct platform_device *pdev) 1561b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de{ 1562b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct net_device *ndev = platform_get_drvdata(pdev); 1563b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de struct netdata_local *pldat; 1564b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1565b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (device_may_wakeup(&pdev->dev)) 1566b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de disable_irq_wake(ndev->irq); 1567b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1568b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (ndev) { 1569b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de if (netif_running(ndev)) { 1570b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de pldat = netdev_priv(ndev); 1571b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1572b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Enable interface clock */ 1573b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de clk_enable(pldat->clk); 1574b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1575b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de /* Reset and initialize */ 1576b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_reset(pldat); 1577b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de __lpc_eth_init(pldat); 1578b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1579b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de netif_device_attach(ndev); 1580b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1581b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de } 1582b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1583b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de return 0; 1584b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de} 1585b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#endif 1586b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1587b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.destatic struct platform_driver lpc_eth_driver = { 1588b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .probe = lpc_eth_drv_probe, 1589b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .remove = __devexit_p(lpc_eth_drv_remove), 1590b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#ifdef CONFIG_PM 1591b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .suspend = lpc_eth_drv_suspend, 1592b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .resume = lpc_eth_drv_resume, 1593b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de#endif 1594b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .driver = { 1595b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de .name = MODNAME, 1596b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de }, 1597b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de}; 1598b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1599b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.demodule_platform_driver(lpc_eth_driver); 1600b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.de 1601b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deMODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>"); 1602b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deMODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); 1603b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deMODULE_DESCRIPTION("LPC Ethernet Driver"); 1604b7370112f5195ae2e2e52b5ef46961422fa4daf0stigge@antcom.deMODULE_LICENSE("GPL"); 1605