/*
 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/*
 * ZynqMP system level PM-API functions for pin control.
 */

#include <arch_helpers.h>
#include <platform.h>
#include "pm_api_pinctrl.h"
#include "pm_api_sys.h"
#include "pm_client.h"
#include "pm_common.h"
#include "pm_ipi.h"

#define PINCTRL_FUNCTION_MASK			0xFE
#define PINCTRL_VOLTAGE_STATUS_MASK		0x01
#define NFUNCS_PER_PIN				13
#define PINCTRL_NUM_MIOS			78
#define MAX_PIN_PER_REG				26
#define PINCTRL_BANK_ADDR_STEP			28

#define PINCTRL_DRVSTRN0_REG_OFFSET		0
#define PINCTRL_DRVSTRN1_REG_OFFSET		4
#define PINCTRL_SCHCMOS_REG_OFFSET		8
#define PINCTRL_PULLCTRL_REG_OFFSET		12
#define PINCTRL_PULLSTAT_REG_OFFSET		16
#define PINCTRL_SLEWCTRL_REG_OFFSET		20
#define PINCTRL_VOLTAGE_STAT_REG_OFFSET		24

#define IOU_SLCR_BANK1_CTRL5			0XFF180164

#define PINCTRL_CFG_ADDR_OFFSET(addr, reg, pin)				\
	((addr) + 4 * PINCTRL_NUM_MIOS + PINCTRL_BANK_ADDR_STEP *	\
	((pin) / MAX_PIN_PER_REG) + (reg))

#define PINCTRL_PIN_OFFSET(pin) \
	((pin) - (MAX_PIN_PER_REG * ((pin) / MAX_PIN_PER_REG)))

#define PINCTRL_REGVAL_TO_PIN_CONFIG(pin, value)			\
	(((value) >> PINCTRL_PIN_OFFSET(pin)) & 0x1)

#define PINMUX_MAP(pin, f0, f1, f2, f3, f4, f5, f6,	\
		   f7, f8, f9, f10, f11, f12)		\
	[pin] = {					\
		.funcs =  {				\
			f0,				\
			f1,				\
			f2,				\
			f3,				\
			f4,				\
			f5,				\
			f6,				\
			f7,				\
			f8,				\
			f9,				\
			f10,				\
			f11,				\
			f12,				\
		},					\
	}

struct pm_pinctrl_pinmux_map {
	uint8_t funcs[NFUNCS_PER_PIN];
};

static uint8_t pm_pinctrl_mux[NFUNCS_PER_PIN] = {
	0x02, 0x04, 0x08, 0x10, 0x18,
	0x00, 0x20, 0x40, 0x60, 0x80,
	0xA0, 0xC0, 0xE0
};

