Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F135946773
D36262.id109550.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D36262.id109550.diff
View Options
diff --git a/sys/arm64/rockchip/rk_gpio.c b/sys/arm64/rockchip/rk_gpio.c
--- a/sys/arm64/rockchip/rk_gpio.c
+++ b/sys/arm64/rockchip/rk_gpio.c
@@ -2,6 +2,7 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ * Copyright (c) 2021 Soren Schmidt <sos@deepcore.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -53,20 +54,21 @@
#include "fdt_pinctrl_if.h"
-#define RK_GPIO_SWPORTA_DR 0x00 /* Data register */
-#define RK_GPIO_SWPORTA_DDR 0x04 /* Data direction register */
-
-#define RK_GPIO_INTEN 0x30 /* Interrupt enable register */
-#define RK_GPIO_INTMASK 0x34 /* Interrupt mask register */
-#define RK_GPIO_INTTYPE_LEVEL 0x38 /* Interrupt level register */
-#define RK_GPIO_INT_POLARITY 0x3C /* Interrupt polarity register */
-#define RK_GPIO_INT_STATUS 0x40 /* Interrupt status register */
-#define RK_GPIO_INT_RAWSTATUS 0x44 /* Raw Interrupt status register */
-
-#define RK_GPIO_DEBOUNCE 0x48 /* Debounce enable register */
-
-#define RK_GPIO_PORTA_EOI 0x4C /* Clear interrupt register */
-#define RK_GPIO_EXT_PORTA 0x50 /* External port register */
+enum gpio_regs {
+ RK_GPIO_SWPORTA_DR = 1, /* Data register */
+ RK_GPIO_SWPORTA_DDR, /* Data direction register */
+ RK_GPIO_INTEN, /* Interrupt enable register */
+ RK_GPIO_INTMASK, /* Interrupt mask register */
+ RK_GPIO_INTTYPE_LEVEL, /* Interrupt level register */
+ RK_GPIO_INTTYPE_BOTH, /* Both rise and falling edge */
+ RK_GPIO_INT_POLARITY, /* Interrupt polarity register */
+ RK_GPIO_INT_STATUS, /* Interrupt status register */
+ RK_GPIO_INT_RAWSTATUS, /* Raw Interrupt status register */
+ RK_GPIO_DEBOUNCE, /* Debounce enable register */
+ RK_GPIO_PORTA_EOI, /* Clear interrupt register */
+ RK_GPIO_EXT_PORTA, /* External port register */
+ RK_GPIO_REGNUM
+};
#define RK_GPIO_LS_SYNC 0x60 /* Level sensitive syncronization enable register */
@@ -90,9 +92,9 @@
bus_space_handle_t sc_bsh;
clk_t clk;
device_t pinctrl;
- uint32_t swporta;
- uint32_t swporta_ddr;
+ uint32_t version;
struct pin_cached pin_cached[RK_GPIO_MAX_PINS];
+ uint8_t regs[RK_GPIO_REGNUM];
};
static struct ofw_compat_data compat_data[] = {
@@ -106,6 +108,10 @@
{ -1, 0 }
};
+#define RK_GPIO_VERSION 0x78
+#define RK_GPIO_TYPE_V1 0x00000000
+#define RK_GPIO_TYPE_V2 0x01000c2b
+
static int rk_gpio_detach(device_t dev);
#define RK_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->sc_mtx)
@@ -117,6 +123,80 @@
#define RK_GPIO_READ(_sc, _off) \
bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
+static int
+rk_gpio_read_bit(struct rk_gpio_softc *sc, int reg, int bit)
+{
+ int offset = sc->regs[reg];
+ uint32_t value;
+
+ RK_GPIO_LOCK(sc);
+ if (sc->version == RK_GPIO_TYPE_V1) {
+ value = RK_GPIO_READ(sc, offset);
+ value >>= bit;
+ } else {
+ value = RK_GPIO_READ(sc, bit > 15 ? offset + 4 : offset);
+ value >>= (bit % 16);
+ }
+ RK_GPIO_UNLOCK(sc);
+ return (value & 1);
+}
+
+static void
+rk_gpio_write_bit(struct rk_gpio_softc *sc, int reg, int bit, int data)
+{
+ int offset = sc->regs[reg];
+ uint32_t value;
+
+ RK_GPIO_LOCK(sc);
+ if (sc->version == RK_GPIO_TYPE_V1) {
+ value = RK_GPIO_READ(sc, offset);
+ if (data)
+ value |= (1 << bit);
+ else
+ value &= ~(1 << bit);
+ RK_GPIO_WRITE(sc, offset, value);
+ } else {
+ if (data)
+ value = (1 << (bit % 16));
+ else
+ value = 0;
+ value |= (1 << ((bit % 16) + 16));
+ RK_GPIO_WRITE(sc, bit > 15 ? offset + 4 : offset, value);
+ }
+ RK_GPIO_UNLOCK(sc);
+}
+
+static uint32_t
+rk_gpio_read_4(struct rk_gpio_softc *sc, int reg)
+{
+ int offset = sc->regs[reg];
+ uint32_t value;
+
+ RK_GPIO_LOCK(sc);
+ if (sc->version == RK_GPIO_TYPE_V1)
+ value = RK_GPIO_READ(sc, offset);
+ else
+ value = (RK_GPIO_READ(sc, offset) & 0xffff) |
+ (RK_GPIO_READ(sc, offset + 4) << 16);
+ RK_GPIO_UNLOCK(sc);
+ return (value);
+}
+
+static void
+rk_gpio_write_4(struct rk_gpio_softc *sc, int reg, uint32_t value)
+{
+ int offset = sc->regs[reg];
+
+ RK_GPIO_LOCK(sc);
+ if (sc->version == RK_GPIO_TYPE_V1)
+ RK_GPIO_WRITE(sc, offset, value);
+ else {
+ RK_GPIO_WRITE(sc, offset, (value & 0xffff) | 0xffff0000);
+ RK_GPIO_WRITE(sc, offset + 4, (value >> 16) | 0xffff0000);
+ }
+ RK_GPIO_UNLOCK(sc);
+}
+
static int
rk_gpio_probe(device_t dev)
{
@@ -171,6 +251,40 @@
return (ENXIO);
}
+ switch ((sc->version = rk_gpio_read_4(sc, RK_GPIO_VERSION))) {
+ case RK_GPIO_TYPE_V1:
+ sc->regs[RK_GPIO_SWPORTA_DR] = 0x00;
+ sc->regs[RK_GPIO_SWPORTA_DDR] = 0x04;
+ sc->regs[RK_GPIO_INTEN] = 0x30;
+ sc->regs[RK_GPIO_INTMASK] = 0x34;
+ sc->regs[RK_GPIO_INTTYPE_LEVEL] = 0x38;
+ sc->regs[RK_GPIO_INT_POLARITY] = 0x3c;
+ sc->regs[RK_GPIO_INT_STATUS] = 0x40;
+ sc->regs[RK_GPIO_INT_RAWSTATUS] = 0x44;
+ sc->regs[RK_GPIO_DEBOUNCE] = 0x48;
+ sc->regs[RK_GPIO_PORTA_EOI] = 0x4c;
+ sc->regs[RK_GPIO_EXT_PORTA] = 0x50;
+ break;
+ case RK_GPIO_TYPE_V2:
+ sc->regs[RK_GPIO_SWPORTA_DR] = 0x00;
+ sc->regs[RK_GPIO_SWPORTA_DDR] = 0x08;
+ sc->regs[RK_GPIO_INTEN] = 0x10;
+ sc->regs[RK_GPIO_INTMASK] = 0x18;
+ sc->regs[RK_GPIO_INTTYPE_LEVEL] = 0x20;
+ sc->regs[RK_GPIO_INTTYPE_BOTH] = 0x30;
+ sc->regs[RK_GPIO_INT_POLARITY] = 0x28;
+ sc->regs[RK_GPIO_INT_STATUS] = 0x50;
+ sc->regs[RK_GPIO_INT_RAWSTATUS] = 0x58;
+ sc->regs[RK_GPIO_DEBOUNCE] = 0x38;
+ sc->regs[RK_GPIO_PORTA_EOI] = 0x60;
+ sc->regs[RK_GPIO_EXT_PORTA] = 0x70;
+ break;
+ default:
+ device_printf(dev, "Unknown gpio version %08x\n", sc->version);
+ rk_gpio_detach(dev);
+ return (ENXIO);
+ }
+
sc->sc_busdev = gpiobus_attach_bus(dev);
if (sc->sc_busdev == NULL) {
rk_gpio_detach(dev);
@@ -181,11 +295,6 @@
for (i = 0; i < RK_GPIO_MAX_PINS; i++)
sc->pin_cached[i].is_gpio = 2;
- RK_GPIO_LOCK(sc);
- sc->swporta = RK_GPIO_READ(sc, RK_GPIO_SWPORTA_DR);
- sc->swporta_ddr = RK_GPIO_READ(sc, RK_GPIO_SWPORTA_DDR);
- RK_GPIO_UNLOCK(sc);
-
return (0);
}
@@ -267,7 +376,7 @@
return (rv);
sc->pin_cached[pin].flags = *flags;
- if (sc->swporta_ddr & (1 << pin))
+ if (rk_gpio_read_bit(sc, RK_GPIO_SWPORTA_DDR, pin))
*flags |= GPIO_PIN_OUTPUT;
else
*flags |= GPIO_PIN_INPUT;
@@ -279,6 +388,9 @@
rk_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
+ if (pin >= RK_GPIO_MAX_PINS)
+ return EINVAL;
+
*caps = RK_GPIO_DEFAULT_CAPS;
return (0);
}
@@ -291,6 +403,9 @@
sc = device_get_softc(dev);
+ if (pin >= RK_GPIO_MAX_PINS)
+ return (EINVAL);
+
if (__predict_false(sc->pin_cached[pin].is_gpio != 1)) {
rv = FDT_PINCTRL_IS_GPIO(sc->pinctrl, dev, pin, (bool *)&sc->pin_cached[pin].is_gpio);
if (rv != 0)
@@ -306,14 +421,8 @@
return (rv);
}
- RK_GPIO_LOCK(sc);
- if (flags & GPIO_PIN_INPUT)
- sc->swporta_ddr &= ~(1 << pin);
- else if (flags & GPIO_PIN_OUTPUT)
- sc->swporta_ddr |= (1 << pin);
-
- RK_GPIO_WRITE(sc, RK_GPIO_SWPORTA_DDR, sc->swporta_ddr);
- RK_GPIO_UNLOCK(sc);
+ rk_gpio_write_bit(sc, RK_GPIO_SWPORTA_DDR, pin,
+ (flags & GPIO_PIN_OUTPUT ? 1 : 0));
return (0);
}
@@ -322,16 +431,13 @@
rk_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
{
struct rk_gpio_softc *sc;
- uint32_t reg;
sc = device_get_softc(dev);
- RK_GPIO_LOCK(sc);
- reg = RK_GPIO_READ(sc, RK_GPIO_EXT_PORTA);
- RK_GPIO_UNLOCK(sc);
-
- *val = reg & (1 << pin) ? 1 : 0;
+ if (pin >= RK_GPIO_MAX_PINS)
+ return (EINVAL);
+ *val = rk_gpio_read_bit(sc, RK_GPIO_EXT_PORTA, pin);
return (0);
}
@@ -342,14 +448,10 @@
sc = device_get_softc(dev);
- RK_GPIO_LOCK(sc);
- if (value)
- sc->swporta |= (1 << pin);
- else
- sc->swporta &= ~(1 << pin);
- RK_GPIO_WRITE(sc, RK_GPIO_SWPORTA_DR, sc->swporta);
- RK_GPIO_UNLOCK(sc);
+ if (pin >= RK_GPIO_MAX_PINS)
+ return (EINVAL);
+ rk_gpio_write_bit(sc, RK_GPIO_SWPORTA_DR, pin, value);
return (0);
}
@@ -357,16 +459,15 @@
rk_gpio_pin_toggle(device_t dev, uint32_t pin)
{
struct rk_gpio_softc *sc;
+ int value;
sc = device_get_softc(dev);
- RK_GPIO_LOCK(sc);
- if (sc->swporta & (1 << pin))
- sc->swporta &= ~(1 << pin);
- else
- sc->swporta |= (1 << pin);
- RK_GPIO_WRITE(sc, RK_GPIO_SWPORTA_DR, sc->swporta);
- RK_GPIO_UNLOCK(sc);
+ if (pin >= RK_GPIO_MAX_PINS)
+ return (EINVAL);
+
+ value = rk_gpio_read_bit(sc, RK_GPIO_EXT_PORTA, pin);
+ rk_gpio_write_bit(sc, RK_GPIO_SWPORTA_DR, pin, !value);
return (0);
}
@@ -380,17 +481,14 @@
sc = device_get_softc(dev);
- RK_GPIO_LOCK(sc);
- reg = RK_GPIO_READ(sc, RK_GPIO_SWPORTA_DR);
+ reg = rk_gpio_read_4(sc, RK_GPIO_SWPORTA_DR);
if (orig_pins)
*orig_pins = reg;
- sc->swporta = reg;
if ((clear_pins | change_pins) != 0) {
reg = (reg & ~clear_pins) ^ change_pins;
- RK_GPIO_WRITE(sc, RK_GPIO_SWPORTA_DR, reg);
+ rk_gpio_write_4(sc, RK_GPIO_SWPORTA_DR, reg);
}
- RK_GPIO_UNLOCK(sc);
return (0);
}
@@ -420,13 +518,10 @@
}
}
- RK_GPIO_LOCK(sc);
- reg = RK_GPIO_READ(sc, RK_GPIO_SWPORTA_DDR);
+ reg = rk_gpio_read_4(sc, RK_GPIO_SWPORTA_DDR);
reg &= ~mask;
reg |= set;
- RK_GPIO_WRITE(sc, RK_GPIO_SWPORTA_DDR, reg);
- sc->swporta_ddr = reg;
- RK_GPIO_UNLOCK(sc);
+ rk_gpio_write_4(sc, RK_GPIO_SWPORTA_DDR, reg);
return (0);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 15, 10:57 AM (6 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25324338
Default Alt Text
D36262.id109550.diff (8 KB)
Attached To
Mode
D36262: Code refactoring for rk_pgio driver
Attached
Detach File
Event Timeline
Log In to Comment