2017-11-30 09:46:48 +01:00
// SPDX-License-Identifier: GPL-2.0
2016-01-14 13:16:30 +01:00
/*
* Copyright ( C ) Maxime Coquelin 2015
2017-11-30 09:46:48 +01:00
* Copyright ( C ) STMicroelectronics 2017
2016-01-14 13:16:30 +01:00
* Author : Maxime Coquelin < mcoquelin . stm32 @ gmail . com >
*
* Heavily based on Mediatek ' s pinctrl driver
*/
# include <linux/clk.h>
2016-02-05 23:47:13 +01:00
# include <linux/gpio/driver.h>
2018-11-13 10:51:41 +01:00
# include <linux/hwspinlock.h>
2016-01-14 13:16:30 +01:00
# include <linux/io.h>
2016-09-09 16:42:01 +02:00
# include <linux/irq.h>
# include <linux/mfd/syscon.h>
2016-01-14 13:16:30 +01:00
# include <linux/module.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/of_device.h>
# include <linux/of_irq.h>
# include <linux/pinctrl/consumer.h>
# include <linux/pinctrl/machine.h>
# include <linux/pinctrl/pinconf.h>
# include <linux/pinctrl/pinconf-generic.h>
# include <linux/pinctrl/pinctrl.h>
# include <linux/pinctrl/pinmux.h>
# include <linux/platform_device.h>
2022-04-01 13:35:55 +03:00
# include <linux/property.h>
2016-09-09 16:42:01 +02:00
# include <linux/regmap.h>
2016-01-14 13:16:30 +01:00
# include <linux/reset.h>
# include <linux/slab.h>
# include "../core.h"
# include "../pinconf.h"
# include "../pinctrl-utils.h"
# include "pinctrl-stm32.h"
# define STM32_GPIO_MODER 0x00
# define STM32_GPIO_TYPER 0x04
# define STM32_GPIO_SPEEDR 0x08
# define STM32_GPIO_PUPDR 0x0c
# define STM32_GPIO_IDR 0x10
# define STM32_GPIO_ODR 0x14
# define STM32_GPIO_BSRR 0x18
# define STM32_GPIO_LCKR 0x1c
# define STM32_GPIO_AFRL 0x20
# define STM32_GPIO_AFRH 0x24
2022-05-02 17:31:14 +02:00
# define STM32_GPIO_SECCFGR 0x30
2016-01-14 13:16:30 +01:00
2019-05-10 09:42:29 +02:00
/* custom bitfield to backup pin status */
# define STM32_GPIO_BKP_MODE_SHIFT 0
# define STM32_GPIO_BKP_MODE_MASK GENMASK(1, 0)
# define STM32_GPIO_BKP_ALT_SHIFT 2
# define STM32_GPIO_BKP_ALT_MASK GENMASK(5, 2)
# define STM32_GPIO_BKP_SPEED_SHIFT 6
# define STM32_GPIO_BKP_SPEED_MASK GENMASK(7, 6)
# define STM32_GPIO_BKP_PUPD_SHIFT 8
# define STM32_GPIO_BKP_PUPD_MASK GENMASK(9, 8)
# define STM32_GPIO_BKP_TYPE 10
# define STM32_GPIO_BKP_VAL 11
2016-01-14 13:16:30 +01:00
# define STM32_GPIO_PINS_PER_BANK 16
2016-09-09 16:42:01 +02:00
# define STM32_GPIO_IRQ_LINE 16
2016-01-14 13:16:30 +01:00
2018-07-17 11:56:27 +02:00
# define SYSCFG_IRQMUX_MASK GENMASK(3, 0)
2016-01-14 13:16:30 +01:00
# define gpio_range_to_bank(chip) \
container_of ( chip , struct stm32_gpio_bank , range )
2020-06-15 14:44:56 +02:00
# define HWSPNLCK_TIMEOUT 1000 /* usec */
2018-11-13 10:51:41 +01:00
2016-01-14 13:16:30 +01:00
static const char * const stm32_gpio_functions [ ] = {
" gpio " , " af0 " , " af1 " ,
" af2 " , " af3 " , " af4 " ,
" af5 " , " af6 " , " af7 " ,
" af8 " , " af9 " , " af10 " ,
" af11 " , " af12 " , " af13 " ,
" af14 " , " af15 " , " analog " ,
} ;
struct stm32_pinctrl_group {
const char * name ;
unsigned long config ;
unsigned pin ;
} ;
struct stm32_gpio_bank {
void __iomem * base ;
struct clk * clk ;
2020-06-15 14:54:07 +02:00
struct reset_control * rstc ;
2016-01-14 13:16:30 +01:00
spinlock_t lock ;
struct gpio_chip gpio_chip ;
struct pinctrl_gpio_range range ;
2016-09-09 16:42:01 +02:00
struct fwnode_handle * fwnode ;
struct irq_domain * domain ;
2017-04-07 14:42:58 +02:00
u32 bank_nr ;
2018-07-16 14:57:36 +02:00
u32 bank_ioport_nr ;
2019-05-10 09:42:29 +02:00
u32 pin_backup [ STM32_GPIO_PINS_PER_BANK ] ;
2020-02-19 15:32:29 +01:00
u8 irq_type [ STM32_GPIO_PINS_PER_BANK ] ;
2022-05-02 17:31:14 +02:00
bool secure_control ;
2016-01-14 13:16:30 +01:00
} ;
struct stm32_pinctrl {
struct device * dev ;
struct pinctrl_dev * pctl_dev ;
struct pinctrl_desc pctl_desc ;
struct stm32_pinctrl_group * groups ;
unsigned ngroups ;
const char * * grp_names ;
struct stm32_gpio_bank * banks ;
unsigned nbanks ;
const struct stm32_pinctrl_match_data * match_data ;
2016-09-09 16:42:01 +02:00
struct irq_domain * domain ;
struct regmap * regmap ;
struct regmap_field * irqmux [ STM32_GPIO_PINS_PER_BANK ] ;
2018-11-13 10:51:41 +01:00
struct hwspinlock * hwlock ;
2019-04-10 13:30:21 +02:00
struct stm32_desc_pin * pins ;
u32 npins ;
u32 pkg ;
2019-05-10 09:43:03 +02:00
u16 irqmux_map ;
spinlock_t irqmux_lock ;
2016-01-14 13:16:30 +01:00
} ;
static inline int stm32_gpio_pin ( int gpio )
{
return gpio % STM32_GPIO_PINS_PER_BANK ;
}
static inline u32 stm32_gpio_get_mode ( u32 function )
{
switch ( function ) {
case STM32_PIN_GPIO :
return 0 ;
case STM32_PIN_AF ( 0 ) . . . STM32_PIN_AF ( 15 ) :
return 2 ;
case STM32_PIN_ANALOG :
return 3 ;
}
return 0 ;
}
static inline u32 stm32_gpio_get_alt ( u32 function )
{
switch ( function ) {
case STM32_PIN_GPIO :
return 0 ;
case STM32_PIN_AF ( 0 ) . . . STM32_PIN_AF ( 15 ) :
return function - 1 ;
case STM32_PIN_ANALOG :
return 0 ;
}
return 0 ;
}
2019-05-10 09:42:29 +02:00
static void stm32_gpio_backup_value ( struct stm32_gpio_bank * bank ,
u32 offset , u32 value )
{
bank - > pin_backup [ offset ] & = ~ BIT ( STM32_GPIO_BKP_VAL ) ;
bank - > pin_backup [ offset ] | = value < < STM32_GPIO_BKP_VAL ;
}
static void stm32_gpio_backup_mode ( struct stm32_gpio_bank * bank , u32 offset ,
u32 mode , u32 alt )
{
bank - > pin_backup [ offset ] & = ~ ( STM32_GPIO_BKP_MODE_MASK |
STM32_GPIO_BKP_ALT_MASK ) ;
bank - > pin_backup [ offset ] | = mode < < STM32_GPIO_BKP_MODE_SHIFT ;
bank - > pin_backup [ offset ] | = alt < < STM32_GPIO_BKP_ALT_SHIFT ;
}
static void stm32_gpio_backup_driving ( struct stm32_gpio_bank * bank , u32 offset ,
u32 drive )
{
bank - > pin_backup [ offset ] & = ~ BIT ( STM32_GPIO_BKP_TYPE ) ;
bank - > pin_backup [ offset ] | = drive < < STM32_GPIO_BKP_TYPE ;
}
static void stm32_gpio_backup_speed ( struct stm32_gpio_bank * bank , u32 offset ,
u32 speed )
{
bank - > pin_backup [ offset ] & = ~ STM32_GPIO_BKP_SPEED_MASK ;
bank - > pin_backup [ offset ] | = speed < < STM32_GPIO_BKP_SPEED_SHIFT ;
}
static void stm32_gpio_backup_bias ( struct stm32_gpio_bank * bank , u32 offset ,
u32 bias )
{
bank - > pin_backup [ offset ] & = ~ STM32_GPIO_BKP_PUPD_MASK ;
bank - > pin_backup [ offset ] | = bias < < STM32_GPIO_BKP_PUPD_SHIFT ;
}
2016-01-14 13:16:30 +01:00
/* GPIO functions */
static inline void __stm32_gpio_set ( struct stm32_gpio_bank * bank ,
unsigned offset , int value )
{
2019-05-10 09:42:29 +02:00
stm32_gpio_backup_value ( bank , offset , value ) ;
2016-01-14 13:16:30 +01:00
if ( ! value )
offset + = STM32_GPIO_PINS_PER_BANK ;
writel_relaxed ( BIT ( offset ) , bank - > base + STM32_GPIO_BSRR ) ;
}
static int stm32_gpio_request ( struct gpio_chip * chip , unsigned offset )
{
2017-04-07 14:42:58 +02:00
struct stm32_gpio_bank * bank = gpiochip_get_data ( chip ) ;
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
struct pinctrl_gpio_range * range ;
int pin = offset + ( bank - > bank_nr * STM32_GPIO_PINS_PER_BANK ) ;
range = pinctrl_find_gpio_range_from_pin_nolock ( pctl - > pctl_dev , pin ) ;
if ( ! range ) {
dev_err ( pctl - > dev , " pin %d not in range. \n " , pin ) ;
return - EINVAL ;
}
2017-09-22 11:02:10 +02:00
return pinctrl_gpio_request ( chip - > base + offset ) ;
2016-01-14 13:16:30 +01:00
}
static void stm32_gpio_free ( struct gpio_chip * chip , unsigned offset )
{
2017-09-22 11:02:10 +02:00
pinctrl_gpio_free ( chip - > base + offset ) ;
2016-01-14 13:16:30 +01:00
}
static int stm32_gpio_get ( struct gpio_chip * chip , unsigned offset )
{
2016-02-05 23:47:13 +01:00
struct stm32_gpio_bank * bank = gpiochip_get_data ( chip ) ;
2016-01-14 13:16:30 +01:00
2022-04-22 16:36:08 +02:00
return ! ! ( readl_relaxed ( bank - > base + STM32_GPIO_IDR ) & BIT ( offset ) ) ;
2016-01-14 13:16:30 +01:00
}
static void stm32_gpio_set ( struct gpio_chip * chip , unsigned offset , int value )
{
2016-02-05 23:47:13 +01:00
struct stm32_gpio_bank * bank = gpiochip_get_data ( chip ) ;
2016-01-14 13:16:30 +01:00
__stm32_gpio_set ( bank , offset , value ) ;
}
static int stm32_gpio_direction_input ( struct gpio_chip * chip , unsigned offset )
{
return pinctrl_gpio_direction_input ( chip - > base + offset ) ;
}
static int stm32_gpio_direction_output ( struct gpio_chip * chip ,
unsigned offset , int value )
{
2016-02-05 23:47:13 +01:00
struct stm32_gpio_bank * bank = gpiochip_get_data ( chip ) ;
2016-01-14 13:16:30 +01:00
__stm32_gpio_set ( bank , offset , value ) ;
pinctrl_gpio_direction_output ( chip - > base + offset ) ;
return 0 ;
}
2016-09-09 16:42:01 +02:00
static int stm32_gpio_to_irq ( struct gpio_chip * chip , unsigned int offset )
{
struct stm32_gpio_bank * bank = gpiochip_get_data ( chip ) ;
struct irq_fwspec fwspec ;
fwspec . fwnode = bank - > fwnode ;
fwspec . param_count = 2 ;
fwspec . param [ 0 ] = offset ;
fwspec . param [ 1 ] = IRQ_TYPE_NONE ;
return irq_create_fwspec_mapping ( & fwspec ) ;
}
2017-05-29 18:17:32 +02:00
static int stm32_gpio_get_direction ( struct gpio_chip * chip , unsigned int offset )
{
struct stm32_gpio_bank * bank = gpiochip_get_data ( chip ) ;
int pin = stm32_gpio_pin ( offset ) ;
int ret ;
u32 mode , alt ;
stm32_pmx_get_mode ( bank , pin , & mode , & alt ) ;
if ( ( alt = = 0 ) & & ( mode = = 0 ) )
2020-02-14 15:57:12 +02:00
ret = GPIO_LINE_DIRECTION_IN ;
2017-05-29 18:17:32 +02:00
else if ( ( alt = = 0 ) & & ( mode = = 1 ) )
2020-02-14 15:57:12 +02:00
ret = GPIO_LINE_DIRECTION_OUT ;
2017-05-29 18:17:32 +02:00
else
ret = - EINVAL ;
return ret ;
}
2022-05-02 17:31:14 +02:00
static int stm32_gpio_init_valid_mask ( struct gpio_chip * chip ,
unsigned long * valid_mask ,
unsigned int ngpios )
{
struct stm32_gpio_bank * bank = gpiochip_get_data ( chip ) ;
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
unsigned int i ;
u32 sec ;
/* All gpio are valid per default */
bitmap_fill ( valid_mask , ngpios ) ;
if ( bank - > secure_control ) {
/* Tag secured pins as invalid */
sec = readl_relaxed ( bank - > base + STM32_GPIO_SECCFGR ) ;
for ( i = 0 ; i < ngpios ; i + + ) {
if ( sec & BIT ( i ) ) {
clear_bit ( i , valid_mask ) ;
dev_dbg ( pctl - > dev , " No access to gpio %d - %d \n " , bank - > bank_nr , i ) ;
}
}
}
return 0 ;
}
2016-09-11 14:14:40 +02:00
static const struct gpio_chip stm32_gpio_template = {
2016-01-14 13:16:30 +01:00
. request = stm32_gpio_request ,
. free = stm32_gpio_free ,
. get = stm32_gpio_get ,
. set = stm32_gpio_set ,
. direction_input = stm32_gpio_direction_input ,
. direction_output = stm32_gpio_direction_output ,
2016-09-09 16:42:01 +02:00
. to_irq = stm32_gpio_to_irq ,
2017-05-29 18:17:32 +02:00
. get_direction = stm32_gpio_get_direction ,
2020-06-15 14:59:51 +02:00
. set_config = gpiochip_generic_config ,
2022-05-02 17:31:14 +02:00
. init_valid_mask = stm32_gpio_init_valid_mask ,
2016-01-14 13:16:30 +01:00
} ;
2020-03-24 00:51:32 +01:00
static void stm32_gpio_irq_trigger ( struct irq_data * d )
2020-02-19 15:32:29 +01:00
{
struct stm32_gpio_bank * bank = d - > domain - > host_data ;
int level ;
2022-04-15 23:54:10 +02:00
/* Do not access the GPIO if this is not LEVEL triggered IRQ. */
if ( ! ( bank - > irq_type [ d - > hwirq ] & IRQ_TYPE_LEVEL_MASK ) )
return ;
2020-02-19 15:32:29 +01:00
/* If level interrupt type then retrig */
2022-04-22 16:36:08 +02:00
level = stm32_gpio_get ( & bank - > gpio_chip , d - > hwirq ) ;
2020-02-19 15:32:29 +01:00
if ( ( level = = 0 & & bank - > irq_type [ d - > hwirq ] = = IRQ_TYPE_LEVEL_LOW ) | |
( level = = 1 & & bank - > irq_type [ d - > hwirq ] = = IRQ_TYPE_LEVEL_HIGH ) )
irq_chip_retrigger_hierarchy ( d ) ;
2020-03-24 00:51:32 +01:00
}
static void stm32_gpio_irq_eoi ( struct irq_data * d )
{
irq_chip_eoi_parent ( d ) ;
stm32_gpio_irq_trigger ( d ) ;
2020-02-19 15:32:29 +01:00
} ;
static int stm32_gpio_set_type ( struct irq_data * d , unsigned int type )
{
struct stm32_gpio_bank * bank = d - > domain - > host_data ;
u32 parent_type ;
switch ( type ) {
case IRQ_TYPE_EDGE_RISING :
case IRQ_TYPE_EDGE_FALLING :
case IRQ_TYPE_EDGE_BOTH :
parent_type = type ;
break ;
case IRQ_TYPE_LEVEL_HIGH :
parent_type = IRQ_TYPE_EDGE_RISING ;
break ;
case IRQ_TYPE_LEVEL_LOW :
parent_type = IRQ_TYPE_EDGE_FALLING ;
break ;
default :
return - EINVAL ;
}
bank - > irq_type [ d - > hwirq ] = type ;
return irq_chip_set_type_parent ( d , parent_type ) ;
} ;
2017-05-29 18:17:31 +02:00
static int stm32_gpio_irq_request_resources ( struct irq_data * irq_data )
{
struct stm32_gpio_bank * bank = irq_data - > domain - > host_data ;
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
int ret ;
ret = stm32_gpio_direction_input ( & bank - > gpio_chip , irq_data - > hwirq ) ;
if ( ret )
return ret ;
ret = gpiochip_lock_as_irq ( & bank - > gpio_chip , irq_data - > hwirq ) ;
if ( ret ) {
dev_err ( pctl - > dev , " unable to lock HW IRQ %lu for IRQ \n " ,
irq_data - > hwirq ) ;
return ret ;
}
return 0 ;
}
static void stm32_gpio_irq_release_resources ( struct irq_data * irq_data )
{
struct stm32_gpio_bank * bank = irq_data - > domain - > host_data ;
gpiochip_unlock_as_irq ( & bank - > gpio_chip , irq_data - > hwirq ) ;
}
2020-03-24 00:51:32 +01:00
static void stm32_gpio_irq_unmask ( struct irq_data * d )
{
irq_chip_unmask_parent ( d ) ;
stm32_gpio_irq_trigger ( d ) ;
}
2016-09-09 16:42:01 +02:00
static struct irq_chip stm32_gpio_irq_chip = {
2018-04-26 18:18:32 +02:00
. name = " stm32gpio " ,
2020-02-19 15:32:29 +01:00
. irq_eoi = stm32_gpio_irq_eoi ,
2018-04-26 18:18:32 +02:00
. irq_ack = irq_chip_ack_parent ,
. irq_mask = irq_chip_mask_parent ,
2020-03-24 00:51:32 +01:00
. irq_unmask = stm32_gpio_irq_unmask ,
2020-02-19 15:32:29 +01:00
. irq_set_type = stm32_gpio_set_type ,
2018-04-26 18:18:32 +02:00
. irq_set_wake = irq_chip_set_wake_parent ,
2017-05-29 18:17:31 +02:00
. irq_request_resources = stm32_gpio_irq_request_resources ,
. irq_release_resources = stm32_gpio_irq_release_resources ,
2016-09-09 16:42:01 +02:00
} ;
static int stm32_gpio_domain_translate ( struct irq_domain * d ,
struct irq_fwspec * fwspec ,
unsigned long * hwirq ,
unsigned int * type )
{
if ( ( fwspec - > param_count ! = 2 ) | |
( fwspec - > param [ 0 ] > = STM32_GPIO_IRQ_LINE ) )
return - EINVAL ;
* hwirq = fwspec - > param [ 0 ] ;
* type = fwspec - > param [ 1 ] ;
return 0 ;
}
2016-01-14 13:16:30 +01:00
2017-09-13 23:29:10 +02:00
static int stm32_gpio_domain_activate ( struct irq_domain * d ,
2017-12-29 16:59:06 +01:00
struct irq_data * irq_data , bool reserve )
2016-09-09 16:42:01 +02:00
{
struct stm32_gpio_bank * bank = d - > host_data ;
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
2019-05-10 09:43:03 +02:00
int ret = 0 ;
2020-06-15 14:44:56 +02:00
if ( pctl - > hwlock ) {
ret = hwspin_lock_timeout_in_atomic ( pctl - > hwlock ,
HWSPNLCK_TIMEOUT ) ;
if ( ret ) {
dev_err ( pctl - > dev , " Can't get hwspinlock \n " ) ;
2021-06-17 16:46:02 +02:00
return ret ;
2020-06-15 14:44:56 +02:00
}
2019-05-10 09:43:03 +02:00
}
2018-07-16 14:57:36 +02:00
regmap_field_write ( pctl - > irqmux [ irq_data - > hwirq ] , bank - > bank_ioport_nr ) ;
2019-05-10 09:43:03 +02:00
if ( pctl - > hwlock )
2020-06-15 14:44:56 +02:00
hwspin_unlock_in_atomic ( pctl - > hwlock ) ;
2019-05-10 09:43:03 +02:00
return ret ;
}
2016-09-09 16:42:01 +02:00
static int stm32_gpio_domain_alloc ( struct irq_domain * d ,
unsigned int virq ,
unsigned int nr_irqs , void * data )
{
struct stm32_gpio_bank * bank = d - > host_data ;
struct irq_fwspec * fwspec = data ;
struct irq_fwspec parent_fwspec ;
2021-06-17 16:46:02 +02:00
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
irq_hw_number_t hwirq = fwspec - > param [ 0 ] ;
unsigned long flags ;
int ret = 0 ;
/*
* Check first that the IRQ MUX of that line is free .
* gpio irq mux is shared between several banks , protect with a lock
*/
spin_lock_irqsave ( & pctl - > irqmux_lock , flags ) ;
if ( pctl - > irqmux_map & BIT ( hwirq ) ) {
dev_err ( pctl - > dev , " irq line %ld already requested. \n " , hwirq ) ;
ret = - EBUSY ;
} else {
pctl - > irqmux_map | = BIT ( hwirq ) ;
}
spin_unlock_irqrestore ( & pctl - > irqmux_lock , flags ) ;
if ( ret )
return ret ;
2016-09-09 16:42:01 +02:00
parent_fwspec . fwnode = d - > parent - > fwnode ;
parent_fwspec . param_count = 2 ;
parent_fwspec . param [ 0 ] = fwspec - > param [ 0 ] ;
parent_fwspec . param [ 1 ] = fwspec - > param [ 1 ] ;
irq_domain_set_hwirq_and_chip ( d , virq , hwirq , & stm32_gpio_irq_chip ,
bank ) ;
2017-01-27 17:15:14 +01:00
return irq_domain_alloc_irqs_parent ( d , virq , nr_irqs , & parent_fwspec ) ;
2016-09-09 16:42:01 +02:00
}
2021-06-17 16:46:02 +02:00
static void stm32_gpio_domain_free ( struct irq_domain * d , unsigned int virq ,
unsigned int nr_irqs )
{
struct stm32_gpio_bank * bank = d - > host_data ;
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
struct irq_data * irq_data = irq_domain_get_irq_data ( d , virq ) ;
unsigned long flags , hwirq = irq_data - > hwirq ;
irq_domain_free_irqs_common ( d , virq , nr_irqs ) ;
spin_lock_irqsave ( & pctl - > irqmux_lock , flags ) ;
pctl - > irqmux_map & = ~ BIT ( hwirq ) ;
spin_unlock_irqrestore ( & pctl - > irqmux_lock , flags ) ;
}
2016-09-09 16:42:01 +02:00
static const struct irq_domain_ops stm32_gpio_domain_ops = {
2021-06-17 16:46:02 +02:00
. translate = stm32_gpio_domain_translate ,
. alloc = stm32_gpio_domain_alloc ,
. free = stm32_gpio_domain_free ,
2016-09-09 16:42:01 +02:00
. activate = stm32_gpio_domain_activate ,
} ;
/* Pinctrl functions */
2016-01-14 13:16:30 +01:00
static struct stm32_pinctrl_group *
stm32_pctrl_find_group_by_pin ( struct stm32_pinctrl * pctl , u32 pin )
{
int i ;
for ( i = 0 ; i < pctl - > ngroups ; i + + ) {
struct stm32_pinctrl_group * grp = pctl - > groups + i ;
if ( grp - > pin = = pin )
return grp ;
}
return NULL ;
}
static bool stm32_pctrl_is_function_valid ( struct stm32_pinctrl * pctl ,
u32 pin_num , u32 fnum )
{
2022-05-02 17:25:24 +02:00
int i , k ;
2016-01-14 13:16:30 +01:00
2019-04-10 13:30:21 +02:00
for ( i = 0 ; i < pctl - > npins ; i + + ) {
const struct stm32_desc_pin * pin = pctl - > pins + i ;
2016-01-14 13:16:30 +01:00
const struct stm32_desc_function * func = pin - > functions ;
if ( pin - > pin . number ! = pin_num )
continue ;
2022-05-02 17:25:24 +02:00
for ( k = 0 ; k < STM32_CONFIG_NUM ; k + + ) {
2016-01-14 13:16:30 +01:00
if ( func - > num = = fnum )
return true ;
func + + ;
}
break ;
}
2021-04-06 20:00:35 +02:00
dev_err ( pctl - > dev , " invalid function %d on pin %d . \n " , fnum , pin_num ) ;
2016-01-14 13:16:30 +01:00
return false ;
}
static int stm32_pctrl_dt_node_to_map_func ( struct stm32_pinctrl * pctl ,
u32 pin , u32 fnum , struct stm32_pinctrl_group * grp ,
struct pinctrl_map * * map , unsigned * reserved_maps ,
unsigned * num_maps )
{
if ( * num_maps = = * reserved_maps )
return - ENOSPC ;
( * map ) [ * num_maps ] . type = PIN_MAP_TYPE_MUX_GROUP ;
( * map ) [ * num_maps ] . data . mux . group = grp - > name ;
2021-04-06 20:00:35 +02:00
if ( ! stm32_pctrl_is_function_valid ( pctl , pin , fnum ) )
2016-01-14 13:16:30 +01:00
return - EINVAL ;
( * map ) [ * num_maps ] . data . mux . function = stm32_gpio_functions [ fnum ] ;
( * num_maps ) + + ;
return 0 ;
}
static int stm32_pctrl_dt_subnode_to_map ( struct pinctrl_dev * pctldev ,
struct device_node * node ,
struct pinctrl_map * * map ,
unsigned * reserved_maps ,
unsigned * num_maps )
{
struct stm32_pinctrl * pctl ;
struct stm32_pinctrl_group * grp ;
struct property * pins ;
u32 pinfunc , pin , func ;
unsigned long * configs ;
unsigned int num_configs ;
bool has_config = 0 ;
unsigned reserve = 0 ;
2019-02-14 17:54:24 +01:00
int num_pins , num_funcs , maps_per_pin , i , err = 0 ;
2016-01-14 13:16:30 +01:00
pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
pins = of_find_property ( node , " pinmux " , NULL ) ;
if ( ! pins ) {
2018-08-27 20:52:41 -05:00
dev_err ( pctl - > dev , " missing pins property in node %pOFn . \n " ,
node ) ;
2016-01-14 13:16:30 +01:00
return - EINVAL ;
}
err = pinconf_generic_parse_dt_config ( node , pctldev , & configs ,
& num_configs ) ;
if ( err )
return err ;
if ( num_configs )
has_config = 1 ;
num_pins = pins - > length / sizeof ( u32 ) ;
num_funcs = num_pins ;
maps_per_pin = 0 ;
if ( num_funcs )
maps_per_pin + + ;
if ( has_config & & num_pins > = 1 )
maps_per_pin + + ;
2019-02-14 17:54:24 +01:00
if ( ! num_pins | | ! maps_per_pin ) {
err = - EINVAL ;
goto exit ;
}
2016-01-14 13:16:30 +01:00
reserve = num_pins * maps_per_pin ;
err = pinctrl_utils_reserve_map ( pctldev , map ,
reserved_maps , num_maps , reserve ) ;
if ( err )
2019-02-14 17:54:24 +01:00
goto exit ;
2016-01-14 13:16:30 +01:00
for ( i = 0 ; i < num_pins ; i + + ) {
err = of_property_read_u32_index ( node , " pinmux " ,
i , & pinfunc ) ;
if ( err )
2019-02-14 17:54:24 +01:00
goto exit ;
2016-01-14 13:16:30 +01:00
pin = STM32_GET_PIN_NO ( pinfunc ) ;
func = STM32_GET_PIN_FUNC ( pinfunc ) ;
if ( ! stm32_pctrl_is_function_valid ( pctl , pin , func ) ) {
2019-02-14 17:54:24 +01:00
err = - EINVAL ;
goto exit ;
2016-01-14 13:16:30 +01:00
}
grp = stm32_pctrl_find_group_by_pin ( pctl , pin ) ;
if ( ! grp ) {
dev_err ( pctl - > dev , " unable to match pin %d to group \n " ,
pin ) ;
2019-02-14 17:54:24 +01:00
err = - EINVAL ;
goto exit ;
2016-01-14 13:16:30 +01:00
}
err = stm32_pctrl_dt_node_to_map_func ( pctl , pin , func , grp , map ,
reserved_maps , num_maps ) ;
if ( err )
2019-02-14 17:54:24 +01:00
goto exit ;
2016-01-14 13:16:30 +01:00
if ( has_config ) {
err = pinctrl_utils_add_map_configs ( pctldev , map ,
reserved_maps , num_maps , grp - > name ,
configs , num_configs ,
PIN_MAP_TYPE_CONFIGS_GROUP ) ;
if ( err )
2019-02-14 17:54:24 +01:00
goto exit ;
2016-01-14 13:16:30 +01:00
}
}
2019-02-14 17:54:24 +01:00
exit :
kfree ( configs ) ;
return err ;
2016-01-14 13:16:30 +01:00
}
static int stm32_pctrl_dt_node_to_map ( struct pinctrl_dev * pctldev ,
struct device_node * np_config ,
struct pinctrl_map * * map , unsigned * num_maps )
{
struct device_node * np ;
unsigned reserved_maps ;
int ret ;
* map = NULL ;
* num_maps = 0 ;
reserved_maps = 0 ;
for_each_child_of_node ( np_config , np ) {
ret = stm32_pctrl_dt_subnode_to_map ( pctldev , np , map ,
& reserved_maps , num_maps ) ;
if ( ret < 0 ) {
2016-03-31 14:44:42 +03:00
pinctrl_utils_free_map ( pctldev , * map , * num_maps ) ;
2019-08-08 13:24:56 +05:30
of_node_put ( np ) ;
2016-01-14 13:16:30 +01:00
return ret ;
}
}
return 0 ;
}
static int stm32_pctrl_get_groups_count ( struct pinctrl_dev * pctldev )
{
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
return pctl - > ngroups ;
}
static const char * stm32_pctrl_get_group_name ( struct pinctrl_dev * pctldev ,
unsigned group )
{
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
return pctl - > groups [ group ] . name ;
}
static int stm32_pctrl_get_group_pins ( struct pinctrl_dev * pctldev ,
unsigned group ,
const unsigned * * pins ,
unsigned * num_pins )
{
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
* pins = ( unsigned * ) & pctl - > groups [ group ] . pin ;
* num_pins = 1 ;
return 0 ;
}
static const struct pinctrl_ops stm32_pctrl_ops = {
. dt_node_to_map = stm32_pctrl_dt_node_to_map ,
2016-03-31 14:44:42 +03:00
. dt_free_map = pinctrl_utils_free_map ,
2016-01-14 13:16:30 +01:00
. get_groups_count = stm32_pctrl_get_groups_count ,
. get_group_name = stm32_pctrl_get_group_name ,
. get_group_pins = stm32_pctrl_get_group_pins ,
} ;
/* Pinmux functions */
static int stm32_pmx_get_funcs_cnt ( struct pinctrl_dev * pctldev )
{
return ARRAY_SIZE ( stm32_gpio_functions ) ;
}
static const char * stm32_pmx_get_func_name ( struct pinctrl_dev * pctldev ,
unsigned selector )
{
return stm32_gpio_functions [ selector ] ;
}
static int stm32_pmx_get_func_groups ( struct pinctrl_dev * pctldev ,
unsigned function ,
const char * const * * groups ,
unsigned * const num_groups )
{
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
* groups = pctl - > grp_names ;
* num_groups = pctl - > ngroups ;
return 0 ;
}
2019-02-14 17:54:25 +01:00
static int stm32_pmx_set_mode ( struct stm32_gpio_bank * bank ,
int pin , u32 mode , u32 alt )
2016-01-14 13:16:30 +01:00
{
2018-11-13 10:51:41 +01:00
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
2016-01-14 13:16:30 +01:00
u32 val ;
int alt_shift = ( pin % 8 ) * 4 ;
int alt_offset = STM32_GPIO_AFRL + ( pin / 8 ) * 4 ;
unsigned long flags ;
2018-11-13 10:51:41 +01:00
int err = 0 ;
2016-01-14 13:16:30 +01:00
spin_lock_irqsave ( & bank - > lock , flags ) ;
2020-06-15 14:44:56 +02:00
if ( pctl - > hwlock ) {
err = hwspin_lock_timeout_in_atomic ( pctl - > hwlock ,
HWSPNLCK_TIMEOUT ) ;
if ( err ) {
dev_err ( pctl - > dev , " Can't get hwspinlock \n " ) ;
goto unlock ;
}
2018-11-13 10:51:41 +01:00
}
2016-01-14 13:16:30 +01:00
val = readl_relaxed ( bank - > base + alt_offset ) ;
val & = ~ GENMASK ( alt_shift + 3 , alt_shift ) ;
val | = ( alt < < alt_shift ) ;
writel_relaxed ( val , bank - > base + alt_offset ) ;
val = readl_relaxed ( bank - > base + STM32_GPIO_MODER ) ;
val & = ~ GENMASK ( pin * 2 + 1 , pin * 2 ) ;
val | = mode < < ( pin * 2 ) ;
writel_relaxed ( val , bank - > base + STM32_GPIO_MODER ) ;
2018-11-13 10:51:41 +01:00
if ( pctl - > hwlock )
2020-06-15 14:44:56 +02:00
hwspin_unlock_in_atomic ( pctl - > hwlock ) ;
2018-11-13 10:51:41 +01:00
2019-05-10 09:42:29 +02:00
stm32_gpio_backup_mode ( bank , pin , mode , alt ) ;
2018-11-13 10:51:41 +01:00
unlock :
2016-01-14 13:16:30 +01:00
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
2019-02-14 17:54:25 +01:00
return err ;
2016-01-14 13:16:30 +01:00
}
2017-05-29 18:17:32 +02:00
void stm32_pmx_get_mode ( struct stm32_gpio_bank * bank , int pin , u32 * mode ,
u32 * alt )
2016-04-29 16:25:43 +02:00
{
u32 val ;
int alt_shift = ( pin % 8 ) * 4 ;
int alt_offset = STM32_GPIO_AFRL + ( pin / 8 ) * 4 ;
unsigned long flags ;
spin_lock_irqsave ( & bank - > lock , flags ) ;
val = readl_relaxed ( bank - > base + alt_offset ) ;
val & = GENMASK ( alt_shift + 3 , alt_shift ) ;
* alt = val > > alt_shift ;
val = readl_relaxed ( bank - > base + STM32_GPIO_MODER ) ;
val & = GENMASK ( pin * 2 + 1 , pin * 2 ) ;
* mode = val > > ( pin * 2 ) ;
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
}
2016-01-14 13:16:30 +01:00
static int stm32_pmx_set_mux ( struct pinctrl_dev * pctldev ,
unsigned function ,
unsigned group )
{
bool ret ;
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
struct stm32_pinctrl_group * g = pctl - > groups + group ;
struct pinctrl_gpio_range * range ;
struct stm32_gpio_bank * bank ;
u32 mode , alt ;
int pin ;
ret = stm32_pctrl_is_function_valid ( pctl , g - > pin , function ) ;
2021-04-06 20:00:35 +02:00
if ( ! ret )
2016-01-14 13:16:30 +01:00
return - EINVAL ;
range = pinctrl_find_gpio_range_from_pin ( pctldev , g - > pin ) ;
2018-07-16 14:57:37 +02:00
if ( ! range ) {
dev_err ( pctl - > dev , " No gpio range defined. \n " ) ;
return - EINVAL ;
}
2017-04-07 14:42:58 +02:00
bank = gpiochip_get_data ( range - > gc ) ;
2016-01-14 13:16:30 +01:00
pin = stm32_gpio_pin ( g - > pin ) ;
mode = stm32_gpio_get_mode ( function ) ;
alt = stm32_gpio_get_alt ( function ) ;
2019-02-14 17:54:25 +01:00
return stm32_pmx_set_mode ( bank , pin , mode , alt ) ;
2016-01-14 13:16:30 +01:00
}
static int stm32_pmx_gpio_set_direction ( struct pinctrl_dev * pctldev ,
struct pinctrl_gpio_range * range , unsigned gpio ,
bool input )
{
2017-04-07 14:42:58 +02:00
struct stm32_gpio_bank * bank = gpiochip_get_data ( range - > gc ) ;
2016-01-14 13:16:30 +01:00
int pin = stm32_gpio_pin ( gpio ) ;
2019-02-14 17:54:25 +01:00
return stm32_pmx_set_mode ( bank , pin , ! input , 0 ) ;
2016-01-14 13:16:30 +01:00
}
2022-05-02 17:31:14 +02:00
static int stm32_pmx_request ( struct pinctrl_dev * pctldev , unsigned int gpio )
{
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
struct pinctrl_gpio_range * range ;
range = pinctrl_find_gpio_range_from_pin_nolock ( pctldev , gpio ) ;
if ( ! range ) {
dev_err ( pctl - > dev , " No gpio range defined. \n " ) ;
return - EINVAL ;
}
if ( ! gpiochip_line_is_valid ( range - > gc , stm32_gpio_pin ( gpio ) ) ) {
dev_warn ( pctl - > dev , " Can't access gpio %d \n " , gpio ) ;
return - EACCES ;
}
return 0 ;
}
2016-01-14 13:16:30 +01:00
static const struct pinmux_ops stm32_pmx_ops = {
. get_functions_count = stm32_pmx_get_funcs_cnt ,
. get_function_name = stm32_pmx_get_func_name ,
. get_function_groups = stm32_pmx_get_func_groups ,
. set_mux = stm32_pmx_set_mux ,
. gpio_set_direction = stm32_pmx_gpio_set_direction ,
2022-05-02 17:31:14 +02:00
. request = stm32_pmx_request ,
2016-12-14 15:24:16 +01:00
. strict = true ,
2016-01-14 13:16:30 +01:00
} ;
/* Pinconf functions */
2019-02-14 17:54:25 +01:00
static int stm32_pconf_set_driving ( struct stm32_gpio_bank * bank ,
unsigned offset , u32 drive )
2016-01-14 13:16:30 +01:00
{
2018-11-13 10:51:41 +01:00
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
2016-01-14 13:16:30 +01:00
unsigned long flags ;
u32 val ;
2018-11-13 10:51:41 +01:00
int err = 0 ;
2016-01-14 13:16:30 +01:00
spin_lock_irqsave ( & bank - > lock , flags ) ;
2020-06-15 14:44:56 +02:00
if ( pctl - > hwlock ) {
err = hwspin_lock_timeout_in_atomic ( pctl - > hwlock ,
HWSPNLCK_TIMEOUT ) ;
if ( err ) {
dev_err ( pctl - > dev , " Can't get hwspinlock \n " ) ;
goto unlock ;
}
2018-11-13 10:51:41 +01:00
}
2016-01-14 13:16:30 +01:00
val = readl_relaxed ( bank - > base + STM32_GPIO_TYPER ) ;
val & = ~ BIT ( offset ) ;
val | = drive < < offset ;
writel_relaxed ( val , bank - > base + STM32_GPIO_TYPER ) ;
2018-11-13 10:51:41 +01:00
if ( pctl - > hwlock )
2020-06-15 14:44:56 +02:00
hwspin_unlock_in_atomic ( pctl - > hwlock ) ;
2018-11-13 10:51:41 +01:00
2019-05-10 09:42:29 +02:00
stm32_gpio_backup_driving ( bank , offset , drive ) ;
2018-11-13 10:51:41 +01:00
unlock :
2016-01-14 13:16:30 +01:00
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
2019-02-14 17:54:25 +01:00
return err ;
2016-01-14 13:16:30 +01:00
}
2016-04-29 16:25:43 +02:00
static u32 stm32_pconf_get_driving ( struct stm32_gpio_bank * bank ,
unsigned int offset )
{
unsigned long flags ;
u32 val ;
spin_lock_irqsave ( & bank - > lock , flags ) ;
val = readl_relaxed ( bank - > base + STM32_GPIO_TYPER ) ;
val & = BIT ( offset ) ;
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
return ( val > > offset ) ;
}
2019-02-14 17:54:25 +01:00
static int stm32_pconf_set_speed ( struct stm32_gpio_bank * bank ,
unsigned offset , u32 speed )
2016-01-14 13:16:30 +01:00
{
2018-11-13 10:51:41 +01:00
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
2016-01-14 13:16:30 +01:00
unsigned long flags ;
u32 val ;
2018-11-13 10:51:41 +01:00
int err = 0 ;
2016-01-14 13:16:30 +01:00
spin_lock_irqsave ( & bank - > lock , flags ) ;
2020-06-15 14:44:56 +02:00
if ( pctl - > hwlock ) {
err = hwspin_lock_timeout_in_atomic ( pctl - > hwlock ,
HWSPNLCK_TIMEOUT ) ;
if ( err ) {
dev_err ( pctl - > dev , " Can't get hwspinlock \n " ) ;
goto unlock ;
}
2018-11-13 10:51:41 +01:00
}
2016-01-14 13:16:30 +01:00
val = readl_relaxed ( bank - > base + STM32_GPIO_SPEEDR ) ;
val & = ~ GENMASK ( offset * 2 + 1 , offset * 2 ) ;
val | = speed < < ( offset * 2 ) ;
writel_relaxed ( val , bank - > base + STM32_GPIO_SPEEDR ) ;
2018-11-13 10:51:41 +01:00
if ( pctl - > hwlock )
2020-06-15 14:44:56 +02:00
hwspin_unlock_in_atomic ( pctl - > hwlock ) ;
2018-11-13 10:51:41 +01:00
2019-05-10 09:42:29 +02:00
stm32_gpio_backup_speed ( bank , offset , speed ) ;
2018-11-13 10:51:41 +01:00
unlock :
2016-01-14 13:16:30 +01:00
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
2019-02-14 17:54:25 +01:00
return err ;
2016-01-14 13:16:30 +01:00
}
2016-04-29 16:25:43 +02:00
static u32 stm32_pconf_get_speed ( struct stm32_gpio_bank * bank ,
unsigned int offset )
{
unsigned long flags ;
u32 val ;
spin_lock_irqsave ( & bank - > lock , flags ) ;
val = readl_relaxed ( bank - > base + STM32_GPIO_SPEEDR ) ;
val & = GENMASK ( offset * 2 + 1 , offset * 2 ) ;
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
return ( val > > ( offset * 2 ) ) ;
}
2019-02-14 17:54:25 +01:00
static int stm32_pconf_set_bias ( struct stm32_gpio_bank * bank ,
unsigned offset , u32 bias )
2016-01-14 13:16:30 +01:00
{
2018-11-13 10:51:41 +01:00
struct stm32_pinctrl * pctl = dev_get_drvdata ( bank - > gpio_chip . parent ) ;
2016-01-14 13:16:30 +01:00
unsigned long flags ;
u32 val ;
2018-11-13 10:51:41 +01:00
int err = 0 ;
2016-01-14 13:16:30 +01:00
spin_lock_irqsave ( & bank - > lock , flags ) ;
2020-06-15 14:44:56 +02:00
if ( pctl - > hwlock ) {
err = hwspin_lock_timeout_in_atomic ( pctl - > hwlock ,
HWSPNLCK_TIMEOUT ) ;
if ( err ) {
dev_err ( pctl - > dev , " Can't get hwspinlock \n " ) ;
goto unlock ;
}
2018-11-13 10:51:41 +01:00
}
2016-01-14 13:16:30 +01:00
val = readl_relaxed ( bank - > base + STM32_GPIO_PUPDR ) ;
val & = ~ GENMASK ( offset * 2 + 1 , offset * 2 ) ;
val | = bias < < ( offset * 2 ) ;
writel_relaxed ( val , bank - > base + STM32_GPIO_PUPDR ) ;
2018-11-13 10:51:41 +01:00
if ( pctl - > hwlock )
2020-06-15 14:44:56 +02:00
hwspin_unlock_in_atomic ( pctl - > hwlock ) ;
2018-11-13 10:51:41 +01:00
2019-05-10 09:42:29 +02:00
stm32_gpio_backup_bias ( bank , offset , bias ) ;
2018-11-13 10:51:41 +01:00
unlock :
2016-01-14 13:16:30 +01:00
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
2019-02-14 17:54:25 +01:00
return err ;
2016-01-14 13:16:30 +01:00
}
2016-04-29 16:25:43 +02:00
static u32 stm32_pconf_get_bias ( struct stm32_gpio_bank * bank ,
unsigned int offset )
{
unsigned long flags ;
u32 val ;
spin_lock_irqsave ( & bank - > lock , flags ) ;
val = readl_relaxed ( bank - > base + STM32_GPIO_PUPDR ) ;
val & = GENMASK ( offset * 2 + 1 , offset * 2 ) ;
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
return ( val > > ( offset * 2 ) ) ;
}
2016-05-24 13:57:43 +02:00
static bool stm32_pconf_get ( struct stm32_gpio_bank * bank ,
unsigned int offset , bool dir )
2016-04-29 16:25:43 +02:00
{
unsigned long flags ;
u32 val ;
spin_lock_irqsave ( & bank - > lock , flags ) ;
2016-05-24 13:57:43 +02:00
if ( dir )
val = ! ! ( readl_relaxed ( bank - > base + STM32_GPIO_IDR ) &
BIT ( offset ) ) ;
else
val = ! ! ( readl_relaxed ( bank - > base + STM32_GPIO_ODR ) &
BIT ( offset ) ) ;
2016-04-29 16:25:43 +02:00
spin_unlock_irqrestore ( & bank - > lock , flags ) ;
return val ;
}
2016-01-14 13:16:30 +01:00
static int stm32_pconf_parse_conf ( struct pinctrl_dev * pctldev ,
unsigned int pin , enum pin_config_param param ,
enum pin_config_param arg )
{
2018-07-16 14:57:37 +02:00
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
2016-01-14 13:16:30 +01:00
struct pinctrl_gpio_range * range ;
struct stm32_gpio_bank * bank ;
int offset , ret = 0 ;
2020-06-15 14:59:51 +02:00
range = pinctrl_find_gpio_range_from_pin_nolock ( pctldev , pin ) ;
2018-07-16 14:57:37 +02:00
if ( ! range ) {
dev_err ( pctl - > dev , " No gpio range defined. \n " ) ;
return - EINVAL ;
}
2017-04-07 14:42:58 +02:00
bank = gpiochip_get_data ( range - > gc ) ;
2016-01-14 13:16:30 +01:00
offset = stm32_gpio_pin ( pin ) ;
2022-05-02 17:31:14 +02:00
if ( ! gpiochip_line_is_valid ( range - > gc , offset ) ) {
dev_warn ( pctl - > dev , " Can't access gpio %d \n " , pin ) ;
return - EACCES ;
}
2016-01-14 13:16:30 +01:00
switch ( param ) {
case PIN_CONFIG_DRIVE_PUSH_PULL :
2019-02-14 17:54:25 +01:00
ret = stm32_pconf_set_driving ( bank , offset , 0 ) ;
2016-01-14 13:16:30 +01:00
break ;
case PIN_CONFIG_DRIVE_OPEN_DRAIN :
2019-02-14 17:54:25 +01:00
ret = stm32_pconf_set_driving ( bank , offset , 1 ) ;
2016-01-14 13:16:30 +01:00
break ;
case PIN_CONFIG_SLEW_RATE :
2019-02-14 17:54:25 +01:00
ret = stm32_pconf_set_speed ( bank , offset , arg ) ;
2016-01-14 13:16:30 +01:00
break ;
case PIN_CONFIG_BIAS_DISABLE :
2019-02-14 17:54:25 +01:00
ret = stm32_pconf_set_bias ( bank , offset , 0 ) ;
2016-01-14 13:16:30 +01:00
break ;
case PIN_CONFIG_BIAS_PULL_UP :
2019-02-14 17:54:25 +01:00
ret = stm32_pconf_set_bias ( bank , offset , 1 ) ;
2016-01-14 13:16:30 +01:00
break ;
case PIN_CONFIG_BIAS_PULL_DOWN :
2019-02-14 17:54:25 +01:00
ret = stm32_pconf_set_bias ( bank , offset , 2 ) ;
2016-01-14 13:16:30 +01:00
break ;
case PIN_CONFIG_OUTPUT :
__stm32_gpio_set ( bank , offset , arg ) ;
2017-05-30 16:43:04 +02:00
ret = stm32_pmx_gpio_set_direction ( pctldev , range , pin , false ) ;
2016-01-14 13:16:30 +01:00
break ;
default :
2020-06-15 14:59:50 +02:00
ret = - ENOTSUPP ;
2016-01-14 13:16:30 +01:00
}
return ret ;
}
static int stm32_pconf_group_get ( struct pinctrl_dev * pctldev ,
unsigned group ,
unsigned long * config )
{
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
* config = pctl - > groups [ group ] . config ;
return 0 ;
}
static int stm32_pconf_group_set ( struct pinctrl_dev * pctldev , unsigned group ,
unsigned long * configs , unsigned num_configs )
{
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
struct stm32_pinctrl_group * g = & pctl - > groups [ group ] ;
int i , ret ;
for ( i = 0 ; i < num_configs ; i + + ) {
2020-06-15 14:59:51 +02:00
mutex_lock ( & pctldev - > mutex ) ;
2016-01-14 13:16:30 +01:00
ret = stm32_pconf_parse_conf ( pctldev , g - > pin ,
pinconf_to_config_param ( configs [ i ] ) ,
pinconf_to_config_argument ( configs [ i ] ) ) ;
2020-06-15 14:59:51 +02:00
mutex_unlock ( & pctldev - > mutex ) ;
2016-01-14 13:16:30 +01:00
if ( ret < 0 )
return ret ;
g - > config = configs [ i ] ;
}
return 0 ;
}
2020-06-15 14:59:51 +02:00
static int stm32_pconf_set ( struct pinctrl_dev * pctldev , unsigned int pin ,
unsigned long * configs , unsigned int num_configs )
{
int i , ret ;
for ( i = 0 ; i < num_configs ; i + + ) {
ret = stm32_pconf_parse_conf ( pctldev , pin ,
pinconf_to_config_param ( configs [ i ] ) ,
pinconf_to_config_argument ( configs [ i ] ) ) ;
if ( ret < 0 )
return ret ;
}
return 0 ;
}
2022-05-02 17:25:24 +02:00
static struct stm32_desc_pin *
stm32_pconf_get_pin_desc_by_pin_number ( struct stm32_pinctrl * pctl ,
unsigned int pin_number )
{
struct stm32_desc_pin * pins = pctl - > pins ;
int i ;
for ( i = 0 ; i < pctl - > npins ; i + + ) {
if ( pins - > pin . number = = pin_number )
return pins ;
pins + + ;
}
return NULL ;
}
2016-04-29 16:25:43 +02:00
static void stm32_pconf_dbg_show ( struct pinctrl_dev * pctldev ,
struct seq_file * s ,
unsigned int pin )
{
2022-05-02 17:25:24 +02:00
struct stm32_pinctrl * pctl = pinctrl_dev_get_drvdata ( pctldev ) ;
const struct stm32_desc_pin * pin_desc ;
2016-04-29 16:25:43 +02:00
struct pinctrl_gpio_range * range ;
struct stm32_gpio_bank * bank ;
int offset ;
u32 mode , alt , drive , speed , bias ;
static const char * const modes [ ] = {
" input " , " output " , " alternate " , " analog " } ;
static const char * const speeds [ ] = {
" low " , " medium " , " high " , " very high " } ;
static const char * const biasing [ ] = {
" floating " , " pull up " , " pull down " , " " } ;
bool val ;
range = pinctrl_find_gpio_range_from_pin_nolock ( pctldev , pin ) ;
2018-07-16 14:57:37 +02:00
if ( ! range )
return ;
2017-04-07 14:42:58 +02:00
bank = gpiochip_get_data ( range - > gc ) ;
2016-04-29 16:25:43 +02:00
offset = stm32_gpio_pin ( pin ) ;
2022-05-02 17:31:14 +02:00
if ( ! gpiochip_line_is_valid ( range - > gc , offset ) ) {
seq_puts ( s , " NO ACCESS " ) ;
return ;
}
2016-04-29 16:25:43 +02:00
stm32_pmx_get_mode ( bank , offset , & mode , & alt ) ;
bias = stm32_pconf_get_bias ( bank , offset ) ;
seq_printf ( s , " %s " , modes [ mode ] ) ;
switch ( mode ) {
/* input */
case 0 :
2016-05-24 13:57:43 +02:00
val = stm32_pconf_get ( bank , offset , true ) ;
2016-04-29 16:25:43 +02:00
seq_printf ( s , " - %s - %s " ,
val ? " high " : " low " ,
biasing [ bias ] ) ;
break ;
/* output */
case 1 :
drive = stm32_pconf_get_driving ( bank , offset ) ;
speed = stm32_pconf_get_speed ( bank , offset ) ;
2016-05-24 13:57:43 +02:00
val = stm32_pconf_get ( bank , offset , false ) ;
2016-04-29 16:25:43 +02:00
seq_printf ( s , " - %s - %s - %s - %s %s " ,
val ? " high " : " low " ,
drive ? " open drain " : " push pull " ,
biasing [ bias ] ,
speeds [ speed ] , " speed " ) ;
break ;
/* alternate */
case 2 :
drive = stm32_pconf_get_driving ( bank , offset ) ;
speed = stm32_pconf_get_speed ( bank , offset ) ;
2022-05-02 17:25:24 +02:00
pin_desc = stm32_pconf_get_pin_desc_by_pin_number ( pctl , pin ) ;
if ( ! pin_desc )
return ;
seq_printf ( s , " %d (%s) - %s - %s - %s %s " , alt ,
pin_desc - > functions [ alt + 1 ] . name ,
2016-04-29 16:25:43 +02:00
drive ? " open drain " : " push pull " ,
biasing [ bias ] ,
speeds [ speed ] , " speed " ) ;
break ;
/* analog */
case 3 :
break ;
}
}
2016-01-14 13:16:30 +01:00
static const struct pinconf_ops stm32_pconf_ops = {
. pin_config_group_get = stm32_pconf_group_get ,
. pin_config_group_set = stm32_pconf_group_set ,
2020-06-15 14:59:51 +02:00
. pin_config_set = stm32_pconf_set ,
2016-04-29 16:25:43 +02:00
. pin_config_dbg_show = stm32_pconf_dbg_show ,
2016-01-14 13:16:30 +01:00
} ;
2022-04-01 13:35:55 +03:00
static int stm32_gpiolib_register_bank ( struct stm32_pinctrl * pctl , struct fwnode_handle * fwnode )
2016-01-14 13:16:30 +01:00
{
2017-04-07 14:42:58 +02:00
struct stm32_gpio_bank * bank = & pctl - > banks [ pctl - > nbanks ] ;
2018-07-16 14:57:36 +02:00
int bank_ioport_nr ;
2016-01-14 13:16:30 +01:00
struct pinctrl_gpio_range * range = & bank - > range ;
2022-04-01 13:35:55 +03:00
struct fwnode_reference_args args ;
2016-01-14 13:16:30 +01:00
struct device * dev = pctl - > dev ;
struct resource res ;
2017-04-07 14:42:58 +02:00
int npins = STM32_GPIO_PINS_PER_BANK ;
2021-06-17 16:46:29 +02:00
int bank_nr , err , i = 0 ;
2016-01-14 13:16:30 +01:00
2020-06-15 14:54:07 +02:00
if ( ! IS_ERR ( bank - > rstc ) )
reset_control_deassert ( bank - > rstc ) ;
2016-01-14 13:16:30 +01:00
2022-04-01 13:35:55 +03:00
if ( of_address_to_resource ( to_of_node ( fwnode ) , 0 , & res ) )
2016-01-14 13:16:30 +01:00
return - ENODEV ;
bank - > base = devm_ioremap_resource ( dev , & res ) ;
if ( IS_ERR ( bank - > base ) )
return PTR_ERR ( bank - > base ) ;
2022-04-22 16:36:08 +02:00
err = clk_prepare_enable ( bank - > clk ) ;
2016-01-14 13:16:30 +01:00
if ( err ) {
2022-04-22 16:36:08 +02:00
dev_err ( dev , " failed to prepare_enable clk (%d) \n " , err ) ;
2016-01-14 13:16:30 +01:00
return err ;
}
bank - > gpio_chip = stm32_gpio_template ;
2017-04-07 14:42:58 +02:00
2022-04-01 13:35:55 +03:00
fwnode_property_read_string ( fwnode , " st,bank-name " , & bank - > gpio_chip . label ) ;
2017-04-07 14:42:58 +02:00
2022-04-01 13:35:55 +03:00
if ( ! fwnode_property_get_reference_args ( fwnode , " gpio-ranges " , NULL , 3 , i , & args ) ) {
2017-04-07 14:42:58 +02:00
bank_nr = args . args [ 1 ] / STM32_GPIO_PINS_PER_BANK ;
bank - > gpio_chip . base = args . args [ 1 ] ;
2021-06-17 16:46:29 +02:00
2021-12-15 10:58:08 +01:00
/* get the last defined gpio line (offset + nb of pins) */
npins = args . args [ 0 ] + args . args [ 2 ] ;
2022-04-01 13:35:55 +03:00
while ( ! fwnode_property_get_reference_args ( fwnode , " gpio-ranges " , NULL , 3 , + + i , & args ) )
2021-12-15 10:58:08 +01:00
npins = max ( npins , ( int ) ( args . args [ 0 ] + args . args [ 2 ] ) ) ;
2017-04-07 14:42:58 +02:00
} else {
bank_nr = pctl - > nbanks ;
bank - > gpio_chip . base = bank_nr * STM32_GPIO_PINS_PER_BANK ;
range - > name = bank - > gpio_chip . label ;
range - > id = bank_nr ;
range - > pin_base = range - > id * STM32_GPIO_PINS_PER_BANK ;
range - > base = range - > id * STM32_GPIO_PINS_PER_BANK ;
range - > npins = npins ;
range - > gc = & bank - > gpio_chip ;
pinctrl_add_gpio_range ( pctl - > pctl_dev ,
& pctl - > banks [ bank_nr ] . range ) ;
}
2018-07-16 14:57:36 +02:00
2022-04-01 13:35:55 +03:00
if ( fwnode_property_read_u32 ( fwnode , " st,bank-ioport " , & bank_ioport_nr ) )
2018-07-16 14:57:36 +02:00
bank_ioport_nr = bank_nr ;
2016-01-14 13:16:30 +01:00
bank - > gpio_chip . base = bank_nr * STM32_GPIO_PINS_PER_BANK ;
2017-04-07 14:42:58 +02:00
2016-01-14 13:16:30 +01:00
bank - > gpio_chip . ngpio = npins ;
2022-04-01 13:35:55 +03:00
bank - > gpio_chip . fwnode = fwnode ;
2016-02-05 23:47:13 +01:00
bank - > gpio_chip . parent = dev ;
2017-04-07 14:42:58 +02:00
bank - > bank_nr = bank_nr ;
2018-07-16 14:57:36 +02:00
bank - > bank_ioport_nr = bank_ioport_nr ;
2022-05-02 17:31:14 +02:00
bank - > secure_control = pctl - > match_data - > secure_control ;
2016-01-14 13:16:30 +01:00
spin_lock_init ( & bank - > lock ) ;
2016-09-09 16:42:01 +02:00
/* create irq hierarchical domain */
2022-04-01 13:35:55 +03:00
bank - > fwnode = fwnode ;
2016-09-09 16:42:01 +02:00
bank - > domain = irq_domain_create_hierarchy ( pctl - > domain , 0 ,
STM32_GPIO_IRQ_LINE , bank - > fwnode ,
& stm32_gpio_domain_ops , bank ) ;
2022-04-22 16:36:08 +02:00
if ( ! bank - > domain ) {
err = - ENODEV ;
goto err_clk ;
}
2016-09-09 16:42:01 +02:00
2016-02-05 23:47:13 +01:00
err = gpiochip_add_data ( & bank - > gpio_chip , bank ) ;
2016-01-14 13:16:30 +01:00
if ( err ) {
dev_err ( dev , " Failed to add gpiochip(%d)! \n " , bank_nr ) ;
2022-04-22 16:36:08 +02:00
goto err_clk ;
2016-01-14 13:16:30 +01:00
}
2017-04-07 14:42:58 +02:00
dev_info ( dev , " %s bank added \n " , bank - > gpio_chip . label ) ;
2016-01-14 13:16:30 +01:00
return 0 ;
2022-04-22 16:36:08 +02:00
err_clk :
clk_disable_unprepare ( bank - > clk ) ;
return err ;
2016-01-14 13:16:30 +01:00
}
2022-05-07 13:22:57 +03:00
static struct irq_domain * stm32_pctrl_get_irq_domain ( struct platform_device * pdev )
2019-04-24 10:08:44 +02:00
{
2022-05-07 13:22:57 +03:00
struct device_node * np = pdev - > dev . of_node ;
2019-04-24 10:08:44 +02:00
struct device_node * parent ;
struct irq_domain * domain ;
if ( ! of_find_property ( np , " interrupt-parent " , NULL ) )
return NULL ;
parent = of_irq_find_parent ( np ) ;
if ( ! parent )
return ERR_PTR ( - ENXIO ) ;
domain = irq_find_host ( parent ) ;
if ( ! domain )
/* domain not registered yet */
return ERR_PTR ( - EPROBE_DEFER ) ;
return domain ;
}
2016-09-09 16:42:01 +02:00
static int stm32_pctrl_dt_setup_irq ( struct platform_device * pdev ,
struct stm32_pinctrl * pctl )
{
2019-04-24 10:08:44 +02:00
struct device_node * np = pdev - > dev . of_node ;
2016-09-09 16:42:01 +02:00
struct device * dev = & pdev - > dev ;
struct regmap * rm ;
int offset , ret , i ;
2018-07-17 11:56:27 +02:00
int mask , mask_width ;
2016-09-09 16:42:01 +02:00
pctl - > regmap = syscon_regmap_lookup_by_phandle ( np , " st,syscfg " ) ;
if ( IS_ERR ( pctl - > regmap ) )
return PTR_ERR ( pctl - > regmap ) ;
rm = pctl - > regmap ;
ret = of_property_read_u32_index ( np , " st,syscfg " , 1 , & offset ) ;
if ( ret )
return ret ;
2018-07-17 11:56:27 +02:00
ret = of_property_read_u32_index ( np , " st,syscfg " , 2 , & mask ) ;
if ( ret )
mask = SYSCFG_IRQMUX_MASK ;
mask_width = fls ( mask ) ;
2016-09-09 16:42:01 +02:00
for ( i = 0 ; i < STM32_GPIO_PINS_PER_BANK ; i + + ) {
struct reg_field mux ;
mux . reg = offset + ( i / 4 ) * 4 ;
2018-07-17 11:56:27 +02:00
mux . lsb = ( i % 4 ) * mask_width ;
mux . msb = mux . lsb + mask_width - 1 ;
dev_dbg ( dev , " irqmux%d: reg:%#x, lsb:%d, msb:%d \n " ,
i , mux . reg , mux . lsb , mux . msb ) ;
2016-09-09 16:42:01 +02:00
pctl - > irqmux [ i ] = devm_regmap_field_alloc ( dev , rm , mux ) ;
if ( IS_ERR ( pctl - > irqmux [ i ] ) )
return PTR_ERR ( pctl - > irqmux [ i ] ) ;
}
return 0 ;
}
2016-01-14 13:16:30 +01:00
static int stm32_pctrl_build_state ( struct platform_device * pdev )
{
struct stm32_pinctrl * pctl = platform_get_drvdata ( pdev ) ;
int i ;
2019-04-10 13:30:21 +02:00
pctl - > ngroups = pctl - > npins ;
2016-01-14 13:16:30 +01:00
/* Allocate groups */
pctl - > groups = devm_kcalloc ( & pdev - > dev , pctl - > ngroups ,
sizeof ( * pctl - > groups ) , GFP_KERNEL ) ;
if ( ! pctl - > groups )
return - ENOMEM ;
/* We assume that one pin is one group, use pin name as group name. */
pctl - > grp_names = devm_kcalloc ( & pdev - > dev , pctl - > ngroups ,
sizeof ( * pctl - > grp_names ) , GFP_KERNEL ) ;
if ( ! pctl - > grp_names )
return - ENOMEM ;
2019-04-10 13:30:21 +02:00
for ( i = 0 ; i < pctl - > npins ; i + + ) {
const struct stm32_desc_pin * pin = pctl - > pins + i ;
2016-01-14 13:16:30 +01:00
struct stm32_pinctrl_group * group = pctl - > groups + i ;
group - > name = pin - > pin . name ;
group - > pin = pin - > pin . number ;
pctl - > grp_names [ i ] = pin - > pin . name ;
}
return 0 ;
}
2019-04-10 13:30:21 +02:00
static int stm32_pctrl_create_pins_tab ( struct stm32_pinctrl * pctl ,
struct stm32_desc_pin * pins )
{
const struct stm32_desc_pin * p ;
int i , nb_pins_available = 0 ;
for ( i = 0 ; i < pctl - > match_data - > npins ; i + + ) {
p = pctl - > match_data - > pins + i ;
if ( pctl - > pkg & & ! ( pctl - > pkg & p - > pkg ) )
continue ;
pins - > pin = p - > pin ;
2022-05-02 17:25:24 +02:00
memcpy ( ( struct stm32_desc_pin * ) pins - > functions , p - > functions ,
STM32_CONFIG_NUM * sizeof ( struct stm32_desc_function ) ) ;
2019-04-10 13:30:21 +02:00
pins + + ;
nb_pins_available + + ;
}
pctl - > npins = nb_pins_available ;
return 0 ;
}
2016-01-14 13:16:30 +01:00
int stm32_pctl_probe ( struct platform_device * pdev )
{
2022-05-07 13:22:57 +03:00
const struct stm32_pinctrl_match_data * match_data ;
2022-04-01 13:35:55 +03:00
struct fwnode_handle * child ;
2016-01-14 13:16:30 +01:00
struct device * dev = & pdev - > dev ;
struct stm32_pinctrl * pctl ;
struct pinctrl_pin_desc * pins ;
2022-04-01 13:35:54 +03:00
int i , ret , hwlock_id ;
unsigned int banks ;
2016-01-14 13:16:30 +01:00
2022-05-07 13:22:57 +03:00
match_data = device_get_match_data ( dev ) ;
if ( ! match_data )
2016-01-14 13:16:30 +01:00
return - EINVAL ;
2022-05-07 13:22:57 +03:00
if ( ! device_property_present ( dev , " pins-are-numbered " ) ) {
2016-01-14 13:16:30 +01:00
dev_err ( dev , " only support pins-are-numbered format \n " ) ;
return - EINVAL ;
}
pctl = devm_kzalloc ( dev , sizeof ( * pctl ) , GFP_KERNEL ) ;
if ( ! pctl )
return - ENOMEM ;
platform_set_drvdata ( pdev , pctl ) ;
2019-04-24 10:08:44 +02:00
/* check for IRQ controller (may require deferred probe) */
2022-05-07 13:22:57 +03:00
pctl - > domain = stm32_pctrl_get_irq_domain ( pdev ) ;
2019-04-24 10:08:44 +02:00
if ( IS_ERR ( pctl - > domain ) )
return PTR_ERR ( pctl - > domain ) ;
2018-11-13 10:51:41 +01:00
/* hwspinlock is optional */
hwlock_id = of_hwspin_lock_get_id ( pdev - > dev . of_node , 0 ) ;
if ( hwlock_id < 0 ) {
if ( hwlock_id = = - EPROBE_DEFER )
return hwlock_id ;
} else {
pctl - > hwlock = hwspin_lock_request_specific ( hwlock_id ) ;
}
2019-05-10 09:43:03 +02:00
spin_lock_init ( & pctl - > irqmux_lock ) ;
2016-01-14 13:16:30 +01:00
pctl - > dev = dev ;
2022-05-07 13:22:57 +03:00
pctl - > match_data = match_data ;
2019-04-10 13:30:21 +02:00
2021-10-08 14:24:54 +02:00
/* get optional package information */
2022-05-07 13:22:57 +03:00
if ( ! device_property_read_u32 ( dev , " st,package " , & pctl - > pkg ) )
2021-10-08 14:24:54 +02:00
dev_dbg ( pctl - > dev , " package detected: %x \n " , pctl - > pkg ) ;
2019-04-10 13:30:21 +02:00
pctl - > pins = devm_kcalloc ( pctl - > dev , pctl - > match_data - > npins ,
sizeof ( * pctl - > pins ) , GFP_KERNEL ) ;
if ( ! pctl - > pins )
return - ENOMEM ;
ret = stm32_pctrl_create_pins_tab ( pctl , pctl - > pins ) ;
if ( ret )
return ret ;
2016-01-14 13:16:30 +01:00
ret = stm32_pctrl_build_state ( pdev ) ;
if ( ret ) {
dev_err ( dev , " build state failed: %d \n " , ret ) ;
return - EINVAL ;
}
2019-04-24 10:08:44 +02:00
if ( pctl - > domain ) {
2016-10-20 15:26:51 +02:00
ret = stm32_pctrl_dt_setup_irq ( pdev , pctl ) ;
if ( ret )
return ret ;
}
2016-09-09 16:42:01 +02:00
2019-04-10 13:30:21 +02:00
pins = devm_kcalloc ( & pdev - > dev , pctl - > npins , sizeof ( * pins ) ,
2016-01-14 13:16:30 +01:00
GFP_KERNEL ) ;
if ( ! pins )
return - ENOMEM ;
2019-04-10 13:30:21 +02:00
for ( i = 0 ; i < pctl - > npins ; i + + )
pins [ i ] = pctl - > pins [ i ] . pin ;
2016-01-14 13:16:30 +01:00
pctl - > pctl_desc . name = dev_name ( & pdev - > dev ) ;
pctl - > pctl_desc . owner = THIS_MODULE ;
pctl - > pctl_desc . pins = pins ;
2019-04-10 13:30:21 +02:00
pctl - > pctl_desc . npins = pctl - > npins ;
2019-06-01 19:53:31 +02:00
pctl - > pctl_desc . link_consumers = true ;
2016-01-14 13:16:30 +01:00
pctl - > pctl_desc . confops = & stm32_pconf_ops ;
pctl - > pctl_desc . pctlops = & stm32_pctrl_ops ;
pctl - > pctl_desc . pmxops = & stm32_pmx_ops ;
pctl - > dev = & pdev - > dev ;
2016-02-24 14:44:07 +05:30
pctl - > pctl_dev = devm_pinctrl_register ( & pdev - > dev , & pctl - > pctl_desc ,
pctl ) ;
2017-04-07 14:42:58 +02:00
2016-02-24 14:44:07 +05:30
if ( IS_ERR ( pctl - > pctl_dev ) ) {
2016-01-14 13:16:30 +01:00
dev_err ( & pdev - > dev , " Failed pinctrl registration \n " ) ;
2016-02-24 14:44:07 +05:30
return PTR_ERR ( pctl - > pctl_dev ) ;
2016-01-14 13:16:30 +01:00
}
2022-04-01 13:35:54 +03:00
banks = gpiochip_node_count ( dev ) ;
2017-04-07 14:42:58 +02:00
if ( ! banks ) {
dev_err ( dev , " at least one GPIO bank is required \n " ) ;
return - EINVAL ;
}
pctl - > banks = devm_kcalloc ( dev , banks , sizeof ( * pctl - > banks ) ,
GFP_KERNEL ) ;
if ( ! pctl - > banks )
return - ENOMEM ;
2020-06-15 14:54:06 +02:00
i = 0 ;
2022-04-01 13:35:55 +03:00
for_each_gpiochip_node ( dev , child ) {
2020-06-15 14:54:06 +02:00
struct stm32_gpio_bank * bank = & pctl - > banks [ i ] ;
2022-04-01 13:35:55 +03:00
struct device_node * np = to_of_node ( child ) ;
2020-06-15 14:54:06 +02:00
2022-04-01 13:35:55 +03:00
bank - > rstc = of_reset_control_get_exclusive ( np , NULL ) ;
if ( PTR_ERR ( bank - > rstc ) = = - EPROBE_DEFER ) {
fwnode_handle_put ( child ) ;
return - EPROBE_DEFER ;
2020-06-15 14:54:06 +02:00
}
2022-04-22 16:36:08 +02:00
2022-04-01 13:35:55 +03:00
bank - > clk = of_clk_get_by_name ( np , NULL ) ;
if ( IS_ERR ( bank - > clk ) ) {
if ( PTR_ERR ( bank - > clk ) ! = - EPROBE_DEFER )
dev_err ( dev , " failed to get clk (%ld) \n " , PTR_ERR ( bank - > clk ) ) ;
fwnode_handle_put ( child ) ;
return PTR_ERR ( bank - > clk ) ;
}
i + + ;
}
2017-04-07 14:42:58 +02:00
2022-04-01 13:35:55 +03:00
for_each_gpiochip_node ( dev , child ) {
ret = stm32_gpiolib_register_bank ( pctl , child ) ;
if ( ret ) {
fwnode_handle_put ( child ) ;
2022-05-05 16:24:06 +02:00
for ( i = 0 ; i < pctl - > nbanks ; i + + )
clk_disable_unprepare ( pctl - > banks [ i ] . clk ) ;
2022-04-01 13:35:55 +03:00
return ret ;
2017-04-07 14:42:58 +02:00
}
2022-04-01 13:35:55 +03:00
pctl - > nbanks + + ;
2017-04-07 14:42:58 +02:00
}
2016-01-14 13:16:30 +01:00
dev_info ( dev , " Pinctrl STM32 initialized \n " ) ;
return 0 ;
}
2019-05-10 09:42:29 +02:00
static int __maybe_unused stm32_pinctrl_restore_gpio_regs (
struct stm32_pinctrl * pctl , u32 pin )
{
const struct pin_desc * desc = pin_desc_get ( pctl - > pctl_dev , pin ) ;
u32 val , alt , mode , offset = stm32_gpio_pin ( pin ) ;
struct pinctrl_gpio_range * range ;
struct stm32_gpio_bank * bank ;
bool pin_is_irq ;
int ret ;
range = pinctrl_find_gpio_range_from_pin ( pctl - > pctl_dev , pin ) ;
if ( ! range )
return 0 ;
2022-05-02 17:31:14 +02:00
if ( ! gpiochip_line_is_valid ( range - > gc , offset ) )
return 0 ;
2019-05-10 09:42:29 +02:00
pin_is_irq = gpiochip_line_is_irq ( range - > gc , offset ) ;
if ( ! desc | | ( ! pin_is_irq & & ! desc - > gpio_owner ) )
return 0 ;
bank = gpiochip_get_data ( range - > gc ) ;
alt = bank - > pin_backup [ offset ] & STM32_GPIO_BKP_ALT_MASK ;
alt > > = STM32_GPIO_BKP_ALT_SHIFT ;
mode = bank - > pin_backup [ offset ] & STM32_GPIO_BKP_MODE_MASK ;
mode > > = STM32_GPIO_BKP_MODE_SHIFT ;
ret = stm32_pmx_set_mode ( bank , offset , mode , alt ) ;
if ( ret )
return ret ;
if ( mode = = 1 ) {
val = bank - > pin_backup [ offset ] & BIT ( STM32_GPIO_BKP_VAL ) ;
val = val > > STM32_GPIO_BKP_VAL ;
__stm32_gpio_set ( bank , offset , val ) ;
}
val = bank - > pin_backup [ offset ] & BIT ( STM32_GPIO_BKP_TYPE ) ;
val > > = STM32_GPIO_BKP_TYPE ;
ret = stm32_pconf_set_driving ( bank , offset , val ) ;
if ( ret )
return ret ;
val = bank - > pin_backup [ offset ] & STM32_GPIO_BKP_SPEED_MASK ;
val > > = STM32_GPIO_BKP_SPEED_SHIFT ;
ret = stm32_pconf_set_speed ( bank , offset , val ) ;
if ( ret )
return ret ;
val = bank - > pin_backup [ offset ] & STM32_GPIO_BKP_PUPD_MASK ;
val > > = STM32_GPIO_BKP_PUPD_SHIFT ;
ret = stm32_pconf_set_bias ( bank , offset , val ) ;
if ( ret )
return ret ;
if ( pin_is_irq )
regmap_field_write ( pctl - > irqmux [ offset ] , bank - > bank_ioport_nr ) ;
return 0 ;
}
2022-04-22 16:36:08 +02:00
int __maybe_unused stm32_pinctrl_suspend ( struct device * dev )
{
struct stm32_pinctrl * pctl = dev_get_drvdata ( dev ) ;
int i ;
for ( i = 0 ; i < pctl - > nbanks ; i + + )
clk_disable ( pctl - > banks [ i ] . clk ) ;
return 0 ;
}
2019-05-10 09:42:29 +02:00
int __maybe_unused stm32_pinctrl_resume ( struct device * dev )
{
struct stm32_pinctrl * pctl = dev_get_drvdata ( dev ) ;
struct stm32_pinctrl_group * g = pctl - > groups ;
int i ;
2022-04-22 16:36:08 +02:00
for ( i = 0 ; i < pctl - > nbanks ; i + + )
clk_enable ( pctl - > banks [ i ] . clk ) ;
2021-10-08 14:25:17 +02:00
for ( i = 0 ; i < pctl - > ngroups ; i + + , g + + )
stm32_pinctrl_restore_gpio_regs ( pctl , g - > pin ) ;
2019-05-10 09:42:29 +02:00
return 0 ;
}