1*f5b89e41SKrzysztof Hałasa /* 2*f5b89e41SKrzysztof Hałasa * Intel IXP4xx HSS (synchronous serial port) driver for Linux 3*f5b89e41SKrzysztof Hałasa * 4*f5b89e41SKrzysztof Hałasa * Copyright (C) 2007-2008 Krzysztof Hałasa <khc@pm.waw.pl> 5*f5b89e41SKrzysztof Hałasa * 6*f5b89e41SKrzysztof Hałasa * This program is free software; you can redistribute it and/or modify it 7*f5b89e41SKrzysztof Hałasa * under the terms of version 2 of the GNU General Public License 8*f5b89e41SKrzysztof Hałasa * as published by the Free Software Foundation. 9*f5b89e41SKrzysztof Hałasa */ 10*f5b89e41SKrzysztof Hałasa 11*f5b89e41SKrzysztof Hałasa #include <linux/bitops.h> 12*f5b89e41SKrzysztof Hałasa #include <linux/cdev.h> 13*f5b89e41SKrzysztof Hałasa #include <linux/dma-mapping.h> 14*f5b89e41SKrzysztof Hałasa #include <linux/dmapool.h> 15*f5b89e41SKrzysztof Hałasa #include <linux/fs.h> 16*f5b89e41SKrzysztof Hałasa #include <linux/hdlc.h> 17*f5b89e41SKrzysztof Hałasa #include <linux/io.h> 18*f5b89e41SKrzysztof Hałasa #include <linux/kernel.h> 19*f5b89e41SKrzysztof Hałasa #include <linux/platform_device.h> 20*f5b89e41SKrzysztof Hałasa #include <linux/poll.h> 21*f5b89e41SKrzysztof Hałasa #include <mach/npe.h> 22*f5b89e41SKrzysztof Hałasa #include <mach/qmgr.h> 23*f5b89e41SKrzysztof Hałasa 24*f5b89e41SKrzysztof Hałasa #define DEBUG_QUEUES 0 25*f5b89e41SKrzysztof Hałasa #define DEBUG_DESC 0 26*f5b89e41SKrzysztof Hałasa #define DEBUG_RX 0 27*f5b89e41SKrzysztof Hałasa #define DEBUG_TX 0 28*f5b89e41SKrzysztof Hałasa #define DEBUG_PKT_BYTES 0 29*f5b89e41SKrzysztof Hałasa #define DEBUG_CLOSE 0 30*f5b89e41SKrzysztof Hałasa 31*f5b89e41SKrzysztof Hałasa #define DRV_NAME "ixp4xx_hss" 32*f5b89e41SKrzysztof Hałasa 33*f5b89e41SKrzysztof Hałasa #define PKT_EXTRA_FLAGS 0 /* orig 1 */ 34*f5b89e41SKrzysztof Hałasa #define PKT_NUM_PIPES 1 /* 1, 2 or 4 */ 35*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_FIFO_SIZEW 4 /* total 4 dwords per HSS */ 36*f5b89e41SKrzysztof Hałasa 37*f5b89e41SKrzysztof Hałasa #define RX_DESCS 16 /* also length of all RX queues */ 38*f5b89e41SKrzysztof Hałasa #define TX_DESCS 16 /* also length of all TX queues */ 39*f5b89e41SKrzysztof Hałasa 40*f5b89e41SKrzysztof Hałasa #define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS)) 41*f5b89e41SKrzysztof Hałasa #define RX_SIZE (HDLC_MAX_MRU + 4) /* NPE needs more space */ 42*f5b89e41SKrzysztof Hałasa #define MAX_CLOSE_WAIT 1000 /* microseconds */ 43*f5b89e41SKrzysztof Hałasa #define HSS_COUNT 2 44*f5b89e41SKrzysztof Hałasa #define FRAME_SIZE 256 /* doesn't matter at this point */ 45*f5b89e41SKrzysztof Hałasa #define FRAME_OFFSET 0 46*f5b89e41SKrzysztof Hałasa #define MAX_CHANNELS (FRAME_SIZE / 8) 47*f5b89e41SKrzysztof Hałasa 48*f5b89e41SKrzysztof Hałasa #define NAPI_WEIGHT 16 49*f5b89e41SKrzysztof Hałasa 50*f5b89e41SKrzysztof Hałasa /* Queue IDs */ 51*f5b89e41SKrzysztof Hałasa #define HSS0_CHL_RXTRIG_QUEUE 12 /* orig size = 32 dwords */ 52*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_RX_QUEUE 13 /* orig size = 32 dwords */ 53*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_TX0_QUEUE 14 /* orig size = 16 dwords */ 54*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_TX1_QUEUE 15 55*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_TX2_QUEUE 16 56*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_TX3_QUEUE 17 57*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_RXFREE0_QUEUE 18 /* orig size = 16 dwords */ 58*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_RXFREE1_QUEUE 19 59*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_RXFREE2_QUEUE 20 60*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_RXFREE3_QUEUE 21 61*f5b89e41SKrzysztof Hałasa #define HSS0_PKT_TXDONE_QUEUE 22 /* orig size = 64 dwords */ 62*f5b89e41SKrzysztof Hałasa 63*f5b89e41SKrzysztof Hałasa #define HSS1_CHL_RXTRIG_QUEUE 10 64*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_RX_QUEUE 0 65*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_TX0_QUEUE 5 66*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_TX1_QUEUE 6 67*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_TX2_QUEUE 7 68*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_TX3_QUEUE 8 69*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_RXFREE0_QUEUE 1 70*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_RXFREE1_QUEUE 2 71*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_RXFREE2_QUEUE 3 72*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_RXFREE3_QUEUE 4 73*f5b89e41SKrzysztof Hałasa #define HSS1_PKT_TXDONE_QUEUE 9 74*f5b89e41SKrzysztof Hałasa 75*f5b89e41SKrzysztof Hałasa #define NPE_PKT_MODE_HDLC 0 76*f5b89e41SKrzysztof Hałasa #define NPE_PKT_MODE_RAW 1 77*f5b89e41SKrzysztof Hałasa #define NPE_PKT_MODE_56KMODE 2 78*f5b89e41SKrzysztof Hałasa #define NPE_PKT_MODE_56KENDIAN_MSB 4 79*f5b89e41SKrzysztof Hałasa 80*f5b89e41SKrzysztof Hałasa /* PKT_PIPE_HDLC_CFG_WRITE flags */ 81*f5b89e41SKrzysztof Hałasa #define PKT_HDLC_IDLE_ONES 0x1 /* default = flags */ 82*f5b89e41SKrzysztof Hałasa #define PKT_HDLC_CRC_32 0x2 /* default = CRC-16 */ 83*f5b89e41SKrzysztof Hałasa #define PKT_HDLC_MSB_ENDIAN 0x4 /* default = LE */ 84*f5b89e41SKrzysztof Hałasa 85*f5b89e41SKrzysztof Hałasa 86*f5b89e41SKrzysztof Hałasa /* hss_config, PCRs */ 87*f5b89e41SKrzysztof Hałasa /* Frame sync sampling, default = active low */ 88*f5b89e41SKrzysztof Hałasa #define PCR_FRM_SYNC_ACTIVE_HIGH 0x40000000 89*f5b89e41SKrzysztof Hałasa #define PCR_FRM_SYNC_FALLINGEDGE 0x80000000 90*f5b89e41SKrzysztof Hałasa #define PCR_FRM_SYNC_RISINGEDGE 0xC0000000 91*f5b89e41SKrzysztof Hałasa 92*f5b89e41SKrzysztof Hałasa /* Frame sync pin: input (default) or output generated off a given clk edge */ 93*f5b89e41SKrzysztof Hałasa #define PCR_FRM_SYNC_OUTPUT_FALLING 0x20000000 94*f5b89e41SKrzysztof Hałasa #define PCR_FRM_SYNC_OUTPUT_RISING 0x30000000 95*f5b89e41SKrzysztof Hałasa 96*f5b89e41SKrzysztof Hałasa /* Frame and data clock sampling on edge, default = falling */ 97*f5b89e41SKrzysztof Hałasa #define PCR_FCLK_EDGE_RISING 0x08000000 98*f5b89e41SKrzysztof Hałasa #define PCR_DCLK_EDGE_RISING 0x04000000 99*f5b89e41SKrzysztof Hałasa 100*f5b89e41SKrzysztof Hałasa /* Clock direction, default = input */ 101*f5b89e41SKrzysztof Hałasa #define PCR_SYNC_CLK_DIR_OUTPUT 0x02000000 102*f5b89e41SKrzysztof Hałasa 103*f5b89e41SKrzysztof Hałasa /* Generate/Receive frame pulses, default = enabled */ 104*f5b89e41SKrzysztof Hałasa #define PCR_FRM_PULSE_DISABLED 0x01000000 105*f5b89e41SKrzysztof Hałasa 106*f5b89e41SKrzysztof Hałasa /* Data rate is full (default) or half the configured clk speed */ 107*f5b89e41SKrzysztof Hałasa #define PCR_HALF_CLK_RATE 0x00200000 108*f5b89e41SKrzysztof Hałasa 109*f5b89e41SKrzysztof Hałasa /* Invert data between NPE and HSS FIFOs? (default = no) */ 110*f5b89e41SKrzysztof Hałasa #define PCR_DATA_POLARITY_INVERT 0x00100000 111*f5b89e41SKrzysztof Hałasa 112*f5b89e41SKrzysztof Hałasa /* TX/RX endianness, default = LSB */ 113*f5b89e41SKrzysztof Hałasa #define PCR_MSB_ENDIAN 0x00080000 114*f5b89e41SKrzysztof Hałasa 115*f5b89e41SKrzysztof Hałasa /* Normal (default) / open drain mode (TX only) */ 116*f5b89e41SKrzysztof Hałasa #define PCR_TX_PINS_OPEN_DRAIN 0x00040000 117*f5b89e41SKrzysztof Hałasa 118*f5b89e41SKrzysztof Hałasa /* No framing bit transmitted and expected on RX? (default = framing bit) */ 119*f5b89e41SKrzysztof Hałasa #define PCR_SOF_NO_FBIT 0x00020000 120*f5b89e41SKrzysztof Hałasa 121*f5b89e41SKrzysztof Hałasa /* Drive data pins? */ 122*f5b89e41SKrzysztof Hałasa #define PCR_TX_DATA_ENABLE 0x00010000 123*f5b89e41SKrzysztof Hałasa 124*f5b89e41SKrzysztof Hałasa /* Voice 56k type: drive the data pins low (default), high, high Z */ 125*f5b89e41SKrzysztof Hałasa #define PCR_TX_V56K_HIGH 0x00002000 126*f5b89e41SKrzysztof Hałasa #define PCR_TX_V56K_HIGH_IMP 0x00004000 127*f5b89e41SKrzysztof Hałasa 128*f5b89e41SKrzysztof Hałasa /* Unassigned type: drive the data pins low (default), high, high Z */ 129*f5b89e41SKrzysztof Hałasa #define PCR_TX_UNASS_HIGH 0x00000800 130*f5b89e41SKrzysztof Hałasa #define PCR_TX_UNASS_HIGH_IMP 0x00001000 131*f5b89e41SKrzysztof Hałasa 132*f5b89e41SKrzysztof Hałasa /* T1 @ 1.544MHz only: Fbit dictated in FIFO (default) or high Z */ 133*f5b89e41SKrzysztof Hałasa #define PCR_TX_FB_HIGH_IMP 0x00000400 134*f5b89e41SKrzysztof Hałasa 135*f5b89e41SKrzysztof Hałasa /* 56k data endiannes - which bit unused: high (default) or low */ 136*f5b89e41SKrzysztof Hałasa #define PCR_TX_56KE_BIT_0_UNUSED 0x00000200 137*f5b89e41SKrzysztof Hałasa 138*f5b89e41SKrzysztof Hałasa /* 56k data transmission type: 32/8 bit data (default) or 56K data */ 139*f5b89e41SKrzysztof Hałasa #define PCR_TX_56KS_56K_DATA 0x00000100 140*f5b89e41SKrzysztof Hałasa 141*f5b89e41SKrzysztof Hałasa /* hss_config, cCR */ 142*f5b89e41SKrzysztof Hałasa /* Number of packetized clients, default = 1 */ 143*f5b89e41SKrzysztof Hałasa #define CCR_NPE_HFIFO_2_HDLC 0x04000000 144*f5b89e41SKrzysztof Hałasa #define CCR_NPE_HFIFO_3_OR_4HDLC 0x08000000 145*f5b89e41SKrzysztof Hałasa 146*f5b89e41SKrzysztof Hałasa /* default = no loopback */ 147*f5b89e41SKrzysztof Hałasa #define CCR_LOOPBACK 0x02000000 148*f5b89e41SKrzysztof Hałasa 149*f5b89e41SKrzysztof Hałasa /* HSS number, default = 0 (first) */ 150*f5b89e41SKrzysztof Hałasa #define CCR_SECOND_HSS 0x01000000 151*f5b89e41SKrzysztof Hałasa 152*f5b89e41SKrzysztof Hałasa 153*f5b89e41SKrzysztof Hałasa /* hss_config, clkCR: main:10, num:10, denom:12 */ 154*f5b89e41SKrzysztof Hałasa #define CLK42X_SPEED_EXP ((0x3FF << 22) | ( 2 << 12) | 15) /*65 KHz*/ 155*f5b89e41SKrzysztof Hałasa 156*f5b89e41SKrzysztof Hałasa #define CLK42X_SPEED_512KHZ (( 130 << 22) | ( 2 << 12) | 15) 157*f5b89e41SKrzysztof Hałasa #define CLK42X_SPEED_1536KHZ (( 43 << 22) | ( 18 << 12) | 47) 158*f5b89e41SKrzysztof Hałasa #define CLK42X_SPEED_1544KHZ (( 43 << 22) | ( 33 << 12) | 192) 159*f5b89e41SKrzysztof Hałasa #define CLK42X_SPEED_2048KHZ (( 32 << 22) | ( 34 << 12) | 63) 160*f5b89e41SKrzysztof Hałasa #define CLK42X_SPEED_4096KHZ (( 16 << 22) | ( 34 << 12) | 127) 161*f5b89e41SKrzysztof Hałasa #define CLK42X_SPEED_8192KHZ (( 8 << 22) | ( 34 << 12) | 255) 162*f5b89e41SKrzysztof Hałasa 163*f5b89e41SKrzysztof Hałasa #define CLK46X_SPEED_512KHZ (( 130 << 22) | ( 24 << 12) | 127) 164*f5b89e41SKrzysztof Hałasa #define CLK46X_SPEED_1536KHZ (( 43 << 22) | (152 << 12) | 383) 165*f5b89e41SKrzysztof Hałasa #define CLK46X_SPEED_1544KHZ (( 43 << 22) | ( 66 << 12) | 385) 166*f5b89e41SKrzysztof Hałasa #define CLK46X_SPEED_2048KHZ (( 32 << 22) | (280 << 12) | 511) 167*f5b89e41SKrzysztof Hałasa #define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023) 168*f5b89e41SKrzysztof Hałasa #define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047) 169*f5b89e41SKrzysztof Hałasa 170*f5b89e41SKrzysztof Hałasa 171*f5b89e41SKrzysztof Hałasa /* hss_config, LUT entries */ 172*f5b89e41SKrzysztof Hałasa #define TDMMAP_UNASSIGNED 0 173*f5b89e41SKrzysztof Hałasa #define TDMMAP_HDLC 1 /* HDLC - packetized */ 174*f5b89e41SKrzysztof Hałasa #define TDMMAP_VOICE56K 2 /* Voice56K - 7-bit channelized */ 175*f5b89e41SKrzysztof Hałasa #define TDMMAP_VOICE64K 3 /* Voice64K - 8-bit channelized */ 176*f5b89e41SKrzysztof Hałasa 177*f5b89e41SKrzysztof Hałasa /* offsets into HSS config */ 178*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_TX_PCR 0x00 /* port configuration registers */ 179*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_RX_PCR 0x04 180*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_CORE_CR 0x08 /* loopback control, HSS# */ 181*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_CLOCK_CR 0x0C /* clock generator control */ 182*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_TX_FCR 0x10 /* frame configuration registers */ 183*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_RX_FCR 0x14 184*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_TX_LUT 0x18 /* channel look-up tables */ 185*f5b89e41SKrzysztof Hałasa #define HSS_CONFIG_RX_LUT 0x38 186*f5b89e41SKrzysztof Hałasa 187*f5b89e41SKrzysztof Hałasa 188*f5b89e41SKrzysztof Hałasa /* NPE command codes */ 189*f5b89e41SKrzysztof Hałasa /* writes the ConfigWord value to the location specified by offset */ 190*f5b89e41SKrzysztof Hałasa #define PORT_CONFIG_WRITE 0x40 191*f5b89e41SKrzysztof Hałasa 192*f5b89e41SKrzysztof Hałasa /* triggers the NPE to load the contents of the configuration table */ 193*f5b89e41SKrzysztof Hałasa #define PORT_CONFIG_LOAD 0x41 194*f5b89e41SKrzysztof Hałasa 195*f5b89e41SKrzysztof Hałasa /* triggers the NPE to return an HssErrorReadResponse message */ 196*f5b89e41SKrzysztof Hałasa #define PORT_ERROR_READ 0x42 197*f5b89e41SKrzysztof Hałasa 198*f5b89e41SKrzysztof Hałasa /* triggers the NPE to reset internal status and enable the HssPacketized 199*f5b89e41SKrzysztof Hałasa operation for the flow specified by pPipe */ 200*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_FLOW_ENABLE 0x50 201*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_FLOW_DISABLE 0x51 202*f5b89e41SKrzysztof Hałasa #define PKT_NUM_PIPES_WRITE 0x52 203*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_FIFO_SIZEW_WRITE 0x53 204*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_HDLC_CFG_WRITE 0x54 205*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_IDLE_PATTERN_WRITE 0x55 206*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_RX_SIZE_WRITE 0x56 207*f5b89e41SKrzysztof Hałasa #define PKT_PIPE_MODE_WRITE 0x57 208*f5b89e41SKrzysztof Hałasa 209*f5b89e41SKrzysztof Hałasa /* HDLC packet status values - desc->status */ 210*f5b89e41SKrzysztof Hałasa #define ERR_SHUTDOWN 1 /* stop or shutdown occurrance */ 211*f5b89e41SKrzysztof Hałasa #define ERR_HDLC_ALIGN 2 /* HDLC alignment error */ 212*f5b89e41SKrzysztof Hałasa #define ERR_HDLC_FCS 3 /* HDLC Frame Check Sum error */ 213*f5b89e41SKrzysztof Hałasa #define ERR_RXFREE_Q_EMPTY 4 /* RX-free queue became empty while receiving 214*f5b89e41SKrzysztof Hałasa this packet (if buf_len < pkt_len) */ 215*f5b89e41SKrzysztof Hałasa #define ERR_HDLC_TOO_LONG 5 /* HDLC frame size too long */ 216*f5b89e41SKrzysztof Hałasa #define ERR_HDLC_ABORT 6 /* abort sequence received */ 217*f5b89e41SKrzysztof Hałasa #define ERR_DISCONNECTING 7 /* disconnect is in progress */ 218*f5b89e41SKrzysztof Hałasa 219*f5b89e41SKrzysztof Hałasa 220*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 221*f5b89e41SKrzysztof Hałasa typedef struct sk_buff buffer_t; 222*f5b89e41SKrzysztof Hałasa #define free_buffer dev_kfree_skb 223*f5b89e41SKrzysztof Hałasa #define free_buffer_irq dev_kfree_skb_irq 224*f5b89e41SKrzysztof Hałasa #else 225*f5b89e41SKrzysztof Hałasa typedef void buffer_t; 226*f5b89e41SKrzysztof Hałasa #define free_buffer kfree 227*f5b89e41SKrzysztof Hałasa #define free_buffer_irq kfree 228*f5b89e41SKrzysztof Hałasa #endif 229*f5b89e41SKrzysztof Hałasa 230*f5b89e41SKrzysztof Hałasa struct port { 231*f5b89e41SKrzysztof Hałasa struct device *dev; 232*f5b89e41SKrzysztof Hałasa struct npe *npe; 233*f5b89e41SKrzysztof Hałasa struct net_device *netdev; 234*f5b89e41SKrzysztof Hałasa struct napi_struct napi; 235*f5b89e41SKrzysztof Hałasa struct hss_plat_info *plat; 236*f5b89e41SKrzysztof Hałasa buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; 237*f5b89e41SKrzysztof Hałasa struct desc *desc_tab; /* coherent */ 238*f5b89e41SKrzysztof Hałasa u32 desc_tab_phys; 239*f5b89e41SKrzysztof Hałasa unsigned int id; 240*f5b89e41SKrzysztof Hałasa unsigned int clock_type, clock_rate, loopback; 241*f5b89e41SKrzysztof Hałasa unsigned int initialized, carrier; 242*f5b89e41SKrzysztof Hałasa u8 hdlc_cfg; 243*f5b89e41SKrzysztof Hałasa }; 244*f5b89e41SKrzysztof Hałasa 245*f5b89e41SKrzysztof Hałasa /* NPE message structure */ 246*f5b89e41SKrzysztof Hałasa struct msg { 247*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 248*f5b89e41SKrzysztof Hałasa u8 cmd, unused, hss_port, index; 249*f5b89e41SKrzysztof Hałasa union { 250*f5b89e41SKrzysztof Hałasa struct { u8 data8a, data8b, data8c, data8d; }; 251*f5b89e41SKrzysztof Hałasa struct { u16 data16a, data16b; }; 252*f5b89e41SKrzysztof Hałasa struct { u32 data32; }; 253*f5b89e41SKrzysztof Hałasa }; 254*f5b89e41SKrzysztof Hałasa #else 255*f5b89e41SKrzysztof Hałasa u8 index, hss_port, unused, cmd; 256*f5b89e41SKrzysztof Hałasa union { 257*f5b89e41SKrzysztof Hałasa struct { u8 data8d, data8c, data8b, data8a; }; 258*f5b89e41SKrzysztof Hałasa struct { u16 data16b, data16a; }; 259*f5b89e41SKrzysztof Hałasa struct { u32 data32; }; 260*f5b89e41SKrzysztof Hałasa }; 261*f5b89e41SKrzysztof Hałasa #endif 262*f5b89e41SKrzysztof Hałasa }; 263*f5b89e41SKrzysztof Hałasa 264*f5b89e41SKrzysztof Hałasa /* HDLC packet descriptor */ 265*f5b89e41SKrzysztof Hałasa struct desc { 266*f5b89e41SKrzysztof Hałasa u32 next; /* pointer to next buffer, unused */ 267*f5b89e41SKrzysztof Hałasa 268*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 269*f5b89e41SKrzysztof Hałasa u16 buf_len; /* buffer length */ 270*f5b89e41SKrzysztof Hałasa u16 pkt_len; /* packet length */ 271*f5b89e41SKrzysztof Hałasa u32 data; /* pointer to data buffer in RAM */ 272*f5b89e41SKrzysztof Hałasa u8 status; 273*f5b89e41SKrzysztof Hałasa u8 error_count; 274*f5b89e41SKrzysztof Hałasa u16 __reserved; 275*f5b89e41SKrzysztof Hałasa #else 276*f5b89e41SKrzysztof Hałasa u16 pkt_len; /* packet length */ 277*f5b89e41SKrzysztof Hałasa u16 buf_len; /* buffer length */ 278*f5b89e41SKrzysztof Hałasa u32 data; /* pointer to data buffer in RAM */ 279*f5b89e41SKrzysztof Hałasa u16 __reserved; 280*f5b89e41SKrzysztof Hałasa u8 error_count; 281*f5b89e41SKrzysztof Hałasa u8 status; 282*f5b89e41SKrzysztof Hałasa #endif 283*f5b89e41SKrzysztof Hałasa u32 __reserved1[4]; 284*f5b89e41SKrzysztof Hałasa }; 285*f5b89e41SKrzysztof Hałasa 286*f5b89e41SKrzysztof Hałasa 287*f5b89e41SKrzysztof Hałasa #define rx_desc_phys(port, n) ((port)->desc_tab_phys + \ 288*f5b89e41SKrzysztof Hałasa (n) * sizeof(struct desc)) 289*f5b89e41SKrzysztof Hałasa #define rx_desc_ptr(port, n) (&(port)->desc_tab[n]) 290*f5b89e41SKrzysztof Hałasa 291*f5b89e41SKrzysztof Hałasa #define tx_desc_phys(port, n) ((port)->desc_tab_phys + \ 292*f5b89e41SKrzysztof Hałasa ((n) + RX_DESCS) * sizeof(struct desc)) 293*f5b89e41SKrzysztof Hałasa #define tx_desc_ptr(port, n) (&(port)->desc_tab[(n) + RX_DESCS]) 294*f5b89e41SKrzysztof Hałasa 295*f5b89e41SKrzysztof Hałasa /***************************************************************************** 296*f5b89e41SKrzysztof Hałasa * global variables 297*f5b89e41SKrzysztof Hałasa ****************************************************************************/ 298*f5b89e41SKrzysztof Hałasa 299*f5b89e41SKrzysztof Hałasa static int ports_open; 300*f5b89e41SKrzysztof Hałasa static struct dma_pool *dma_pool; 301*f5b89e41SKrzysztof Hałasa static spinlock_t npe_lock; 302*f5b89e41SKrzysztof Hałasa 303*f5b89e41SKrzysztof Hałasa static const struct { 304*f5b89e41SKrzysztof Hałasa int tx, txdone, rx, rxfree; 305*f5b89e41SKrzysztof Hałasa }queue_ids[2] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE, 306*f5b89e41SKrzysztof Hałasa HSS0_PKT_RXFREE0_QUEUE}, 307*f5b89e41SKrzysztof Hałasa {HSS1_PKT_TX0_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE, 308*f5b89e41SKrzysztof Hałasa HSS1_PKT_RXFREE0_QUEUE}, 309*f5b89e41SKrzysztof Hałasa }; 310*f5b89e41SKrzysztof Hałasa 311*f5b89e41SKrzysztof Hałasa /***************************************************************************** 312*f5b89e41SKrzysztof Hałasa * utility functions 313*f5b89e41SKrzysztof Hałasa ****************************************************************************/ 314*f5b89e41SKrzysztof Hałasa 315*f5b89e41SKrzysztof Hałasa static inline struct port* dev_to_port(struct net_device *dev) 316*f5b89e41SKrzysztof Hałasa { 317*f5b89e41SKrzysztof Hałasa return dev_to_hdlc(dev)->priv; 318*f5b89e41SKrzysztof Hałasa } 319*f5b89e41SKrzysztof Hałasa 320*f5b89e41SKrzysztof Hałasa #ifndef __ARMEB__ 321*f5b89e41SKrzysztof Hałasa static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt) 322*f5b89e41SKrzysztof Hałasa { 323*f5b89e41SKrzysztof Hałasa int i; 324*f5b89e41SKrzysztof Hałasa for (i = 0; i < cnt; i++) 325*f5b89e41SKrzysztof Hałasa dest[i] = swab32(src[i]); 326*f5b89e41SKrzysztof Hałasa } 327*f5b89e41SKrzysztof Hałasa #endif 328*f5b89e41SKrzysztof Hałasa 329*f5b89e41SKrzysztof Hałasa /***************************************************************************** 330*f5b89e41SKrzysztof Hałasa * HSS access 331*f5b89e41SKrzysztof Hałasa ****************************************************************************/ 332*f5b89e41SKrzysztof Hałasa 333*f5b89e41SKrzysztof Hałasa static void hss_npe_send(struct port *port, struct msg *msg, const char* what) 334*f5b89e41SKrzysztof Hałasa { 335*f5b89e41SKrzysztof Hałasa u32 *val = (u32*)msg; 336*f5b89e41SKrzysztof Hałasa if (npe_send_message(port->npe, msg, what)) { 337*f5b89e41SKrzysztof Hałasa printk(KERN_CRIT "HSS-%i: unable to send command [%08X:%08X]" 338*f5b89e41SKrzysztof Hałasa " to %s\n", port->id, val[0], val[1], 339*f5b89e41SKrzysztof Hałasa npe_name(port->npe)); 340*f5b89e41SKrzysztof Hałasa BUG(); 341*f5b89e41SKrzysztof Hałasa } 342*f5b89e41SKrzysztof Hałasa } 343*f5b89e41SKrzysztof Hałasa 344*f5b89e41SKrzysztof Hałasa static void hss_config_set_lut(struct port *port) 345*f5b89e41SKrzysztof Hałasa { 346*f5b89e41SKrzysztof Hałasa struct msg msg; 347*f5b89e41SKrzysztof Hałasa int ch; 348*f5b89e41SKrzysztof Hałasa 349*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 350*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_CONFIG_WRITE; 351*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 352*f5b89e41SKrzysztof Hałasa 353*f5b89e41SKrzysztof Hałasa for (ch = 0; ch < MAX_CHANNELS; ch++) { 354*f5b89e41SKrzysztof Hałasa msg.data32 >>= 2; 355*f5b89e41SKrzysztof Hałasa msg.data32 |= TDMMAP_HDLC << 30; 356*f5b89e41SKrzysztof Hałasa 357*f5b89e41SKrzysztof Hałasa if (ch % 16 == 15) { 358*f5b89e41SKrzysztof Hałasa msg.index = HSS_CONFIG_TX_LUT + ((ch / 4) & ~3); 359*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_TX_LUT"); 360*f5b89e41SKrzysztof Hałasa 361*f5b89e41SKrzysztof Hałasa msg.index += HSS_CONFIG_RX_LUT - HSS_CONFIG_TX_LUT; 362*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_RX_LUT"); 363*f5b89e41SKrzysztof Hałasa } 364*f5b89e41SKrzysztof Hałasa } 365*f5b89e41SKrzysztof Hałasa } 366*f5b89e41SKrzysztof Hałasa 367*f5b89e41SKrzysztof Hałasa static void hss_config(struct port *port) 368*f5b89e41SKrzysztof Hałasa { 369*f5b89e41SKrzysztof Hałasa struct msg msg; 370*f5b89e41SKrzysztof Hałasa 371*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 372*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_CONFIG_WRITE; 373*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 374*f5b89e41SKrzysztof Hałasa msg.index = HSS_CONFIG_TX_PCR; 375*f5b89e41SKrzysztof Hałasa msg.data32 = PCR_FRM_SYNC_OUTPUT_RISING | PCR_MSB_ENDIAN | 376*f5b89e41SKrzysztof Hałasa PCR_TX_DATA_ENABLE | PCR_SOF_NO_FBIT; 377*f5b89e41SKrzysztof Hałasa if (port->clock_type == CLOCK_INT) 378*f5b89e41SKrzysztof Hałasa msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT; 379*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_TX_PCR"); 380*f5b89e41SKrzysztof Hałasa 381*f5b89e41SKrzysztof Hałasa msg.index = HSS_CONFIG_RX_PCR; 382*f5b89e41SKrzysztof Hałasa msg.data32 ^= PCR_TX_DATA_ENABLE | PCR_DCLK_EDGE_RISING; 383*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_RX_PCR"); 384*f5b89e41SKrzysztof Hałasa 385*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 386*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_CONFIG_WRITE; 387*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 388*f5b89e41SKrzysztof Hałasa msg.index = HSS_CONFIG_CORE_CR; 389*f5b89e41SKrzysztof Hałasa msg.data32 = (port->loopback ? CCR_LOOPBACK : 0) | 390*f5b89e41SKrzysztof Hałasa (port->id ? CCR_SECOND_HSS : 0); 391*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_CORE_CR"); 392*f5b89e41SKrzysztof Hałasa 393*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 394*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_CONFIG_WRITE; 395*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 396*f5b89e41SKrzysztof Hałasa msg.index = HSS_CONFIG_CLOCK_CR; 397*f5b89e41SKrzysztof Hałasa msg.data32 = CLK42X_SPEED_2048KHZ /* FIXME */; 398*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_CLOCK_CR"); 399*f5b89e41SKrzysztof Hałasa 400*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 401*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_CONFIG_WRITE; 402*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 403*f5b89e41SKrzysztof Hałasa msg.index = HSS_CONFIG_TX_FCR; 404*f5b89e41SKrzysztof Hałasa msg.data16a = FRAME_OFFSET; 405*f5b89e41SKrzysztof Hałasa msg.data16b = FRAME_SIZE - 1; 406*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_TX_FCR"); 407*f5b89e41SKrzysztof Hałasa 408*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 409*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_CONFIG_WRITE; 410*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 411*f5b89e41SKrzysztof Hałasa msg.index = HSS_CONFIG_RX_FCR; 412*f5b89e41SKrzysztof Hałasa msg.data16a = FRAME_OFFSET; 413*f5b89e41SKrzysztof Hałasa msg.data16b = FRAME_SIZE - 1; 414*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_RX_FCR"); 415*f5b89e41SKrzysztof Hałasa 416*f5b89e41SKrzysztof Hałasa hss_config_set_lut(port); 417*f5b89e41SKrzysztof Hałasa 418*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 419*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_CONFIG_LOAD; 420*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 421*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_LOAD_CONFIG"); 422*f5b89e41SKrzysztof Hałasa 423*f5b89e41SKrzysztof Hałasa if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") || 424*f5b89e41SKrzysztof Hałasa /* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */ 425*f5b89e41SKrzysztof Hałasa msg.cmd != PORT_CONFIG_LOAD || msg.data32) { 426*f5b89e41SKrzysztof Hałasa printk(KERN_CRIT "HSS-%i: HSS_LOAD_CONFIG failed\n", 427*f5b89e41SKrzysztof Hałasa port->id); 428*f5b89e41SKrzysztof Hałasa BUG(); 429*f5b89e41SKrzysztof Hałasa } 430*f5b89e41SKrzysztof Hałasa 431*f5b89e41SKrzysztof Hałasa /* HDLC may stop working without this - check FIXME */ 432*f5b89e41SKrzysztof Hałasa npe_recv_message(port->npe, &msg, "FLUSH_IT"); 433*f5b89e41SKrzysztof Hałasa } 434*f5b89e41SKrzysztof Hałasa 435*f5b89e41SKrzysztof Hałasa static void hss_set_hdlc_cfg(struct port *port) 436*f5b89e41SKrzysztof Hałasa { 437*f5b89e41SKrzysztof Hałasa struct msg msg; 438*f5b89e41SKrzysztof Hałasa 439*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 440*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_PIPE_HDLC_CFG_WRITE; 441*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 442*f5b89e41SKrzysztof Hałasa msg.data8a = port->hdlc_cfg; /* rx_cfg */ 443*f5b89e41SKrzysztof Hałasa msg.data8b = port->hdlc_cfg | (PKT_EXTRA_FLAGS << 3); /* tx_cfg */ 444*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_HDLC_CFG"); 445*f5b89e41SKrzysztof Hałasa } 446*f5b89e41SKrzysztof Hałasa 447*f5b89e41SKrzysztof Hałasa static u32 hss_get_status(struct port *port) 448*f5b89e41SKrzysztof Hałasa { 449*f5b89e41SKrzysztof Hałasa struct msg msg; 450*f5b89e41SKrzysztof Hałasa 451*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 452*f5b89e41SKrzysztof Hałasa msg.cmd = PORT_ERROR_READ; 453*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 454*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "PORT_ERROR_READ"); 455*f5b89e41SKrzysztof Hałasa if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) { 456*f5b89e41SKrzysztof Hałasa printk(KERN_CRIT "HSS-%i: unable to read HSS status\n", 457*f5b89e41SKrzysztof Hałasa port->id); 458*f5b89e41SKrzysztof Hałasa BUG(); 459*f5b89e41SKrzysztof Hałasa } 460*f5b89e41SKrzysztof Hałasa 461*f5b89e41SKrzysztof Hałasa return msg.data32; 462*f5b89e41SKrzysztof Hałasa } 463*f5b89e41SKrzysztof Hałasa 464*f5b89e41SKrzysztof Hałasa static void hss_start_hdlc(struct port *port) 465*f5b89e41SKrzysztof Hałasa { 466*f5b89e41SKrzysztof Hałasa struct msg msg; 467*f5b89e41SKrzysztof Hałasa 468*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 469*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_PIPE_FLOW_ENABLE; 470*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 471*f5b89e41SKrzysztof Hałasa msg.data32 = 0; 472*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_ENABLE_PKT_PIPE"); 473*f5b89e41SKrzysztof Hałasa } 474*f5b89e41SKrzysztof Hałasa 475*f5b89e41SKrzysztof Hałasa static void hss_stop_hdlc(struct port *port) 476*f5b89e41SKrzysztof Hałasa { 477*f5b89e41SKrzysztof Hałasa struct msg msg; 478*f5b89e41SKrzysztof Hałasa 479*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 480*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_PIPE_FLOW_DISABLE; 481*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 482*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_DISABLE_PKT_PIPE"); 483*f5b89e41SKrzysztof Hałasa hss_get_status(port); /* make sure it's halted */ 484*f5b89e41SKrzysztof Hałasa } 485*f5b89e41SKrzysztof Hałasa 486*f5b89e41SKrzysztof Hałasa static int hss_load_firmware(struct port *port) 487*f5b89e41SKrzysztof Hałasa { 488*f5b89e41SKrzysztof Hałasa struct msg msg; 489*f5b89e41SKrzysztof Hałasa int err; 490*f5b89e41SKrzysztof Hałasa 491*f5b89e41SKrzysztof Hałasa if (port->initialized) 492*f5b89e41SKrzysztof Hałasa return 0; 493*f5b89e41SKrzysztof Hałasa 494*f5b89e41SKrzysztof Hałasa if (!npe_running(port->npe) && 495*f5b89e41SKrzysztof Hałasa (err = npe_load_firmware(port->npe, npe_name(port->npe), 496*f5b89e41SKrzysztof Hałasa port->dev))) 497*f5b89e41SKrzysztof Hałasa return err; 498*f5b89e41SKrzysztof Hałasa 499*f5b89e41SKrzysztof Hałasa /* HDLC mode configuration */ 500*f5b89e41SKrzysztof Hałasa memset(&msg, 0, sizeof(msg)); 501*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_NUM_PIPES_WRITE; 502*f5b89e41SKrzysztof Hałasa msg.hss_port = port->id; 503*f5b89e41SKrzysztof Hałasa msg.data8a = PKT_NUM_PIPES; 504*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_PKT_PIPES"); 505*f5b89e41SKrzysztof Hałasa 506*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_PIPE_FIFO_SIZEW_WRITE; 507*f5b89e41SKrzysztof Hałasa msg.data8a = PKT_PIPE_FIFO_SIZEW; 508*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_PKT_FIFO"); 509*f5b89e41SKrzysztof Hałasa 510*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_PIPE_MODE_WRITE; 511*f5b89e41SKrzysztof Hałasa msg.data8a = NPE_PKT_MODE_HDLC; 512*f5b89e41SKrzysztof Hałasa /* msg.data8b = inv_mask */ 513*f5b89e41SKrzysztof Hałasa /* msg.data8c = or_mask */ 514*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_PKT_MODE"); 515*f5b89e41SKrzysztof Hałasa 516*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_PIPE_RX_SIZE_WRITE; 517*f5b89e41SKrzysztof Hałasa msg.data16a = HDLC_MAX_MRU; /* including CRC */ 518*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_PKT_RX_SIZE"); 519*f5b89e41SKrzysztof Hałasa 520*f5b89e41SKrzysztof Hałasa msg.cmd = PKT_PIPE_IDLE_PATTERN_WRITE; 521*f5b89e41SKrzysztof Hałasa msg.data32 = 0x7F7F7F7F; /* ??? FIXME */ 522*f5b89e41SKrzysztof Hałasa hss_npe_send(port, &msg, "HSS_SET_PKT_IDLE"); 523*f5b89e41SKrzysztof Hałasa 524*f5b89e41SKrzysztof Hałasa port->initialized = 1; 525*f5b89e41SKrzysztof Hałasa return 0; 526*f5b89e41SKrzysztof Hałasa } 527*f5b89e41SKrzysztof Hałasa 528*f5b89e41SKrzysztof Hałasa /***************************************************************************** 529*f5b89e41SKrzysztof Hałasa * packetized (HDLC) operation 530*f5b89e41SKrzysztof Hałasa ****************************************************************************/ 531*f5b89e41SKrzysztof Hałasa 532*f5b89e41SKrzysztof Hałasa static inline void debug_pkt(struct net_device *dev, const char *func, 533*f5b89e41SKrzysztof Hałasa u8 *data, int len) 534*f5b89e41SKrzysztof Hałasa { 535*f5b89e41SKrzysztof Hałasa #if DEBUG_PKT_BYTES 536*f5b89e41SKrzysztof Hałasa int i; 537*f5b89e41SKrzysztof Hałasa 538*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: %s(%i)", dev->name, func, len); 539*f5b89e41SKrzysztof Hałasa for (i = 0; i < len; i++) { 540*f5b89e41SKrzysztof Hałasa if (i >= DEBUG_PKT_BYTES) 541*f5b89e41SKrzysztof Hałasa break; 542*f5b89e41SKrzysztof Hałasa printk("%s%02X", !(i % 4) ? " " : "", data[i]); 543*f5b89e41SKrzysztof Hałasa } 544*f5b89e41SKrzysztof Hałasa printk("\n"); 545*f5b89e41SKrzysztof Hałasa #endif 546*f5b89e41SKrzysztof Hałasa } 547*f5b89e41SKrzysztof Hałasa 548*f5b89e41SKrzysztof Hałasa 549*f5b89e41SKrzysztof Hałasa static inline void debug_desc(u32 phys, struct desc *desc) 550*f5b89e41SKrzysztof Hałasa { 551*f5b89e41SKrzysztof Hałasa #if DEBUG_DESC 552*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%X: %X %3X %3X %08X %X %X\n", 553*f5b89e41SKrzysztof Hałasa phys, desc->next, desc->buf_len, desc->pkt_len, 554*f5b89e41SKrzysztof Hałasa desc->data, desc->status, desc->error_count); 555*f5b89e41SKrzysztof Hałasa #endif 556*f5b89e41SKrzysztof Hałasa } 557*f5b89e41SKrzysztof Hałasa 558*f5b89e41SKrzysztof Hałasa static inline void debug_queue(unsigned int queue, int is_get, u32 phys) 559*f5b89e41SKrzysztof Hałasa { 560*f5b89e41SKrzysztof Hałasa #if DEBUG_QUEUES 561*f5b89e41SKrzysztof Hałasa static struct { 562*f5b89e41SKrzysztof Hałasa int queue; 563*f5b89e41SKrzysztof Hałasa char *name; 564*f5b89e41SKrzysztof Hałasa } names[] = { 565*f5b89e41SKrzysztof Hałasa { HSS0_PKT_TX0_QUEUE, "TX#0 " }, 566*f5b89e41SKrzysztof Hałasa { HSS0_PKT_TXDONE_QUEUE, "TX-done#0 " }, 567*f5b89e41SKrzysztof Hałasa { HSS0_PKT_RX_QUEUE, "RX#0 " }, 568*f5b89e41SKrzysztof Hałasa { HSS0_PKT_RXFREE0_QUEUE, "RX-free#0 " }, 569*f5b89e41SKrzysztof Hałasa { HSS1_PKT_TX0_QUEUE, "TX#1 " }, 570*f5b89e41SKrzysztof Hałasa { HSS1_PKT_TXDONE_QUEUE, "TX-done#1 " }, 571*f5b89e41SKrzysztof Hałasa { HSS1_PKT_RX_QUEUE, "RX#1 " }, 572*f5b89e41SKrzysztof Hałasa { HSS1_PKT_RXFREE0_QUEUE, "RX-free#1 " }, 573*f5b89e41SKrzysztof Hałasa }; 574*f5b89e41SKrzysztof Hałasa int i; 575*f5b89e41SKrzysztof Hałasa 576*f5b89e41SKrzysztof Hałasa for (i = 0; i < ARRAY_SIZE(names); i++) 577*f5b89e41SKrzysztof Hałasa if (names[i].queue == queue) 578*f5b89e41SKrzysztof Hałasa break; 579*f5b89e41SKrzysztof Hałasa 580*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "Queue %i %s%s %X\n", queue, 581*f5b89e41SKrzysztof Hałasa i < ARRAY_SIZE(names) ? names[i].name : "", 582*f5b89e41SKrzysztof Hałasa is_get ? "->" : "<-", phys); 583*f5b89e41SKrzysztof Hałasa #endif 584*f5b89e41SKrzysztof Hałasa } 585*f5b89e41SKrzysztof Hałasa 586*f5b89e41SKrzysztof Hałasa static inline u32 queue_get_entry(unsigned int queue) 587*f5b89e41SKrzysztof Hałasa { 588*f5b89e41SKrzysztof Hałasa u32 phys = qmgr_get_entry(queue); 589*f5b89e41SKrzysztof Hałasa debug_queue(queue, 1, phys); 590*f5b89e41SKrzysztof Hałasa return phys; 591*f5b89e41SKrzysztof Hałasa } 592*f5b89e41SKrzysztof Hałasa 593*f5b89e41SKrzysztof Hałasa static inline int queue_get_desc(unsigned int queue, struct port *port, 594*f5b89e41SKrzysztof Hałasa int is_tx) 595*f5b89e41SKrzysztof Hałasa { 596*f5b89e41SKrzysztof Hałasa u32 phys, tab_phys, n_desc; 597*f5b89e41SKrzysztof Hałasa struct desc *tab; 598*f5b89e41SKrzysztof Hałasa 599*f5b89e41SKrzysztof Hałasa if (!(phys = queue_get_entry(queue))) 600*f5b89e41SKrzysztof Hałasa return -1; 601*f5b89e41SKrzysztof Hałasa 602*f5b89e41SKrzysztof Hałasa BUG_ON(phys & 0x1F); 603*f5b89e41SKrzysztof Hałasa tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0); 604*f5b89e41SKrzysztof Hałasa tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0); 605*f5b89e41SKrzysztof Hałasa n_desc = (phys - tab_phys) / sizeof(struct desc); 606*f5b89e41SKrzysztof Hałasa BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS)); 607*f5b89e41SKrzysztof Hałasa debug_desc(phys, &tab[n_desc]); 608*f5b89e41SKrzysztof Hałasa BUG_ON(tab[n_desc].next); 609*f5b89e41SKrzysztof Hałasa return n_desc; 610*f5b89e41SKrzysztof Hałasa } 611*f5b89e41SKrzysztof Hałasa 612*f5b89e41SKrzysztof Hałasa static inline void queue_put_desc(unsigned int queue, u32 phys, 613*f5b89e41SKrzysztof Hałasa struct desc *desc) 614*f5b89e41SKrzysztof Hałasa { 615*f5b89e41SKrzysztof Hałasa debug_queue(queue, 0, phys); 616*f5b89e41SKrzysztof Hałasa debug_desc(phys, desc); 617*f5b89e41SKrzysztof Hałasa BUG_ON(phys & 0x1F); 618*f5b89e41SKrzysztof Hałasa qmgr_put_entry(queue, phys); 619*f5b89e41SKrzysztof Hałasa BUG_ON(qmgr_stat_overflow(queue)); 620*f5b89e41SKrzysztof Hałasa } 621*f5b89e41SKrzysztof Hałasa 622*f5b89e41SKrzysztof Hałasa 623*f5b89e41SKrzysztof Hałasa static inline void dma_unmap_tx(struct port *port, struct desc *desc) 624*f5b89e41SKrzysztof Hałasa { 625*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 626*f5b89e41SKrzysztof Hałasa dma_unmap_single(&port->netdev->dev, desc->data, 627*f5b89e41SKrzysztof Hałasa desc->buf_len, DMA_TO_DEVICE); 628*f5b89e41SKrzysztof Hałasa #else 629*f5b89e41SKrzysztof Hałasa dma_unmap_single(&port->netdev->dev, desc->data & ~3, 630*f5b89e41SKrzysztof Hałasa ALIGN((desc->data & 3) + desc->buf_len, 4), 631*f5b89e41SKrzysztof Hałasa DMA_TO_DEVICE); 632*f5b89e41SKrzysztof Hałasa #endif 633*f5b89e41SKrzysztof Hałasa } 634*f5b89e41SKrzysztof Hałasa 635*f5b89e41SKrzysztof Hałasa 636*f5b89e41SKrzysztof Hałasa static void hss_hdlc_set_carrier(void *pdev, int carrier) 637*f5b89e41SKrzysztof Hałasa { 638*f5b89e41SKrzysztof Hałasa struct net_device *netdev = pdev; 639*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(netdev); 640*f5b89e41SKrzysztof Hałasa unsigned long flags; 641*f5b89e41SKrzysztof Hałasa 642*f5b89e41SKrzysztof Hałasa spin_lock_irqsave(&npe_lock, flags); 643*f5b89e41SKrzysztof Hałasa port->carrier = carrier; 644*f5b89e41SKrzysztof Hałasa if (!port->loopback) { 645*f5b89e41SKrzysztof Hałasa if (carrier) 646*f5b89e41SKrzysztof Hałasa netif_carrier_on(netdev); 647*f5b89e41SKrzysztof Hałasa else 648*f5b89e41SKrzysztof Hałasa netif_carrier_off(netdev); 649*f5b89e41SKrzysztof Hałasa } 650*f5b89e41SKrzysztof Hałasa spin_unlock_irqrestore(&npe_lock, flags); 651*f5b89e41SKrzysztof Hałasa } 652*f5b89e41SKrzysztof Hałasa 653*f5b89e41SKrzysztof Hałasa static void hss_hdlc_rx_irq(void *pdev) 654*f5b89e41SKrzysztof Hałasa { 655*f5b89e41SKrzysztof Hałasa struct net_device *dev = pdev; 656*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(dev); 657*f5b89e41SKrzysztof Hałasa 658*f5b89e41SKrzysztof Hałasa #if DEBUG_RX 659*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name); 660*f5b89e41SKrzysztof Hałasa #endif 661*f5b89e41SKrzysztof Hałasa qmgr_disable_irq(queue_ids[port->id].rx); 662*f5b89e41SKrzysztof Hałasa netif_rx_schedule(dev, &port->napi); 663*f5b89e41SKrzysztof Hałasa } 664*f5b89e41SKrzysztof Hałasa 665*f5b89e41SKrzysztof Hałasa static int hss_hdlc_poll(struct napi_struct *napi, int budget) 666*f5b89e41SKrzysztof Hałasa { 667*f5b89e41SKrzysztof Hałasa struct port *port = container_of(napi, struct port, napi); 668*f5b89e41SKrzysztof Hałasa struct net_device *dev = port->netdev; 669*f5b89e41SKrzysztof Hałasa unsigned int rxq = queue_ids[port->id].rx; 670*f5b89e41SKrzysztof Hałasa unsigned int rxfreeq = queue_ids[port->id].rxfree; 671*f5b89e41SKrzysztof Hałasa int received = 0; 672*f5b89e41SKrzysztof Hałasa 673*f5b89e41SKrzysztof Hałasa #if DEBUG_RX 674*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_poll\n", dev->name); 675*f5b89e41SKrzysztof Hałasa #endif 676*f5b89e41SKrzysztof Hałasa 677*f5b89e41SKrzysztof Hałasa while (received < budget) { 678*f5b89e41SKrzysztof Hałasa struct sk_buff *skb; 679*f5b89e41SKrzysztof Hałasa struct desc *desc; 680*f5b89e41SKrzysztof Hałasa int n; 681*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 682*f5b89e41SKrzysztof Hałasa struct sk_buff *temp; 683*f5b89e41SKrzysztof Hałasa u32 phys; 684*f5b89e41SKrzysztof Hałasa #endif 685*f5b89e41SKrzysztof Hałasa 686*f5b89e41SKrzysztof Hałasa if ((n = queue_get_desc(rxq, port, 0)) < 0) { 687*f5b89e41SKrzysztof Hałasa #if DEBUG_RX 688*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_poll" 689*f5b89e41SKrzysztof Hałasa " netif_rx_complete\n", dev->name); 690*f5b89e41SKrzysztof Hałasa #endif 691*f5b89e41SKrzysztof Hałasa netif_rx_complete(dev, napi); 692*f5b89e41SKrzysztof Hałasa qmgr_enable_irq(rxq); 693*f5b89e41SKrzysztof Hałasa if (!qmgr_stat_empty(rxq) && 694*f5b89e41SKrzysztof Hałasa netif_rx_reschedule(dev, napi)) { 695*f5b89e41SKrzysztof Hałasa #if DEBUG_RX 696*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_poll" 697*f5b89e41SKrzysztof Hałasa " netif_rx_reschedule succeeded\n", 698*f5b89e41SKrzysztof Hałasa dev->name); 699*f5b89e41SKrzysztof Hałasa #endif 700*f5b89e41SKrzysztof Hałasa qmgr_disable_irq(rxq); 701*f5b89e41SKrzysztof Hałasa continue; 702*f5b89e41SKrzysztof Hałasa } 703*f5b89e41SKrzysztof Hałasa #if DEBUG_RX 704*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_poll all done\n", 705*f5b89e41SKrzysztof Hałasa dev->name); 706*f5b89e41SKrzysztof Hałasa #endif 707*f5b89e41SKrzysztof Hałasa return received; /* all work done */ 708*f5b89e41SKrzysztof Hałasa } 709*f5b89e41SKrzysztof Hałasa 710*f5b89e41SKrzysztof Hałasa desc = rx_desc_ptr(port, n); 711*f5b89e41SKrzysztof Hałasa #if 0 /* FIXME - error_count counts modulo 256, perhaps we should use it */ 712*f5b89e41SKrzysztof Hałasa if (desc->error_count) 713*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_poll status 0x%02X" 714*f5b89e41SKrzysztof Hałasa " errors %u\n", dev->name, desc->status, 715*f5b89e41SKrzysztof Hałasa desc->error_count); 716*f5b89e41SKrzysztof Hałasa #endif 717*f5b89e41SKrzysztof Hałasa skb = NULL; 718*f5b89e41SKrzysztof Hałasa switch (desc->status) { 719*f5b89e41SKrzysztof Hałasa case 0: 720*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 721*f5b89e41SKrzysztof Hałasa if ((skb = netdev_alloc_skb(dev, RX_SIZE)) != NULL) { 722*f5b89e41SKrzysztof Hałasa phys = dma_map_single(&dev->dev, skb->data, 723*f5b89e41SKrzysztof Hałasa RX_SIZE, 724*f5b89e41SKrzysztof Hałasa DMA_FROM_DEVICE); 725*f5b89e41SKrzysztof Hałasa if (dma_mapping_error(&dev->dev, phys)) { 726*f5b89e41SKrzysztof Hałasa dev_kfree_skb(skb); 727*f5b89e41SKrzysztof Hałasa skb = NULL; 728*f5b89e41SKrzysztof Hałasa } 729*f5b89e41SKrzysztof Hałasa } 730*f5b89e41SKrzysztof Hałasa #else 731*f5b89e41SKrzysztof Hałasa skb = netdev_alloc_skb(dev, desc->pkt_len); 732*f5b89e41SKrzysztof Hałasa #endif 733*f5b89e41SKrzysztof Hałasa if (!skb) 734*f5b89e41SKrzysztof Hałasa dev->stats.rx_dropped++; 735*f5b89e41SKrzysztof Hałasa break; 736*f5b89e41SKrzysztof Hałasa case ERR_HDLC_ALIGN: 737*f5b89e41SKrzysztof Hałasa case ERR_HDLC_ABORT: 738*f5b89e41SKrzysztof Hałasa dev->stats.rx_frame_errors++; 739*f5b89e41SKrzysztof Hałasa dev->stats.rx_errors++; 740*f5b89e41SKrzysztof Hałasa break; 741*f5b89e41SKrzysztof Hałasa case ERR_HDLC_FCS: 742*f5b89e41SKrzysztof Hałasa dev->stats.rx_crc_errors++; 743*f5b89e41SKrzysztof Hałasa dev->stats.rx_errors++; 744*f5b89e41SKrzysztof Hałasa break; 745*f5b89e41SKrzysztof Hałasa case ERR_HDLC_TOO_LONG: 746*f5b89e41SKrzysztof Hałasa dev->stats.rx_length_errors++; 747*f5b89e41SKrzysztof Hałasa dev->stats.rx_errors++; 748*f5b89e41SKrzysztof Hałasa break; 749*f5b89e41SKrzysztof Hałasa default: /* FIXME - remove printk */ 750*f5b89e41SKrzysztof Hałasa printk(KERN_ERR "%s: hss_hdlc_poll: status 0x%02X" 751*f5b89e41SKrzysztof Hałasa " errors %u\n", dev->name, desc->status, 752*f5b89e41SKrzysztof Hałasa desc->error_count); 753*f5b89e41SKrzysztof Hałasa dev->stats.rx_errors++; 754*f5b89e41SKrzysztof Hałasa } 755*f5b89e41SKrzysztof Hałasa 756*f5b89e41SKrzysztof Hałasa if (!skb) { 757*f5b89e41SKrzysztof Hałasa /* put the desc back on RX-ready queue */ 758*f5b89e41SKrzysztof Hałasa desc->buf_len = RX_SIZE; 759*f5b89e41SKrzysztof Hałasa desc->pkt_len = desc->status = 0; 760*f5b89e41SKrzysztof Hałasa queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); 761*f5b89e41SKrzysztof Hałasa continue; 762*f5b89e41SKrzysztof Hałasa } 763*f5b89e41SKrzysztof Hałasa 764*f5b89e41SKrzysztof Hałasa /* process received frame */ 765*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 766*f5b89e41SKrzysztof Hałasa temp = skb; 767*f5b89e41SKrzysztof Hałasa skb = port->rx_buff_tab[n]; 768*f5b89e41SKrzysztof Hałasa dma_unmap_single(&dev->dev, desc->data, 769*f5b89e41SKrzysztof Hałasa RX_SIZE, DMA_FROM_DEVICE); 770*f5b89e41SKrzysztof Hałasa #else 771*f5b89e41SKrzysztof Hałasa dma_sync_single(&dev->dev, desc->data, 772*f5b89e41SKrzysztof Hałasa RX_SIZE, DMA_FROM_DEVICE); 773*f5b89e41SKrzysztof Hałasa memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n], 774*f5b89e41SKrzysztof Hałasa ALIGN(desc->pkt_len, 4) / 4); 775*f5b89e41SKrzysztof Hałasa #endif 776*f5b89e41SKrzysztof Hałasa skb_put(skb, desc->pkt_len); 777*f5b89e41SKrzysztof Hałasa 778*f5b89e41SKrzysztof Hałasa debug_pkt(dev, "hss_hdlc_poll", skb->data, skb->len); 779*f5b89e41SKrzysztof Hałasa 780*f5b89e41SKrzysztof Hałasa skb->protocol = hdlc_type_trans(skb, dev); 781*f5b89e41SKrzysztof Hałasa dev->stats.rx_packets++; 782*f5b89e41SKrzysztof Hałasa dev->stats.rx_bytes += skb->len; 783*f5b89e41SKrzysztof Hałasa netif_receive_skb(skb); 784*f5b89e41SKrzysztof Hałasa 785*f5b89e41SKrzysztof Hałasa /* put the new buffer on RX-free queue */ 786*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 787*f5b89e41SKrzysztof Hałasa port->rx_buff_tab[n] = temp; 788*f5b89e41SKrzysztof Hałasa desc->data = phys; 789*f5b89e41SKrzysztof Hałasa #endif 790*f5b89e41SKrzysztof Hałasa desc->buf_len = RX_SIZE; 791*f5b89e41SKrzysztof Hałasa desc->pkt_len = 0; 792*f5b89e41SKrzysztof Hałasa queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); 793*f5b89e41SKrzysztof Hałasa received++; 794*f5b89e41SKrzysztof Hałasa } 795*f5b89e41SKrzysztof Hałasa #if DEBUG_RX 796*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "hss_hdlc_poll: end, not all work done\n"); 797*f5b89e41SKrzysztof Hałasa #endif 798*f5b89e41SKrzysztof Hałasa return received; /* not all work done */ 799*f5b89e41SKrzysztof Hałasa } 800*f5b89e41SKrzysztof Hałasa 801*f5b89e41SKrzysztof Hałasa 802*f5b89e41SKrzysztof Hałasa static void hss_hdlc_txdone_irq(void *pdev) 803*f5b89e41SKrzysztof Hałasa { 804*f5b89e41SKrzysztof Hałasa struct net_device *dev = pdev; 805*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(dev); 806*f5b89e41SKrzysztof Hałasa int n_desc; 807*f5b89e41SKrzysztof Hałasa 808*f5b89e41SKrzysztof Hałasa #if DEBUG_TX 809*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG DRV_NAME ": hss_hdlc_txdone_irq\n"); 810*f5b89e41SKrzysztof Hałasa #endif 811*f5b89e41SKrzysztof Hałasa while ((n_desc = queue_get_desc(queue_ids[port->id].txdone, 812*f5b89e41SKrzysztof Hałasa port, 1)) >= 0) { 813*f5b89e41SKrzysztof Hałasa struct desc *desc; 814*f5b89e41SKrzysztof Hałasa int start; 815*f5b89e41SKrzysztof Hałasa 816*f5b89e41SKrzysztof Hałasa desc = tx_desc_ptr(port, n_desc); 817*f5b89e41SKrzysztof Hałasa 818*f5b89e41SKrzysztof Hałasa dev->stats.tx_packets++; 819*f5b89e41SKrzysztof Hałasa dev->stats.tx_bytes += desc->pkt_len; 820*f5b89e41SKrzysztof Hałasa 821*f5b89e41SKrzysztof Hałasa dma_unmap_tx(port, desc); 822*f5b89e41SKrzysztof Hałasa #if DEBUG_TX 823*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq free %p\n", 824*f5b89e41SKrzysztof Hałasa dev->name, port->tx_buff_tab[n_desc]); 825*f5b89e41SKrzysztof Hałasa #endif 826*f5b89e41SKrzysztof Hałasa free_buffer_irq(port->tx_buff_tab[n_desc]); 827*f5b89e41SKrzysztof Hałasa port->tx_buff_tab[n_desc] = NULL; 828*f5b89e41SKrzysztof Hałasa 829*f5b89e41SKrzysztof Hałasa start = qmgr_stat_empty(port->plat->txreadyq); 830*f5b89e41SKrzysztof Hałasa queue_put_desc(port->plat->txreadyq, 831*f5b89e41SKrzysztof Hałasa tx_desc_phys(port, n_desc), desc); 832*f5b89e41SKrzysztof Hałasa if (start) { 833*f5b89e41SKrzysztof Hałasa #if DEBUG_TX 834*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" 835*f5b89e41SKrzysztof Hałasa " ready\n", dev->name); 836*f5b89e41SKrzysztof Hałasa #endif 837*f5b89e41SKrzysztof Hałasa netif_wake_queue(dev); 838*f5b89e41SKrzysztof Hałasa } 839*f5b89e41SKrzysztof Hałasa } 840*f5b89e41SKrzysztof Hałasa } 841*f5b89e41SKrzysztof Hałasa 842*f5b89e41SKrzysztof Hałasa static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) 843*f5b89e41SKrzysztof Hałasa { 844*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(dev); 845*f5b89e41SKrzysztof Hałasa unsigned int txreadyq = port->plat->txreadyq; 846*f5b89e41SKrzysztof Hałasa int len, offset, bytes, n; 847*f5b89e41SKrzysztof Hałasa void *mem; 848*f5b89e41SKrzysztof Hałasa u32 phys; 849*f5b89e41SKrzysztof Hałasa struct desc *desc; 850*f5b89e41SKrzysztof Hałasa 851*f5b89e41SKrzysztof Hałasa #if DEBUG_TX 852*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_xmit\n", dev->name); 853*f5b89e41SKrzysztof Hałasa #endif 854*f5b89e41SKrzysztof Hałasa 855*f5b89e41SKrzysztof Hałasa if (unlikely(skb->len > HDLC_MAX_MRU)) { 856*f5b89e41SKrzysztof Hałasa dev_kfree_skb(skb); 857*f5b89e41SKrzysztof Hałasa dev->stats.tx_errors++; 858*f5b89e41SKrzysztof Hałasa return NETDEV_TX_OK; 859*f5b89e41SKrzysztof Hałasa } 860*f5b89e41SKrzysztof Hałasa 861*f5b89e41SKrzysztof Hałasa debug_pkt(dev, "hss_hdlc_xmit", skb->data, skb->len); 862*f5b89e41SKrzysztof Hałasa 863*f5b89e41SKrzysztof Hałasa len = skb->len; 864*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 865*f5b89e41SKrzysztof Hałasa offset = 0; /* no need to keep alignment */ 866*f5b89e41SKrzysztof Hałasa bytes = len; 867*f5b89e41SKrzysztof Hałasa mem = skb->data; 868*f5b89e41SKrzysztof Hałasa #else 869*f5b89e41SKrzysztof Hałasa offset = (int)skb->data & 3; /* keep 32-bit alignment */ 870*f5b89e41SKrzysztof Hałasa bytes = ALIGN(offset + len, 4); 871*f5b89e41SKrzysztof Hałasa if (!(mem = kmalloc(bytes, GFP_ATOMIC))) { 872*f5b89e41SKrzysztof Hałasa dev_kfree_skb(skb); 873*f5b89e41SKrzysztof Hałasa dev->stats.tx_dropped++; 874*f5b89e41SKrzysztof Hałasa return NETDEV_TX_OK; 875*f5b89e41SKrzysztof Hałasa } 876*f5b89e41SKrzysztof Hałasa memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); 877*f5b89e41SKrzysztof Hałasa dev_kfree_skb(skb); 878*f5b89e41SKrzysztof Hałasa #endif 879*f5b89e41SKrzysztof Hałasa 880*f5b89e41SKrzysztof Hałasa phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); 881*f5b89e41SKrzysztof Hałasa if (dma_mapping_error(&dev->dev, phys)) { 882*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 883*f5b89e41SKrzysztof Hałasa dev_kfree_skb(skb); 884*f5b89e41SKrzysztof Hałasa #else 885*f5b89e41SKrzysztof Hałasa kfree(mem); 886*f5b89e41SKrzysztof Hałasa #endif 887*f5b89e41SKrzysztof Hałasa dev->stats.tx_dropped++; 888*f5b89e41SKrzysztof Hałasa return NETDEV_TX_OK; 889*f5b89e41SKrzysztof Hałasa } 890*f5b89e41SKrzysztof Hałasa 891*f5b89e41SKrzysztof Hałasa n = queue_get_desc(txreadyq, port, 1); 892*f5b89e41SKrzysztof Hałasa BUG_ON(n < 0); 893*f5b89e41SKrzysztof Hałasa desc = tx_desc_ptr(port, n); 894*f5b89e41SKrzysztof Hałasa 895*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 896*f5b89e41SKrzysztof Hałasa port->tx_buff_tab[n] = skb; 897*f5b89e41SKrzysztof Hałasa #else 898*f5b89e41SKrzysztof Hałasa port->tx_buff_tab[n] = mem; 899*f5b89e41SKrzysztof Hałasa #endif 900*f5b89e41SKrzysztof Hałasa desc->data = phys + offset; 901*f5b89e41SKrzysztof Hałasa desc->buf_len = desc->pkt_len = len; 902*f5b89e41SKrzysztof Hałasa 903*f5b89e41SKrzysztof Hałasa wmb(); 904*f5b89e41SKrzysztof Hałasa queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); 905*f5b89e41SKrzysztof Hałasa dev->trans_start = jiffies; 906*f5b89e41SKrzysztof Hałasa 907*f5b89e41SKrzysztof Hałasa if (qmgr_stat_empty(txreadyq)) { 908*f5b89e41SKrzysztof Hałasa #if DEBUG_TX 909*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); 910*f5b89e41SKrzysztof Hałasa #endif 911*f5b89e41SKrzysztof Hałasa netif_stop_queue(dev); 912*f5b89e41SKrzysztof Hałasa /* we could miss TX ready interrupt */ 913*f5b89e41SKrzysztof Hałasa if (!qmgr_stat_empty(txreadyq)) { 914*f5b89e41SKrzysztof Hałasa #if DEBUG_TX 915*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", 916*f5b89e41SKrzysztof Hałasa dev->name); 917*f5b89e41SKrzysztof Hałasa #endif 918*f5b89e41SKrzysztof Hałasa netif_wake_queue(dev); 919*f5b89e41SKrzysztof Hałasa } 920*f5b89e41SKrzysztof Hałasa } 921*f5b89e41SKrzysztof Hałasa 922*f5b89e41SKrzysztof Hałasa #if DEBUG_TX 923*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: hss_hdlc_xmit end\n", dev->name); 924*f5b89e41SKrzysztof Hałasa #endif 925*f5b89e41SKrzysztof Hałasa return NETDEV_TX_OK; 926*f5b89e41SKrzysztof Hałasa } 927*f5b89e41SKrzysztof Hałasa 928*f5b89e41SKrzysztof Hałasa 929*f5b89e41SKrzysztof Hałasa static int request_hdlc_queues(struct port *port) 930*f5b89e41SKrzysztof Hałasa { 931*f5b89e41SKrzysztof Hałasa int err; 932*f5b89e41SKrzysztof Hałasa 933*f5b89e41SKrzysztof Hałasa err = qmgr_request_queue(queue_ids[port->id].rxfree, RX_DESCS, 0, 0); 934*f5b89e41SKrzysztof Hałasa if (err) 935*f5b89e41SKrzysztof Hałasa return err; 936*f5b89e41SKrzysztof Hałasa 937*f5b89e41SKrzysztof Hałasa err = qmgr_request_queue(queue_ids[port->id].rx, RX_DESCS, 0, 0); 938*f5b89e41SKrzysztof Hałasa if (err) 939*f5b89e41SKrzysztof Hałasa goto rel_rxfree; 940*f5b89e41SKrzysztof Hałasa 941*f5b89e41SKrzysztof Hałasa err = qmgr_request_queue(queue_ids[port->id].tx, TX_DESCS, 0, 0); 942*f5b89e41SKrzysztof Hałasa if (err) 943*f5b89e41SKrzysztof Hałasa goto rel_rx; 944*f5b89e41SKrzysztof Hałasa 945*f5b89e41SKrzysztof Hałasa err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0); 946*f5b89e41SKrzysztof Hałasa if (err) 947*f5b89e41SKrzysztof Hałasa goto rel_tx; 948*f5b89e41SKrzysztof Hałasa 949*f5b89e41SKrzysztof Hałasa err = qmgr_request_queue(queue_ids[port->id].txdone, TX_DESCS, 0, 0); 950*f5b89e41SKrzysztof Hałasa if (err) 951*f5b89e41SKrzysztof Hałasa goto rel_txready; 952*f5b89e41SKrzysztof Hałasa return 0; 953*f5b89e41SKrzysztof Hałasa 954*f5b89e41SKrzysztof Hałasa rel_txready: 955*f5b89e41SKrzysztof Hałasa qmgr_release_queue(port->plat->txreadyq); 956*f5b89e41SKrzysztof Hałasa rel_tx: 957*f5b89e41SKrzysztof Hałasa qmgr_release_queue(queue_ids[port->id].tx); 958*f5b89e41SKrzysztof Hałasa rel_rx: 959*f5b89e41SKrzysztof Hałasa qmgr_release_queue(queue_ids[port->id].rx); 960*f5b89e41SKrzysztof Hałasa rel_rxfree: 961*f5b89e41SKrzysztof Hałasa qmgr_release_queue(queue_ids[port->id].rxfree); 962*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "%s: unable to request hardware queues\n", 963*f5b89e41SKrzysztof Hałasa port->netdev->name); 964*f5b89e41SKrzysztof Hałasa return err; 965*f5b89e41SKrzysztof Hałasa } 966*f5b89e41SKrzysztof Hałasa 967*f5b89e41SKrzysztof Hałasa static void release_hdlc_queues(struct port *port) 968*f5b89e41SKrzysztof Hałasa { 969*f5b89e41SKrzysztof Hałasa qmgr_release_queue(queue_ids[port->id].rxfree); 970*f5b89e41SKrzysztof Hałasa qmgr_release_queue(queue_ids[port->id].rx); 971*f5b89e41SKrzysztof Hałasa qmgr_release_queue(queue_ids[port->id].txdone); 972*f5b89e41SKrzysztof Hałasa qmgr_release_queue(queue_ids[port->id].tx); 973*f5b89e41SKrzysztof Hałasa qmgr_release_queue(port->plat->txreadyq); 974*f5b89e41SKrzysztof Hałasa } 975*f5b89e41SKrzysztof Hałasa 976*f5b89e41SKrzysztof Hałasa static int init_hdlc_queues(struct port *port) 977*f5b89e41SKrzysztof Hałasa { 978*f5b89e41SKrzysztof Hałasa int i; 979*f5b89e41SKrzysztof Hałasa 980*f5b89e41SKrzysztof Hałasa if (!ports_open) 981*f5b89e41SKrzysztof Hałasa if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, 982*f5b89e41SKrzysztof Hałasa POOL_ALLOC_SIZE, 32, 0))) 983*f5b89e41SKrzysztof Hałasa return -ENOMEM; 984*f5b89e41SKrzysztof Hałasa 985*f5b89e41SKrzysztof Hałasa if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, 986*f5b89e41SKrzysztof Hałasa &port->desc_tab_phys))) 987*f5b89e41SKrzysztof Hałasa return -ENOMEM; 988*f5b89e41SKrzysztof Hałasa memset(port->desc_tab, 0, POOL_ALLOC_SIZE); 989*f5b89e41SKrzysztof Hałasa memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */ 990*f5b89e41SKrzysztof Hałasa memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab)); 991*f5b89e41SKrzysztof Hałasa 992*f5b89e41SKrzysztof Hałasa /* Setup RX buffers */ 993*f5b89e41SKrzysztof Hałasa for (i = 0; i < RX_DESCS; i++) { 994*f5b89e41SKrzysztof Hałasa struct desc *desc = rx_desc_ptr(port, i); 995*f5b89e41SKrzysztof Hałasa buffer_t *buff; 996*f5b89e41SKrzysztof Hałasa void *data; 997*f5b89e41SKrzysztof Hałasa #ifdef __ARMEB__ 998*f5b89e41SKrzysztof Hałasa if (!(buff = netdev_alloc_skb(port->netdev, RX_SIZE))) 999*f5b89e41SKrzysztof Hałasa return -ENOMEM; 1000*f5b89e41SKrzysztof Hałasa data = buff->data; 1001*f5b89e41SKrzysztof Hałasa #else 1002*f5b89e41SKrzysztof Hałasa if (!(buff = kmalloc(RX_SIZE, GFP_KERNEL))) 1003*f5b89e41SKrzysztof Hałasa return -ENOMEM; 1004*f5b89e41SKrzysztof Hałasa data = buff; 1005*f5b89e41SKrzysztof Hałasa #endif 1006*f5b89e41SKrzysztof Hałasa desc->buf_len = RX_SIZE; 1007*f5b89e41SKrzysztof Hałasa desc->data = dma_map_single(&port->netdev->dev, data, 1008*f5b89e41SKrzysztof Hałasa RX_SIZE, DMA_FROM_DEVICE); 1009*f5b89e41SKrzysztof Hałasa if (dma_mapping_error(&port->netdev->dev, desc->data)) { 1010*f5b89e41SKrzysztof Hałasa free_buffer(buff); 1011*f5b89e41SKrzysztof Hałasa return -EIO; 1012*f5b89e41SKrzysztof Hałasa } 1013*f5b89e41SKrzysztof Hałasa port->rx_buff_tab[i] = buff; 1014*f5b89e41SKrzysztof Hałasa } 1015*f5b89e41SKrzysztof Hałasa 1016*f5b89e41SKrzysztof Hałasa return 0; 1017*f5b89e41SKrzysztof Hałasa } 1018*f5b89e41SKrzysztof Hałasa 1019*f5b89e41SKrzysztof Hałasa static void destroy_hdlc_queues(struct port *port) 1020*f5b89e41SKrzysztof Hałasa { 1021*f5b89e41SKrzysztof Hałasa int i; 1022*f5b89e41SKrzysztof Hałasa 1023*f5b89e41SKrzysztof Hałasa if (port->desc_tab) { 1024*f5b89e41SKrzysztof Hałasa for (i = 0; i < RX_DESCS; i++) { 1025*f5b89e41SKrzysztof Hałasa struct desc *desc = rx_desc_ptr(port, i); 1026*f5b89e41SKrzysztof Hałasa buffer_t *buff = port->rx_buff_tab[i]; 1027*f5b89e41SKrzysztof Hałasa if (buff) { 1028*f5b89e41SKrzysztof Hałasa dma_unmap_single(&port->netdev->dev, 1029*f5b89e41SKrzysztof Hałasa desc->data, RX_SIZE, 1030*f5b89e41SKrzysztof Hałasa DMA_FROM_DEVICE); 1031*f5b89e41SKrzysztof Hałasa free_buffer(buff); 1032*f5b89e41SKrzysztof Hałasa } 1033*f5b89e41SKrzysztof Hałasa } 1034*f5b89e41SKrzysztof Hałasa for (i = 0; i < TX_DESCS; i++) { 1035*f5b89e41SKrzysztof Hałasa struct desc *desc = tx_desc_ptr(port, i); 1036*f5b89e41SKrzysztof Hałasa buffer_t *buff = port->tx_buff_tab[i]; 1037*f5b89e41SKrzysztof Hałasa if (buff) { 1038*f5b89e41SKrzysztof Hałasa dma_unmap_tx(port, desc); 1039*f5b89e41SKrzysztof Hałasa free_buffer(buff); 1040*f5b89e41SKrzysztof Hałasa } 1041*f5b89e41SKrzysztof Hałasa } 1042*f5b89e41SKrzysztof Hałasa dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys); 1043*f5b89e41SKrzysztof Hałasa port->desc_tab = NULL; 1044*f5b89e41SKrzysztof Hałasa } 1045*f5b89e41SKrzysztof Hałasa 1046*f5b89e41SKrzysztof Hałasa if (!ports_open && dma_pool) { 1047*f5b89e41SKrzysztof Hałasa dma_pool_destroy(dma_pool); 1048*f5b89e41SKrzysztof Hałasa dma_pool = NULL; 1049*f5b89e41SKrzysztof Hałasa } 1050*f5b89e41SKrzysztof Hałasa } 1051*f5b89e41SKrzysztof Hałasa 1052*f5b89e41SKrzysztof Hałasa static int hss_hdlc_open(struct net_device *dev) 1053*f5b89e41SKrzysztof Hałasa { 1054*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(dev); 1055*f5b89e41SKrzysztof Hałasa unsigned long flags; 1056*f5b89e41SKrzysztof Hałasa int i, err = 0; 1057*f5b89e41SKrzysztof Hałasa 1058*f5b89e41SKrzysztof Hałasa if ((err = hdlc_open(dev))) 1059*f5b89e41SKrzysztof Hałasa return err; 1060*f5b89e41SKrzysztof Hałasa 1061*f5b89e41SKrzysztof Hałasa if ((err = hss_load_firmware(port))) 1062*f5b89e41SKrzysztof Hałasa goto err_hdlc_close; 1063*f5b89e41SKrzysztof Hałasa 1064*f5b89e41SKrzysztof Hałasa if ((err = request_hdlc_queues(port))) 1065*f5b89e41SKrzysztof Hałasa goto err_hdlc_close; 1066*f5b89e41SKrzysztof Hałasa 1067*f5b89e41SKrzysztof Hałasa if ((err = init_hdlc_queues(port))) 1068*f5b89e41SKrzysztof Hałasa goto err_destroy_queues; 1069*f5b89e41SKrzysztof Hałasa 1070*f5b89e41SKrzysztof Hałasa spin_lock_irqsave(&npe_lock, flags); 1071*f5b89e41SKrzysztof Hałasa if (port->plat->open) 1072*f5b89e41SKrzysztof Hałasa if ((err = port->plat->open(port->id, dev, 1073*f5b89e41SKrzysztof Hałasa hss_hdlc_set_carrier))) 1074*f5b89e41SKrzysztof Hałasa goto err_unlock; 1075*f5b89e41SKrzysztof Hałasa spin_unlock_irqrestore(&npe_lock, flags); 1076*f5b89e41SKrzysztof Hałasa 1077*f5b89e41SKrzysztof Hałasa /* Populate queues with buffers, no failure after this point */ 1078*f5b89e41SKrzysztof Hałasa for (i = 0; i < TX_DESCS; i++) 1079*f5b89e41SKrzysztof Hałasa queue_put_desc(port->plat->txreadyq, 1080*f5b89e41SKrzysztof Hałasa tx_desc_phys(port, i), tx_desc_ptr(port, i)); 1081*f5b89e41SKrzysztof Hałasa 1082*f5b89e41SKrzysztof Hałasa for (i = 0; i < RX_DESCS; i++) 1083*f5b89e41SKrzysztof Hałasa queue_put_desc(queue_ids[port->id].rxfree, 1084*f5b89e41SKrzysztof Hałasa rx_desc_phys(port, i), rx_desc_ptr(port, i)); 1085*f5b89e41SKrzysztof Hałasa 1086*f5b89e41SKrzysztof Hałasa napi_enable(&port->napi); 1087*f5b89e41SKrzysztof Hałasa netif_start_queue(dev); 1088*f5b89e41SKrzysztof Hałasa 1089*f5b89e41SKrzysztof Hałasa qmgr_set_irq(queue_ids[port->id].rx, QUEUE_IRQ_SRC_NOT_EMPTY, 1090*f5b89e41SKrzysztof Hałasa hss_hdlc_rx_irq, dev); 1091*f5b89e41SKrzysztof Hałasa 1092*f5b89e41SKrzysztof Hałasa qmgr_set_irq(queue_ids[port->id].txdone, QUEUE_IRQ_SRC_NOT_EMPTY, 1093*f5b89e41SKrzysztof Hałasa hss_hdlc_txdone_irq, dev); 1094*f5b89e41SKrzysztof Hałasa qmgr_enable_irq(queue_ids[port->id].txdone); 1095*f5b89e41SKrzysztof Hałasa 1096*f5b89e41SKrzysztof Hałasa ports_open++; 1097*f5b89e41SKrzysztof Hałasa 1098*f5b89e41SKrzysztof Hałasa hss_set_hdlc_cfg(port); 1099*f5b89e41SKrzysztof Hałasa hss_config(port); 1100*f5b89e41SKrzysztof Hałasa 1101*f5b89e41SKrzysztof Hałasa hss_start_hdlc(port); 1102*f5b89e41SKrzysztof Hałasa 1103*f5b89e41SKrzysztof Hałasa /* we may already have RX data, enables IRQ */ 1104*f5b89e41SKrzysztof Hałasa netif_rx_schedule(dev, &port->napi); 1105*f5b89e41SKrzysztof Hałasa return 0; 1106*f5b89e41SKrzysztof Hałasa 1107*f5b89e41SKrzysztof Hałasa err_unlock: 1108*f5b89e41SKrzysztof Hałasa spin_unlock_irqrestore(&npe_lock, flags); 1109*f5b89e41SKrzysztof Hałasa err_destroy_queues: 1110*f5b89e41SKrzysztof Hałasa destroy_hdlc_queues(port); 1111*f5b89e41SKrzysztof Hałasa release_hdlc_queues(port); 1112*f5b89e41SKrzysztof Hałasa err_hdlc_close: 1113*f5b89e41SKrzysztof Hałasa hdlc_close(dev); 1114*f5b89e41SKrzysztof Hałasa return err; 1115*f5b89e41SKrzysztof Hałasa } 1116*f5b89e41SKrzysztof Hałasa 1117*f5b89e41SKrzysztof Hałasa static int hss_hdlc_close(struct net_device *dev) 1118*f5b89e41SKrzysztof Hałasa { 1119*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(dev); 1120*f5b89e41SKrzysztof Hałasa unsigned long flags; 1121*f5b89e41SKrzysztof Hałasa int i, buffs = RX_DESCS; /* allocated RX buffers */ 1122*f5b89e41SKrzysztof Hałasa 1123*f5b89e41SKrzysztof Hałasa spin_lock_irqsave(&npe_lock, flags); 1124*f5b89e41SKrzysztof Hałasa ports_open--; 1125*f5b89e41SKrzysztof Hałasa qmgr_disable_irq(queue_ids[port->id].rx); 1126*f5b89e41SKrzysztof Hałasa netif_stop_queue(dev); 1127*f5b89e41SKrzysztof Hałasa napi_disable(&port->napi); 1128*f5b89e41SKrzysztof Hałasa 1129*f5b89e41SKrzysztof Hałasa hss_stop_hdlc(port); 1130*f5b89e41SKrzysztof Hałasa 1131*f5b89e41SKrzysztof Hałasa while (queue_get_desc(queue_ids[port->id].rxfree, port, 0) >= 0) 1132*f5b89e41SKrzysztof Hałasa buffs--; 1133*f5b89e41SKrzysztof Hałasa while (queue_get_desc(queue_ids[port->id].rx, port, 0) >= 0) 1134*f5b89e41SKrzysztof Hałasa buffs--; 1135*f5b89e41SKrzysztof Hałasa 1136*f5b89e41SKrzysztof Hałasa if (buffs) 1137*f5b89e41SKrzysztof Hałasa printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)" 1138*f5b89e41SKrzysztof Hałasa " left in NPE\n", dev->name, buffs); 1139*f5b89e41SKrzysztof Hałasa 1140*f5b89e41SKrzysztof Hałasa buffs = TX_DESCS; 1141*f5b89e41SKrzysztof Hałasa while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0) 1142*f5b89e41SKrzysztof Hałasa buffs--; /* cancel TX */ 1143*f5b89e41SKrzysztof Hałasa 1144*f5b89e41SKrzysztof Hałasa i = 0; 1145*f5b89e41SKrzysztof Hałasa do { 1146*f5b89e41SKrzysztof Hałasa while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0) 1147*f5b89e41SKrzysztof Hałasa buffs--; 1148*f5b89e41SKrzysztof Hałasa if (!buffs) 1149*f5b89e41SKrzysztof Hałasa break; 1150*f5b89e41SKrzysztof Hałasa } while (++i < MAX_CLOSE_WAIT); 1151*f5b89e41SKrzysztof Hałasa 1152*f5b89e41SKrzysztof Hałasa if (buffs) 1153*f5b89e41SKrzysztof Hałasa printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) " 1154*f5b89e41SKrzysztof Hałasa "left in NPE\n", dev->name, buffs); 1155*f5b89e41SKrzysztof Hałasa #if DEBUG_CLOSE 1156*f5b89e41SKrzysztof Hałasa if (!buffs) 1157*f5b89e41SKrzysztof Hałasa printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i); 1158*f5b89e41SKrzysztof Hałasa #endif 1159*f5b89e41SKrzysztof Hałasa qmgr_disable_irq(queue_ids[port->id].txdone); 1160*f5b89e41SKrzysztof Hałasa 1161*f5b89e41SKrzysztof Hałasa if (port->plat->close) 1162*f5b89e41SKrzysztof Hałasa port->plat->close(port->id, dev); 1163*f5b89e41SKrzysztof Hałasa spin_unlock_irqrestore(&npe_lock, flags); 1164*f5b89e41SKrzysztof Hałasa 1165*f5b89e41SKrzysztof Hałasa destroy_hdlc_queues(port); 1166*f5b89e41SKrzysztof Hałasa release_hdlc_queues(port); 1167*f5b89e41SKrzysztof Hałasa hdlc_close(dev); 1168*f5b89e41SKrzysztof Hałasa return 0; 1169*f5b89e41SKrzysztof Hałasa } 1170*f5b89e41SKrzysztof Hałasa 1171*f5b89e41SKrzysztof Hałasa 1172*f5b89e41SKrzysztof Hałasa static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding, 1173*f5b89e41SKrzysztof Hałasa unsigned short parity) 1174*f5b89e41SKrzysztof Hałasa { 1175*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(dev); 1176*f5b89e41SKrzysztof Hałasa 1177*f5b89e41SKrzysztof Hałasa if (encoding != ENCODING_NRZ) 1178*f5b89e41SKrzysztof Hałasa return -EINVAL; 1179*f5b89e41SKrzysztof Hałasa 1180*f5b89e41SKrzysztof Hałasa switch(parity) { 1181*f5b89e41SKrzysztof Hałasa case PARITY_CRC16_PR1_CCITT: 1182*f5b89e41SKrzysztof Hałasa port->hdlc_cfg = 0; 1183*f5b89e41SKrzysztof Hałasa return 0; 1184*f5b89e41SKrzysztof Hałasa 1185*f5b89e41SKrzysztof Hałasa case PARITY_CRC32_PR1_CCITT: 1186*f5b89e41SKrzysztof Hałasa port->hdlc_cfg = PKT_HDLC_CRC_32; 1187*f5b89e41SKrzysztof Hałasa return 0; 1188*f5b89e41SKrzysztof Hałasa 1189*f5b89e41SKrzysztof Hałasa default: 1190*f5b89e41SKrzysztof Hałasa return -EINVAL; 1191*f5b89e41SKrzysztof Hałasa } 1192*f5b89e41SKrzysztof Hałasa } 1193*f5b89e41SKrzysztof Hałasa 1194*f5b89e41SKrzysztof Hałasa 1195*f5b89e41SKrzysztof Hałasa static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 1196*f5b89e41SKrzysztof Hałasa { 1197*f5b89e41SKrzysztof Hałasa const size_t size = sizeof(sync_serial_settings); 1198*f5b89e41SKrzysztof Hałasa sync_serial_settings new_line; 1199*f5b89e41SKrzysztof Hałasa sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; 1200*f5b89e41SKrzysztof Hałasa struct port *port = dev_to_port(dev); 1201*f5b89e41SKrzysztof Hałasa unsigned long flags; 1202*f5b89e41SKrzysztof Hałasa int clk; 1203*f5b89e41SKrzysztof Hałasa 1204*f5b89e41SKrzysztof Hałasa if (cmd != SIOCWANDEV) 1205*f5b89e41SKrzysztof Hałasa return hdlc_ioctl(dev, ifr, cmd); 1206*f5b89e41SKrzysztof Hałasa 1207*f5b89e41SKrzysztof Hałasa switch(ifr->ifr_settings.type) { 1208*f5b89e41SKrzysztof Hałasa case IF_GET_IFACE: 1209*f5b89e41SKrzysztof Hałasa ifr->ifr_settings.type = IF_IFACE_V35; 1210*f5b89e41SKrzysztof Hałasa if (ifr->ifr_settings.size < size) { 1211*f5b89e41SKrzysztof Hałasa ifr->ifr_settings.size = size; /* data size wanted */ 1212*f5b89e41SKrzysztof Hałasa return -ENOBUFS; 1213*f5b89e41SKrzysztof Hałasa } 1214*f5b89e41SKrzysztof Hałasa memset(&new_line, 0, sizeof(new_line)); 1215*f5b89e41SKrzysztof Hałasa new_line.clock_type = port->clock_type; 1216*f5b89e41SKrzysztof Hałasa new_line.clock_rate = 2048000; /* FIXME */ 1217*f5b89e41SKrzysztof Hałasa new_line.loopback = port->loopback; 1218*f5b89e41SKrzysztof Hałasa if (copy_to_user(line, &new_line, size)) 1219*f5b89e41SKrzysztof Hałasa return -EFAULT; 1220*f5b89e41SKrzysztof Hałasa return 0; 1221*f5b89e41SKrzysztof Hałasa 1222*f5b89e41SKrzysztof Hałasa case IF_IFACE_SYNC_SERIAL: 1223*f5b89e41SKrzysztof Hałasa case IF_IFACE_V35: 1224*f5b89e41SKrzysztof Hałasa if(!capable(CAP_NET_ADMIN)) 1225*f5b89e41SKrzysztof Hałasa return -EPERM; 1226*f5b89e41SKrzysztof Hałasa if (copy_from_user(&new_line, line, size)) 1227*f5b89e41SKrzysztof Hałasa return -EFAULT; 1228*f5b89e41SKrzysztof Hałasa 1229*f5b89e41SKrzysztof Hałasa clk = new_line.clock_type; 1230*f5b89e41SKrzysztof Hałasa if (port->plat->set_clock) 1231*f5b89e41SKrzysztof Hałasa clk = port->plat->set_clock(port->id, clk); 1232*f5b89e41SKrzysztof Hałasa 1233*f5b89e41SKrzysztof Hałasa if (clk != CLOCK_EXT && clk != CLOCK_INT) 1234*f5b89e41SKrzysztof Hałasa return -EINVAL; /* No such clock setting */ 1235*f5b89e41SKrzysztof Hałasa 1236*f5b89e41SKrzysztof Hałasa if (new_line.loopback != 0 && new_line.loopback != 1) 1237*f5b89e41SKrzysztof Hałasa return -EINVAL; 1238*f5b89e41SKrzysztof Hałasa 1239*f5b89e41SKrzysztof Hałasa port->clock_type = clk; /* Update settings */ 1240*f5b89e41SKrzysztof Hałasa /* FIXME port->clock_rate = new_line.clock_rate */; 1241*f5b89e41SKrzysztof Hałasa port->loopback = new_line.loopback; 1242*f5b89e41SKrzysztof Hałasa 1243*f5b89e41SKrzysztof Hałasa spin_lock_irqsave(&npe_lock, flags); 1244*f5b89e41SKrzysztof Hałasa 1245*f5b89e41SKrzysztof Hałasa if (dev->flags & IFF_UP) 1246*f5b89e41SKrzysztof Hałasa hss_config(port); 1247*f5b89e41SKrzysztof Hałasa 1248*f5b89e41SKrzysztof Hałasa if (port->loopback || port->carrier) 1249*f5b89e41SKrzysztof Hałasa netif_carrier_on(port->netdev); 1250*f5b89e41SKrzysztof Hałasa else 1251*f5b89e41SKrzysztof Hałasa netif_carrier_off(port->netdev); 1252*f5b89e41SKrzysztof Hałasa spin_unlock_irqrestore(&npe_lock, flags); 1253*f5b89e41SKrzysztof Hałasa 1254*f5b89e41SKrzysztof Hałasa return 0; 1255*f5b89e41SKrzysztof Hałasa 1256*f5b89e41SKrzysztof Hałasa default: 1257*f5b89e41SKrzysztof Hałasa return hdlc_ioctl(dev, ifr, cmd); 1258*f5b89e41SKrzysztof Hałasa } 1259*f5b89e41SKrzysztof Hałasa } 1260*f5b89e41SKrzysztof Hałasa 1261*f5b89e41SKrzysztof Hałasa /***************************************************************************** 1262*f5b89e41SKrzysztof Hałasa * initialization 1263*f5b89e41SKrzysztof Hałasa ****************************************************************************/ 1264*f5b89e41SKrzysztof Hałasa 1265*f5b89e41SKrzysztof Hałasa static int __devinit hss_init_one(struct platform_device *pdev) 1266*f5b89e41SKrzysztof Hałasa { 1267*f5b89e41SKrzysztof Hałasa struct port *port; 1268*f5b89e41SKrzysztof Hałasa struct net_device *dev; 1269*f5b89e41SKrzysztof Hałasa hdlc_device *hdlc; 1270*f5b89e41SKrzysztof Hałasa int err; 1271*f5b89e41SKrzysztof Hałasa 1272*f5b89e41SKrzysztof Hałasa if ((port = kzalloc(sizeof(*port), GFP_KERNEL)) == NULL) 1273*f5b89e41SKrzysztof Hałasa return -ENOMEM; 1274*f5b89e41SKrzysztof Hałasa 1275*f5b89e41SKrzysztof Hałasa if ((port->npe = npe_request(0)) == NULL) { 1276*f5b89e41SKrzysztof Hałasa err = -ENOSYS; 1277*f5b89e41SKrzysztof Hałasa goto err_free; 1278*f5b89e41SKrzysztof Hałasa } 1279*f5b89e41SKrzysztof Hałasa 1280*f5b89e41SKrzysztof Hałasa if ((port->netdev = dev = alloc_hdlcdev(port)) == NULL) { 1281*f5b89e41SKrzysztof Hałasa err = -ENOMEM; 1282*f5b89e41SKrzysztof Hałasa goto err_plat; 1283*f5b89e41SKrzysztof Hałasa } 1284*f5b89e41SKrzysztof Hałasa 1285*f5b89e41SKrzysztof Hałasa SET_NETDEV_DEV(dev, &pdev->dev); 1286*f5b89e41SKrzysztof Hałasa hdlc = dev_to_hdlc(dev); 1287*f5b89e41SKrzysztof Hałasa hdlc->attach = hss_hdlc_attach; 1288*f5b89e41SKrzysztof Hałasa hdlc->xmit = hss_hdlc_xmit; 1289*f5b89e41SKrzysztof Hałasa dev->open = hss_hdlc_open; 1290*f5b89e41SKrzysztof Hałasa dev->stop = hss_hdlc_close; 1291*f5b89e41SKrzysztof Hałasa dev->do_ioctl = hss_hdlc_ioctl; 1292*f5b89e41SKrzysztof Hałasa dev->tx_queue_len = 100; 1293*f5b89e41SKrzysztof Hałasa port->clock_type = CLOCK_EXT; 1294*f5b89e41SKrzysztof Hałasa port->clock_rate = 2048000; 1295*f5b89e41SKrzysztof Hałasa port->id = pdev->id; 1296*f5b89e41SKrzysztof Hałasa port->dev = &pdev->dev; 1297*f5b89e41SKrzysztof Hałasa port->plat = pdev->dev.platform_data; 1298*f5b89e41SKrzysztof Hałasa netif_napi_add(dev, &port->napi, hss_hdlc_poll, NAPI_WEIGHT); 1299*f5b89e41SKrzysztof Hałasa 1300*f5b89e41SKrzysztof Hałasa if ((err = register_hdlc_device(dev))) 1301*f5b89e41SKrzysztof Hałasa goto err_free_netdev; 1302*f5b89e41SKrzysztof Hałasa 1303*f5b89e41SKrzysztof Hałasa platform_set_drvdata(pdev, port); 1304*f5b89e41SKrzysztof Hałasa 1305*f5b89e41SKrzysztof Hałasa printk(KERN_INFO "%s: HSS-%i\n", dev->name, port->id); 1306*f5b89e41SKrzysztof Hałasa return 0; 1307*f5b89e41SKrzysztof Hałasa 1308*f5b89e41SKrzysztof Hałasa err_free_netdev: 1309*f5b89e41SKrzysztof Hałasa free_netdev(dev); 1310*f5b89e41SKrzysztof Hałasa err_plat: 1311*f5b89e41SKrzysztof Hałasa npe_release(port->npe); 1312*f5b89e41SKrzysztof Hałasa err_free: 1313*f5b89e41SKrzysztof Hałasa kfree(port); 1314*f5b89e41SKrzysztof Hałasa return err; 1315*f5b89e41SKrzysztof Hałasa } 1316*f5b89e41SKrzysztof Hałasa 1317*f5b89e41SKrzysztof Hałasa static int __devexit hss_remove_one(struct platform_device *pdev) 1318*f5b89e41SKrzysztof Hałasa { 1319*f5b89e41SKrzysztof Hałasa struct port *port = platform_get_drvdata(pdev); 1320*f5b89e41SKrzysztof Hałasa 1321*f5b89e41SKrzysztof Hałasa unregister_hdlc_device(port->netdev); 1322*f5b89e41SKrzysztof Hałasa free_netdev(port->netdev); 1323*f5b89e41SKrzysztof Hałasa npe_release(port->npe); 1324*f5b89e41SKrzysztof Hałasa platform_set_drvdata(pdev, NULL); 1325*f5b89e41SKrzysztof Hałasa kfree(port); 1326*f5b89e41SKrzysztof Hałasa return 0; 1327*f5b89e41SKrzysztof Hałasa } 1328*f5b89e41SKrzysztof Hałasa 1329*f5b89e41SKrzysztof Hałasa static struct platform_driver ixp4xx_hss_driver = { 1330*f5b89e41SKrzysztof Hałasa .driver.name = DRV_NAME, 1331*f5b89e41SKrzysztof Hałasa .probe = hss_init_one, 1332*f5b89e41SKrzysztof Hałasa .remove = hss_remove_one, 1333*f5b89e41SKrzysztof Hałasa }; 1334*f5b89e41SKrzysztof Hałasa 1335*f5b89e41SKrzysztof Hałasa static int __init hss_init_module(void) 1336*f5b89e41SKrzysztof Hałasa { 1337*f5b89e41SKrzysztof Hałasa if ((ixp4xx_read_feature_bits() & 1338*f5b89e41SKrzysztof Hałasa (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) != 1339*f5b89e41SKrzysztof Hałasa (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) 1340*f5b89e41SKrzysztof Hałasa return -ENOSYS; 1341*f5b89e41SKrzysztof Hałasa 1342*f5b89e41SKrzysztof Hałasa spin_lock_init(&npe_lock); 1343*f5b89e41SKrzysztof Hałasa 1344*f5b89e41SKrzysztof Hałasa return platform_driver_register(&ixp4xx_hss_driver); 1345*f5b89e41SKrzysztof Hałasa } 1346*f5b89e41SKrzysztof Hałasa 1347*f5b89e41SKrzysztof Hałasa static void __exit hss_cleanup_module(void) 1348*f5b89e41SKrzysztof Hałasa { 1349*f5b89e41SKrzysztof Hałasa platform_driver_unregister(&ixp4xx_hss_driver); 1350*f5b89e41SKrzysztof Hałasa } 1351*f5b89e41SKrzysztof Hałasa 1352*f5b89e41SKrzysztof Hałasa MODULE_AUTHOR("Krzysztof Halasa"); 1353*f5b89e41SKrzysztof Hałasa MODULE_DESCRIPTION("Intel IXP4xx HSS driver"); 1354*f5b89e41SKrzysztof Hałasa MODULE_LICENSE("GPL v2"); 1355*f5b89e41SKrzysztof Hałasa MODULE_ALIAS("platform:ixp4xx_hss"); 1356*f5b89e41SKrzysztof Hałasa module_init(hss_init_module); 1357*f5b89e41SKrzysztof Hałasa module_exit(hss_cleanup_module); 1358