struct pm_pinctrl_pinmux_map pinmux_maps[] = {
	PINMUX_MAP(0, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(1, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(2, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(3, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(4, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(5, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(6, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(7, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(8, NODE_QSPI, NODE_UNKNOWN, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(9, NODE_QSPI, NODE_NAND, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(10, NODE_QSPI, NODE_NAND, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(11, NODE_QSPI, NODE_NAND, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(12, NODE_QSPI, NODE_NAND, NODE_UNKNOWN, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(13, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(14, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(15, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(16, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(17, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(18, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(19, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(20, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(21, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(22, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(23, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(24, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_UNKNOWN, NODE_TTC_3, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(25, NODE_UNKNOWN, NODE_NAND, NODE_SD_0, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_UNKNOWN, NODE_TTC_3, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(26, NODE_ETH_0, NODE_NAND, NODE_PMU, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(27, NODE_ETH_0, NODE_NAND, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(28, NODE_ETH_0, NODE_NAND, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(29, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(30, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(31, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(32, NODE_ETH_0, NODE_NAND, NODE_PMU, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(33, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_CSU, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(34, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(35, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(36, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(37, NODE_ETH_0, NODE_PCIE, NODE_PMU, NODE_TESTSCAN,
		   NODE_DP, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(38, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(39, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(40, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(41, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(42, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(43, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(44, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(45, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(46, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(47, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(48, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_3, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(49, NODE_ETH_1, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_TTC_3, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(50, NODE_GEM_TSU, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_ETH_1, NODE_TTC_2, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(51, NODE_GEM_TSU, NODE_UNKNOWN, NODE_UNKNOWN, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_ETH_1, NODE_TTC_2, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(52, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(53, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(54, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(55, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_0, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(56, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(57, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(58, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(59, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_PJTAG,
		   NODE_SPI_1, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(60, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(61, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_PJTAG,
		   NODE_SPI_1, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(62, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(63, NODE_ETH_2, NODE_USB_0, NODE_UNKNOWN, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(64, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(65, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_3, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(66, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(67, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_0, NODE_TTC_2, NODE_UART_0, NODE_TRACE),
	PINMUX_MAP(68, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_UNKNOWN,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(69, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_0, NODE_TTC_1, NODE_UART_1, NODE_TRACE),
	PINMUX_MAP(70, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(71, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_TTC_0, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(72, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_UNKNOWN, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(73, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_SWDT_1,
		   NODE_SPI_1, NODE_UNKNOWN, NODE_UART_1, NODE_UNKNOWN),
	PINMUX_MAP(74, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_UNKNOWN, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(75, NODE_ETH_3, NODE_USB_1, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_0, NODE_I2C_0, NODE_SWDT_0,
		   NODE_SPI_1, NODE_UNKNOWN, NODE_UART_0, NODE_UNKNOWN),
	PINMUX_MAP(76, NODE_UNKNOWN, NODE_UNKNOWN, NODE_SD_0, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_ETH_0,
		   NODE_ETH_1, NODE_ETH_2, NODE_ETH_3, NODE_UNKNOWN),
	PINMUX_MAP(77, NODE_UNKNOWN, NODE_UNKNOWN, NODE_UNKNOWN, NODE_SD_1,
		   NODE_UNKNOWN, NODE_GPIO, NODE_CAN_1, NODE_I2C_1, NODE_ETH_0,
		   NODE_ETH_1, NODE_ETH_2, NODE_ETH_3, NODE_UNKNOWN),
};

/**
 * pm_api_pinctrl_get_function() - Read function id set for the given pin
 * @pin		Pin number
 * @nid		Node ID of function currently set for given pin
 *
 * This function provides the function currently set for the given pin.
 *
 * @return	Returns status, either success or error+reason
 */
enum pm_ret_status pm_api_pinctrl_get_function(unsigned int pin,
					       enum pm_node_id *nid)
{
	struct pm_pinctrl_pinmux_map *pinmux_map = &pinmux_maps[pin];
	int i, ret = PM_RET_SUCCESS;
	unsigned int reg, val;

	reg = IOU_SLCR_BASEADDR + 4 * pin;
	ret = pm_mmio_read(reg, &val);
	if (ret)
		return ret;

	val &= PINCTRL_FUNCTION_MASK;

	for (i = 0; i < NFUNCS_PER_PIN; i++)
		if (val == pm_pinctrl_mux[i])
			break;

	if (i == NFUNCS_PER_PIN)
		return PM_RET_ERROR_NOTSUPPORTED;

	*nid = pinmux_map->funcs[i];

	return ret;
}

/**
 * pm_api_pinctrl_set_function() - Set function id set for the given pin
 * @pin		Pin number
 * @nid		Node ID of function to set for given pin
 *
 * This function provides the function currently set for the given pin.
 *
 * @return	Returns status, either success or error+reason
 */
enum pm_ret_status pm_api_pinctrl_set_function(unsigned int pin,
					       enum pm_node_id nid)
{
	struct pm_pinctrl_pinmux_map *pinmux_map = &pinmux_maps[pin];
	int i;
	unsigned int reg, val;

	for (i = 0; i < NFUNCS_PER_PIN; i++)
		if (nid == pinmux_map->funcs[i])
			break;

	if (i == NFUNCS_PER_PIN)
		return PM_RET_ERROR_NOTSUPPORTED;

	reg = IOU_SLCR_BASEADDR + 4 * pin;
	val = pm_pinctrl_mux[i];

	return pm_mmio_write(reg, PINCTRL_FUNCTION_MASK, val);
}

/**
 * pm_api_pinctrl_set_config() - Set configuration parameter for given pin
 * @pin: Pin for which configuration is to be set
 * @param: Configuration parameter to be set
 * @value: Value to be set for configuration parameter
 *
 * This function sets value of requested configuration parameter for given pin.
 *
 * @return	Returns status, either success or error+reason
 */
enum pm_ret_status pm_api_pinctrl_set_config(unsigned int pin,
					     unsigned int param,
					     unsigned int value)
{
	int ret;
	unsigned int reg, mask, val, offset;

	if (param >= PINCTRL_CONFIG_MAX)
		return PM_RET_ERROR_NOTSUPPORTED;

	if (pin >=  PINCTRL_NUM_MIOS)
		return PM_RET_ERROR_ARGS;

	mask = 1 << PINCTRL_PIN_OFFSET(pin);

	switch (param) {
	case PINCTRL_CONFIG_SLEW_RATE:
		if (value != PINCTRL_SLEW_RATE_FAST &&
		    value != PINCTRL_SLEW_RATE_SLOW)
			return PM_RET_ERROR_ARGS;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_SLEWCTRL_REG_OFFSET,
					      pin);
		val = value << PINCTRL_PIN_OFFSET(pin);
		ret = pm_mmio_write(reg, mask, val);
		break;
	case PINCTRL_CONFIG_BIAS_STATUS:
		if (value != PINCTRL_BIAS_ENABLE &&
		    value != PINCTRL_BIAS_DISABLE)
			return PM_RET_ERROR_ARGS;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_PULLSTAT_REG_OFFSET,
					      pin);

		offset = PINCTRL_PIN_OFFSET(pin);
		if (reg == IOU_SLCR_BANK1_CTRL5)
			offset = (offset < 12) ? (offset + 14) : (offset - 12);

		val = value << offset;
		mask = 1 << offset;
		ret = pm_mmio_write(reg, mask, val);
		break;
	case PINCTRL_CONFIG_PULL_CTRL:

		if (value != PINCTRL_BIAS_PULL_DOWN &&
		    value != PINCTRL_BIAS_PULL_UP)
			return PM_RET_ERROR_ARGS;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_PULLSTAT_REG_OFFSET,
					      pin);

		offset = PINCTRL_PIN_OFFSET(pin);
		if (reg == IOU_SLCR_BANK1_CTRL5)
			offset = (offset < 12) ? (offset + 14) : (offset - 12);

		val = PINCTRL_BIAS_ENABLE << offset;
		ret = pm_mmio_write(reg, 1 << offset, val);
		if (ret)
			return ret;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_PULLCTRL_REG_OFFSET,
					      pin);
		val = value << PINCTRL_PIN_OFFSET(pin);
		ret = pm_mmio_write(reg, mask, val);
		break;
	case PINCTRL_CONFIG_SCHMITT_CMOS:
		if (value != PINCTRL_INPUT_TYPE_CMOS &&
		    value != PINCTRL_INPUT_TYPE_SCHMITT)
			return PM_RET_ERROR_ARGS;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_SCHCMOS_REG_OFFSET,
					      pin);

		val = value << PINCTRL_PIN_OFFSET(pin);
		ret = pm_mmio_write(reg, mask, val);
		break;
	case PINCTRL_CONFIG_DRIVE_STRENGTH:
		if (value > PINCTRL_DRIVE_STRENGTH_12MA)
			return PM_RET_ERROR_ARGS;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_DRVSTRN0_REG_OFFSET,
					      pin);
		val = (value >> 1) << PINCTRL_PIN_OFFSET(pin);
		ret = pm_mmio_write(reg, mask, val);
		if (ret)
			return ret;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_DRVSTRN1_REG_OFFSET,
					      pin);
		val = (value & 0x01) << PINCTRL_PIN_OFFSET(pin);
		ret = pm_mmio_write(reg, mask, val);
		break;
	default:
		ERROR("Invalid parameter %u\n", param);
		ret = PM_RET_ERROR_NOTSUPPORTED;
		break;
	}

	return ret;
}

/**
 * pm_api_pinctrl_get_config() - Get configuration parameter value for given pin
 * @pin: Pin for which configuration is to be read
 * @param: Configuration parameter to be read
 * @value: buffer to store value of configuration parameter
 *
 * This function reads value of requested configuration parameter for given pin.
 *
 * @return	Returns status, either success or error+reason
 */
enum pm_ret_status pm_api_pinctrl_get_config(unsigned int pin,
					     unsigned int param,
					     unsigned int *value)
{
	int ret;
	unsigned int reg, val;

	if (param >= PINCTRL_CONFIG_MAX)
		return PM_RET_ERROR_NOTSUPPORTED;

	if (pin >=  PINCTRL_NUM_MIOS)
		return PM_RET_ERROR_ARGS;

	switch (param) {
	case PINCTRL_CONFIG_SLEW_RATE:
		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_SLEWCTRL_REG_OFFSET,
					      pin);

		ret = pm_mmio_read(reg, &val);
		if (ret)
			return ret;

		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
		break;
	case PINCTRL_CONFIG_BIAS_STATUS:
		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_PULLSTAT_REG_OFFSET,
					      pin);

		ret = pm_mmio_read(reg, &val);
		if (ret)
			return ret;

		if (reg == IOU_SLCR_BANK1_CTRL5)
			val = ((val & 0x3FFF) << 12) | ((val >> 14) & 0xFFF);

		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
		break;
	case PINCTRL_CONFIG_PULL_CTRL:

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_PULLCTRL_REG_OFFSET,
					      pin);

		ret = pm_mmio_read(reg, &val);
		if (ret)
			return ret;

		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
		break;
	case PINCTRL_CONFIG_SCHMITT_CMOS:
		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_SCHCMOS_REG_OFFSET,
					      pin);

		ret = pm_mmio_read(reg, &val);
		if (ret)
			return ret;

		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
		break;
	case PINCTRL_CONFIG_DRIVE_STRENGTH:
		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_DRVSTRN0_REG_OFFSET,
					      pin);
		ret = pm_mmio_read(reg, &val);
		if (ret)
			return ret;

		*value = PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val) << 1;

		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_DRVSTRN1_REG_OFFSET,
					      pin);
		ret = pm_mmio_read(reg, &val);
		if (ret)
			return ret;

		*value |= PINCTRL_REGVAL_TO_PIN_CONFIG(pin, val);
		break;
	case PINCTRL_CONFIG_VOLTAGE_STATUS:
		reg = PINCTRL_CFG_ADDR_OFFSET(IOU_SLCR_BASEADDR,
					      PINCTRL_VOLTAGE_STAT_REG_OFFSET,
					      pin);

		ret = pm_mmio_read(reg, &val);
		if (ret)
			return ret;

		*value = val & PINCTRL_VOLTAGE_STATUS_MASK;
		break;
	default:
		return PM_RET_ERROR_NOTSUPPORTED;
	}

	return 0;
}
