/*
* Copyright (C) 2013 STMicroelectronics (R&D) Limited.
* Authors:
* Srinivas Kandagatla <srinivas.kandagatla@st.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/platform_device.h>
#include "core.h"
/* PIO Block registers */
/* PIO output */
#define REG_PIO_POUT 0x00
/* Set bits of POUT */
#define REG_PIO_SET_POUT 0x04
/* Clear bits of POUT */
#define REG_PIO_CLR_POUT 0x08
/* PIO input */
#define REG_PIO_PIN 0x10
/* PIO configuration */
#define REG_PIO_PC(n) (0x20 + (n) * 0x10)
/* Set bits of PC[2:0] */
#define REG_PIO_SET_PC(n) (0x24 + (n) * 0x10)
/* Clear bits of PC[2:0] */
#define REG_PIO_CLR_PC(n) (0x28 + (n) * 0x10)
/* PIO input comparison */
#define REG_PIO_PCOMP 0x50
/* Set bits of PCOMP */
#define REG_PIO_SET_PCOMP 0x54
/* Clear bits of PCOMP */
#define REG_PIO_CLR_PCOMP 0x58
/* PIO input comparison mask */
#define REG_PIO_PMASK 0x60
/* Set bits of PMASK */
#define REG_PIO_SET_PMASK 0x64
/* Clear bits of PMASK */
#define REG_PIO_CLR_PMASK 0x68
#define ST_GPIO_DIRECTION_BIDIR 0x1
#define ST_GPIO_DIRECTION_OUT 0x2
#define ST_GPIO_DIRECTION_IN 0x4
/**
* Packed style retime configuration.
* There are two registers cfg0 and cfg1 in this style for each bank.
* Each field in this register is 8 bit corresponding to 8 pins in the bank.
*/
#define RT_P_CFGS_PER_BANK 2
#define RT_P_CFG0_CLK1NOTCLK0_FIELD(reg) REG_FIELD(reg, 0, 7)
#define RT_P_CFG0_DELAY_0_FIELD(reg) REG_FIELD(reg, 16, 23)
#define RT_P_CFG0_DELAY_1_FIELD(reg) REG_FIELD(reg, 24, 31)
#define RT_P_CFG1_INVERTCLK_FIELD(reg) REG_FIELD(reg, 0, 7)
#define RT_P_CFG1_RETIME_FIELD(reg) REG_FIELD(reg, 8, 15)
#define RT_P_CFG1_CLKNOTDATA_FIELD(reg) REG_FIELD(reg, 16, 23)
#define RT_P_CFG1_DOUBLE_EDGE_FIELD(reg) REG_FIELD(reg, 24, 31)
/**
* Dedicated style retime Configuration register
* each register is dedicated per pin.
*/
#define RT_D_CFGS_PER_BANK 8
#define RT_D_CFG_CLK_SHIFT 0
#define RT_D_CFG_CLK_MASK (0x3 << 0)
#define RT_D_CFG_CLKNOTDATA_SHIFT 2
#define RT_D_CFG_CLKNOTDATA_MASK BIT(2)
#define RT_D_CFG_DELAY_SHIFT 3
#define RT_D_CFG_DELAY_MASK (0xf << 3)
#define RT_D_CFG_DELAY_INNOTOUT_SHIFT 7
#define RT_D_CFG_DELAY_INNOTOUT_MASK BIT(7)
#define RT_D_CFG_DOUBLE_EDGE_SHIFT 8
#define RT_D_CFG_DOUBLE_EDGE_MASK BIT(8)
#define RT_D_CFG_INVERTCLK_SHIFT 9
#define RT_D_CFG_INVERTCLK_MASK BIT(9)
#define RT_D_CFG_RETIME_SHIFT 10
#define RT_D_CFG_RETIME_MASK BIT(10)
/*
* Pinconf is represented in an opaque unsigned long variable.
* Below is the bit allocation details for each possible configuration.
* All the bit fields can be encapsulated into four variables
* (direction, retime-type, retime-clk, retime-delay)
*
* +----------------+
*[31:28]| reserved-3 |
* +----------------+-------------
*[27] | oe | |
* +----------------+ v
*[26] | pu | [Direction ]
* +----------------+ ^
*[25] | od | |
* +----------------+-------------
*[24] | reserved-2 |
* +----------------+-------------
*[23] | retime | |
* +----------------+ |
*[22] | retime-invclk | |
* +----------------+ v
*[21] |retime-clknotdat| [Retime-type ]
* +----------------+ ^
*[20] | retime-de | |
* +----------------+-------------
*[19:18]| retime-clk |------>[Retime-Clk ]
* +----------------+
*[17:16]| reserved-1 |
* +----------------+
*[15..0]| retime-delay |------>[Retime Delay]
* +----------------+
*/
#define ST_PINCONF_UNPACK(conf, param)\
((conf >> ST_PINCONF_ ##param ##_SHIFT) \
& ST_PINCONF_ ##param ##_MASK)
#define ST_PINCONF_PACK(conf, val, param) (conf |=\
((val & ST_PINCONF_ ##param ##_MASK) << \
ST_PINCONF_ ##param ##_SHIFT))
/* Output enable */
#define ST_PINCONF_OE_MASK 0x1
#define ST_PINCONF_OE_SHIFT 27