#ifndef _HERMIT_ARCH_RMA1_PINMUX_H_
#define _HERMIT_ARCH_RMA1_PINMUX_H_

#include <arch/system.h>

/*
 * RMA1_PIN
 * ========
 *            (31....24)(23....16)(15.....8)(7......0)
 *       ALL: [reserved][   mux  ][  port  ][   irq  ]
 *   _PIN_FN:          ,  present,  present,  present
 * _PIN_INFO:          ,         ,  present,  present
 *   PIN_MUX:          ,  present,         ,
 *  PIN_PORT:          ,         ,  present,
 *   PIN_IRQ:          ,         ,         ,  present
 *
 * We use _PIN_FN and _PIN_INFO in a definition.
 */
#define _PIN_FN(info, mux)	((((mux) & 0xff) << 16) | ((info) & 0xffff))
#define _PIN_INFO(port, irq)	((((port) & 0xff) << 8) | ((irq) & 0xff))

#define PIN_MUX(pin)		(((pin) >> 16) & 0xff)
#define PIN_PORT(pin)		(((pin) >> 8) & 0xff)
#define PIN_IRQ(pin)		(((pin) >> 0) & 0xff)

#define PIN_PORTSO(pin)		/* PORT Side-Offset */			\
	(PIN_PORT(pin) < 84 ? 0x0000 :					\
	 (PIN_PORT(pin) < 115 ? 0x1000 :				\
	  (PIN_PORT(pin) < 210 ? 0x2000 :				\
	   0x3000)))
#define PIN_PORTCR(pin)							\
	(GPIO_BASE_ADDR | PIN_PORT(pin) |				\
	 (PIN_PORT(pin) < 84 ? 0x0000 :					\
	  (PIN_PORT(pin) < 115 ? 0x1000 :				\
	   0x2000)))
#define PIN_GPIODR(pin)							\
	(GPIO_BASE_ADDR | 0x4800 | PIN_PORT(pin)/32*4 |			\
	 PIN_PORTSO(pin))
#define PIN_GPIODSR(pin)						\
	(GPIO_BASE_ADDR | 0x4900 | PIN_PORT(pin)/32*4 |			\
	 PIN_PORTSO(pin))
#define PIN_GPIODCR(pin)						\
	(GPIO_BASE_ADDR | 0x4a00 | PIN_PORT(pin)/32*4 |			\
	 PIN_PORTSO(pin))
#define PIN_GPIO32(pin)	(PIN_PORT(pin) & 0x1f)

#define PIN_INVALID		(~0UL)
#define NOIRQ			(0xff)

