Skip to content
Permalink
Browse files

gpio: rv32m1: enable GPIO port clocks

Enable the clock for GPIO ports on the RV32M1 SoC before attempting to
access the port controller registers.

Fixes: #15339

Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
  • Loading branch information...
henrikbrixandersen authored and galak committed Apr 8, 2019
1 parent 3e798df commit 36ff55cba08740dd54d4c8393d0a027fc2c1ca6b
Showing with 77 additions and 5 deletions.
  1. +71 −5 drivers/gpio/gpio_rv32m1.c
  2. +6 −0 dts/bindings/gpio/openisa,rv32m1-gpio.yaml
@@ -12,13 +12,17 @@
#include <soc.h>
#include <fsl_common.h>
#include <fsl_port.h>
#include <clock_control.h>

#include "gpio_utils.h"

struct gpio_rv32m1_config {
GPIO_Type *gpio_base;
PORT_Type *port_base;
unsigned int flags;
char *clock_controller;
clock_control_subsys_t clock_subsys;
int (*irq_config_func)(struct device *dev);
};

struct gpio_rv32m1_data {
@@ -228,6 +232,27 @@ static void gpio_rv32m1_port_isr(void *arg)
config->port_base->ISFR = 0xFFFFFFFF;
}

static int gpio_rv32m1_init(struct device *dev)
{
const struct gpio_rv32m1_config *config = dev->config->config_info;
struct device *clk;
int ret;

if (config->clock_controller) {
clk = device_get_binding(config->clock_controller);
if (!clk) {
return -ENODEV;
}

ret = clock_control_on(clk, config->clock_subsys);

if (ret < 0) {
return ret;
}
}

return config->irq_config_func(dev);
}

static const struct gpio_driver_api gpio_rv32m1_driver_api = {
.config = gpio_rv32m1_configure,
@@ -248,13 +273,21 @@ static const struct gpio_rv32m1_config gpio_rv32m1_porta_config = {
.flags = GPIO_INT,
#else
.flags = 0,
#endif
.irq_config_func = gpio_rv32m1_porta_init,
#ifdef DT_OPENISA_RV32M1_GPIO_GPIO_A_CLOCK_CONTROLLER
.clock_controller = DT_OPENISA_RV32M1_GPIO_GPIO_A_CLOCK_CONTROLLER,
.clock_subsys = (clock_control_subsys_t)
DT_OPENISA_RV32M1_GPIO_GPIO_A_CLOCK_NAME,
#else
.clock_controller = NULL,
#endif
};

static struct gpio_rv32m1_data gpio_rv32m1_porta_data;

DEVICE_AND_API_INIT(gpio_rv32m1_porta, DT_OPENISA_RV32M1_GPIO_GPIO_A_LABEL,
gpio_rv32m1_porta_init,
gpio_rv32m1_init,
&gpio_rv32m1_porta_data, &gpio_rv32m1_porta_config,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_rv32m1_driver_api);
@@ -285,13 +318,21 @@ static const struct gpio_rv32m1_config gpio_rv32m1_portb_config = {
.flags = GPIO_INT,
#else
.flags = 0,
#endif
.irq_config_func = gpio_rv32m1_portb_init,
#ifdef DT_OPENISA_RV32M1_GPIO_GPIO_B_CLOCK_CONTROLLER
.clock_controller = DT_OPENISA_RV32M1_GPIO_GPIO_B_CLOCK_CONTROLLER,
.clock_subsys = (clock_control_subsys_t)
DT_OPENISA_RV32M1_GPIO_GPIO_B_CLOCK_NAME,
#else
.clock_controller = NULL,
#endif
};

static struct gpio_rv32m1_data gpio_rv32m1_portb_data;

DEVICE_AND_API_INIT(gpio_rv32m1_portb, DT_OPENISA_RV32M1_GPIO_GPIO_B_LABEL,
gpio_rv32m1_portb_init,
gpio_rv32m1_init,
&gpio_rv32m1_portb_data, &gpio_rv32m1_portb_config,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_rv32m1_driver_api);
@@ -323,12 +364,21 @@ static const struct gpio_rv32m1_config gpio_rv32m1_portc_config = {
#else
.flags = 0,
#endif
.irq_config_func = gpio_rv32m1_portc_init,
#ifdef DT_OPENISA_RV32M1_GPIO_GPIO_C_CLOCK_CONTROLLER
.clock_controller = DT_OPENISA_RV32M1_GPIO_GPIO_C_CLOCK_CONTROLLER,
.clock_subsys = (clock_control_subsys_t)
DT_OPENISA_RV32M1_GPIO_GPIO_C_CLOCK_NAME,
#else
.clock_controller = NULL,
#endif

};

static struct gpio_rv32m1_data gpio_rv32m1_portc_data;

DEVICE_AND_API_INIT(gpio_rv32m1_portc, DT_OPENISA_RV32M1_GPIO_GPIO_C_LABEL,
gpio_rv32m1_portc_init,
gpio_rv32m1_init,
&gpio_rv32m1_portc_data, &gpio_rv32m1_portc_config,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_rv32m1_driver_api);
@@ -359,13 +409,21 @@ static const struct gpio_rv32m1_config gpio_rv32m1_portd_config = {
.flags = GPIO_INT,
#else
.flags = 0,
#endif
.irq_config_func = gpio_rv32m1_portd_init,
#ifdef DT_OPENISA_RV32M1_GPIO_GPIO_D_CLOCK_CONTROLLER
.clock_controller = DT_OPENISA_RV32M1_GPIO_GPIO_D_CLOCK_CONTROLLER,
.clock_subsys = (clock_control_subsys_t)
DT_OPENISA_RV32M1_GPIO_GPIO_D_CLOCK_NAME,
#else
.clock_controller = NULL,
#endif
};

static struct gpio_rv32m1_data gpio_rv32m1_portd_data;

DEVICE_AND_API_INIT(gpio_rv32m1_portd, DT_OPENISA_RV32M1_GPIO_GPIO_D_LABEL,
gpio_rv32m1_portd_init,
gpio_rv32m1_init,
&gpio_rv32m1_portd_data, &gpio_rv32m1_portd_config,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_rv32m1_driver_api);
@@ -396,13 +454,21 @@ static const struct gpio_rv32m1_config gpio_rv32m1_porte_config = {
.flags = GPIO_INT,
#else
.flags = 0,
#endif
.irq_config_func = gpio_rv32m1_porte_init,
#ifdef DT_OPENISA_RV32M1_GPIO_GPIO_E_CLOCK_CONTROLLER
.clock_controller = DT_OPENISA_RV32M1_GPIO_GPIO_E_CLOCK_CONTROLLER,
.clock_subsys = (clock_control_subsys_t)
DT_OPENISA_RV32M1_GPIO_GPIO_E_CLOCK_NAME,
#else
.clock_controller = NULL,
#endif
};

static struct gpio_rv32m1_data gpio_rv32m1_porte_data;

DEVICE_AND_API_INIT(gpio_rv32m1_porte, DT_OPENISA_RV32M1_GPIO_GPIO_E_LABEL,
gpio_rv32m1_porte_init,
gpio_rv32m1_init,
&gpio_rv32m1_porte_data, &gpio_rv32m1_porte_config,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_rv32m1_driver_api);
@@ -31,6 +31,12 @@ properties:
description: Human readable string describing the device (used by Zephyr for API name)
generation: define

clocks:
type: array
category: optional
description: Clock gate control information
generation: define

"#cells":
- pin
- flags

0 comments on commit 36ff55c

Please sign in to comment.
You can’t perform that action at this time.