embox

Форк
0
306 строк · 7.4 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @author  Andrew Bursian
6
 * @date    21.02.2023
7
 */
8

9
#include <stdint.h>
10
#include <hal/reg.h>
11
#include <kernel/irq.h>
12

13
#include <drivers/gpio/gpio_driver.h>
14

15
#include <drivers/clk/k1921vg015_rcu.h>
16

17
#include <config/board_config.h>
18

19
#include <framework/mod/options.h>
20

21
#define GPIO_CHIP_ID       OPTION_GET(NUMBER,gpio_chip_id)
22
#define GPIO_PINS_NUMBER   16
23

24
#define GPIOA     ((volatile struct gpio_reg *)CONF_GPIO_PORT_A_REGION_BASE)
25
#define GPIOB     ((volatile struct gpio_reg *)CONF_GPIO_PORT_B_REGION_BASE)
26
#if defined(CONF_GPIO_PORT_C_REGION_BASE)
27
# define GPIOC     ((volatile struct gpio_reg *)CONF_GPIO_PORT_C_REGION_BASE)
28
#endif /* defined(CONF_GPIO_PORT_C_REGION_BASE) */
29

30
struct gpio_reg {
31
    uint32_t 	GPIO_DATA_reg;        /* 0x00 */
32
    uint32_t 	GPIO_DATAOUT_reg;     /* 0x04 */
33
    uint32_t 	GPIO_DATAOUTSET_reg;  /* 0x08 */
34
    uint32_t 	GPIO_DATAOUTCLR_reg;  /* 0x0C */
35
    uint32_t 	GPIO_DATAOUTTGL_reg;  /* 0x10 */
36
    uint32_t 	GPIO_DENSET_reg;      /* 0x14 */
37
    uint32_t 	GPIO_DENCLR_reg;      /* 0x18 */
38
    uint32_t 	GPIO_INMODE_reg;      /* 0x1C */
39
    uint32_t 	GPIO_PULLMODE_reg;    /* 0x20 */
40
    uint32_t 	GPIO_OUTMODE_reg;     /* 0x24 */
41
    uint32_t 	GPIO_DRIVEMODE_reg;   /* 0x28 */
42
    uint32_t 	GPIO_OUTENSET_reg;    /* 0x2C */
43
    uint32_t 	GPIO_OUTENCLR_reg;    /* 0x30 */
44
    uint32_t 	GPIO_ALTFUNCSET_reg;  /* 0x34 */
45
    uint32_t 	GPIO_ALTFUNCCLR_reg;  /* 0x38 */
46
    uint32_t 	GPIO_ALTFUNCNUM_reg;  /* 0x3C */
47
    uint32_t reserved2[1];
48
    uint32_t 	GPIO_SYNCSET_reg;	  /* 0x44 */
49
    uint32_t 	GPIO_SYNCCLR_reg;     /* 0x48 */
50
    uint32_t 	GPIO_QUALSET_reg;     /* 0x4C */
51
    uint32_t 	GPIO_QUALCLR_reg;     /* 0x50 */
52
    uint32_t 	GPIO_QUALMODESET_reg; /* 0x54 */
53
    uint32_t 	GPIO_QUALMODECLR_reg; /* 0x58 */
54
    uint32_t 	GPIO_QUALSAMPLE_reg;  /* 0x5C */
55
    uint32_t 	GPIO_INTENSET_reg;    /* 0x60 */
56
    uint32_t 	GPIO_INTENCLR_reg;    /* 0x64 */
57
    uint32_t 	GPIO_INTTYPESET_reg;  /* 0x68 */
58
    uint32_t 	GPIO_INTTYPECLR_reg;  /* 0x6C */
59
    uint32_t 	GPIO_INTPOLSET_reg;   /* 0x70 */
60
    uint32_t 	GPIO_INTPOLCLR_reg;   /* 0x74 */
61
    uint32_t 	GPIO_INTEDGESET_reg;  /* 0x78 */
62
    uint32_t 	GPIO_INTEDGECLR_reg;  /* 0x7C */
63
    uint32_t 	GPIO_INTSTATUS_reg;   /* 0x80 */
64
    uint32_t 	GPIO_DMAREQSET_reg;   /* 0x84 */
65
    uint32_t 	GPIO_DMAREQCLR_reg;   /* 0x88 */
66
    uint32_t 	GPIO_ADCSOCSET_reg;   /* 0x8C */
67
    uint32_t 	GPIO_ADCSOCCLR_reg;   /* 0x90 */
68
    uint32_t reserved3[2];
69
    uint32_t 	GPIO_LOCKKEY_reg;     /* 0x9C */
70
    uint32_t 	GPIO_LOCKSET_reg;     /* 0xA0 */
71
    uint32_t 	GPIO_LOCKCLR_reg;     /* 0xA4 */
72
};
73