enum {
	PIN_DBGMDT2		= _PIN_INFO(0, 5),
	PIN_DBGMDT1		= _PIN_INFO(1, 5),
	PIN_DBGMDT0		= _PIN_INFO(2, 0),
	PIN_DBGMD21		= _PIN_INFO(3, NOIRQ),
	PIN_DBGMD20		= _PIN_INFO(4, NOIRQ),
	PIN_DBGMD11		= _PIN_INFO(5, NOIRQ),
	PIN_DBGMD10		= _PIN_INFO(6, NOIRQ),
	PIN_FSIAOLR		= _PIN_INFO(7, NOIRQ),
	PIN_FSIAOBT		= _PIN_INFO(8, NOIRQ),
	PIN_FSIAOSLD		= _PIN_INFO(9, NOIRQ),
	PIN_FSIAOMC		= _PIN_INFO(10, 3),
	PIN_FSIACK		= _PIN_INFO(11, 2),
	PIN_FSIAILR		= _PIN_INFO(12, 2),
	PIN_FSIAIBT		= _PIN_INFO(13, 0),
	PIN_FMSOILR		= _PIN_INFO(14, 3),
	PIN_FMSOIBT		= _PIN_INFO(15, 4),
	PIN_FMSOOLR		= _PIN_INFO(16, NOIRQ),
	PIN_FMSOOBT		= _PIN_INFO(17, NOIRQ),
	PIN_FMSOSLD		= _PIN_INFO(18, NOIRQ),
	PIN_FMSICK		= _PIN_INFO(19, 10),
	PIN_FMSOCK		= _PIN_INFO(20, 1),
	PIN_SCIFA_CTS_1_N	= _PIN_INFO(21, NOIRQ),
	PIN_SCIFA_SCK_2		= _PIN_INFO(22, NOIRQ),
	PIN_SCIFA_RTS_1_N	= _PIN_INFO(23, NOIRQ),
	PIN_VIO_D15_0		= _PIN_INFO(24, NOIRQ),
	PIN_VIO_D14_0		= _PIN_INFO(25, NOIRQ),
	PIN_VIO_D13_0		= _PIN_INFO(26, NOIRQ),
	PIN_VIO_D7_0		= _PIN_INFO(27, NOIRQ),
	PIN_VIO_D6_0		= _PIN_INFO(28, NOIRQ),
	PIN_VIO_D5_0		= _PIN_INFO(29, NOIRQ),
	PIN_VIO_D4_0		= _PIN_INFO(30, NOIRQ),
	PIN_VIO_D3_0		= _PIN_INFO(31, NOIRQ),
	PIN_VIO_D2_0		= _PIN_INFO(32, NOIRQ),
	PIN_VIO_D1_0		= _PIN_INFO(33, NOIRQ),
	PIN_VIO_D0_0		= _PIN_INFO(34, NOIRQ),
	PIN_VIO_CLK_0		= _PIN_INFO(35, NOIRQ),
	PIN_VIO_CKO_0		= _PIN_INFO(36, NOIRQ),
	PIN_VIO_HD_0		= _PIN_INFO(37, NOIRQ),
	PIN_VIO_FIELD_0		= _PIN_INFO(38, 25),
	PIN_VIO_VD_0		= _PIN_INFO(39, NOIRQ),
	PIN_LCDD18_0		= _PIN_INFO(40, NOIRQ),
	PIN_LCDD17_0		= _PIN_INFO(41, 31),
	PIN_LCDD16_0		= _PIN_INFO(42, 12),
	PIN_LCDD15_0		= _PIN_INFO(43, NOIRQ),
	PIN_LCDD14_0		= _PIN_INFO(44, NOIRQ),
	PIN_LCDD13_0		= _PIN_INFO(45, NOIRQ),
	PIN_LCDD12_0		= _PIN_INFO(46, NOIRQ),
	PIN_LCDD11_0		= _PIN_INFO(47, NOIRQ),
	PIN_LCDD10_0		= _PIN_INFO(48, NOIRQ),
	PIN_LCDD9_0		= _PIN_INFO(49, 30),
	PIN_LCDD8_0		= _PIN_INFO(50, 29),
	PIN_LCDD7_0		= _PIN_INFO(51, NOIRQ),
	PIN_LCDD6_0		= _PIN_INFO(52, NOIRQ),
	PIN_LCDD5_0		= _PIN_INFO(53, NOIRQ),
	PIN_LCDD4_0		= _PIN_INFO(54, NOIRQ),
	PIN_LCDD3_0		= _PIN_INFO(55, NOIRQ),
	PIN_LCDD2_0		= _PIN_INFO(56, 28),
	PIN_LCDD1_0		= _PIN_INFO(57, 27),
	PIN_LCDD0_0		= _PIN_INFO(58, 26),
	PIN_LCDVCPWC_0		= _PIN_INFO(59, NOIRQ),
	PIN_LCDVEPWC_0		= _PIN_INFO(60, NOIRQ),
	PIN_LCDDON_0		= _PIN_INFO(61, NOIRQ),
	PIN_LCDDCK_0		= _PIN_INFO(62, 15),
	PIN_LCDVSYN_0		= _PIN_INFO(63, 14),
	PIN_LCDHSYN_0		= _PIN_INFO(64, 13),
	PIN_LCDDISP_0		= _PIN_INFO(65, NOIRQ),
	PIN_MEMC_INT		= _PIN_INFO(66, NOIRQ),
	PIN_MEMC_CS0		= _PIN_INFO(67, 20),
	PIN_MEMC_AD8		= _PIN_INFO(68, 16),
	PIN_MEMC_AD9		= _PIN_INFO(69, 17),
	PIN_MEMC_AD10		= _PIN_INFO(70, 18),
	PIN_MEMC_AD11		= _PIN_INFO(71, 19),
	PIN_MEMC_AD12		= _PIN_INFO(72, NOIRQ),
	PIN_MEMC_AD13		= _PIN_INFO(73, NOIRQ),
	PIN_MEMC_AD14		= _PIN_INFO(74, NOIRQ),
	PIN_MEMC_AD15		= _PIN_INFO(75, NOIRQ),
	PIN_SDHICMD_0		= _PIN_INFO(76, NOIRQ),
	PIN_SDHID0_0		= _PIN_INFO(77, NOIRQ),
	PIN_SDHID1_0		= _PIN_INFO(78, NOIRQ),
	PIN_SDHID2_0		= _PIN_INFO(79, NOIRQ),
	PIN_SDHID3_0		= _PIN_INFO(80, NOIRQ),
	PIN_SDHICD_0		= _PIN_INFO(81, 26),
	PIN_SDHICLK_0		= _PIN_INFO(82, NOIRQ),
	PIN_SDHIWP_0		= _PIN_INFO(83, NOIRQ),
	PIN_RESETOUTS_N		= _PIN_INFO(84, NOIRQ),
	PIN_PPON_0		= _PIN_INFO(85, NOIRQ),
	PIN_OCI_0		= _PIN_INFO(86, NOIRQ),
	PIN_PPON_1		= _PIN_INFO(87, NOIRQ),
	PIN_OCI_1 		= _PIN_INFO(88, NOIRQ),
	PIN_DREQ_0_N		= _PIN_INFO(89, NOIRQ),
	PIN_DACK_0_N		= _PIN_INFO(90, NOIRQ),
	PIN_MEMC_AD0		= _PIN_INFO(91, NOIRQ),
	PIN_MEMC_AD1		= _PIN_INFO(92, NOIRQ),
	PIN_MEMC_AD2		= _PIN_INFO(93, NOIRQ),
	PIN_MEMC_AD3		= _PIN_INFO(94, NOIRQ),
	PIN_MEMC_CS1		= _PIN_INFO(95, 22),
	PIN_MEMC_ADV		= _PIN_INFO(96, 23),
	PIN_MEMC_AD4		= _PIN_INFO(97, 12),
	PIN_MEMC_AD5		= _PIN_INFO(98, 13),
	PIN_MEMC_AD6		= _PIN_INFO(99, 14),
	PIN_MEMC_AD7		= _PIN_INFO(100, 15),
	PIN_FCE0_N		= _PIN_INFO(101, NOIRQ),
	PIN_FRB			= _PIN_INFO(102, NOIRQ),
	PIN_CS5B_N		= _PIN_INFO(103, NOIRQ),
	PIN_CS6A_N		= _PIN_INFO(104, 11),
	PIN_CS5A_N		= _PIN_INFO(105, NOIRQ),
	PIN_IOIS16_N		= _PIN_INFO(106, NOIRQ),
	PIN_WE3_N		= _PIN_INFO(107, NOIRQ),
	PIN_WE2_N		= _PIN_INFO(108, NOIRQ),
	PIN_CS0_N		= _PIN_INFO(109, NOIRQ),
	PIN_CS2_N		= _PIN_INFO(110, NOIRQ),
	PIN_CS4_N		= _PIN_INFO(111, NOIRQ),
	PIN_WE1_N		= _PIN_INFO(112, NOIRQ),
	PIN_WE0_N		= _PIN_INFO(113, NOIRQ),
	PIN_RDWR		= _PIN_INFO(114, NOIRQ),
	PIN_RD_N		= _PIN_INFO(115, NOIRQ),
	PIN_A25			= _PIN_INFO(116, NOIRQ),
	PIN_A24			= _PIN_INFO(117, NOIRQ),
	PIN_A23			= _PIN_INFO(118, 9),
	PIN_A22			= _PIN_INFO(119, 8),
	PIN_A21			= _PIN_INFO(120, 7),
	PIN_A20			= _PIN_INFO(121, 6),
	PIN_A19			= _PIN_INFO(122, NOIRQ),
	PIN_A18			= _PIN_INFO(123, NOIRQ),
	PIN_A17			= _PIN_INFO(124, NOIRQ),
	PIN_A16			= _PIN_INFO(125, NOIRQ),
	PIN_A15			= _PIN_INFO(126, NOIRQ),
	PIN_A14			= _PIN_INFO(127, NOIRQ),
	PIN_A13			= _PIN_INFO(128, NOIRQ),
	PIN_A12			= _PIN_INFO(129, NOIRQ),
	PIN_A11			= _PIN_INFO(130, NOIRQ),
	PIN_A10			= _PIN_INFO(131, NOIRQ),
	PIN_A9			= _PIN_INFO(132, NOIRQ),
	PIN_A8			= _PIN_INFO(133, NOIRQ),
	PIN_A7			= _PIN_INFO(134, NOIRQ),
	PIN_A6			= _PIN_INFO(135, NOIRQ),
	PIN_A5			= _PIN_INFO(136, NOIRQ),
	PIN_A4			= _PIN_INFO(137, NOIRQ),
	PIN_A3			= _PIN_INFO(138, NOIRQ),
	PIN_A2			= _PIN_INFO(139, NOIRQ),
	PIN_A1			= _PIN_INFO(140, NOIRQ),
	PIN_CKO			= _PIN_INFO(141, NOIRQ),
	PIN_D15			= _PIN_INFO(142, NOIRQ),
	PIN_D14			= _PIN_INFO(143, NOIRQ),
	PIN_D13			= _PIN_INFO(144, NOIRQ),
	PIN_D12			= _PIN_INFO(145, NOIRQ),
	PIN_D11			= _PIN_INFO(146, NOIRQ),
	PIN_D10			= _PIN_INFO(147, NOIRQ),
	PIN_D9			= _PIN_INFO(148, NOIRQ),
	PIN_D8			= _PIN_INFO(149, NOIRQ),
	PIN_D7			= _PIN_INFO(150, NOIRQ),
	PIN_D6			= _PIN_INFO(151, NOIRQ),
	PIN_D5			= _PIN_INFO(152, NOIRQ),
	PIN_D4			= _PIN_INFO(153, NOIRQ),
	PIN_D3			= _PIN_INFO(154, NOIRQ),
	PIN_D2			= _PIN_INFO(155, NOIRQ),
	PIN_D1			= _PIN_INFO(156, NOIRQ),
	PIN_D0			= _PIN_INFO(157, NOIRQ),
	PIN_D31			= _PIN_INFO(158, NOIRQ),
	PIN_D30			= _PIN_INFO(159, NOIRQ),
	PIN_D29			= _PIN_INFO(160, NOIRQ),
	PIN_D28			= _PIN_INFO(161, NOIRQ),
	PIN_D27			= _PIN_INFO(162, NOIRQ),
	PIN_D26			= _PIN_INFO(163, NOIRQ),
	PIN_D25			= _PIN_INFO(164, NOIRQ),
	PIN_D24			= _PIN_INFO(165, NOIRQ),
	PIN_D21			= _PIN_INFO(166, NOIRQ),
	PIN_D20			= _PIN_INFO(167, 31),
	PIN_D19			= _PIN_INFO(168, 27),
	PIN_D18			= _PIN_INFO(169, 28),
	PIN_D17			= _PIN_INFO(170, 29),
	PIN_D16			= _PIN_INFO(171, 30),
	PIN_D23			= _PIN_INFO(172, 4),
	PIN_D22			= _PIN_INFO(173, 6),
	PIN_A26			= _PIN_INFO(174, NOIRQ),
	PIN_A0			= _PIN_INFO(175, NOIRQ),
	PIN_ET_GTX_CLK		= _PIN_INFO(176, NOIRQ),
	PIN_WAIT_N		= _PIN_INFO(177, NOIRQ),
	PIN_VIO_D12_0		= _PIN_INFO(178, NOIRQ),
	PIN_VIO_D11_0		= _PIN_INFO(179, NOIRQ),
	PIN_VIO_D10_0		= _PIN_INFO(180, 24),
	PIN_VIO_D9_0		= _PIN_INFO(181, NOIRQ),
	PIN_VIO_D8_0		= _PIN_INFO(182, NOIRQ),
	PIN_DREQ_1_N		= _PIN_INFO(183, NOIRQ),
	PIN_DACK_1_N		= _PIN_INFO(184, NOIRQ),
	PIN_SCIFA_SCK_1		= _PIN_INFO(185, NOIRQ),
	PIN_SCIFB_RTS_N		= _PIN_INFO(186, NOIRQ),
	PIN_SCIFB_CTS_N		= _PIN_INFO(187, NOIRQ),
	PIN_SCIFA_SCK_0		= _PIN_INFO(188, NOIRQ),
	PIN_STP_IPCLK_0		= _PIN_INFO(189, NOIRQ),
	PIN_SCIFB_SCK		= _PIN_INFO(190, NOIRQ),
	PIN_SCIFB_RXD		= _PIN_INFO(191, NOIRQ),
	PIN_SCIFB_TXD		= _PIN_INFO(192, NOIRQ),
	PIN_SCIFA_CTS_0_N	= _PIN_INFO(193, NOIRQ),
	PIN_SCIFA_RTS_0_N	= _PIN_INFO(194, NOIRQ),
	PIN_SCIFA_RXD_1		= _PIN_INFO(195, NOIRQ),
	PIN_SCIFA_TXD_1		= _PIN_INFO(196, NOIRQ),
	PIN_SCIFA_RXD_0		= _PIN_INFO(197, NOIRQ),
	PIN_SCIFA_TXD_0		= _PIN_INFO(198, NOIRQ),
	PIN_MEMC_NWE		= _PIN_INFO(199, NOIRQ),
	PIN_MEMC_NOE		= _PIN_INFO(200, NOIRQ),
	PIN_MEMC_WAIT		= _PIN_INFO(201, NOIRQ),
	PIN_MEMC_BUSCLK		= _PIN_INFO(202, 21),
	PIN_SDHICLK_2		= _PIN_INFO(203, NOIRQ),
	PIN_SDHICMD_2		= _PIN_INFO(204, NOIRQ),
	PIN_SDHID0_2		= _PIN_INFO(205, NOIRQ),
	PIN_SDHID1_2		= _PIN_INFO(206, NOIRQ),
	PIN_SDHID2_2		= _PIN_INFO(207, NOIRQ),
	PIN_SDHID3_2		= _PIN_INFO(208, NOIRQ),
	PIN_VBUS		= _PIN_INFO(209, 7),
	PIN_HDMI_HPD		= _PIN_INFO(210, 9),
	PIN_HDMI_CEC		= _PIN_INFO(211, 16),
};

/*
 * MUX() - PINMUX setup macro.
 * @func:	function select [0..7: function number]
 * @out:	enable or disable output of port [1: output enable]
 * @in:		enable or disable input of port [1: input enable]
 * @pull:	specify pull-up or pull-down of port. See pulltype definitions
 *
 * Examples:
 *	_PIN_FN(PIN_SCIFA_TXD_1, MUX(0, 1, 1, PULL_UP))
 */
typedef enum {
	PULL_OFF = 0,
	PULL_DOWN = 2,
	PULL_UP = 3,
} pulltype;

#define CR_PULL(val) (((val) & 0xc0) >> 6)
#define CR_IN(val)   (((val) & 0x20) >> 5)
#define CR_OUT(val)  (((val) & 0x10) >> 4)
#define CR_FUNC(val) (((val) & 0x0f) >> 0)

#define MUX(func, out, in, pull) \
	(((pull) << 6) | ((in) << 5) | ((out) << 4) | (func))

#define pinmux(pin)					\
	({						\
	if ((pin) != PIN_INVALID)			\
		write8(PIN_PORTCR(pin), PIN_MUX(pin));	\
	})

#endif
