/*
* Intel IXP4xx HSS (synchronous serial port) driver for Linux
*
* Copyright (C) 2007-2008 Krzysztof Hałasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*/
#include <linux/bitops.h>
#include <linux/cdev.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/fs.h>
#include <linux/hdlc.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <mach/npe.h>
#include <mach/qmgr.h>
#define DEBUG_DESC 0
#define DEBUG_RX 0
#define DEBUG_TX 0
#define DEBUG_PKT_BYTES 0
#define DEBUG_CLOSE 0
#define DRV_NAME "ixp4xx_hss"
#define PKT_EXTRA_FLAGS 0 /* orig 1 */
#define PKT_NUM_PIPES 1 /* 1, 2 or 4 */
#define PKT_PIPE_FIFO_SIZEW 4 /* total 4 dwords per HSS */
#define RX_DESCS 16 /* also length of all RX queues */
#define TX_DESCS 16 /* also length of all TX queues */
#define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS))
#define RX_SIZE (HDLC_MAX_MRU + 4) /* NPE needs more space */
#define MAX_CLOSE_WAIT 1000 /* microseconds */
#define HSS_COUNT 2
#define FRAME_SIZE 256 /* doesn't matter at this point */
#define FRAME_OFFSET 0
#define MAX_CHANNELS (FRAME_SIZE / 8)
#define NAPI_WEIGHT 16
/* Queue IDs */
#define HSS0_CHL_RXTRIG_QUEUE 12 /* orig size = 32 dwords */
#define HSS0_PKT_RX_QUEUE 13 /* orig size = 32 dwords */
#define HSS0_PKT_TX0_QUEUE 14 /* orig size = 16 dwords */
#define HSS0_PKT_TX1_QUEUE 15
#define HSS0_PKT_TX2_QUEUE 16
#define HSS0_PKT_TX3_QUEUE 17
#define HSS0_PKT_RXFREE0_QUEUE 18 /* orig size = 16 dwords */
#define HSS0_PKT_RXFREE1_QUEUE 19
#define HSS0_PKT_RXFREE2_QUEUE 20
#define HSS0_PKT_RXFREE3_QUEUE 21
#define HSS0_PKT_TXDONE_QUEUE 22 /* orig size = 64 dwords */
#define HSS1_CHL_RXTRIG_QUEUE 10
#define HSS1_PKT_RX_QUEUE 0
#define HSS1_PKT_TX0_QUEUE 5
#define HSS1_PKT_TX1_QUEUE 6
#define HSS1_PKT_TX2_QUEUE 7
#define HSS1_PKT_TX3_QUEUE 8
#define HSS1_PKT_RXFREE0_QUEUE 1
#define HSS1_PKT_RXFREE1_QUEUE 2
#define HSS1_PKT_RXFREE2_QUEUE 3
#define HSS1_PKT_RXFREE3_QUEUE 4
#define HSS1_PKT_TXDONE_QUEUE 9
#define NPE_PKT_MODE_HDLC 0
#define NPE_PKT_MODE_RAW 1
#define NPE_PKT_MODE_56KMODE 2
#define NPE_PKT_MODE_56KENDIAN_MSB 4
/* PKT_PIPE_HDLC_CFG_WRITE flags */
#define PKT_HDLC_IDLE_ONES 0x1 /* default = flags */
#define PKT_HDLC_CRC_32 0x2 /* default = CRC-16 */
#define PKT_HDLC_MSB_ENDIAN 0x4 /* default = LE */
/* hss_config, PCRs */
/* Frame sync sampling, default = active low */
#define PCR_FRM_SYNC_ACTIVE_HIGH 0x40000000
#define PCR_FRM_SYNC_FALLINGEDGE 0x80000000
#define PCR_FRM_SYNC_RISINGEDGE 0xC0000000
/* Frame sync pin: input (default) or output generated off a given clk edge */
#define PCR_FRM_SYNC_OUTPUT_FALLING 0x20000000
#define PCR_FRM_SYNC_OUTPUT_RISING 0x30000000
/* Frame and data clock sampling on edge, default = falling */
#define PCR_FCLK_EDGE_RISING 0x08000000
#define PCR_DCLK_EDGE_RISING 0x04000000
/* Clock direction, default = input */
#define PCR_SYNC_CLK_DIR_OUTPUT 0x02000000
/* Generate/Receive frame pulses, default = enabled */
#define PCR_FRM_PULSE_DISABLED 0x01000000
/* Data rate is full (default) or half the configured clk speed */
#define PCR_HALF_CLK_RATE 0x00200000
/* Invert data between NPE and HSS FIFOs? (default = no) */
#define PCR_DATA_POLARITY_INVERT 0x00100000
/* TX/RX endianness, default = LSB */
#define PCR_MSB_ENDIAN 0x00080000
/* Normal (default) / open drain mode (TX only) */
#define PCR_TX_PINS_OPEN_DRAIN 0x00040000
/* No framing bit transmitted and expected on RX? (default = framing bit) */
#define PCR_SOF_NO_FBIT 0x00020000
/* Drive data pins? */
#define PCR_TX_DATA_ENABLE 0x00010000
/* Voice 56k type: drive the data pins low (default), high, high Z */
#define PCR_TX_V56K_HIGH 0x00002000
#define PCR_TX_V56K_HIGH_IMP 0x00004000
/* Unassigned type: drive the data pins low (default), high, high Z */
#define PCR_TX_UNASS_HIGH 0x00000800
#define PCR_TX_UNASS_HIGH_IMP 0x00001000
/* T1 @ 1.544MHz only: Fbit dictated in FIFO (default) or high Z */
#define PCR_TX_FB_HIGH_IMP 0x00000400
/* 56k data endiannes - which bit unused: high (default) or low */
#define PCR_TX_56KE_BIT_0_UNUSED 0x00000200
/* 56k data transmission type: 32/8 bit data (default) or 56K data */
#define PCR_TX_56KS_56K_DATA 0x00000100
/* hss_config, cCR */
/* Number of packetized clients, default = 1 */
#define CCR_NPE_HFIFO_2_HDLC 0x04000000
#define CCR_NPE_HFIFO_3_OR_4HDLC 0x08000000
/* default = no loopback */
#define CCR_LOOPBACK 0x02000000
/* HSS number, default = 0 (first) */
#define CCR_SECOND_HSS 0x01000000
/* hss_config, clkCR: main:10, num:10, denom:12 */
#define CLK42X_SPEED_EXP ((0x3FF << 22) | ( 2 << 12) | 15) /*65 KHz*/
#define CLK42X_SPEED_512KHZ (( 130 << 22) | ( 2 << 12) | 15)
#define CLK42X_SPEED_1536KHZ (( 43 << 22) | ( 18 << 12) | 47)
#define CLK42X_SPEED_1544KHZ (( 43 << 22) | ( 33 << 12) | 192)
#define CLK42X_SPEED_2048KHZ (( 32 << 22) | ( 34 << 12) | 63)
#define CLK42X_SPEED_4096KHZ (( 16 << 22) | ( 34 << 12) | 127)
#define CLK42X_SPEED_8192KHZ (( 8 << 22) | ( 34 << 12) | 255)
#define CLK46X_SPEED_512KHZ (( 130 << 22) | ( 24 << 12) | 127)
#define CLK46X_SPEED_1536KHZ (( 43 << 22) | (152 << 12) | 383)
#define CLK46X_SPEED_1544KHZ (( 43 << 22) | ( 66 << 12) | 385)
#define CLK46X_SPEED_2048KHZ (( 32 << 22) | (280 << 12) | 511)
#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023)
#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047)
/* hss_config, LUT entries */
#define TDMMAP_UNASSIGNED 0
#define TDMMAP_HDLC 1 /* HDLC - packetized */
#define TDMMAP_VOICE56K 2 /* Voice56K - 7-bit channelized */
#define TDMMAP_VOICE64K 3 /* Voice64K - 8-bit channelized */
/* offsets into HSS config */
#define HSS_CONFIG_TX_PCR 0x00 /* port configuration registers */
#define HSS_CONFIG_RX_PCR 0x04
#define HSS_CONFIG_CORE_CR 0x08 /* loopback control, H