332 lines
10 KiB
C
332 lines
10 KiB
C
|
/*
|
||
|
* (c) 2010 STMicroelectronics Limited
|
||
|
*
|
||
|
* Author: Pawel Moll <pawel.moll@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.
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
#ifndef __LINUX_STM_PAD_H
|
||
|
#define __LINUX_STM_PAD_H
|
||
|
|
||
|
#include <linux/stm/sysconf.h>
|
||
|
|
||
|
/* The stm_pad_gpio_value structure describes PIOs that are to be claimed in
|
||
|
* order to achieve I/O configuration required by a driver.
|
||
|
*
|
||
|
* "function" means the so-called "alternative PIO function",
|
||
|
* usually described in SOCs datasheets. It just describes
|
||
|
* which one of possible signals is to be multiplexed to
|
||
|
* the actual pin. It is then used by SOC-specific "gpio_config"
|
||
|
* callback provided when stm_pad_init() is called (see below).
|
||
|
*
|
||
|
* Function number meaning is absolutely up to the BSP author.
|
||
|
* There is just a polite suggestion that 0 could mean "normal"
|
||
|
* PIO functionality (as in: input/output, set high/low level).
|
||
|
* Other numbers may be related to datasheet definitions (usually
|
||
|
* 1 and more).
|
||
|
*
|
||
|
* "ignored" direction means that the PIO will not be claimed at,
|
||
|
* so setting it can be used to "remove" a PIO from configuration
|
||
|
* in runtime. */
|
||
|
|
||
|
enum stm_pad_gpio_direction {
|
||
|
stm_pad_gpio_direction_unknown,
|
||
|
stm_pad_gpio_direction_in,
|
||
|
stm_pad_gpio_direction_out,
|
||
|
stm_pad_gpio_direction_bidir,
|
||
|
stm_pad_gpio_direction_custom,
|
||
|
stm_pad_gpio_direction_ignored
|
||
|
};
|
||
|
|
||
|
struct stm_pad_gpio {
|
||
|
unsigned gpio;
|
||
|
enum stm_pad_gpio_direction direction;
|
||
|
int out_value;
|
||
|
int function;
|
||
|
const char *name;
|
||
|
void *priv;
|
||
|
};
|
||
|
|
||
|
#define STM_PAD_PIO_IN(_port, _pin, _function) \
|
||
|
{ \
|
||
|
.gpio = stm_gpio(_port, _pin), \
|
||
|
.direction = stm_pad_gpio_direction_in, \
|
||
|
.function = _function, \
|
||
|
}
|
||
|
|
||
|
#define STM_PAD_PIO_IN_NAMED(_port, _pin, _function, _name) \
|
||
|
{ \
|
||
|
.gpio = stm_gpio(_port, _pin), \
|
||
|
.direction = stm_pad_gpio_direction_in, \
|
||
|
.function = _function, \
|
||
|
.name = _name, \
|
||
|
}
|
||
|
|
||
|
#define STM_PAD_PIO_OUT(_port, _pin, _function) \
|
||
|
{ \
|
||
|
.gpio = stm_gpio(_port, _pin), \
|
||
|
.direction = stm_pad_gpio_direction_out, \
|
||
|
.out_value = -1, \
|
||
|
.function = _function, \
|
||
|
}
|
||
|
|
||
|
#define STM_PAD_PIO_OUT_NAMED(_port, _pin, _function, _name) \
|
||
|
{ \
|
||
|
.gpio = stm_gpio(_port, _pin), \
|
||
|
.direction = stm_pad_gpio_direction_out, \
|
||
|
.out_value = -1, \
|
||
|
.function = _function, \
|
||
|
.name = _name, \
|
||
|
}
|
||
|
|
||
|
#define STM_PAD_PIO_BIDIR(_port, _pin, _function) \
|
||
|
{ \
|
||
|
.gpio = stm_gpio(_port, _pin), \
|
||
|
.direction = stm_pad_gpio_direction_bidir, \
|
||
|
.out_value = -1, \
|
||
|
.function = _function, \
|
||
|
}
|
||
|
|
||
|
#define STM_PAD_PIO_BIDIR_NAMED(_port, _pin, _function, _name) \
|
||
|
{ \
|
||
|
.gpio = stm_gpio(_port, _pin), \
|
||
|
.direction = stm_pad_gpio_direction_bidir, \
|
||
|
.out_value = -1, \
|
||
|
.function = _function, \
|
||
|
.name = _name, \
|
||
|
}
|
||
|
|
||
|
#define STM_PAD_PIO_STUB_NAMED(_port, _pin, _name) \
|
||
|
{ \
|
||
|
.gpio = stm_gpio(_port, _pin), \
|
||
|
.direction = stm_pad_gpio_direction_unknown, \
|
||
|
.name = _name, \
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* The bits that give us the most grief are "sysconf" values, and
|
||
|
* they are the most likely the SOC-specific settings that must
|
||
|
* be set while configuring the chip to some function, as required
|
||
|
* by a driver.
|
||
|
*
|
||
|
* Notice that you are not supposed to define GPIO muxing (the
|
||
|
* "alternative functions" mentioned above) related bits here.
|
||
|
* They should be configured automagically via SOC-specific
|
||
|
* muxing funtions (see stm_pad_init() below) */
|
||
|
|
||
|
struct stm_pad_sysconf {
|
||
|
int regtype;
|
||
|
int regnum;
|
||
|
int lsb;
|
||
|
int msb;
|
||
|
int value;
|
||
|
};
|
||
|
|
||
|
#define STM_PAD_SYS_CFG(_regnum, _lsb, _msb, _value) \
|
||
|
{ \
|
||
|
.regtype = SYS_CFG, \
|
||
|
.regnum = _regnum, \
|
||
|
.lsb = _lsb, \
|
||
|
.msb = _msb, \
|
||
|
.value = _value, \
|
||
|
}
|
||
|
|
||
|
#define STM_PAD_SYS_CFG_BANK(_bank, _regnum, _lsb, _msb, _value) \
|
||
|
{ \
|
||
|
.regtype = SYS_CFG_BANK##_bank, \
|
||
|
.regnum = _regnum, \
|
||
|
.lsb = _lsb, \
|
||
|
.msb = _msb, \
|
||
|
.value = _value, \
|
||
|
}
|
||
|
|
||
|
/* We have to do this indirection to allow the first argument to
|
||
|
* STM_PAD_SYSCONF to be a macro, as used by 5197 for example. */
|
||
|
#define ___STM_PAD_SYSCONF(_regtype, _regnum, _lsb, _msb, _value) \
|
||
|
{ \
|
||
|
.regtype = _regtype, \
|
||
|
.regnum = _regnum, \
|
||
|
.lsb = _lsb, \
|
||
|
.msb = _msb, \
|
||
|
.value = _value, \
|
||
|
}
|
||
|
#define STM_PAD_SYSCONF(_reg, _lsb, _msb, _value) \
|
||
|
___STM_PAD_SYSCONF(_reg, _lsb, _msb, _value)
|
||
|
|
||
|
|
||
|
|
||
|
/* Pad state structure pointer is returned by the claim functions */
|
||
|
struct stm_pad_state;
|
||
|
|
||
|
|
||
|
|
||
|
/* All above bits and pieces are gathered together in the below
|
||
|
* structure, known as "pad configuration".
|
||
|
*
|
||
|
* It contains lists of GPIOs used and sysconfig bits to be
|
||
|
* configured on demand of a driver.
|
||
|
*
|
||
|
* In special cases one may wish to use custom claim function,
|
||
|
* which is executed as the _last_ in order when claiming
|
||
|
* and must return 0 or other value in case of error. */
|
||
|
|
||
|
struct stm_pad_config {
|
||
|
int gpios_num;
|
||
|
struct stm_pad_gpio *gpios;
|
||
|
int sysconfs_num;
|
||
|
struct stm_pad_sysconf *sysconfs;
|
||
|
int (*custom_claim)(struct stm_pad_state *state, void *priv);
|
||
|
void (*custom_release)(struct stm_pad_state *state, void *priv);
|
||
|
void *custom_priv;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
/* Pad manager initialization
|
||
|
*
|
||
|
* The gpio_config function should be provided by the SOC BSP
|
||
|
* and configure given GPIO to requested direction & alternative function.
|
||
|
*
|
||
|
* gpios_num is a overall number of PIO lines provided by the SOC,
|
||
|
* gpio_function_in and gpio_function_out are the numbers that should be passed
|
||
|
* to the gpio_config function in order to select generic PIO functionality, for
|
||
|
* input and output directions respectively.
|
||
|
*
|
||
|
* See also above (stm_pad_gpio_value definition). */
|
||
|
|
||
|
int stm_pad_init(int gpios_num, int gpio_function_in, int gpio_function_out,
|
||
|
int (*gpio_config)(unsigned gpio,
|
||
|
enum stm_pad_gpio_direction direction,
|
||
|
int function, void *priv));
|
||
|
|
||
|
|
||
|
|
||
|
/* Driver interface */
|
||
|
|
||
|
struct stm_pad_state *stm_pad_claim(struct stm_pad_config *config,
|
||
|
const char *owner);
|
||
|
void stm_pad_release(struct stm_pad_state *state);
|
||
|
|
||
|
struct stm_pad_state *devm_stm_pad_claim(struct device *dev,
|
||
|
struct stm_pad_config *config, const char *owner);
|
||
|
void devm_stm_pad_release(struct device *dev, struct stm_pad_state *state);
|
||
|
|
||
|
/* Functions below are private methods, for the GPIO driver use only! */
|
||
|
int stm_pad_claim_gpio(unsigned gpio);
|
||
|
void stm_pad_configure_gpio(unsigned gpio, unsigned direction);
|
||
|
void stm_pad_release_gpio(unsigned gpio);
|
||
|
const char *stm_pad_get_gpio_owner(unsigned gpio);
|
||
|
|
||
|
|
||
|
|
||
|
/* GPIO interface */
|
||
|
|
||
|
/* "name" is the GPIO name as defined in "struct stm_pad_gpio".
|
||
|
* Returns gpio number or STM_GPIO_INVALID in case of error */
|
||
|
unsigned stm_pad_gpio_request_input(struct stm_pad_state *state,
|
||
|
const char *name);
|
||
|
unsigned stm_pad_gpio_request_output(struct stm_pad_state *state,
|
||
|
const char *name, int value);
|
||
|
void stm_pad_gpio_free(struct stm_pad_state *state, unsigned gpio);
|
||
|
|
||
|
|
||
|
|
||
|
/* GPIO definition helpers
|
||
|
*
|
||
|
* If a GPIO on the list in pad configuration is defined with a name,
|
||
|
* it is possible to perform some operations on it in easy way... */
|
||
|
|
||
|
int stm_pad_set_gpio(struct stm_pad_config *config, const char *name,
|
||
|
unsigned gpio);
|
||
|
|
||
|
#define stm_pad_set_pio(config, name, port, pin) \
|
||
|
stm_pad_set_gpio(config, name, stm_gpio(port, pin))
|
||
|
|
||
|
int stm_pad_set_direction_function(struct stm_pad_config *config,
|
||
|
const char *name, enum stm_pad_gpio_direction direction,
|
||
|
int out_value, int function);
|
||
|
|
||
|
#define stm_pad_set_pio_in(config, name, function) \
|
||
|
stm_pad_set_direction_function(config, name, \
|
||
|
stm_pad_gpio_direction_in, -1, function)
|
||
|
|
||
|
#define stm_pad_set_pio_out(config, name, function) \
|
||
|
stm_pad_set_direction_function(config, name, \
|
||
|
stm_pad_gpio_direction_out, -1, function)
|
||
|
|
||
|
#define stm_pad_set_pio_bidir(config, name, function) \
|
||
|
stm_pad_set_direction_function(config, name, \
|
||
|
stm_pad_gpio_direction_bidir, -1, function)
|
||
|
|
||
|
#define stm_pad_set_pio_ignored(config, name) \
|
||
|
stm_pad_set_direction_function(config, name, \
|
||
|
stm_pad_gpio_direction_ignored, -1, -1)
|
||
|
|
||
|
int stm_pad_set_priv(struct stm_pad_config *config, const char *name,
|
||
|
void *priv);
|
||
|
|
||
|
|
||
|
|
||
|
/* Dynamic pad configuration allocation
|
||
|
*
|
||
|
* In some cases it's easier to create a pad configuration in runtime,
|
||
|
* rather then to prepare 2^16 different static blobs (or to alter
|
||
|
* 90% of pre-defined one). The API below helps in this... */
|
||
|
|
||
|
struct stm_pad_config *stm_pad_config_alloc(int gpio_values_num,
|
||
|
int sysconf_values_num);
|
||
|
|
||
|
int stm_pad_config_add_sysconf(struct stm_pad_config *config,
|
||
|
int regtype, int regnum, int lsb, int msb, int value);
|
||
|
|
||
|
#define stm_pad_config_add_sys_cfg(config, regnum, lsb, msb, value) \
|
||
|
stm_pad_config_add_sysconf(config, SYS_CFG, regnum, lsb, msb, value)
|
||
|
|
||
|
int stm_pad_config_add_gpio_named(struct stm_pad_config *config,
|
||
|
unsigned gpio, enum stm_pad_gpio_direction direction,
|
||
|
int out_value, int function, const char *name);
|
||
|
|
||
|
#define stm_pad_config_add_pio(config, port, pin, \
|
||
|
direction, out_value, function) \
|
||
|
stm_pad_config_add_gpio_named(config, stm_gpio(port, pin), \
|
||
|
direction, out_value, function, NULL)
|
||
|
|
||
|
#define stm_pad_config_add_pio_named(config, port, pin, \
|
||
|
direction, out_value, function, name) \
|
||
|
stm_pad_config_add_gpio_named(config, stm_gpio(port, pin), \
|
||
|
direction, out_value, function, name)
|
||
|
|
||
|
#define stm_pad_config_add_pio_in(config, port, pin, function) \
|
||
|
stm_pad_config_add_pio(config, port, pin, \
|
||
|
stm_pad_gpio_direction_in, -1, function)
|
||
|
|
||
|
#define stm_pad_config_add_pio_in_named(config, port, pin, function, name) \
|
||
|
stm_pad_config_add_pio_named(config, port, pin, \
|
||
|
stm_pad_gpio_direction_in, -1, function, name)
|
||
|
|
||
|
#define stm_pad_config_add_pio_out(config, port, pin, function) \
|
||
|
stm_pad_config_add_pio(config, port, pin, \
|
||
|
stm_pad_gpio_direction_out, -1, function)
|
||
|
|
||
|
#define stm_pad_config_add_pio_out_named(config, port, pin, \
|
||
|
function, name) \
|
||
|
stm_pad_config_add_pio_named(config, port, pin, \
|
||
|
stm_pad_gpio_direction_out, -1, function, name)
|
||
|
|
||
|
#define stm_pad_config_add_pio_bidir(config, port, pin, function) \
|
||
|
stm_pad_config_add_pio(config, port, pin, \
|
||
|
stm_pad_gpio_direction_bidir, -1, function)
|
||
|
|
||
|
#define stm_pad_config_add_pio_bidir_named(config, port, pin, \
|
||
|
function, name) \
|
||
|
stm_pad_config_add_pio_named(config, port, pin, \
|
||
|
stm_pad_gpio_direction_bidir, -1, function, name)
|
||
|
|
||
|
#endif
|