/*
* Zynq pin controller
*
* Copyright (C) 2014 Xilinx
*
* Sören Brinkmann <soren.brinkmann@xilinx.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/regmap.h>
#include "pinctrl-utils.h"
#include "core.h"
#define ZYNQ_NUM_MIOS 54
#define ZYNQ_PCTRL_MIO_MST_TRI0 0x10c
#define ZYNQ_PCTRL_MIO_MST_TRI1 0x110
#define ZYNQ_PINMUX_MUX_SHIFT 1
#define ZYNQ_PINMUX_MUX_MASK (0x7f << ZYNQ_PINMUX_MUX_SHIFT)
/**
* struct zynq_pinctrl - driver data
* @pctrl: Pinctrl device
* @syscon: Syscon regmap
* @pctrl_offset: Offset for pinctrl into the @syscon space
* @groups: Pingroups
* @ngroupos: Number of @groups
* @funcs: Pinmux functions
* @nfuncs: Number of @funcs
*/
struct zynq_pinctrl {
struct pinctrl_dev *pctrl;
struct regmap *syscon;
u32 pctrl_offset;
const struct zynq_pctrl_group *groups;
unsigned int ngroups;
const struct zynq_pinmux_function *funcs;
unsigned int nfuncs;
};
struct zynq_pctrl_group {
const char *name;
const unsigned int *pins;
const unsigned npins;
};
/**
* struct zynq_pinmux_function - a pinmux function
* @name: Name of the pinmux function.
* @groups: List of pingroups for this function.
* @ngroups: Number of entries in @groups.
* @mux_val: Selector for this function
* @mux: Offset of function specific mux
* @mux_mask: Mask for function specific selector
* @mux_shift: Shift for function specific selector
*/
struct zynq_pinmux_function {
const char *name;
const char * const *groups;
unsigned int ngroups;
unsigned int mux_val;
u32 mux;
u32 mux_mask;
u8 mux_shift;
};
enum zynq_pinmux_functions {
ZYNQ_PMUX_can0,
ZYNQ_PMUX_can1,
ZYNQ_PMUX_ethernet0,
ZYNQ_PMUX_ethernet1,
ZYNQ_PMUX_gpio0,
ZYNQ_PMUX_i2c0,
ZYNQ_PMUX_i2c1,
ZYNQ_PMUX_mdio0,
ZYNQ_PMUX_mdio1,
ZYNQ_PMUX_qspi0,
ZYNQ_PMUX_qspi1,
ZYNQ_PMUX_qspi_fbclk,
ZYNQ_PMUX_qspi_cs1,
ZYNQ_PMUX_spi0,
ZYNQ_PMUX_spi1,
ZYNQ_PMUX_spi0_ss,
ZYNQ_PMUX_spi1_ss,
ZYNQ_PMUX_sdio0,
ZYNQ_PMUX_sdio0_pc,
ZYNQ_PMUX_sdio0_cd,
ZYNQ_PMUX_sdio0_wp,
ZYNQ_PMUX_sdio1,
ZYNQ_PMUX_sdio1_pc,
ZYNQ_PMUX_sdio1_cd,
ZYNQ_PMUX_sdio1_wp,
ZYNQ_PMUX_smc0_nor,
ZYNQ_PMUX_smc0_nor_cs1,
ZYNQ_PMUX_smc0_nor_addr25,
ZYNQ_PMUX_smc0_nand,
ZYNQ_PMUX_ttc0,
ZYNQ_PMUX_ttc1,
ZYNQ_PMUX_uart0,
ZYNQ_PMUX_uart1,
ZYNQ_PMUX_usb0,
ZYNQ_PMUX_usb1,
ZYNQ_PMUX_swdt0,
ZYNQ_PMUX_MAX_FUNC
};
static const struct pinctrl_pin_desc zynq_pins[] = {
PINCTRL_PIN(0, "MIO0"),
PINCTRL_PIN(1, "MIO1"),
PINCTRL_PIN(2, "MIO2"),
PINCTRL_PIN(3, "MIO3"),
PINCTRL_PIN(4, "MIO4"),
PINCTRL_PIN(5, "MIO5"),
PINCTRL_PIN(6, "MIO6"),
PINCTRL_PIN(7, "MIO7"),
PINCTRL_PIN(8, "MIO8"),
PINCTRL_PIN(9, "MIO9"),
PINCTRL_PIN(10, "MIO10"),
PINCTRL_PIN(11, "MIO11"),
PINCTRL_PIN(12, "MIO12"),
PINCTRL_PIN(13, "MIO13"),
PINCTRL_PIN(14, "MIO14"),
PINCTRL_PIN(15, "MIO15"),
PINCTRL_PIN(16, "MIO16"),
PINCTRL_PIN(17, "MIO17"),
PINCTRL_PIN(18, "MIO18"),
PINCTRL_PIN(19, "MIO19"),
PINCTRL_PIN(20, "MIO20"),
PINCTRL_PIN(21, "MIO21"),
PINCTRL_PIN(22, "MIO22"),
PINCTRL_PIN(23, "MIO23"),
PINCTRL_PIN(24, "MIO24"),
PINCTRL_PIN(25, "MIO25"),
PINCTRL_PIN(26, "MIO26"