1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
|
/*
* Nuvoton NPCM7xx EMC Module
*
* Copyright 2020 Google LLC
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef NPCM7XX_EMC_H
#define NPCM7XX_EMC_H
#include "hw/irq.h"
#include "hw/sysbus.h"
#include "net/net.h"
/* 32-bit register indices. */
enum NPCM7xxPWMRegister {
/* Control registers. */
REG_CAMCMR,
REG_CAMEN,
/* There are 16 CAMn[ML] registers. */
REG_CAMM_BASE,
REG_CAML_BASE,
REG_CAMML_LAST = 0x21,
REG_TXDLSA = 0x22,
REG_RXDLSA,
REG_MCMDR,
REG_MIID,
REG_MIIDA,
REG_FFTCR,
REG_TSDR,
REG_RSDR,
REG_DMARFC,
REG_MIEN,
/* Status registers. */
REG_MISTA,
REG_MGSTA,
REG_MPCNT,
REG_MRPC,
REG_MRPCC,
REG_MREPC,
REG_DMARFS,
REG_CTXDSA,
REG_CTXBSA,
REG_CRXDSA,
REG_CRXBSA,
NPCM7XX_NUM_EMC_REGS,
};
/* REG_CAMCMR fields */
/* Enable CAM Compare */
#define REG_CAMCMR_ECMP (1 << 4)
/* Complement CAM Compare */
#define REG_CAMCMR_CCAM (1 << 3)
/* Accept Broadcast Packet */
#define REG_CAMCMR_ABP (1 << 2)
/* Accept Multicast Packet */
#define REG_CAMCMR_AMP (1 << 1)
/* Accept Unicast Packet */
#define REG_CAMCMR_AUP (1 << 0)
/* REG_MCMDR fields */
/* Software Reset */
#define REG_MCMDR_SWR (1 << 24)
/* Internal Loopback Select */
#define REG_MCMDR_LBK (1 << 21)
/* Operation Mode Select */
#define REG_MCMDR_OPMOD (1 << 20)
/* Enable MDC Clock Generation */
#define REG_MCMDR_ENMDC (1 << 19)
/* Full-Duplex Mode Select */
#define REG_MCMDR_FDUP (1 << 18)
/* Enable SQE Checking */
#define REG_MCMDR_ENSEQ (1 << 17)
/* Send PAUSE Frame */
#define REG_MCMDR_SDPZ (1 << 16)
/* No Defer */
#define REG_MCMDR_NDEF (1 << 9)
/* Frame Transmission On */
#define REG_MCMDR_TXON (1 << 8)
/* Strip CRC Checksum */
#define REG_MCMDR_SPCRC (1 << 5)
/* Accept CRC Error Packet */
#define REG_MCMDR_AEP (1 << 4)
/* Accept Control Packet */
#define REG_MCMDR_ACP (1 << 3)
/* Accept Runt Packet */
#define REG_MCMDR_ARP (1 << 2)
/* Accept Long Packet */
#define REG_MCMDR_ALP (1 << 1)
/* Frame Reception On */
#define REG_MCMDR_RXON (1 << 0)
/* REG_MIEN fields */
/* Enable Transmit Descriptor Unavailable Interrupt */
#define REG_MIEN_ENTDU (1 << 23)
/* Enable Transmit Completion Interrupt */
#define REG_MIEN_ENTXCP (1 << 18)
/* Enable Transmit Interrupt */
#define REG_MIEN_ENTXINTR (1 << 16)
/* Enable Receive Descriptor Unavailable Interrupt */
#define REG_MIEN_ENRDU (1 << 10)
/* Enable Receive Good Interrupt */
#define REG_MIEN_ENRXGD (1 << 4)
/* Enable Receive Interrupt */
#define REG_MIEN_ENRXINTR (1 << 0)
/* REG_MISTA fields */
/* TODO: Add error fields and support simulated errors? */
/* Transmit Bus Error Interrupt */
#define REG_MISTA_TXBERR (1 << 24)
/* Transmit Descriptor Unavailable Interrupt */
#define REG_MISTA_TDU (1 << 23)
/* Transmit Completion Interrupt */
#define REG_MISTA_TXCP (1 << 18)
/* Transmit Interrupt */
#define REG_MISTA_TXINTR (1 << 16)
/* Receive Bus Error Interrupt */
#define REG_MISTA_RXBERR (1 << 11)
/* Receive Descriptor Unavailable Interrupt */
#define REG_MISTA_RDU (1 << 10)
/* DMA Early Notification Interrupt */
#define REG_MISTA_DENI (1 << 9)
/* Maximum Frame Length Interrupt */
#define REG_MISTA_DFOI (1 << 8)
/* Receive Good Interrupt */
#define REG_MISTA_RXGD (1 << 4)
/* Packet Too Long Interrupt */
#define REG_MISTA_PTLE (1 << 3)
/* Receive Interrupt */
#define REG_MISTA_RXINTR (1 << 0)
/* REG_MGSTA fields */
/* Transmission Halted */
#define REG_MGSTA_TXHA (1 << 11)
/* Receive Halted */
#define REG_MGSTA_RXHA (1 << 11)
/* REG_DMARFC fields */
/* Maximum Receive Frame Length */
#define REG_DMARFC_RXMS(word) extract32((word), 0, 16)
/* REG MIIDA fields */
/* Busy Bit */
#define REG_MIIDA_BUSY (1 << 17)
/* Transmit and receive descriptors */
typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
struct NPCM7xxEMCTxDesc {
uint32_t flags;
uint32_t txbsa;
uint32_t status_and_length;
uint32_t ntxdsa;
};
struct NPCM7xxEMCRxDesc {
uint32_t status_and_length;
uint32_t rxbsa;
uint32_t reserved;
uint32_t nrxdsa;
};
/* NPCM7xxEMCTxDesc.flags values */
/* Owner: 0 = cpu, 1 = emc */
#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
/* Transmit interrupt enable */
#define TX_DESC_FLAG_INTEN (1 << 2)
/* CRC append */
#define TX_DESC_FLAG_CRCAPP (1 << 1)
/* Padding enable */
#define TX_DESC_FLAG_PADEN (1 << 0)
/* NPCM7xxEMCTxDesc.status_and_length values */
/* Collision count */
#define TX_DESC_STATUS_CCNT_SHIFT 28
#define TX_DESC_STATUS_CCNT_BITSIZE 4
/* SQE error */
#define TX_DESC_STATUS_SQE (1 << 26)
/* Transmission paused */
#define TX_DESC_STATUS_PAU (1 << 25)
/* P transmission halted */
#define TX_DESC_STATUS_TXHA (1 << 24)
/* Late collision */
#define TX_DESC_STATUS_LC (1 << 23)
/* Transmission abort */
#define TX_DESC_STATUS_TXABT (1 << 22)
/* No carrier sense */
#define TX_DESC_STATUS_NCS (1 << 21)
/* Defer exceed */
#define TX_DESC_STATUS_EXDEF (1 << 20)
/* Transmission complete */
#define TX_DESC_STATUS_TXCP (1 << 19)
/* Transmission deferred */
#define TX_DESC_STATUS_DEF (1 << 17)
/* Transmit interrupt */
#define TX_DESC_STATUS_TXINTR (1 << 16)
#define TX_DESC_PKT_LEN(word) extract32((word), 0, 16)
/* Transmit buffer start address */
#define TX_DESC_TXBSA(word) ((uint32_t) (word) & ~3u)
/* Next transmit descriptor start address */
#define TX_DESC_NTXDSA(word) ((uint32_t) (word) & ~3u)
/* NPCM7xxEMCRxDesc.status_and_length values */
/* Owner: 0b00 = cpu, 0b01 = undefined, 0b10 = emc, 0b11 = undefined */
#define RX_DESC_STATUS_OWNER_SHIFT 30
#define RX_DESC_STATUS_OWNER_BITSIZE 2
#define RX_DESC_STATUS_OWNER_MASK (3 << RX_DESC_STATUS_OWNER_SHIFT)
/* Runt packet */
#define RX_DESC_STATUS_RP (1 << 22)
/* Alignment error */
#define RX_DESC_STATUS_ALIE (1 << 21)
/* Frame reception complete */
#define RX_DESC_STATUS_RXGD (1 << 20)
/* Packet too long */
#define RX_DESC_STATUS_PTLE (1 << 19)
/* CRC error */
#define RX_DESC_STATUS_CRCE (1 << 17)
/* Receive interrupt */
#define RX_DESC_STATUS_RXINTR (1 << 16)
#define RX_DESC_PKT_LEN(word) extract32((word), 0, 16)
/* Receive buffer start address */
#define RX_DESC_RXBSA(word) ((uint32_t) (word) & ~3u)
/* Next receive descriptor start address */
#define RX_DESC_NRXDSA(word) ((uint32_t) (word) & ~3u)
/* Minimum packet length, when TX_DESC_FLAG_PADEN is set. */
#define MIN_PACKET_LENGTH 64
struct NPCM7xxEMCState {
/*< private >*/
SysBusDevice parent;
/*< public >*/
MemoryRegion iomem;
qemu_irq tx_irq;
qemu_irq rx_irq;
NICState *nic;
NICConf conf;
/* 0 or 1, for log messages */
uint8_t emc_num;
uint32_t regs[NPCM7XX_NUM_EMC_REGS];
/*
* tx is active. Set to true by TSDR and then switches off when out of
* descriptors. If the TXON bit in REG_MCMDR is off then this is off.
*/
bool tx_active;
/*
* rx is active. Set to true by RSDR and then switches off when out of
* descriptors. If the RXON bit in REG_MCMDR is off then this is off.
*/
bool rx_active;
};
typedef struct NPCM7xxEMCState NPCM7xxEMCState;
#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
#define NPCM7XX_EMC(obj) \
OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
#endif /* NPCM7XX_EMC_H */
|