2013-06-20 13:26:27 +04:00
/*
* Pinctrl driver for the Toumaz Xenif TZ1090 SoC
*
* Copyright ( c ) 2013 , Imagination Technologies Ltd .
*
* Derived from Tegra code :
* Copyright ( c ) 2011 - 2012 , NVIDIA CORPORATION . All rights reserved .
*
* Derived from code :
* Copyright ( C ) 2010 Google , Inc .
* Copyright ( C ) 2010 NVIDIA Corporation
* Copyright ( C ) 2009 - 2011 ST - Ericsson AB
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope 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 .
*/
# include <linux/bitops.h>
# include <linux/io.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/platform_device.h>
# include <linux/pinctrl/machine.h>
# include <linux/pinctrl/pinconf-generic.h>
# include <linux/pinctrl/pinctrl.h>
# include <linux/pinctrl/pinmux.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
/*
* The registers may be shared with other threads / cores , so we need to use the
* metag global lock2 for atomicity .
*/
# include <asm/global_lock.h>
# include "core.h"
# include "pinconf.h"
/* Register offsets from bank base address */
# define REG_PINCTRL_SELECT 0x10
# define REG_PINCTRL_SCHMITT 0x90
# define REG_PINCTRL_PU_PD 0xa0
# define REG_PINCTRL_SR 0xc0
# define REG_PINCTRL_DR 0xd0
# define REG_PINCTRL_IF_CTL 0xe0
/* REG_PINCTRL_PU_PD field values */
# define REG_PU_PD_TRISTATE 0
# define REG_PU_PD_UP 1
# define REG_PU_PD_DOWN 2
# define REG_PU_PD_REPEATER 3
/* REG_PINCTRL_DR field values */
# define REG_DR_2mA 0
# define REG_DR_4mA 1
# define REG_DR_8mA 2
# define REG_DR_12mA 3
/**
* struct tz1090_function - TZ1090 pinctrl mux function
* @ name : The name of the function , exported to pinctrl core .
* @ groups : An array of pin groups that may select this function .
* @ ngroups : The number of entries in @ groups .
*/
struct tz1090_function {
const char * name ;
const char * const * groups ;
unsigned int ngroups ;
} ;
/**
* struct tz1090_muxdesc - TZ1090 individual mux description
* @ funcs : Function for each mux value .
* @ reg : Mux register offset . 0 if unsupported .
* @ bit : Mux register bit . 0 if unsupported .
* @ width : Mux field width . 0 if unsupported .
*
* A representation of a group of signals ( possibly just one signal ) in the
* TZ1090 which can be muxed to a set of functions or sub muxes .
*/
struct tz1090_muxdesc {
int funcs [ 5 ] ;
u16 reg ;
u8 bit ;
u8 width ;
} ;
/**
* struct tz1090_pingroup - TZ1090 pin group
* @ name : Name of pin group .
* @ pins : Array of pin numbers in this pin group .
* @ npins : Number of pins in this pin group .
* @ mux : Top level mux .
* @ drv : Drive control supported , 0 if unsupported .
* This means Schmitt , Slew , and Drive strength .
* @ slw_bit : Slew register bit . 0 if unsupported .
* The same bit is used for Schmitt , and Drive ( * 2 ) .
* @ func : Currently muxed function .
* @ func_count : Number of pins using current mux function .
*
* A representation of a group of pins ( possibly just one pin ) in the TZ1090
* pin controller . Each group allows some parameter or parameters to be
* configured . The most common is mux function selection .
*/
struct tz1090_pingroup {
const char * name ;
const unsigned int * pins ;
unsigned int npins ;
struct tz1090_muxdesc mux ;
bool drv ;
u8 slw_bit ;
int func ;
unsigned int func_count ;
} ;
/*
* Most pins affected by the pinmux can also be GPIOs . Define these first .
* These must match how the GPIO driver names / numbers its pins .
*/
enum tz1090_pin {
/* GPIO pins */
TZ1090_PIN_SDIO_CLK ,
TZ1090_PIN_SDIO_CMD ,
TZ1090_PIN_SDIO_D0 ,
TZ1090_PIN_SDIO_D1 ,
TZ1090_PIN_SDIO_D2 ,
TZ1090_PIN_SDIO_D3 ,
TZ1090_PIN_SDH_CD ,
TZ1090_PIN_SDH_WP ,
TZ1090_PIN_SPI0_MCLK ,
TZ1090_PIN_SPI0_CS0 ,
TZ1090_PIN_SPI0_CS1 ,
TZ1090_PIN_SPI0_CS2 ,
TZ1090_PIN_SPI0_DOUT ,
TZ1090_PIN_SPI0_DIN ,
TZ1090_PIN_SPI1_MCLK ,
TZ1090_PIN_SPI1_CS0 ,
TZ1090_PIN_SPI1_CS1 ,
TZ1090_PIN_SPI1_CS2 ,
TZ1090_PIN_SPI1_DOUT ,
TZ1090_PIN_SPI1_DIN ,
TZ1090_PIN_UART0_RXD ,
TZ1090_PIN_UART0_TXD ,
TZ1090_PIN_UART0_CTS ,
TZ1090_PIN_UART0_RTS ,
TZ1090_PIN_UART1_RXD ,
TZ1090_PIN_UART1_TXD ,
TZ1090_PIN_SCB0_SDAT ,
TZ1090_PIN_SCB0_SCLK ,
TZ1090_PIN_SCB1_SDAT ,
TZ1090_PIN_SCB1_SCLK ,
TZ1090_PIN_SCB2_SDAT ,
TZ1090_PIN_SCB2_SCLK ,
TZ1090_PIN_I2S_MCLK ,
TZ1090_PIN_I2S_BCLK_OUT ,
TZ1090_PIN_I2S_LRCLK_OUT ,
TZ1090_PIN_I2S_DOUT0 ,
TZ1090_PIN_I2S_DOUT1 ,
TZ1090_PIN_I2S_DOUT2 ,
TZ1090_PIN_I2S_DIN ,
TZ1090_PIN_PDM_A ,
TZ1090_PIN_PDM_B ,
TZ1090_PIN_PDM_C ,
TZ1090_PIN_PDM_D ,
TZ1090_PIN_TFT_RED0 ,
TZ1090_PIN_TFT_RED1 ,
TZ1090_PIN_TFT_RED2 ,
TZ1090_PIN_TFT_RED3 ,
TZ1090_PIN_TFT_RED4 ,
TZ1090_PIN_TFT_RED5 ,
TZ1090_PIN_TFT_RED6 ,
TZ1090_PIN_TFT_RED7 ,
TZ1090_PIN_TFT_GREEN0 ,
TZ1090_PIN_TFT_GREEN1 ,
TZ1090_PIN_TFT_GREEN2 ,
TZ1090_PIN_TFT_GREEN3 ,
TZ1090_PIN_TFT_GREEN4 ,
TZ1090_PIN_TFT_GREEN5 ,
TZ1090_PIN_TFT_GREEN6 ,
TZ1090_PIN_TFT_GREEN7 ,
TZ1090_PIN_TFT_BLUE0 ,
TZ1090_PIN_TFT_BLUE1 ,
TZ1090_PIN_TFT_BLUE2 ,
TZ1090_PIN_TFT_BLUE3 ,
TZ1090_PIN_TFT_BLUE4 ,
TZ1090_PIN_TFT_BLUE5 ,
TZ1090_PIN_TFT_BLUE6 ,
TZ1090_PIN_TFT_BLUE7 ,
TZ1090_PIN_TFT_VDDEN_GD ,
TZ1090_PIN_TFT_PANELCLK ,
TZ1090_PIN_TFT_BLANK_LS ,
TZ1090_PIN_TFT_VSYNC_NS ,
TZ1090_PIN_TFT_HSYNC_NR ,
TZ1090_PIN_TFT_VD12ACB ,
TZ1090_PIN_TFT_PWRSAVE ,
TZ1090_PIN_TX_ON ,
TZ1090_PIN_RX_ON ,
TZ1090_PIN_PLL_ON ,
TZ1090_PIN_PA_ON ,
TZ1090_PIN_RX_HP ,
TZ1090_PIN_GAIN0 ,
TZ1090_PIN_GAIN1 ,
TZ1090_PIN_GAIN2 ,
TZ1090_PIN_GAIN3 ,
TZ1090_PIN_GAIN4 ,
TZ1090_PIN_GAIN5 ,
TZ1090_PIN_GAIN6 ,
TZ1090_PIN_GAIN7 ,
TZ1090_PIN_ANT_SEL0 ,
TZ1090_PIN_ANT_SEL1 ,
TZ1090_PIN_SDH_CLK_IN ,
/* Non-GPIO pins */
TZ1090_PIN_TCK ,
TZ1090_PIN_TRST ,
TZ1090_PIN_TDI ,
TZ1090_PIN_TDO ,
TZ1090_PIN_TMS ,
TZ1090_PIN_CLK_OUT0 ,
TZ1090_PIN_CLK_OUT1 ,
NUM_GPIOS = TZ1090_PIN_TCK ,
} ;
/* Pin names */
static const struct pinctrl_pin_desc tz1090_pins [ ] = {
/* GPIO pins */
PINCTRL_PIN ( TZ1090_PIN_SDIO_CLK , " sdio_clk " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDIO_CMD , " sdio_cmd " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDIO_D0 , " sdio_d0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDIO_D1 , " sdio_d1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDIO_D2 , " sdio_d2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDIO_D3 , " sdio_d3 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDH_CD , " sdh_cd " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDH_WP , " sdh_wp " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI0_MCLK , " spi0_mclk " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI0_CS0 , " spi0_cs0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI0_CS1 , " spi0_cs1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI0_CS2 , " spi0_cs2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI0_DOUT , " spi0_dout " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI0_DIN , " spi0_din " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI1_MCLK , " spi1_mclk " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI1_CS0 , " spi1_cs0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI1_CS1 , " spi1_cs1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI1_CS2 , " spi1_cs2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI1_DOUT , " spi1_dout " ) ,
PINCTRL_PIN ( TZ1090_PIN_SPI1_DIN , " spi1_din " ) ,
PINCTRL_PIN ( TZ1090_PIN_UART0_RXD , " uart0_rxd " ) ,
PINCTRL_PIN ( TZ1090_PIN_UART0_TXD , " uart0_txd " ) ,
PINCTRL_PIN ( TZ1090_PIN_UART0_CTS , " uart0_cts " ) ,
PINCTRL_PIN ( TZ1090_PIN_UART0_RTS , " uart0_rts " ) ,
PINCTRL_PIN ( TZ1090_PIN_UART1_RXD , " uart1_rxd " ) ,
PINCTRL_PIN ( TZ1090_PIN_UART1_TXD , " uart1_txd " ) ,
PINCTRL_PIN ( TZ1090_PIN_SCB0_SDAT , " scb0_sdat " ) ,
PINCTRL_PIN ( TZ1090_PIN_SCB0_SCLK , " scb0_sclk " ) ,
PINCTRL_PIN ( TZ1090_PIN_SCB1_SDAT , " scb1_sdat " ) ,
PINCTRL_PIN ( TZ1090_PIN_SCB1_SCLK , " scb1_sclk " ) ,
PINCTRL_PIN ( TZ1090_PIN_SCB2_SDAT , " scb2_sdat " ) ,
PINCTRL_PIN ( TZ1090_PIN_SCB2_SCLK , " scb2_sclk " ) ,
PINCTRL_PIN ( TZ1090_PIN_I2S_MCLK , " i2s_mclk " ) ,
PINCTRL_PIN ( TZ1090_PIN_I2S_BCLK_OUT , " i2s_bclk_out " ) ,
PINCTRL_PIN ( TZ1090_PIN_I2S_LRCLK_OUT , " i2s_lrclk_out " ) ,
PINCTRL_PIN ( TZ1090_PIN_I2S_DOUT0 , " i2s_dout0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_I2S_DOUT1 , " i2s_dout1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_I2S_DOUT2 , " i2s_dout2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_I2S_DIN , " i2s_din " ) ,
PINCTRL_PIN ( TZ1090_PIN_PDM_A , " pdm_a " ) ,
PINCTRL_PIN ( TZ1090_PIN_PDM_B , " pdm_b " ) ,
PINCTRL_PIN ( TZ1090_PIN_PDM_C , " pdm_c " ) ,
PINCTRL_PIN ( TZ1090_PIN_PDM_D , " pdm_d " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED0 , " tft_red0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED1 , " tft_red1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED2 , " tft_red2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED3 , " tft_red3 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED4 , " tft_red4 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED5 , " tft_red5 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED6 , " tft_red6 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_RED7 , " tft_red7 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN0 , " tft_green0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN1 , " tft_green1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN2 , " tft_green2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN3 , " tft_green3 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN4 , " tft_green4 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN5 , " tft_green5 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN6 , " tft_green6 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_GREEN7 , " tft_green7 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE0 , " tft_blue0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE1 , " tft_blue1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE2 , " tft_blue2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE3 , " tft_blue3 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE4 , " tft_blue4 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE5 , " tft_blue5 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE6 , " tft_blue6 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLUE7 , " tft_blue7 " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_VDDEN_GD , " tft_vdden_gd " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_PANELCLK , " tft_panelclk " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_BLANK_LS , " tft_blank_ls " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_VSYNC_NS , " tft_vsync_ns " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_HSYNC_NR , " tft_hsync_nr " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_VD12ACB , " tft_vd12acb " ) ,
PINCTRL_PIN ( TZ1090_PIN_TFT_PWRSAVE , " tft_pwrsave " ) ,
PINCTRL_PIN ( TZ1090_PIN_TX_ON , " tx_on " ) ,
PINCTRL_PIN ( TZ1090_PIN_RX_ON , " rx_on " ) ,
PINCTRL_PIN ( TZ1090_PIN_PLL_ON , " pll_on " ) ,
PINCTRL_PIN ( TZ1090_PIN_PA_ON , " pa_on " ) ,
PINCTRL_PIN ( TZ1090_PIN_RX_HP , " rx_hp " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN0 , " gain0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN1 , " gain1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN2 , " gain2 " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN3 , " gain3 " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN4 , " gain4 " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN5 , " gain5 " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN6 , " gain6 " ) ,
PINCTRL_PIN ( TZ1090_PIN_GAIN7 , " gain7 " ) ,
PINCTRL_PIN ( TZ1090_PIN_ANT_SEL0 , " ant_sel0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_ANT_SEL1 , " ant_sel1 " ) ,
PINCTRL_PIN ( TZ1090_PIN_SDH_CLK_IN , " sdh_clk_in " ) ,
/* Non-GPIO pins */
PINCTRL_PIN ( TZ1090_PIN_TCK , " tck " ) ,
PINCTRL_PIN ( TZ1090_PIN_TRST , " trst " ) ,
PINCTRL_PIN ( TZ1090_PIN_TDI , " tdi " ) ,
PINCTRL_PIN ( TZ1090_PIN_TDO , " tdo " ) ,
PINCTRL_PIN ( TZ1090_PIN_TMS , " tms " ) ,
PINCTRL_PIN ( TZ1090_PIN_CLK_OUT0 , " clk_out0 " ) ,
PINCTRL_PIN ( TZ1090_PIN_CLK_OUT1 , " clk_out1 " ) ,
} ;
/* Pins in each pin group */
static const unsigned int spi1_cs2_pins [ ] = {
TZ1090_PIN_SPI1_CS2 ,
} ;
static const unsigned int pdm_d_pins [ ] = {
TZ1090_PIN_PDM_D ,
} ;
static const unsigned int tft_pins [ ] = {
TZ1090_PIN_TFT_RED0 ,
TZ1090_PIN_TFT_RED1 ,
TZ1090_PIN_TFT_RED2 ,
TZ1090_PIN_TFT_RED3 ,
TZ1090_PIN_TFT_RED4 ,
TZ1090_PIN_TFT_RED5 ,
TZ1090_PIN_TFT_RED6 ,
TZ1090_PIN_TFT_RED7 ,
TZ1090_PIN_TFT_GREEN0 ,
TZ1090_PIN_TFT_GREEN1 ,
TZ1090_PIN_TFT_GREEN2 ,
TZ1090_PIN_TFT_GREEN3 ,
TZ1090_PIN_TFT_GREEN4 ,
TZ1090_PIN_TFT_GREEN5 ,
TZ1090_PIN_TFT_GREEN6 ,
TZ1090_PIN_TFT_GREEN7 ,
TZ1090_PIN_TFT_BLUE0 ,
TZ1090_PIN_TFT_BLUE1 ,
TZ1090_PIN_TFT_BLUE2 ,
TZ1090_PIN_TFT_BLUE3 ,
TZ1090_PIN_TFT_BLUE4 ,
TZ1090_PIN_TFT_BLUE5 ,
TZ1090_PIN_TFT_BLUE6 ,
TZ1090_PIN_TFT_BLUE7 ,
TZ1090_PIN_TFT_VDDEN_GD ,
TZ1090_PIN_TFT_PANELCLK ,
TZ1090_PIN_TFT_BLANK_LS ,
TZ1090_PIN_TFT_VSYNC_NS ,
TZ1090_PIN_TFT_HSYNC_NR ,
TZ1090_PIN_TFT_VD12ACB ,
TZ1090_PIN_TFT_PWRSAVE ,
} ;
static const unsigned int afe_pins [ ] = {
TZ1090_PIN_TX_ON ,
TZ1090_PIN_RX_ON ,
TZ1090_PIN_PLL_ON ,
TZ1090_PIN_PA_ON ,
TZ1090_PIN_RX_HP ,
TZ1090_PIN_ANT_SEL0 ,
TZ1090_PIN_ANT_SEL1 ,
TZ1090_PIN_GAIN0 ,
TZ1090_PIN_GAIN1 ,
TZ1090_PIN_GAIN2 ,
TZ1090_PIN_GAIN3 ,
TZ1090_PIN_GAIN4 ,
TZ1090_PIN_GAIN5 ,
TZ1090_PIN_GAIN6 ,
TZ1090_PIN_GAIN7 ,
} ;
static const unsigned int sdio_pins [ ] = {
TZ1090_PIN_SDIO_CLK ,
TZ1090_PIN_SDIO_CMD ,
TZ1090_PIN_SDIO_D0 ,
TZ1090_PIN_SDIO_D1 ,
TZ1090_PIN_SDIO_D2 ,
TZ1090_PIN_SDIO_D3 ,
} ;
static const unsigned int sdh_pins [ ] = {
TZ1090_PIN_SDH_CD ,
TZ1090_PIN_SDH_WP ,
TZ1090_PIN_SDH_CLK_IN ,
} ;
static const unsigned int spi0_pins [ ] = {
TZ1090_PIN_SPI0_MCLK ,
TZ1090_PIN_SPI0_CS0 ,
TZ1090_PIN_SPI0_CS1 ,
TZ1090_PIN_SPI0_CS2 ,
TZ1090_PIN_SPI0_DOUT ,
TZ1090_PIN_SPI0_DIN ,
} ;
static const unsigned int spi1_pins [ ] = {
TZ1090_PIN_SPI1_MCLK ,
TZ1090_PIN_SPI1_CS0 ,
TZ1090_PIN_SPI1_CS1 ,
TZ1090_PIN_SPI1_CS2 ,
TZ1090_PIN_SPI1_DOUT ,
TZ1090_PIN_SPI1_DIN ,
} ;
static const unsigned int uart0_pins [ ] = {
TZ1090_PIN_UART0_RTS ,
TZ1090_PIN_UART0_CTS ,
TZ1090_PIN_UART0_TXD ,
TZ1090_PIN_UART0_RXD ,
} ;
static const unsigned int uart1_pins [ ] = {
TZ1090_PIN_UART1_TXD ,
TZ1090_PIN_UART1_RXD ,
} ;
static const unsigned int uart_pins [ ] = {
TZ1090_PIN_UART1_TXD ,
TZ1090_PIN_UART1_RXD ,
TZ1090_PIN_UART0_RTS ,
TZ1090_PIN_UART0_CTS ,
TZ1090_PIN_UART0_TXD ,
TZ1090_PIN_UART0_RXD ,
} ;
static const unsigned int scb0_pins [ ] = {
TZ1090_PIN_SCB0_SDAT ,
TZ1090_PIN_SCB0_SCLK ,
} ;
static const unsigned int scb1_pins [ ] = {
TZ1090_PIN_SCB1_SDAT ,
TZ1090_PIN_SCB1_SCLK ,
} ;
static const unsigned int scb2_pins [ ] = {
TZ1090_PIN_SCB2_SDAT ,
TZ1090_PIN_SCB2_SCLK ,
} ;
static const unsigned int i2s_pins [ ] = {
TZ1090_PIN_I2S_MCLK ,
TZ1090_PIN_I2S_BCLK_OUT ,
TZ1090_PIN_I2S_LRCLK_OUT ,
TZ1090_PIN_I2S_DOUT0 ,
TZ1090_PIN_I2S_DOUT1 ,
TZ1090_PIN_I2S_DOUT2 ,
TZ1090_PIN_I2S_DIN ,
} ;
static const unsigned int jtag_pins [ ] = {
TZ1090_PIN_TCK ,
TZ1090_PIN_TRST ,
TZ1090_PIN_TDI ,
TZ1090_PIN_TDO ,
TZ1090_PIN_TMS ,
} ;
/* Pins in each drive pin group */
static const unsigned int drive_sdio_pins [ ] = {
TZ1090_PIN_SDIO_CLK ,
TZ1090_PIN_SDIO_CMD ,
TZ1090_PIN_SDIO_D0 ,
TZ1090_PIN_SDIO_D1 ,
TZ1090_PIN_SDIO_D2 ,
TZ1090_PIN_SDIO_D3 ,
TZ1090_PIN_SDH_WP ,
TZ1090_PIN_SDH_CD ,
TZ1090_PIN_SDH_CLK_IN ,
} ;
static const unsigned int drive_i2s_pins [ ] = {
TZ1090_PIN_CLK_OUT1 ,
TZ1090_PIN_I2S_DIN ,
TZ1090_PIN_I2S_DOUT0 ,
TZ1090_PIN_I2S_DOUT1 ,
TZ1090_PIN_I2S_DOUT2 ,
TZ1090_PIN_I2S_LRCLK_OUT ,
TZ1090_PIN_I2S_BCLK_OUT ,
TZ1090_PIN_I2S_MCLK ,
} ;
static const unsigned int drive_scb0_pins [ ] = {
TZ1090_PIN_SCB0_SCLK ,
TZ1090_PIN_SCB0_SDAT ,
TZ1090_PIN_PDM_D ,
TZ1090_PIN_PDM_C ,
} ;
static const unsigned int drive_pdm_pins [ ] = {
TZ1090_PIN_CLK_OUT0 ,
TZ1090_PIN_PDM_B ,
TZ1090_PIN_PDM_A ,
} ;
/* Pin groups each function can be muxed to */
/*
* The magic " perip " function allows otherwise non - muxing pins to be enabled in
* peripheral mode .
*/
static const char * const perip_groups [ ] = {
/* non-muxing convenient gpio pingroups */
" uart " ,
" uart0 " ,
" uart1 " ,
" spi0 " ,
" spi1 " ,
" scb0 " ,
" scb1 " ,
" scb2 " ,
" i2s " ,
/* individual pins not part of a pin mux group */
" spi0_mclk " ,
" spi0_cs0 " ,
" spi0_cs1 " ,
" spi0_cs2 " ,
" spi0_dout " ,
" spi0_din " ,
" spi1_mclk " ,
" spi1_cs0 " ,
" spi1_cs1 " ,
" spi1_dout " ,
" spi1_din " ,
" uart0_rxd " ,
" uart0_txd " ,
" uart0_cts " ,
" uart0_rts " ,
" uart1_rxd " ,
" uart1_txd " ,
" scb0_sdat " ,
" scb0_sclk " ,
" scb1_sdat " ,
" scb1_sclk " ,
" scb2_sdat " ,
" scb2_sclk " ,
" i2s_mclk " ,
" i2s_bclk_out " ,
" i2s_lrclk_out " ,
" i2s_dout0 " ,
" i2s_dout1 " ,
" i2s_dout2 " ,
" i2s_din " ,
" pdm_a " ,
" pdm_b " ,
" pdm_c " ,
} ;
static const char * const sdh_sdio_groups [ ] = {
" sdh " ,
" sdio " ,
/* sdh pins */
" sdh_cd " ,
" sdh_wp " ,
" sdh_clk_in " ,
/* sdio pins */
" sdio_clk " ,
" sdio_cmd " ,
" sdio_d0 " ,
" sdio_d1 " ,
" sdio_d2 " ,
" sdio_d3 " ,
} ;
static const char * const spi1_cs2_groups [ ] = {
" spi1_cs2 " ,
} ;
static const char * const pdm_dac_groups [ ] = {
" pdm_d " ,
} ;
static const char * const usb_vbus_groups [ ] = {
" spi1_cs2 " ,
" pdm_d " ,
} ;
static const char * const afe_groups [ ] = {
" afe " ,
/* afe pins */
" tx_on " ,
" rx_on " ,
" pll_on " ,
" pa_on " ,
" rx_hp " ,
" ant_sel0 " ,
" ant_sel1 " ,
" gain0 " ,
" gain1 " ,
" gain2 " ,
" gain3 " ,
" gain4 " ,
" gain5 " ,
" gain6 " ,
" gain7 " ,
} ;
static const char * const tft_groups [ ] = {
" tft " ,
/* tft pins */
" tft_red0 " ,
" tft_red1 " ,
" tft_red2 " ,
" tft_red3 " ,
" tft_red4 " ,
" tft_red5 " ,
" tft_red6 " ,
" tft_red7 " ,
" tft_green0 " ,
" tft_green1 " ,
" tft_green2 " ,
" tft_green3 " ,
" tft_green4 " ,
" tft_green5 " ,
" tft_green6 " ,
" tft_green7 " ,
" tft_blue0 " ,
" tft_blue1 " ,
" tft_blue2 " ,
" tft_blue3 " ,
" tft_blue4 " ,
" tft_blue5 " ,
" tft_blue6 " ,
" tft_blue7 " ,
" tft_vdden_gd " ,
" tft_panelclk " ,
" tft_blank_ls " ,
" tft_vsync_ns " ,
" tft_hsync_nr " ,
" tft_vd12acb " ,
" tft_pwrsave " ,
} ;
/* Mux functions that can be used by a mux */
enum tz1090_mux {
/* internal placeholder */
TZ1090_MUX_NA = - 1 ,
/* magic per-non-muxing-GPIO-pin peripheral mode mux */
TZ1090_MUX_PERIP ,
/* SDH/SDIO mux */
TZ1090_MUX_SDH ,
TZ1090_MUX_SDIO ,
/* USB_VBUS muxes */
TZ1090_MUX_SPI1_CS2 ,
TZ1090_MUX_PDM_DAC ,
TZ1090_MUX_USB_VBUS ,
/* AFE mux */
TZ1090_MUX_AFE ,
TZ1090_MUX_TS_OUT_0 ,
/* EXT_DAC mux */
TZ1090_MUX_DAC ,
TZ1090_MUX_NOT_IQADC_STB ,
TZ1090_MUX_IQDAC_STB ,
/* TFT mux */
TZ1090_MUX_TFT ,
TZ1090_MUX_EXT_DAC ,
TZ1090_MUX_TS_OUT_1 ,
TZ1090_MUX_LCD_TRACE ,
TZ1090_MUX_PHY_RINGOSC ,
} ;
# define FUNCTION(mux, fname, group) \
[ ( TZ1090_MUX_ # # mux ) ] = { \
. name = # fname , \
. groups = group # # _groups , \
. ngroups = ARRAY_SIZE ( group # # _groups ) , \
}
/* For intermediate functions with submuxes */
# define NULL_FUNCTION(mux, fname) \
[ ( TZ1090_MUX_ # # mux ) ] = { \
. name = # fname , \
}
/* Must correlate with enum tz1090_mux */
static const struct tz1090_function tz1090_functions [ ] = {
/* FUNCTION function name pingroups */
FUNCTION ( PERIP , perip , perip ) ,
FUNCTION ( SDH , sdh , sdh_sdio ) ,
FUNCTION ( SDIO , sdio , sdh_sdio ) ,
FUNCTION ( SPI1_CS2 , spi1_cs2 , spi1_cs2 ) ,
FUNCTION ( PDM_DAC , pdm_dac , pdm_dac ) ,
FUNCTION ( USB_VBUS , usb_vbus , usb_vbus ) ,
FUNCTION ( AFE , afe , afe ) ,
FUNCTION ( TS_OUT_0 , ts_out_0 , afe ) ,
FUNCTION ( DAC , ext_dac , tft ) ,
FUNCTION ( NOT_IQADC_STB , not_iqadc_stb , tft ) ,
FUNCTION ( IQDAC_STB , iqdac_stb , tft ) ,
FUNCTION ( TFT , tft , tft ) ,
NULL_FUNCTION ( EXT_DAC , _ext_dac ) ,
FUNCTION ( TS_OUT_1 , ts_out_1 , tft ) ,
FUNCTION ( LCD_TRACE , lcd_trace , tft ) ,
FUNCTION ( PHY_RINGOSC , phy_ringosc , tft ) ,
} ;
/* Sub muxes */
/**
* MUX ( ) - Initialise a mux description .
* @ f0 : Function 0 ( TZ1090_MUX_ is prepended , NA for none )
* @ f1 : Function 1 ( TZ1090_MUX_ is prepended , NA for none )
* @ f2 : Function 2 ( TZ1090_MUX_ is prepended , NA for none )
* @ f3 : Function 3 ( TZ1090_MUX_ is prepended , NA for none )
* @ f4 : Function 4 ( TZ1090_MUX_ is prepended , NA for none )
* @ mux_r : Mux register ( REG_PINCTRL_ is prepended )
* @ mux_b : Bit number in register that the mux field begins
* @ mux_w : Width of mux field in register
*/
# define MUX(f0, f1, f2, f3, f4, mux_r, mux_b, mux_w) \
{ \
. funcs = { \
TZ1090_MUX_ # # f0 , \
TZ1090_MUX_ # # f1 , \
TZ1090_MUX_ # # f2 , \
TZ1090_MUX_ # # f3 , \
TZ1090_MUX_ # # f4 , \
} , \
. reg = ( REG_PINCTRL_ # # mux_r ) , \
. bit = ( mux_b ) , \
. width = ( mux_w ) , \
}
/**
* DEFINE_SUBMUX ( ) - Defines a submux description separate from a pin group .
* @ mux : Mux name ( _submux is appended )
* @ f0 : Function 0 ( TZ1090_MUX_ is prepended , NA for none )
* @ f1 : Function 1 ( TZ1090_MUX_ is prepended , NA for none )
* @ f2 : Function 2 ( TZ1090_MUX_ is prepended , NA for none )
* @ f3 : Function 3 ( TZ1090_MUX_ is prepended , NA for none )
* @ f4 : Function 4 ( TZ1090_MUX_ is prepended , NA for none )
* @ mux_r : Mux register ( REG_PINCTRL_ is prepended )
* @ mux_b : Bit number in register that the mux field begins
* @ mux_w : Width of mux field in register
*
* A sub mux is a nested mux that can be bound to a magic function number used
* by another mux description . For example value 4 of the top level mux might
* correspond to a function which has a submux pointed to in tz1090_submux [ ] .
* The outer mux can then take on any function in the top level mux or the
* submux , and if a submux function is chosen both muxes are updated to route
* the signal from the submux .
*
* The submux can be defined with DEFINE_SUBMUX and pointed to from
* tz1090_submux [ ] using SUBMUX .
*/
# define DEFINE_SUBMUX(mux, f0, f1, f2, f3, f4, mux_r, mux_b, mux_w) \
static struct tz1090_muxdesc mux # # _submux = \
MUX ( f0 , f1 , f2 , f3 , f4 , mux_r , mux_b , mux_w )
/**
* SUBMUX ( ) - Link a submux to a function number .
* @ f : Function name ( TZ1090_MUX_ is prepended )
* @ submux : Submux name ( _submux is appended )
*
* For use in tz1090_submux [ ] initialisation to link an intermediate function
* number to a particular submux description . It indicates that when the
* function is chosen the signal is connected to the submux .
*/
# define SUBMUX(f, submux) [(TZ1090_MUX_ ## f)] = &(submux ## _submux)
/**
* MUX_PG ( ) - Initialise a pin group with mux control
* @ pg_name : Pin group name ( stringified , _pins appended to get pins array )
* @ f0 : Function 0 ( TZ1090_MUX_ is prepended , NA for none )
* @ f1 : Function 1 ( TZ1090_MUX_ is prepended , NA for none )
* @ f2 : Function 2 ( TZ1090_MUX_ is prepended , NA for none )
* @ f3 : Function 3 ( TZ1090_MUX_ is prepended , NA for none )
* @ f4 : Function 4 ( TZ1090_MUX_ is prepended , NA for none )
* @ mux_r : Mux register ( REG_PINCTRL_ is prepended )
* @ mux_b : Bit number in register that the mux field begins
* @ mux_w : Width of mux field in register
*/
# define MUX_PG(pg_name, f0, f1, f2, f3, f4, \
mux_r , mux_b , mux_w ) \
{ \
. name = # pg_name , \
. pins = pg_name # # _pins , \
. npins = ARRAY_SIZE ( pg_name # # _pins ) , \
. mux = MUX ( f0 , f1 , f2 , f3 , f4 , \
mux_r , mux_b , mux_w ) , \
}
/**
* SIMPLE_PG ( ) - Initialise a simple convenience pin group
* @ pg_name : Pin group name ( stringified , _pins appended to get pins array )
*
* A simple pin group is simply used for binding pins together so they can be
* referred to by a single name instead of having to list every pin
* individually .
*/
# define SIMPLE_PG(pg_name) \
{ \
. name = # pg_name , \
. pins = pg_name # # _pins , \
. npins = ARRAY_SIZE ( pg_name # # _pins ) , \
}
/**
* DRV_PG ( ) - Initialise a pin group with drive control
* @ pg_name : Pin group name ( stringified , _pins appended to get pins array )
* @ slw_b : Slew register bit .
* The same bit is used for Schmitt , and Drive ( * 2 ) .
*/
# define DRV_PG(pg_name, slw_b) \
{ \
. name = # pg_name , \
. pins = pg_name # # _pins , \
. npins = ARRAY_SIZE ( pg_name # # _pins ) , \
. drv = true , \
. slw_bit = ( slw_b ) , \
}
/*
* Define main muxing pin groups
*/
/* submuxes */
/* name f0, f1, f2, f3, f4, mux r/b/w */
DEFINE_SUBMUX ( ext_dac , DAC , NOT_IQADC_STB , IQDAC_STB , NA , NA , IF_CTL , 6 , 2 ) ;
/* bind submuxes to internal functions */
static struct tz1090_muxdesc * tz1090_submux [ ] = {
SUBMUX ( EXT_DAC , ext_dac ) ,
} ;
/*
* These are the pin mux groups . Pin muxing can be enabled and disabled for each
* pin individually so these groups are internal . The mapping of pins to pin mux
* group is below ( tz1090_mux_pins ) .
*/
static struct tz1090_pingroup tz1090_mux_groups [ ] = {
/* Muxing pin groups */
/* pg_name, f0, f1, f2, f3, f4, mux r/b/w */
MUX_PG ( sdh , SDH , SDIO , NA , NA , NA , IF_CTL , 20 , 2 ) ,
MUX_PG ( sdio , SDIO , SDH , NA , NA , NA , IF_CTL , 16 , 2 ) ,
MUX_PG ( spi1_cs2 , SPI1_CS2 , USB_VBUS , NA , NA , NA , IF_CTL , 10 , 2 ) ,
MUX_PG ( pdm_d , PDM_DAC , USB_VBUS , NA , NA , NA , IF_CTL , 8 , 2 ) ,
MUX_PG ( afe , AFE , TS_OUT_0 , NA , NA , NA , IF_CTL , 4 , 2 ) ,
MUX_PG ( tft , TFT , EXT_DAC , TS_OUT_1 , LCD_TRACE , PHY_RINGOSC , IF_CTL , 0 , 3 ) ,
} ;
/*
* This is the mapping from GPIO pins to pin mux groups in tz1090_mux_groups [ ] .
* Pins which aren ' t muxable to multiple peripherals are set to
* TZ1090_MUX_GROUP_MAX to enable the " perip " function to enable / disable
* peripheral control of the pin .
*
* This array is initialised in tz1090_init_mux_pins ( ) .
*/
static u8 tz1090_mux_pins [ NUM_GPIOS ] ;
/* TZ1090_MUX_GROUP_MAX is used in tz1090_mux_pins[] for non-muxing pins */
# define TZ1090_MUX_GROUP_MAX ARRAY_SIZE(tz1090_mux_groups)
/**
* tz1090_init_mux_pins ( ) - Initialise GPIO pin to mux group mapping .
*
* Initialises the tz1090_mux_pins [ ] array to be the inverse of the pin lists in
* each pin mux group in tz1090_mux_groups [ ] .
*
* It is assumed that no pin mux groups overlap ( share pins ) .
*/
static void __init tz1090_init_mux_pins ( void )
{
unsigned int g , p ;
const struct tz1090_pingroup * grp ;
const unsigned int * pin ;
for ( p = 0 ; p < NUM_GPIOS ; + + p )
tz1090_mux_pins [ p ] = TZ1090_MUX_GROUP_MAX ;
grp = tz1090_mux_groups ;
for ( g = 0 , grp = tz1090_mux_groups ;
g < ARRAY_SIZE ( tz1090_mux_groups ) ; + + g , + + grp )
for ( pin = grp - > pins , p = 0 ; p < grp - > npins ; + + p , + + pin )
tz1090_mux_pins [ * pin ] = g ;
}
/*
* These are the externally visible pin groups . Some of them allow group control
* of drive configuration . Some are just simple convenience pingroups . All the
* internal pin mux groups in tz1090_mux_groups [ ] are mirrored here with the
* same pins .
* Pseudo pin groups follow in the group numbers after this array for each GPIO
* pin . Any group used for muxing must have all pins belonging to the same pin
* mux group .
*/
static struct tz1090_pingroup tz1090_groups [ ] = {
/* Pin groups with drive control (with no out of place pins) */
/* pg_name, slw/schmitt/drv b */
DRV_PG ( jtag , 11 /* 11, 22 */ ) ,
DRV_PG ( tft , 10 /* 10, 20 */ ) ,
DRV_PG ( scb2 , 9 /* 9, 18 */ ) ,
DRV_PG ( spi0 , 7 /* 7, 14 */ ) ,
DRV_PG ( uart , 5 /* 5, 10 */ ) ,
DRV_PG ( scb1 , 4 /* 4, 8 */ ) ,
DRV_PG ( spi1 , 3 /* 3, 6 */ ) ,
DRV_PG ( afe , 0 /* 0, 0 */ ) ,
/*
* Drive specific pin groups ( with odd combinations of pins which makes
* the pin group naming somewhat arbitrary )
*/
/* pg_name, slw/schmitt/drv b */
DRV_PG ( drive_sdio , 8 /* 8, 16 */ ) , /* sdio_* + sdh_* */
DRV_PG ( drive_i2s , 6 /* 6, 12 */ ) , /* i2s_* + clk_out1 */
DRV_PG ( drive_scb0 , 2 /* 2, 4 */ ) , /* scb0_* + pdm_{c,d} */
DRV_PG ( drive_pdm , 1 /* 1, 2 */ ) , /* pdm_{a,b} + clk_out0 */
/* Convenience pin groups */
/* pg_name */
SIMPLE_PG ( uart0 ) ,
SIMPLE_PG ( uart1 ) ,
SIMPLE_PG ( scb0 ) ,
SIMPLE_PG ( i2s ) ,
SIMPLE_PG ( sdh ) ,
SIMPLE_PG ( sdio ) ,
/* pseudo-pingroups for each GPIO pin follow */
} ;
/**
* struct tz1090_pmx - Private pinctrl data
* @ dev : Platform device
* @ pctl : Pin control device
* @ regs : Register region
* @ lock : Lock protecting coherency of pin_en , gpio_en , and SELECT regs
* @ pin_en : Pins that have been enabled ( 32 pins packed into each element )
* @ gpio_en : GPIOs that have been enabled ( 32 pins packed into each element )
*/
struct tz1090_pmx {
struct device * dev ;
struct pinctrl_dev * pctl ;
void __iomem * regs ;
spinlock_t lock ;
u32 pin_en [ 3 ] ;
u32 gpio_en [ 3 ] ;
} ;
static inline u32 pmx_read ( struct tz1090_pmx * pmx , u32 reg )
{
return ioread32 ( pmx - > regs + reg ) ;
}
static inline void pmx_write ( struct tz1090_pmx * pmx , u32 val , u32 reg )
{
iowrite32 ( val , pmx - > regs + reg ) ;
}
/*
* Pin control operations
*/
/* each GPIO pin has it's own pseudo pingroup containing only itself */
static int tz1090_pinctrl_get_groups_count ( struct pinctrl_dev * pctldev )
{
return ARRAY_SIZE ( tz1090_groups ) + NUM_GPIOS ;
}
static const char * tz1090_pinctrl_get_group_name ( struct pinctrl_dev * pctldev ,
unsigned int group )
{
if ( group < ARRAY_SIZE ( tz1090_groups ) ) {
/* normal pingroup */
return tz1090_groups [ group ] . name ;
} else {
/* individual gpio pin pseudo-pingroup */
unsigned int pin = group - ARRAY_SIZE ( tz1090_groups ) ;
return tz1090_pins [ pin ] . name ;
}
}
static int tz1090_pinctrl_get_group_pins ( struct pinctrl_dev * pctldev ,
unsigned int group ,
const unsigned int * * pins ,
unsigned int * num_pins )
{
if ( group < ARRAY_SIZE ( tz1090_groups ) ) {
/* normal pingroup */
* pins = tz1090_groups [ group ] . pins ;
* num_pins = tz1090_groups [ group ] . npins ;
} else {
/* individual gpio pin pseudo-pingroup */
unsigned int pin = group - ARRAY_SIZE ( tz1090_groups ) ;
* pins = & tz1090_pins [ pin ] . number ;
* num_pins = 1 ;
}
return 0 ;
}
# ifdef CONFIG_DEBUG_FS
static void tz1090_pinctrl_pin_dbg_show ( struct pinctrl_dev * pctldev ,
struct seq_file * s ,
unsigned int offset )
{
seq_printf ( s , " %s " , dev_name ( pctldev - > dev ) ) ;
}
# endif
static int reserve_map ( struct device * dev , struct pinctrl_map * * map ,
unsigned int * reserved_maps , unsigned int * num_maps ,
unsigned int reserve )
{
unsigned int old_num = * reserved_maps ;
unsigned int new_num = * num_maps + reserve ;
struct pinctrl_map * new_map ;
if ( old_num > = new_num )
return 0 ;
new_map = krealloc ( * map , sizeof ( * new_map ) * new_num , GFP_KERNEL ) ;
if ( ! new_map ) {
dev_err ( dev , " krealloc(map) failed \n " ) ;
return - ENOMEM ;
}
memset ( new_map + old_num , 0 , ( new_num - old_num ) * sizeof ( * new_map ) ) ;
* map = new_map ;
* reserved_maps = new_num ;
return 0 ;
}
static int add_map_mux ( struct pinctrl_map * * map , unsigned int * reserved_maps ,
unsigned int * num_maps , const char * group ,
const char * function )
{
if ( WARN_ON ( * num_maps = = * reserved_maps ) )
return - ENOSPC ;
( * map ) [ * num_maps ] . type = PIN_MAP_TYPE_MUX_GROUP ;
( * map ) [ * num_maps ] . data . mux . group = group ;
( * map ) [ * num_maps ] . data . mux . function = function ;
( * num_maps ) + + ;
return 0 ;
}
static int add_map_configs ( struct device * dev ,
struct pinctrl_map * * map ,
unsigned int * reserved_maps , unsigned int * num_maps ,
const char * group , unsigned long * configs ,
unsigned int num_configs )
{
unsigned long * dup_configs ;
if ( WARN_ON ( * num_maps = = * reserved_maps ) )
return - ENOSPC ;
dup_configs = kmemdup ( configs , num_configs * sizeof ( * dup_configs ) ,
GFP_KERNEL ) ;
if ( ! dup_configs ) {
dev_err ( dev , " kmemdup(configs) failed \n " ) ;
return - ENOMEM ;
}
( * map ) [ * num_maps ] . type = PIN_MAP_TYPE_CONFIGS_GROUP ;
( * map ) [ * num_maps ] . data . configs . group_or_pin = group ;
( * map ) [ * num_maps ] . data . configs . configs = dup_configs ;
( * map ) [ * num_maps ] . data . configs . num_configs = num_configs ;
( * num_maps ) + + ;
return 0 ;
}
static void tz1090_pinctrl_dt_free_map ( struct pinctrl_dev * pctldev ,
struct pinctrl_map * map ,
unsigned int num_maps )
{
int i ;
for ( i = 0 ; i < num_maps ; i + + )
if ( map [ i ] . type = = PIN_MAP_TYPE_CONFIGS_GROUP )
kfree ( map [ i ] . data . configs . configs ) ;
kfree ( map ) ;
}
static int tz1090_pinctrl_dt_subnode_to_map ( struct device * dev ,
struct device_node * np ,
struct pinctrl_map * * map ,
unsigned int * reserved_maps ,
unsigned int * num_maps )
{
int ret ;
const char * function ;
unsigned long * configs = NULL ;
unsigned int num_configs = 0 ;
unsigned int reserve ;
struct property * prop ;
const char * group ;
ret = of_property_read_string ( np , " tz1090,function " , & function ) ;
if ( ret < 0 ) {
/* EINVAL=missing, which is fine since it's optional */
if ( ret ! = - EINVAL )
dev_err ( dev , " could not parse property function \n " ) ;
function = NULL ;
}
ret = pinconf_generic_parse_dt_config ( np , & configs , & num_configs ) ;
if ( ret )
return ret ;
reserve = 0 ;
if ( function ! = NULL )
reserve + + ;
if ( num_configs )
reserve + + ;
ret = of_property_count_strings ( np , " tz1090,pins " ) ;
if ( ret < 0 ) {
dev_err ( dev , " could not parse property pins \n " ) ;
goto exit ;
}
reserve * = ret ;
ret = reserve_map ( dev , map , reserved_maps , num_maps , reserve ) ;
if ( ret < 0 )
goto exit ;
of_property_for_each_string ( np , " tz1090,pins " , prop , group ) {
if ( function ) {
ret = add_map_mux ( map , reserved_maps , num_maps ,
group , function ) ;
if ( ret < 0 )
goto exit ;
}
if ( num_configs ) {
ret = add_map_configs ( dev , map , reserved_maps ,
num_maps , group , configs ,
num_configs ) ;
if ( ret < 0 )
goto exit ;
}
}
ret = 0 ;
exit :
kfree ( configs ) ;
return ret ;
}
static int tz1090_pinctrl_dt_node_to_map ( struct pinctrl_dev * pctldev ,
struct device_node * np_config ,
struct pinctrl_map * * map ,
unsigned int * num_maps )
{
unsigned int reserved_maps ;
struct device_node * np ;
int ret ;
reserved_maps = 0 ;
* map = NULL ;
* num_maps = 0 ;
for_each_child_of_node ( np_config , np ) {
ret = tz1090_pinctrl_dt_subnode_to_map ( pctldev - > dev , np , map ,
& reserved_maps ,
num_maps ) ;
if ( ret < 0 ) {
tz1090_pinctrl_dt_free_map ( pctldev , * map , * num_maps ) ;
return ret ;
}
}
return 0 ;
}
static struct pinctrl_ops tz1090_pinctrl_ops = {
. get_groups_count = tz1090_pinctrl_get_groups_count ,
. get_group_name = tz1090_pinctrl_get_group_name ,
. get_group_pins = tz1090_pinctrl_get_group_pins ,
# ifdef CONFIG_DEBUG_FS
. pin_dbg_show = tz1090_pinctrl_pin_dbg_show ,
# endif
. dt_node_to_map = tz1090_pinctrl_dt_node_to_map ,
. dt_free_map = tz1090_pinctrl_dt_free_map ,
} ;
/*
* Pin mux operations
*/
static int tz1090_pinctrl_get_funcs_count ( struct pinctrl_dev * pctldev )
{
return ARRAY_SIZE ( tz1090_functions ) ;
}
static const char * tz1090_pinctrl_get_func_name ( struct pinctrl_dev * pctldev ,
unsigned int function )
{
return tz1090_functions [ function ] . name ;
}
static int tz1090_pinctrl_get_func_groups ( struct pinctrl_dev * pctldev ,
unsigned int function ,
const char * const * * groups ,
unsigned int * const num_groups )
{
/* pingroup functions */
* groups = tz1090_functions [ function ] . groups ;
* num_groups = tz1090_functions [ function ] . ngroups ;
return 0 ;
}
/**
* tz1090_pinctrl_select ( ) - update bit in SELECT register
* @ pmx : Pinmux data
* @ pin : Pin number ( must be within GPIO range )
*/
static void tz1090_pinctrl_select ( struct tz1090_pmx * pmx ,
unsigned int pin )
{
u32 reg , reg_shift , select , val ;
unsigned int pmx_index , pmx_shift ;
unsigned long flags ;
/* uses base 32 instead of base 30 */
pmx_index = pin > > 5 ;
pmx_shift = pin & 0x1f ;
/* select = !perip || gpio */
select = ( ( ~ pmx - > pin_en [ pmx_index ] |
pmx - > gpio_en [ pmx_index ] ) > > pmx_shift ) & 1 ;
/* find register and bit offset (base 30) */
reg = REG_PINCTRL_SELECT + 4 * ( pin / 30 ) ;
reg_shift = pin % 30 ;
/* modify gpio select bit */
__global_lock2 ( flags ) ;
val = pmx_read ( pmx , reg ) ;
val & = ~ BIT ( reg_shift ) ;
val | = select < < reg_shift ;
pmx_write ( pmx , val , reg ) ;
__global_unlock2 ( flags ) ;
}
/**
* tz1090_pinctrl_gpio_select ( ) - enable / disable GPIO usage for a pin
* @ pmx : Pinmux data
* @ pin : Pin number
* @ gpio_select : true to enable pin as GPIO ,
* false to leave control to whatever function is enabled
*
* Records that GPIO usage is enabled / disabled so that enabling a function
* doesn ' t override the SELECT register bit .
*/
static void tz1090_pinctrl_gpio_select ( struct tz1090_pmx * pmx ,
unsigned int pin ,
bool gpio_select )
{
unsigned int index , shift ;
u32 gpio_en ;
if ( pin > = NUM_GPIOS )
return ;
/* uses base 32 instead of base 30 */
index = pin > > 5 ;
shift = pin & 0x1f ;
spin_lock ( & pmx - > lock ) ;
/* keep a record whether gpio is selected */
gpio_en = pmx - > gpio_en [ index ] ;
gpio_en & = ~ BIT ( shift ) ;
if ( gpio_select )
gpio_en | = BIT ( shift ) ;
pmx - > gpio_en [ index ] = gpio_en ;
/* update the select bit */
tz1090_pinctrl_select ( pmx , pin ) ;
spin_unlock ( & pmx - > lock ) ;
}
/**
* tz1090_pinctrl_perip_select ( ) - enable / disable peripheral interface for a pin
* @ pmx : Pinmux data
* @ pin : Pin number
* @ perip_select : true to enable peripheral interface when not GPIO ,
* false to leave pin in GPIO mode
*
* Records that peripheral usage is enabled / disabled so that SELECT register can
* be set appropriately when GPIO is disabled .
*/
static void tz1090_pinctrl_perip_select ( struct tz1090_pmx * pmx ,
unsigned int pin ,
bool perip_select )
{
unsigned int index , shift ;
u32 pin_en ;
if ( pin > = NUM_GPIOS )
return ;
/* uses base 32 instead of base 30 */
index = pin > > 5 ;
shift = pin & 0x1f ;
spin_lock ( & pmx - > lock ) ;
/* keep a record whether peripheral is selected */
pin_en = pmx - > pin_en [ index ] ;
pin_en & = ~ BIT ( shift ) ;
if ( perip_select )
pin_en | = BIT ( shift ) ;
pmx - > pin_en [ index ] = pin_en ;
/* update the select bit */
tz1090_pinctrl_select ( pmx , pin ) ;
spin_unlock ( & pmx - > lock ) ;
}
/**
* tz1090_pinctrl_enable_mux ( ) - Switch a pin mux group to a function .
* @ pmx : Pinmux data
* @ desc : Pinmux description
* @ function : Function to switch to
*
* Enable a particular function on a pin mux group . Since pin mux descriptions
* are nested this function is recursive .
*/
static int tz1090_pinctrl_enable_mux ( struct tz1090_pmx * pmx ,
const struct tz1090_muxdesc * desc ,
unsigned int function )
{
const int * fit ;
unsigned long flags ;
int mux ;
unsigned int func , ret ;
u32 reg , mask ;
/* find the mux value for this function, searching recursively */
for ( mux = 0 , fit = desc - > funcs ;
mux < ARRAY_SIZE ( desc - > funcs ) ; + + mux , + + fit ) {
func = * fit ;
if ( func = = function )
goto found_mux ;
/* maybe it's a sub-mux */
if ( func < ARRAY_SIZE ( tz1090_submux ) & & tz1090_submux [ func ] ) {
ret = tz1090_pinctrl_enable_mux ( pmx ,
tz1090_submux [ func ] ,
function ) ;
if ( ! ret )
goto found_mux ;
}
}
return - EINVAL ;
found_mux :
/* Set up the mux */
if ( desc - > width ) {
mask = ( BIT ( desc - > width ) - 1 ) < < desc - > bit ;
__global_lock2 ( flags ) ;
reg = pmx_read ( pmx , desc - > reg ) ;
reg & = ~ mask ;
reg | = ( mux < < desc - > bit ) & mask ;
pmx_write ( pmx , reg , desc - > reg ) ;
__global_unlock2 ( flags ) ;
}
return 0 ;
}
/**
* tz1090_pinctrl_enable ( ) - Enable a function on a pin group .
* @ pctldev : Pin control data
* @ function : Function index to enable
* @ group : Group index to enable
*
* Enable a particular function on a group of pins . The per GPIO pin pseudo pin
* groups can be used ( in which case the pin will be enabled in peripheral mode
* and if it belongs to a pin mux group the mux will be switched if it isn ' t
* already in use . Some convenience pin groups can also be used in which case
* the effect is the same as enabling the function on each individual pin in the
* group .
*/
static int tz1090_pinctrl_enable ( struct pinctrl_dev * pctldev ,
unsigned int function , unsigned int group )
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
struct tz1090_pingroup * grp ;
int ret ;
unsigned int pin_num , mux_group , i , npins ;
const unsigned int * pins ;
/* group of pins? */
if ( group < ARRAY_SIZE ( tz1090_groups ) ) {
grp = & tz1090_groups [ group ] ;
npins = grp - > npins ;
pins = grp - > pins ;
/*
* All pins in the group must belong to the same mux group ,
* which allows us to just use the mux group of the first pin .
* By explicitly listing permitted pingroups for each function
* the pinmux core should ensure this is always the case .
*/
} else {
pin_num = group - ARRAY_SIZE ( tz1090_groups ) ;
npins = 1 ;
pins = & pin_num ;
}
mux_group = tz1090_mux_pins [ * pins ] ;
/* no mux group, but can still be individually muxed to peripheral */
if ( mux_group > = TZ1090_MUX_GROUP_MAX ) {
if ( function = = TZ1090_MUX_PERIP )
goto mux_pins ;
return - EINVAL ;
}
/* mux group already set to a different function? */
grp = & tz1090_mux_groups [ mux_group ] ;
if ( grp - > func_count & & grp - > func ! = function ) {
dev_err ( pctldev - > dev ,
" %s: can't mux pin(s) to '%s', group already muxed to '%s' \n " ,
__func__ , tz1090_functions [ function ] . name ,
tz1090_functions [ grp - > func ] . name ) ;
return - EBUSY ;
}
dev_dbg ( pctldev - > dev , " %s: muxing %u pin(s) in '%s' to '%s' \n " ,
__func__ , npins , grp - > name , tz1090_functions [ function ] . name ) ;
/* if first pin in mux group to be enabled, enable the group mux */
if ( ! grp - > func_count ) {
grp - > func = function ;
ret = tz1090_pinctrl_enable_mux ( pmx , & grp - > mux , function ) ;
if ( ret )
return ret ;
}
/* add pins to ref count and mux individually to peripheral */
grp - > func_count + = npins ;
mux_pins :
for ( i = 0 ; i < npins ; + + i )
tz1090_pinctrl_perip_select ( pmx , pins [ i ] , true ) ;
return 0 ;
}
/**
* tz1090_pinctrl_disable ( ) - Disable a function on a pin group .
* @ pctldev : Pin control data
* @ function : Function index to disable
* @ group : Group index to disable
*
* Disable a particular function on a group of pins . The per GPIO pin pseudo pin
* groups can be used ( in which case the pin will be taken out of peripheral
* mode . Some convenience pin groups can also be used in which case the effect
* is the same as enabling the function on each individual pin in the group .
*/
static void tz1090_pinctrl_disable ( struct pinctrl_dev * pctldev ,
unsigned int function , unsigned int group )
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
struct tz1090_pingroup * grp ;
unsigned int pin_num , mux_group , i , npins ;
const unsigned int * pins ;
/* group of pins? */
if ( group < ARRAY_SIZE ( tz1090_groups ) ) {
grp = & tz1090_groups [ group ] ;
npins = grp - > npins ;
pins = grp - > pins ;
/*
* All pins in the group must belong to the same mux group ,
* which allows us to just use the mux group of the first pin .
* By explicitly listing permitted pingroups for each function
* the pinmux core should ensure this is always the case .
*/
} else {
pin_num = group - ARRAY_SIZE ( tz1090_groups ) ;
npins = 1 ;
pins = & pin_num ;
}
mux_group = tz1090_mux_pins [ * pins ] ;
/* no mux group, but can still be individually muxed to peripheral */
if ( mux_group > = TZ1090_MUX_GROUP_MAX ) {
if ( function = = TZ1090_MUX_PERIP )
goto unmux_pins ;
return ;
}
/* mux group already set to a different function? */
grp = & tz1090_mux_groups [ mux_group ] ;
dev_dbg ( pctldev - > dev , " %s: unmuxing %u pin(s) in '%s' from '%s' \n " ,
__func__ , npins , grp - > name , tz1090_functions [ function ] . name ) ;
/* subtract pins from ref count and unmux individually */
WARN_ON ( grp - > func_count < npins ) ;
grp - > func_count - = npins ;
unmux_pins :
for ( i = 0 ; i < npins ; + + i )
tz1090_pinctrl_perip_select ( pmx , pins [ i ] , false ) ;
}
/**
* tz1090_pinctrl_gpio_request_enable ( ) - Put pin in GPIO mode .
* @ pctldev : Pin control data
* @ range : GPIO range
* @ pin : Pin number
*
* Puts a particular pin into GPIO mode , disabling peripheral control until it ' s
* disabled again .
*/
static int tz1090_pinctrl_gpio_request_enable ( struct pinctrl_dev * pctldev ,
struct pinctrl_gpio_range * range ,
unsigned int pin )
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
tz1090_pinctrl_gpio_select ( pmx , pin , true ) ;
return 0 ;
}
/**
* tz1090_pinctrl_gpio_disable_free ( ) - Take pin out of GPIO mode .
* @ pctldev : Pin control data
* @ range : GPIO range
* @ pin : Pin number
*
* Take a particular pin out of GPIO mode . If the pin is enabled for a
* peripheral it will return to peripheral mode .
*/
static void tz1090_pinctrl_gpio_disable_free ( struct pinctrl_dev * pctldev ,
struct pinctrl_gpio_range * range ,
unsigned int pin )
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
tz1090_pinctrl_gpio_select ( pmx , pin , false ) ;
}
static struct pinmux_ops tz1090_pinmux_ops = {
. get_functions_count = tz1090_pinctrl_get_funcs_count ,
. get_function_name = tz1090_pinctrl_get_func_name ,
. get_function_groups = tz1090_pinctrl_get_func_groups ,
. enable = tz1090_pinctrl_enable ,
. disable = tz1090_pinctrl_disable ,
. gpio_request_enable = tz1090_pinctrl_gpio_request_enable ,
. gpio_disable_free = tz1090_pinctrl_gpio_disable_free ,
} ;
/*
* Pin config operations
*/
struct tz1090_pinconf_pullup {
unsigned char index ;
unsigned char shift ;
} ;
/* The mapping of pin to pull up/down register index and shift */
static struct tz1090_pinconf_pullup tz1090_pinconf_pullup [ ] = {
{ 5 , 22 } , /* 0 - TZ1090_PIN_SDIO_CLK */
{ 0 , 14 } , /* 1 - TZ1090_PIN_SDIO_CMD */
{ 0 , 6 } , /* 2 - TZ1090_PIN_SDIO_D0 */
{ 0 , 8 } , /* 3 - TZ1090_PIN_SDIO_D1 */
{ 0 , 10 } , /* 4 - TZ1090_PIN_SDIO_D2 */
{ 0 , 12 } , /* 5 - TZ1090_PIN_SDIO_D3 */
{ 0 , 2 } , /* 6 - TZ1090_PIN_SDH_CD */
{ 0 , 4 } , /* 7 - TZ1090_PIN_SDH_WP */
{ 0 , 16 } , /* 8 - TZ1090_PIN_SPI0_MCLK */
{ 0 , 18 } , /* 9 - TZ1090_PIN_SPI0_CS0 */
{ 0 , 20 } , /* 10 - TZ1090_PIN_SPI0_CS1 */
{ 0 , 22 } , /* 11 - TZ1090_PIN_SPI0_CS2 */
{ 0 , 24 } , /* 12 - TZ1090_PIN_SPI0_DOUT */
{ 0 , 26 } , /* 13 - TZ1090_PIN_SPI0_DIN */
{ 0 , 28 } , /* 14 - TZ1090_PIN_SPI1_MCLK */
{ 0 , 30 } , /* 15 - TZ1090_PIN_SPI1_CS0 */
{ 1 , 0 } , /* 16 - TZ1090_PIN_SPI1_CS1 */
{ 1 , 2 } , /* 17 - TZ1090_PIN_SPI1_CS2 */
{ 1 , 4 } , /* 18 - TZ1090_PIN_SPI1_DOUT */
{ 1 , 6 } , /* 19 - TZ1090_PIN_SPI1_DIN */
{ 1 , 8 } , /* 20 - TZ1090_PIN_UART0_RXD */
{ 1 , 10 } , /* 21 - TZ1090_PIN_UART0_TXD */
{ 1 , 12 } , /* 22 - TZ1090_PIN_UART0_CTS */
{ 1 , 14 } , /* 23 - TZ1090_PIN_UART0_RTS */
{ 1 , 16 } , /* 24 - TZ1090_PIN_UART1_RXD */
{ 1 , 18 } , /* 25 - TZ1090_PIN_UART1_TXD */
{ 1 , 20 } , /* 26 - TZ1090_PIN_SCB0_SDAT */
{ 1 , 22 } , /* 27 - TZ1090_PIN_SCB0_SCLK */
{ 1 , 24 } , /* 28 - TZ1090_PIN_SCB1_SDAT */
{ 1 , 26 } , /* 29 - TZ1090_PIN_SCB1_SCLK */
{ 1 , 28 } , /* 30 - TZ1090_PIN_SCB2_SDAT */
{ 1 , 30 } , /* 31 - TZ1090_PIN_SCB2_SCLK */
{ 2 , 0 } , /* 32 - TZ1090_PIN_I2S_MCLK */
{ 2 , 2 } , /* 33 - TZ1090_PIN_I2S_BCLK_OUT */
{ 2 , 4 } , /* 34 - TZ1090_PIN_I2S_LRCLK_OUT */
{ 2 , 6 } , /* 35 - TZ1090_PIN_I2S_DOUT0 */
{ 2 , 8 } , /* 36 - TZ1090_PIN_I2S_DOUT1 */
{ 2 , 10 } , /* 37 - TZ1090_PIN_I2S_DOUT2 */
{ 2 , 12 } , /* 38 - TZ1090_PIN_I2S_DIN */
{ 4 , 12 } , /* 39 - TZ1090_PIN_PDM_A */
{ 4 , 14 } , /* 40 - TZ1090_PIN_PDM_B */
{ 4 , 18 } , /* 41 - TZ1090_PIN_PDM_C */
{ 4 , 20 } , /* 42 - TZ1090_PIN_PDM_D */
{ 2 , 14 } , /* 43 - TZ1090_PIN_TFT_RED0 */
{ 2 , 16 } , /* 44 - TZ1090_PIN_TFT_RED1 */
{ 2 , 18 } , /* 45 - TZ1090_PIN_TFT_RED2 */
{ 2 , 20 } , /* 46 - TZ1090_PIN_TFT_RED3 */
{ 2 , 22 } , /* 47 - TZ1090_PIN_TFT_RED4 */
{ 2 , 24 } , /* 48 - TZ1090_PIN_TFT_RED5 */
{ 2 , 26 } , /* 49 - TZ1090_PIN_TFT_RED6 */
{ 2 , 28 } , /* 50 - TZ1090_PIN_TFT_RED7 */
{ 2 , 30 } , /* 51 - TZ1090_PIN_TFT_GREEN0 */
{ 3 , 0 } , /* 52 - TZ1090_PIN_TFT_GREEN1 */
{ 3 , 2 } , /* 53 - TZ1090_PIN_TFT_GREEN2 */
{ 3 , 4 } , /* 54 - TZ1090_PIN_TFT_GREEN3 */
{ 3 , 6 } , /* 55 - TZ1090_PIN_TFT_GREEN4 */
{ 3 , 8 } , /* 56 - TZ1090_PIN_TFT_GREEN5 */
{ 3 , 10 } , /* 57 - TZ1090_PIN_TFT_GREEN6 */
{ 3 , 12 } , /* 58 - TZ1090_PIN_TFT_GREEN7 */
{ 3 , 14 } , /* 59 - TZ1090_PIN_TFT_BLUE0 */
{ 3 , 16 } , /* 60 - TZ1090_PIN_TFT_BLUE1 */
{ 3 , 18 } , /* 61 - TZ1090_PIN_TFT_BLUE2 */
{ 3 , 20 } , /* 62 - TZ1090_PIN_TFT_BLUE3 */
{ 3 , 22 } , /* 63 - TZ1090_PIN_TFT_BLUE4 */
{ 3 , 24 } , /* 64 - TZ1090_PIN_TFT_BLUE5 */
{ 3 , 26 } , /* 65 - TZ1090_PIN_TFT_BLUE6 */
{ 3 , 28 } , /* 66 - TZ1090_PIN_TFT_BLUE7 */
{ 3 , 30 } , /* 67 - TZ1090_PIN_TFT_VDDEN_GD */
{ 4 , 0 } , /* 68 - TZ1090_PIN_TFT_PANELCLK */
{ 4 , 2 } , /* 69 - TZ1090_PIN_TFT_BLANK_LS */
{ 4 , 4 } , /* 70 - TZ1090_PIN_TFT_VSYNC_NS */
{ 4 , 6 } , /* 71 - TZ1090_PIN_TFT_HSYNC_NR */
{ 4 , 8 } , /* 72 - TZ1090_PIN_TFT_VD12ACB */
{ 4 , 10 } , /* 73 - TZ1090_PIN_TFT_PWRSAVE */
{ 4 , 24 } , /* 74 - TZ1090_PIN_TX_ON */
{ 4 , 26 } , /* 75 - TZ1090_PIN_RX_ON */
{ 4 , 28 } , /* 76 - TZ1090_PIN_PLL_ON */
{ 4 , 30 } , /* 77 - TZ1090_PIN_PA_ON */
{ 5 , 0 } , /* 78 - TZ1090_PIN_RX_HP */
{ 5 , 6 } , /* 79 - TZ1090_PIN_GAIN0 */
{ 5 , 8 } , /* 80 - TZ1090_PIN_GAIN1 */
{ 5 , 10 } , /* 81 - TZ1090_PIN_GAIN2 */
{ 5 , 12 } , /* 82 - TZ1090_PIN_GAIN3 */
{ 5 , 14 } , /* 83 - TZ1090_PIN_GAIN4 */
{ 5 , 16 } , /* 84 - TZ1090_PIN_GAIN5 */
{ 5 , 18 } , /* 85 - TZ1090_PIN_GAIN6 */
{ 5 , 20 } , /* 86 - TZ1090_PIN_GAIN7 */
{ 5 , 2 } , /* 87 - TZ1090_PIN_ANT_SEL0 */
{ 5 , 4 } , /* 88 - TZ1090_PIN_ANT_SEL1 */
{ 0 , 0 } , /* 89 - TZ1090_PIN_SDH_CLK_IN */
{ 5 , 24 } , /* 90 - TZ1090_PIN_TCK */
{ 5 , 26 } , /* 91 - TZ1090_PIN_TRST */
{ 5 , 28 } , /* 92 - TZ1090_PIN_TDI */
{ 5 , 30 } , /* 93 - TZ1090_PIN_TDO */
{ 6 , 0 } , /* 94 - TZ1090_PIN_TMS */
{ 4 , 16 } , /* 95 - TZ1090_PIN_CLK_OUT0 */
{ 4 , 22 } , /* 96 - TZ1090_PIN_CLK_OUT1 */
} ;
static int tz1090_pinconf_reg ( struct pinctrl_dev * pctldev ,
unsigned int pin ,
enum pin_config_param param ,
bool report_err ,
u32 * reg , u32 * width , u32 * mask , u32 * shift ,
u32 * val )
{
struct tz1090_pinconf_pullup * pu ;
/* All supported pins have controllable input bias */
switch ( param ) {
case PIN_CONFIG_BIAS_DISABLE :
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE :
* val = REG_PU_PD_TRISTATE ;
break ;
case PIN_CONFIG_BIAS_PULL_UP :
* val = REG_PU_PD_UP ;
break ;
case PIN_CONFIG_BIAS_PULL_DOWN :
* val = REG_PU_PD_DOWN ;
break ;
case PIN_CONFIG_BIAS_BUS_HOLD :
* val = REG_PU_PD_REPEATER ;
break ;
default :
return - ENOTSUPP ;
} ;
/* Only input bias parameters supported */
pu = & tz1090_pinconf_pullup [ pin ] ;
* reg = REG_PINCTRL_PU_PD + 4 * pu - > index ;
* shift = pu - > shift ;
* width = 2 ;
/* Calculate field information */
* mask = ( BIT ( * width ) - 1 ) < < * shift ;
return 0 ;
}
static int tz1090_pinconf_get ( struct pinctrl_dev * pctldev ,
unsigned int pin , unsigned long * config )
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
enum pin_config_param param = pinconf_to_config_param ( * config ) ;
int ret ;
u32 reg , width , mask , shift , val , tmp , arg ;
/* Get register information */
ret = tz1090_pinconf_reg ( pctldev , pin , param , true ,
& reg , & width , & mask , & shift , & val ) ;
if ( ret < 0 )
return ret ;
/* Extract field from register */
tmp = pmx_read ( pmx , reg ) ;
arg = ( ( tmp & mask ) > > shift ) = = val ;
/* Config not active */
if ( ! arg )
return - EINVAL ;
/* And pack config */
* config = pinconf_to_config_packed ( param , arg ) ;
return 0 ;
}
static int tz1090_pinconf_set ( struct pinctrl_dev * pctldev ,
2013-08-27 22:32:12 +04:00
unsigned int pin , unsigned long * configs ,
unsigned num_configs )
2013-06-20 13:26:27 +04:00
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
2013-08-27 22:32:12 +04:00
enum pin_config_param param ;
unsigned int arg ;
2013-06-20 13:26:27 +04:00
int ret ;
u32 reg , width , mask , shift , val , tmp ;
unsigned long flags ;
2013-08-27 22:32:12 +04:00
int i ;
2013-06-20 13:26:27 +04:00
2013-08-27 22:32:12 +04:00
for ( i = 0 ; i < num_configs ; i + + ) {
param = pinconf_to_config_param ( configs [ i ] ) ;
arg = pinconf_to_config_argument ( configs [ i ] ) ;
2013-06-20 13:26:27 +04:00
2013-08-27 22:32:12 +04:00
dev_dbg ( pctldev - > dev , " %s(pin=%s, config=%#lx) \n " ,
__func__ , tz1090_pins [ pin ] . name , configs [ i ] ) ;
2013-06-20 13:26:27 +04:00
2013-08-27 22:32:12 +04:00
/* Get register information */
ret = tz1090_pinconf_reg ( pctldev , pin , param , true ,
& reg , & width , & mask , & shift , & val ) ;
if ( ret < 0 )
return ret ;
2013-06-20 13:26:27 +04:00
2013-08-27 22:32:12 +04:00
/* Unpack argument and range check it */
if ( arg > 1 ) {
dev_dbg ( pctldev - > dev , " %s: arg %u out of range \n " ,
__func__ , arg ) ;
return - EINVAL ;
}
/* Write register field */
__global_lock2 ( flags ) ;
tmp = pmx_read ( pmx , reg ) ;
tmp & = ~ mask ;
if ( arg )
tmp | = val < < shift ;
pmx_write ( pmx , tmp , reg ) ;
__global_unlock2 ( flags ) ;
} /* for each config */
2013-06-20 13:26:27 +04:00
return 0 ;
}
static const int tz1090_boolean_map [ ] = {
[ 0 ] = - EINVAL ,
[ 1 ] = 1 ,
} ;
static const int tz1090_dr_map [ ] = {
[ REG_DR_2mA ] = 2 ,
[ REG_DR_4mA ] = 4 ,
[ REG_DR_8mA ] = 8 ,
[ REG_DR_12mA ] = 12 ,
} ;
static int tz1090_pinconf_group_reg ( struct pinctrl_dev * pctldev ,
const struct tz1090_pingroup * g ,
enum pin_config_param param ,
bool report_err ,
u32 * reg , u32 * width , u32 * mask , u32 * shift ,
const int * * map )
{
/* Drive configuration applies in groups, but not to all groups. */
if ( ! g - > drv ) {
if ( report_err )
dev_dbg ( pctldev - > dev ,
" %s: group %s has no drive control \n " ,
__func__ , g - > name ) ;
return - ENOTSUPP ;
}
/* Find information about drive parameter's register */
switch ( param ) {
case PIN_CONFIG_INPUT_SCHMITT_ENABLE :
* reg = REG_PINCTRL_SCHMITT ;
* width = 1 ;
* map = tz1090_boolean_map ;
break ;
case PIN_CONFIG_DRIVE_STRENGTH :
* reg = REG_PINCTRL_DR ;
* width = 2 ;
* map = tz1090_dr_map ;
break ;
default :
return - ENOTSUPP ;
} ;
/* Calculate field information */
* shift = g - > slw_bit * * width ;
* mask = ( BIT ( * width ) - 1 ) < < * shift ;
return 0 ;
}
static int tz1090_pinconf_group_get ( struct pinctrl_dev * pctldev ,
unsigned int group ,
unsigned long * config )
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct tz1090_pingroup * g ;
enum pin_config_param param = pinconf_to_config_param ( * config ) ;
int ret , arg ;
unsigned int pin ;
u32 reg , width , mask , shift , val ;
const int * map ;
if ( group > = ARRAY_SIZE ( tz1090_groups ) ) {
pin = group - ARRAY_SIZE ( tz1090_groups ) ;
return tz1090_pinconf_get ( pctldev , pin , config ) ;
}
g = & tz1090_groups [ group ] ;
if ( g - > npins = = 1 ) {
pin = g - > pins [ 0 ] ;
ret = tz1090_pinconf_get ( pctldev , pin , config ) ;
if ( ret ! = - ENOTSUPP )
return ret ;
}
/* Get register information */
ret = tz1090_pinconf_group_reg ( pctldev , g , param , true ,
& reg , & width , & mask , & shift , & map ) ;
if ( ret < 0 )
return ret ;
/* Extract field from register */
val = pmx_read ( pmx , reg ) ;
arg = map [ ( val & mask ) > > shift ] ;
if ( arg < 0 )
return arg ;
/* And pack config */
* config = pinconf_to_config_packed ( param , arg ) ;
return 0 ;
}
static int tz1090_pinconf_group_set ( struct pinctrl_dev * pctldev ,
2013-08-27 22:32:12 +04:00
unsigned int group , unsigned long * configs ,
unsigned num_configs )
2013-06-20 13:26:27 +04:00
{
struct tz1090_pmx * pmx = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct tz1090_pingroup * g ;
2013-08-27 22:32:12 +04:00
enum pin_config_param param ;
2013-06-20 13:26:27 +04:00
unsigned int arg , pin , i ;
const unsigned int * pit ;
int ret ;
u32 reg , width , mask , shift , val ;
unsigned long flags ;
const int * map ;
2013-08-27 22:32:12 +04:00
int j ;
2013-06-20 13:26:27 +04:00
if ( group > = ARRAY_SIZE ( tz1090_groups ) ) {
pin = group - ARRAY_SIZE ( tz1090_groups ) ;
2013-08-27 22:32:12 +04:00
return tz1090_pinconf_set ( pctldev , pin , configs , num_configs ) ;
2013-06-20 13:26:27 +04:00
}
g = & tz1090_groups [ group ] ;
if ( g - > npins = = 1 ) {
pin = g - > pins [ 0 ] ;
2013-08-27 22:32:12 +04:00
ret = tz1090_pinconf_set ( pctldev , pin , configs , num_configs ) ;
2013-06-20 13:26:27 +04:00
if ( ret ! = - ENOTSUPP )
return ret ;
}
2013-08-27 22:32:12 +04:00
for ( j = 0 ; j < num_configs ; j + + ) {
param = pinconf_to_config_param ( configs [ j ] ) ;
2013-06-20 13:26:27 +04:00
2013-08-27 22:32:12 +04:00
dev_dbg ( pctldev - > dev , " %s(group=%s, config=%#lx) \n " ,
__func__ , g - > name , configs [ j ] ) ;
2013-06-20 13:26:27 +04:00
2013-08-27 22:32:12 +04:00
/* Get register information */
ret = tz1090_pinconf_group_reg ( pctldev , g , param , true , & reg ,
& width , & mask , & shift , & map ) ;
if ( ret < 0 ) {
/*
* Maybe we ' re trying to set a per - pin configuration
* of a group , so do the pins one by one . This is
* mainly as a convenience .
*/
for ( i = 0 , pit = g - > pins ; i < g - > npins ; + + i , + + pit ) {
ret = tz1090_pinconf_set ( pctldev , * pit , configs ,
num_configs ) ;
if ( ret )
return ret ;
}
2013-06-20 13:26:27 +04:00
return 0 ;
}
2013-08-27 22:32:12 +04:00
/* Unpack argument and map it to register value */
arg = pinconf_to_config_argument ( configs [ j ] ) ;
for ( i = 0 ; i < BIT ( width ) ; + + i ) {
if ( map [ i ] = = arg | | ( map [ i ] = = - EINVAL & & ! arg ) ) {
/* Write register field */
__global_lock2 ( flags ) ;
val = pmx_read ( pmx , reg ) ;
val & = ~ mask ;
val | = i < < shift ;
pmx_write ( pmx , val , reg ) ;
__global_unlock2 ( flags ) ;
goto next_config ;
}
}
dev_dbg ( pctldev - > dev , " %s: arg %u not supported \n " ,
__func__ , arg ) ;
return - EINVAL ;
next_config :
;
} /* for each config */
return 0 ;
2013-06-20 13:26:27 +04:00
}
static struct pinconf_ops tz1090_pinconf_ops = {
. is_generic = true ,
. pin_config_get = tz1090_pinconf_get ,
. pin_config_set = tz1090_pinconf_set ,
. pin_config_group_get = tz1090_pinconf_group_get ,
. pin_config_group_set = tz1090_pinconf_group_set ,
. pin_config_config_dbg_show = pinconf_generic_dump_config ,
} ;
/*
* Pin control driver setup
*/
static struct pinctrl_desc tz1090_pinctrl_desc = {
. pctlops = & tz1090_pinctrl_ops ,
. pmxops = & tz1090_pinmux_ops ,
. confops = & tz1090_pinconf_ops ,
. owner = THIS_MODULE ,
} ;
static int tz1090_pinctrl_probe ( struct platform_device * pdev )
{
struct tz1090_pmx * pmx ;
struct resource * res ;
pmx = devm_kzalloc ( & pdev - > dev , sizeof ( * pmx ) , GFP_KERNEL ) ;
if ( ! pmx ) {
dev_err ( & pdev - > dev , " Can't alloc tz1090_pmx \n " ) ;
return - ENOMEM ;
}
pmx - > dev = & pdev - > dev ;
spin_lock_init ( & pmx - > lock ) ;
tz1090_pinctrl_desc . name = dev_name ( & pdev - > dev ) ;
tz1090_pinctrl_desc . pins = tz1090_pins ;
tz1090_pinctrl_desc . npins = ARRAY_SIZE ( tz1090_pins ) ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2013-08-26 06:21:44 +04:00
pmx - > regs = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( pmx - > regs ) )
return PTR_ERR ( pmx - > regs ) ;
2013-06-20 13:26:27 +04:00
pmx - > pctl = pinctrl_register ( & tz1090_pinctrl_desc , & pdev - > dev , pmx ) ;
if ( ! pmx - > pctl ) {
dev_err ( & pdev - > dev , " Couldn't register pinctrl driver \n " ) ;
return - ENODEV ;
}
platform_set_drvdata ( pdev , pmx ) ;
dev_info ( & pdev - > dev , " TZ1090 pinctrl driver initialised \n " ) ;
return 0 ;
}
static int tz1090_pinctrl_remove ( struct platform_device * pdev )
{
struct tz1090_pmx * pmx = platform_get_drvdata ( pdev ) ;
pinctrl_unregister ( pmx - > pctl ) ;
return 0 ;
}
static struct of_device_id tz1090_pinctrl_of_match [ ] = {
{ . compatible = " img,tz1090-pinctrl " , } ,
{ } ,
} ;
static struct platform_driver tz1090_pinctrl_driver = {
. driver = {
. name = " tz1090-pinctrl " ,
. owner = THIS_MODULE ,
. of_match_table = tz1090_pinctrl_of_match ,
} ,
. probe = tz1090_pinctrl_probe ,
. remove = tz1090_pinctrl_remove ,
} ;
static int __init tz1090_pinctrl_init ( void )
{
tz1090_init_mux_pins ( ) ;
return platform_driver_register ( & tz1090_pinctrl_driver ) ;
}
arch_initcall ( tz1090_pinctrl_init ) ;
static void __exit tz1090_pinctrl_exit ( void )
{
platform_driver_unregister ( & tz1090_pinctrl_driver ) ;
}
module_exit ( tz1090_pinctrl_exit ) ;
MODULE_AUTHOR ( " Imagination Technologies Ltd. " ) ;
MODULE_DESCRIPTION ( " Toumaz Xenif TZ1090 pinctrl driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DEVICE_TABLE ( of , tz1090_pinctrl_of_match ) ;