#ifndef IODEV_H
#define IODEV_H

#include "compiler.h"
#include "iodevs.h"
#include "iodeva.h"

#define CPU_HZ			84000000
#define TIMER_HZ		(1 << TIMER_SHIFT)

/* Basic system registers */
#define SYS_MAGIC		IODEVRL(SYS,0)
#define SYS_BOARDCFG		IODEVRL(SYS,1)
#define SYS_BOARDFIX		IODEVRB0(SYS,1)
#define SYS_BOARDMINOR		IODEVRB1(SYS,1)
#define SYS_BOARDMAJOR		IODEVRB2(SYS,1)
#define SYS_BOARDFPGA		IODEVRB3(SYS,1)
#define SYS_LED			IODEVL(SYS,2)
#define SYS_RESET		IODEVL(SYS,3)
#define SYS_RESET_SOFT		1
#define SYS_RESET_HARD		2
#define SYS_RESET_RECONFIG	3

#define ROMCOPY_RAMADDR		IODEVL(ROMCOPY,0)
#define ROMCOPY_ROMCMD		IODEVL(ROMCOPY,1)
#define ROMCOPY_DATALEN		IODEVL(ROMCOPY,2)
#define ROMCOPY_SPI_CMDLEN(x)	((x) << 24)
#define ROMCOPY_ZERO_BUFFER	ROMCOPY_SPI_CMDLEN(0)
#define ROMCOPY_SPI_DUAL	(1 << 27)
#define ROMCOPY_SPI_MORE	(1 << 28)
#define ROMCOPY_WRITE_RAM	(1 << 29)
#define ROMCOPY_STATUS		IODEVRL(ROMCOPY,3)
#define ROMCOPY_INPUT		IODEVRL(ROMCOPY,4)
#define ROMCOPY_STATUS_DONE	1

/* n = 0...7 */
#define TTY_DATA(n)		IODEVB(TTY,0+((n) << 2))
#define TTY_WATERCTL(n)		IODEVH0(TTY,1+((n) << 2))
#define TTY_WATERCTL_TX_LOW(x)	((x) << 0)
#define TTY_WATERCTL_TX_HIGH(x)	((x) << 4)
#define TTY_WATERCTL_RX_LOW(x)	((x) << 8)
#define TTY_WATERCTL_RX_HIGH(x)	((x) << 12)
#define TTY_STATUS(n)		IODEVH0(TTY,2+((n) << 2))
#define TTY_STATUS_TX_EMPTY	0x0001
#define TTY_STATUS_TX_LOW	0x0002
#define TTY_STATUS_TX_HIGH	0x0004
#define TTY_STATUS_TX_FULL	0x0008
#define TTY_STATUS_RX_EMPTY	0x0010
#define TTY_STATUS_RX_LOW	0x0020
#define TTY_STATUS_RX_HIGH	0x0040
#define TTY_STATUS_RX_FULL	0x0080
#define TTY_STATUS_RX_STALE	0x0100
#define TTY_STATUS_RX_BREAK	0x0200
#define TTY_STATUS_USB_CONFIG	0x0400
#define TTY_STATUS_DTR_IN	0x0800
#define TTY_STATUS_RTS_IN	0x1000
#define TTY_IRQEN(n)		IODEVH0(TTY,3+((n) << 2))
#define TTY_IRQPOL(n)		IODEVH1(TTY,3+((n) << 2))

#define TTY_CHANNEL_MASK	((1U << TTY_CHANNELS) - 1)
#define TTY_IRQ_MASK		(TTY_CHANNEL_MASK << TTY_IRQ)
#define TTY_NIRQ(n)		(TTY_IRQ+(n))

#define CON_DATA		TTY_DATA(0)
#define CON_WATERCTL		TTY_WATERCTL(0)
#define CON_STATUS		TTY_STATUS(0)
#define CON_IRQEN		TTY_IRQEN(0)
#define CON_IRQ			TTY_NIRQ(0)

#define SDCARD_CTL		IODEVL(SDCARD,0)
#define SDCARD_CTL_SPEED	IODEVB0(SDCARD,0)
#define SDCARD_CTL_IRQEN	IODEVB1(SDCARD,0)
#define SDCARD_CTL_CLRCRC	IODEVB2(SDCARD,0)
#define SDCARD_CRC7_RD		IODEVRB0(SDCARD,4)
#define SDCARD_CRC16_RD		IODEVRH1(SDCARD,4)
#define SDCARD_CRC7_WR		IODEVRB0(SDCARD,5)
#define SDCARD_CRC16_WR		IODEVRH1(SDCARD,5)
#define SDCARD_IRQ_READY	1
#define SDCARD_IRQ_CD		2
#define SDCARD_IRQ_EXT		4