74
static struct gpio_chip niiet_gpio_chip;
75

76
static inline void
77
niiet_gpio_irq_conf_type(volatile struct gpio_reg *gpio_reg, uint32_t mask, int type) {
78
	if (1 == type) {
79
		gpio_reg->GPIO_INTTYPESET_reg = mask;
80
	} else {
81
		gpio_reg->GPIO_INTTYPECLR_reg = mask;
82
	}
83
}
84

85
static inline void
86
niiet_gpio_irq_conf_pol(volatile struct gpio_reg *gpio_reg, uint32_t mask, int pol) {
87
	if (1 == pol) {
88
		gpio_reg->GPIO_INTPOLSET_reg = mask;
89
	} else {
90
		gpio_reg->GPIO_INTPOLCLR_reg = mask;
91
	}
92
}
93

94
static inline void
95
niiet_gpio_irq_conf_edge(volatile struct gpio_reg *gpio_reg, uint32_t mask, int edge) {
96
	if (1 == edge) {
97
		gpio_reg->GPIO_INTEDGESET_reg = mask;
98
	} else {
99
		gpio_reg->GPIO_INTEDGECLR_reg = mask;
100
	}
101
}
102

103
static inline void 
104
niiet_gpio_irq_en(volatile struct gpio_reg *gpio_reg, uint32_t mask) {
105
	gpio_reg->GPIO_INTENSET_reg = mask;
106
}
107

108
static inline void 
109
niiet_gpio_irq_dis(volatile struct gpio_reg *gpio_reg, uint32_t mask) {
110
	gpio_reg->GPIO_INTENCLR_reg = mask;
111
}
112

113
static inline uint32_t 
114
niiet_gpio_irq_get_status(volatile struct gpio_reg *gpio_reg) {
115
	return gpio_reg->GPIO_INTSTATUS_reg;
116
}
117

118
static inline void 
119
niiet_gpio_irq_clear_status(volatile struct gpio_reg *gpio_reg, uint32_t mask) {
120
	gpio_reg->GPIO_INTSTATUS_reg = mask;
121
}
122

123
static inline volatile struct gpio_reg *niiet_gpio_get_gpio_port(unsigned char port) {
124
		switch (port) {
125
		case 0:
126
			return GPIOA;
127
		case 1:
128
			return GPIOB;
129
#if defined (CONF_GPIO_PORT_C_REGION_BASE)
130
		case 2:
131
			return GPIOC;
132
		break;
133
#endif /* defined (PORTC) */
134
		default:
135
			return NULL;
136
	}
137

138
	return 0;
139
}
140

141
irq_return_t niiet_gpio_irq_handler(unsigned int irq_nr, void *gpio) {
142
	uint32_t mask = 0;
143
	uint8_t port_num = 0;
144
	volatile struct gpio_reg *gpio_reg = gpio;
145
	
146
	mask = niiet_gpio_irq_get_status(gpio_reg);
147

148
	niiet_gpio_irq_clear_status(gpio_reg, mask);
149

150
	gpio_handle_irq(&niiet_gpio_chip, port_num, mask);
151

152
	return IRQ_HANDLED;
153
}
154

155
static int niiet_gpio_setup_irq(int port, uint32_t mask, int mode) {
156
	int res;
157
	volatile struct gpio_reg *gpio_reg;
158
	int type;
159
	int edge;
160
	int pol;
161

162
	gpio_reg = niiet_gpio_get_gpio_port(port);
163
	if (gpio_reg == NULL) {
164
		return -1;
165
	}
166

167
	res = irq_attach(0, niiet_gpio_irq_handler, 0, (void*)gpio_reg, "GPIO Irq");
168
	if (res < 0) {
169
		return res;
170
	}
171

172
	if ( (mode & GPIO_MODE_INT_MODE_LEVEL0)
173
			|| (mode & GPIO_MODE_INT_MODE_LEVEL1) ) {
174
		type = 0;
175
	} else {
176
		type = 1;
177
	}
178
	
179
	if ((mode & GPIO_MODE_INT_MODE_RISING)
180
			&& (mode & GPIO_MODE_INT_MODE_FALLING)) {
181
		edge = 1;
182
	} else {
183
		edge = 0;
184
	}
185

186
	if ((mode & GPIO_MODE_INT_MODE_RISING)
187
			|| (mode & GPIO_MODE_INT_MODE_LEVEL1)) {
188
		pol = 1;
189
	} else {
190
		pol = 0;
191
	}
192

193
	niiet_gpio_irq_conf_pol(gpio_reg, mask, pol);
194
	niiet_gpio_irq_conf_edge(gpio_reg, mask, edge);
195
	niiet_gpio_irq_conf_type(gpio_reg, mask, type);
196

197
	if (mode & GPIO_MODE_IN_INT_EN) {
198
		niiet_gpio_irq_en(gpio_reg, mask);
199
	}
200

201
	return res;
202
}
203

