// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2015 Maxime Coquelin * Copyright (C) 2017 STMicroelectronics * Copyright (C) 2019 Ahmad Fatoum, Pengutronix */ #ifndef __STM32_GPIO_H__ #define __STM32_GPIO_H__ #include <io.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 #define STM32_PIN_GPIO 0 #define STM32_PIN_AF(x) ((x) + 1) #define STM32_PIN_ANALOG (STM32_PIN_AF(15) + 1) #define STM32_GPIO_PINS_PER_BANK 16 enum stm32_pin_bias { STM32_PIN_NO_BIAS, STM32_PIN_PULL_UP, STM32_PIN_PULL_DOWN }; enum stm32_pin_out_type { STM32_PIN_OUT_PUSHPULL, STM32_PIN_OUT_OPENDRAIN }; static inline void __stm32_pmx_set_speed(void __iomem *base, unsigned offset, u32 speed) { u32 val = readl(base + STM32_GPIO_SPEEDR); val &= ~GENMASK(offset * 2 + 1, offset * 2); val |= speed << (offset * 2); writel(val, base + STM32_GPIO_SPEEDR); } static inline void __stm32_pmx_set_bias(void __iomem *base, unsigned offset, enum stm32_pin_bias bias) { u32 val = readl(base + STM32_GPIO_PUPDR); val &= ~GENMASK(offset * 2 + 1, offset * 2); val |= bias << (offset * 2); writel(val, base + STM32_GPIO_PUPDR); } static inline void __stm32_pmx_set_mode(void __iomem *base, int pin, u32 mode, u32 alt) { u32 val; int alt_shift = (pin % 8) * 4; int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; val = readl(base + alt_offset); val &= ~GENMASK(alt_shift + 3, alt_shift); val |= (alt << alt_shift); writel(val, base + alt_offset); val = readl(base + STM32_GPIO_MODER); val &= ~GENMASK(pin * 2 + 1, pin * 2); val |= mode << (pin * 2); writel(val, base + STM32_GPIO_MODER); } static inline void __stm32_pmx_get_mode(void __iomem *base, int pin, u32 *mode, u32 *alt) { u32 val; int alt_shift = (pin % 8) * 4; int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; val = readl(base + alt_offset); val &= GENMASK(alt_shift + 3, alt_shift); *alt = val >> alt_shift; val = readl(base + STM32_GPIO_MODER); val &= GENMASK(pin * 2 + 1, pin * 2); *mode = val >> (pin * 2); } static inline int __stm32_pmx_gpio_get(void __iomem *base, unsigned offset) { return !!(readl(base + STM32_GPIO_IDR) & BIT(offset)); } static inline void __stm32_pmx_gpio_set(void __iomem *base, unsigned offset, unsigned value) { if (!value) offset += STM32_GPIO_PINS_PER_BANK; writel(BIT(offset), base + STM32_GPIO_BSRR); } static inline void __stm32_pmx_gpio_input(void __iomem *base, unsigned offset) { __stm32_pmx_set_mode(base, offset, 0, 0); } static inline void __stm32_pmx_gpio_output(void __iomem *base, unsigned offset, unsigned value) { __stm32_pmx_gpio_set(base, offset, value); __stm32_pmx_set_mode(base, offset, 1, 0); } static inline void __stm32_pmx_set_output_type(void __iomem *base, unsigned offset, enum stm32_pin_out_type type) { u32 val = readl(base + STM32_GPIO_TYPER); val &= ~BIT(offset); val |= type << offset; writel(val, base + STM32_GPIO_TYPER); } #endif /* __STM32_GPIO_H__ */