summaryrefslogtreecommitdiffstats
path: root/include/soc/stm32/gpio.h
blob: 448fb19e2ef86eceba764eefc1299834c107bbad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 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_PINMODE_GPIO	0
#define STM32_PINMODE_AF	2
#define STM32_PINMODE_ANALOG	3

#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__ */