/* Speed values, not including -1 adjustment */
#define SD_SLOW		128	/* 328 kHz */
#define SD_20MHZ	3	/* Really 14 MHz */
#define SD_25MHZ	2	/* Really 21 MHz */
#define SD_50MHZ	1	/* Really 42 MHz */

#define I2C_WDATA		IODEVL(I2C,0)
#define I2C_WDATA_DATA		IODEVB1(I2C,0)
#define I2C_RDATA		IODEVL(I2C,1)
#define I2C_RDATA_DATA		IODEVB1(I2C,1)
#define I2C_BUSY		1
#define I2C_SR			2
#define I2C_P			4
#define I2C_DUMMY		6
#define I2C_STARTED		0x10
#define I2C_SCL			0x20
#define I2C_SDA			0x40
#define I2C_NAK			0x80
#define I2C_DIVISOR		IODEVL(I2C,2)

#define SYSCLOCK_DATETIME	IODEVL(SYSCLOCK,0)
#define SYSCLOCK_TICK		IODEVL(SYSCLOCK,1)
#define SYSCLOCK_TICK_HOLD	IODEVH0(SYSCLOCK,1)
#define SYSCLOCK_TICK_NOW	IODEVH1(SYSCLOCK,1)

#define ABC_STATUS		IODEVL(ABC,0)
#define ABC_STATUS_LIVE		1
#define ABC_STATUS_RST		2
#define ABC_STATUS_800		4
#define ABC_IOSEL		IODEVL(ABC,1)
#define ABC_IOSEL_INVALID	0x100
#define ABC_BUSY		IODEVL(ABC,2)
#define ABC_BUSY_STATUS		IODEVH0(ABC,2)
#define ABC_BUSY_MASK		IODEVH1(ABC,2)
#define ABC_BUSY_OUT		0x00ff
#define ABC_BUSY_INP		0x0300
#define ABC_BUSY_BUSCHG		0xf000
#define ABC_BUSCTL		IODEVL(ABC,3)
#define ABC_BUSCTL_WAIT		1
#define ABC_BUSCTL_INT		2
#define ABC_BUSCTL_NMI		4
#define ABC_BUSCTL_RESET	8
#define ABC_OUT			IODEVL(ABC,4)
#define ABC_OUT_DATA		IODEVB0(ABC,4)
#define ABC_OUT_ADDR		IODEVB1(ABC,4)
#define ABC_INP			IODEVL(ABC,5)
#define ABC_INP0_DATA		IODEVB0(ABC,5)
#define ABC_INP1_DATA		IODEVB1(ABC,5)
#define ABC_INP_ENABLE		IODEVB2(ABC,5)
#define ABC_LATENCY		IODEVRL(ABC,7)
#define ABC_LATENCY_CTR		IODEVRB0(ABC,7)
#define ABC_LATENCY_ERR		IODEVRB1(ABC,7)

/* n = 0 ... 511 */
#define ABCMEMMAP_PAGE(n)	IODEVL(ABCMEMMAP,n)

/* n = 0 ... 255 */
#define ABCMEMMAP_WRPORT(n)	IODEVL(ABCMEMMAP,128+((n) << 1))
#define ABCMEMMAP_RDPORT(n)	IODEVL(ABCMEMMAP,129+((n) << 1))
#define ABCMEMMAP_WRCOUNT(n)	IODEVL(ABCMEMMAP,384+((n) << 1))
#define ABCMEMMAP_RDCOUNT(n)	IODEVL(ABCMEMMAP,385+((n) << 1))
#define ABCMEMMAP_WR		(1 << 30)
#define ABCMEMMAP_RD		(1 << 31)

#define ABCMEMMAP_STATUS(n)	IODEVL(ABCMEMMAP,512+(n))
#define ABCMEMMAP_CLR7DMA	0x800
#define ABCMEMMAP_CLR1WEMP	0x400
#define ABCMEMMAP_CLR0WEMP	0x200
#define ABCMEMMAP_CLR0REMP	0x100

#define RANDOM_DATA		IODEVRL(RANDOM,0)

#define VJTAG_CPUCMD		IODEVRL(VJTAG,0)
#define VJTAG_CPUINFO		IODEVL(VJTAG,1)
#define VJTAG_CPUSTATUS		IODEVL(VJTAG,2)
#define VJTAG_CPUSTATUS_SET	IODEVL(VJTAG,3)

#define USBDESC_ROM		IODEVL(USBDESC,0)
#define usbdesc_rom		PTR(USBDESC_ROM)

#endif /* IODEV_H */
