blob: bbee1387cb379560f6c40bba8c0b2acccfbf1943 [file] [log] [blame]
Yann Gautierd0ca7f42018-07-13 21:33:09 +02001/*
Yann Gautier1a3fc9f2019-01-17 14:35:22 +01002 * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
Yann Gautierd0ca7f42018-07-13 21:33:09 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautierd0ca7f42018-07-13 21:33:09 +02007#include <stdbool.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
9#include <common/bl_common.h>
10#include <common/debug.h>
11#include <drivers/st/stm32_gpio.h>
12#include <lib/mmio.h>
Yann Gautierd0ca7f42018-07-13 21:33:09 +020013
14static bool check_gpio(uint32_t bank, uint32_t pin)
15{
16 if (pin > GPIO_PIN_MAX) {
17 ERROR("%s: wrong pin number (%d)\n", __func__, pin);
18 return false;
19 }
20
21 if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) {
22 ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank);
23 return false;
24 }
25
26 return true;
27}
28
29void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
30 uint32_t pull, uint32_t alternate)
31{
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010032 uintptr_t base;
Yann Gautierd0ca7f42018-07-13 21:33:09 +020033
34 if (!check_gpio(bank, pin)) {
35 return;
36 }
37
38 if (bank == GPIO_BANK_Z) {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010039 base = STM32_GPIOZ_BANK;
Yann Gautierd0ca7f42018-07-13 21:33:09 +020040 } else {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010041 base = STM32_GPIOA_BANK +
Yann Gautierd0ca7f42018-07-13 21:33:09 +020042 (bank * STM32_GPIO_BANK_OFFSET);
43 }
44
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010045 mmio_clrbits_32(base + GPIO_MODE_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020046 ((uint32_t)GPIO_MODE_MASK << (pin << 1)));
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010047 mmio_setbits_32(base + GPIO_MODE_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020048 (mode & ~GPIO_OPEN_DRAIN) << (pin << 1));
49
50 if ((mode & GPIO_OPEN_DRAIN) != 0U) {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010051 mmio_setbits_32(base + GPIO_TYPE_OFFSET, BIT(pin));
52 } else {
53 mmio_clrbits_32(base + GPIO_TYPE_OFFSET, BIT(pin));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020054 }
55
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010056 mmio_clrbits_32(base + GPIO_SPEED_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020057 ((uint32_t)GPIO_SPEED_MASK << (pin << 1)));
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010058 mmio_setbits_32(base + GPIO_SPEED_OFFSET, speed << (pin << 1));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020059
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010060 mmio_clrbits_32(base + GPIO_PUPD_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020061 ((uint32_t)GPIO_PULL_MASK << (pin << 1)));
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010062 mmio_setbits_32(base + GPIO_PUPD_OFFSET, pull << (pin << 1));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020063
64 if (pin < GPIO_ALT_LOWER_LIMIT) {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010065 mmio_clrbits_32(base + GPIO_AFRL_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020066 ((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2)));
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010067 mmio_setbits_32(base + GPIO_AFRL_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020068 alternate << (pin << 2));
69 } else {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010070 mmio_clrbits_32(base + GPIO_AFRH_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020071 ((uint32_t)GPIO_ALTERNATE_MASK <<
72 ((pin - GPIO_ALT_LOWER_LIMIT) << 2)));
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010073 mmio_setbits_32(base + GPIO_AFRH_OFFSET,
Yann Gautierd0ca7f42018-07-13 21:33:09 +020074 alternate << ((pin - GPIO_ALT_LOWER_LIMIT) <<
75 2));
76 }
77
78 VERBOSE("GPIO %u mode set to 0x%x\n", bank,
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010079 mmio_read_32(base + GPIO_MODE_OFFSET));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020080 VERBOSE("GPIO %u speed set to 0x%x\n", bank,
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010081 mmio_read_32(base + GPIO_SPEED_OFFSET));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020082 VERBOSE("GPIO %u mode pull to 0x%x\n", bank,
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010083 mmio_read_32(base + GPIO_PUPD_OFFSET));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020084 VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank,
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010085 mmio_read_32(base + GPIO_AFRL_OFFSET));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020086 VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank,
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010087 mmio_read_32(base + GPIO_AFRH_OFFSET));
Yann Gautierd0ca7f42018-07-13 21:33:09 +020088}