/* * (c) 2010 STMicroelectronics Limited * * Author: Pawel Moll * * 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 /* 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