204
static int niiet_gpio_setup_mode(unsigned char port, gpio_mask_t pins, int mode) {
205
	volatile struct gpio_reg *gpio_reg;
206
	char *clk_name;
207

208
	gpio_reg = niiet_gpio_get_gpio_port(port);
209
	if (gpio_reg == NULL) {
210
		return -1;
211
	}
212

213
	switch(port) {
214
		case 0:
215
		clk_name = CONF_GPIO_PORT_A_CLK_ENABLE();
216
		break;
217
		case 1:
218
		clk_name = CONF_GPIO_PORT_B_CLK_ENABLE();
219
		break;
220
		case 2:
221
#if defined CONF_GPIO_PORT_C_CLK_ENABLE
222
		clk_name = CONF_GPIO_PORT_C_CLK_ENABLE();
223
#endif /* defined CONF_GPIO_PORT_C_CLK_ENABLE */
224
		break;
225
		default:
226
		return -1;
227
	}
228

229
	/* Enable port */
230
	clk_enable(clk_name);
231

232
	gpio_reg->GPIO_DENSET_reg |= pins;
233

234
	if (mode & GPIO_MODE_IN) {
235
		gpio_reg->GPIO_OUTENCLR_reg |= pins;
236
	}
237

238
	if (mode & GPIO_MODE_IN_PULL_UP) {
239
		gpio_reg->GPIO_PULLMODE_reg |= pins;
240
	}
241

242
	if (mode & GPIO_MODE_OUT) {
243
		gpio_reg->GPIO_OUTENSET_reg |= pins;
244
	}
245

246
	if (mode & GPIO_MODE_INT_SECTION) {
247
		niiet_gpio_setup_irq(port, pins, mode);
248
	}
249

250
	if (mode & GPIO_MODE_OUT_ALTERNATE) {
251
		/* Enable ALTFUNC */
252
		gpio_reg->GPIO_ALTFUNCSET_reg |= pins;
253

254
		for (int i = 0; i < GPIO_PINS_NUMBER; i++) {			
255
			if (pins & (1 << i)) {
256
				uint32_t alt = GPIO_GET_ALTERNATE(mode);
257

258
				gpio_reg->GPIO_ALTFUNCNUM_reg &= ~(0x3 << i * 2);
259
				gpio_reg->GPIO_ALTFUNCNUM_reg |= alt << i * 2;
260
			}
261
		}
262
	}
263

264
	return 0;
265
}
266

267
static void niiet_gpio_set(unsigned char port, gpio_mask_t pins, char level) {
268
	volatile struct gpio_reg *gpio_reg;
269

270
	gpio_reg = niiet_gpio_get_gpio_port(port);
271
	if (gpio_reg == NULL) {
272
		return;
273
	}
274

275
	if (level) {
276
		gpio_reg->GPIO_DATAOUTSET_reg |= pins;
277
	} else {		
278
		gpio_reg->GPIO_DATAOUTCLR_reg |= pins;
279
	}
280
}
281

282
static gpio_mask_t niiet_gpio_get(unsigned char port, gpio_mask_t pins) {
283
	volatile struct gpio_reg *gpio_reg;
284

285
	gpio_reg = niiet_gpio_get_gpio_port(port);
286
	if (gpio_reg == NULL) {
287
		return -1;
288
	}
289

290
	return gpio_reg->GPIO_DATA_reg & pins;
291
}
292

293
static struct gpio_chip niiet_gpio_chip = {
294
	.setup_mode = niiet_gpio_setup_mode,
295
	.get = niiet_gpio_get,
296
	.set = niiet_gpio_set,
297
#if defined (CONF_GPIO_PORT_C_REGION_BASE)
298
	.nports = 3
299
#else
300
	.nports = 2
301
#endif
302
};
303

304
GPIO_CHIP_DEF(&niiet_gpio_chip);
305

306
STATIC_IRQ_ATTACH(GPIO_IRQ, gpio_irq_handler, NULL);
307

308

309

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.