commit ba6597ca8c8b24b0bf7480d91492639c3066912e
parent b2ad041ecacc7a7284b1871f650176790d386850
Author: Brian Swetland <swetland@frotz.net>
Date:   Wed, 19 Mar 2014 21:19:19 -0700
lpc15xx: hw: basic gpio support
Diffstat:
3 files changed, 100 insertions(+), 6 deletions(-)
diff --git a/arch/lpc15xx/config.mk b/arch/lpc15xx/config.mk
@@ -22,5 +22,6 @@ ARCH_lpc15xx_START := arch/arm-cm3/start.o
 ARCH_lpc15xx_CONFIG := \
 	ARCH_LPC15XX=1 \
 	STACKTOP=0x02008f00
-ARCH_lpc15xx_OBJS :=
+ARCH_lpc15xx_OBJS := \
+	arch/lpc15xx/gpio.o
 
diff --git a/arch/lpc15xx/gpio.c b/arch/lpc15xx/gpio.c
@@ -0,0 +1,48 @@
+/* gpio.c
+ *
+ * Copyright 2014 Brian Swetland <swetland@frotz.net>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fw/io.h>
+#include <fw/lib.h>
+#include <arch/hardware.h>
+
+#define GPIO_OFF(n) ((n >> 5) << 2)
+#define GPIO_BIT(n) (1 << ((n) & 31))
+
+void gpio_cfg_dir(unsigned n, unsigned dir) {
+	u32 r = GPIO0_DIR + GPIO_OFF(n);
+	if (dir == GPIO_CFG_OUT) {
+		writel(readl(r) | GPIO_BIT(n), r);
+	} else {
+		writel(readl(r) & (~GPIO_BIT(n)), r);
+	}
+}
+
+void gpio_set(unsigned n) {
+	writeb(1, GPIO_BYTE(n));
+}
+
+void gpio_clr(unsigned n) {
+	writeb(0, GPIO_BYTE(n));
+}
+
+int gpio_rd(unsigned n) {
+	return readb(GPIO_BYTE(n));
+}
+
+void gpio_wr(unsigned n, unsigned v) {
+	writeb(!!v, GPIO_BYTE(n));
+}
diff --git a/arch/lpc15xx/include/arch/hardware.h b/arch/lpc15xx/include/arch/hardware.h
@@ -205,7 +205,10 @@
 /* 2_0:2_2     Y       Y       Y        N           N          */
 /* 2_3:2_13    N       N       Y        N           N          */
 
-#define IOCON_PIO(m,n)		(0x400F8000 + ((m)*32+(n))*4)
+#define PIO_IDX_NONE		0xFF
+#define PIO_IDX(m,n)		(((m) << 5) + n)
+
+#define IOCON_PIO(m,n)		(0x400F8000 + (PIO_IDX(m,n) << 2))
 
 #define IOCON_MODE_INACTIVE	(0 << 3)  /* mode */
 #define IOCON_MODE_PULL_DOWN	(1 << 3)
@@ -304,14 +307,11 @@
 #define FUNC_GPIO_INT_BMAT	60
 #define FUNC_SWO		61
 
-#define PIO_IDX_NONE		0xFF
-#define PIO_IDX(n,m)		(((n)*32) + m)
-
 #define PINASSIGN(func)		(0x4003800+((func)/4))
 #define  PA_SHIFT(func)		(((func) & 3) * 8)
 #define  PA_MASK(func)		(~(0xFF << PA_SHIFT(func)))
 
-static inline pin_assign(u32 func, u32 pio_idx) {
+static inline void pin_assign(u32 func, u32 pio_idx) {
 	u32 r = PINASSIGN(func);
 	u32 v = readl(v);
 	writel((v & PA_MASK(func)) | (pio_idx << PA_SHIFT(func)), r);
@@ -381,4 +381,49 @@ static inline pin_assign(u32 func, u32 pio_idx) {
 #define  PE1_SWCLK_ON_0_19	(1 << 22)
 #define  PE1_SWDIO_ON_0_20	(1 << 23)
 
+/* GPIO */
+
+/* Transform PIOm_n to GPIO index number */
+#define GPIO_IDX(m, n)		(((m) * 32) + (n))
+
+/* Reads as 0x00 or 0x01 (gpio is 0 or 1) */
+/* Write 0 to clear 1 to set gpio, bits 1:7 ignored */
+#define GPIO_BYTE(idx)		(0x1C000000 + (idx))
+
+/* Reads as 0x00000000 or 0xFFFFFFFF (gpio is 0 or 1) */
+/* Write 0 to clear, nonzero to set gpio */
+#define GPIO_WORD(idx)		(0x1C001000 + ((idx) * 4))
+
+/* bit 0..31 are direction of io 0..31 for that port */
+/* 0 is input, 1 is output */
+#define GPIO0_DIR		0x1C002000
+#define GPIO1_DIR		0x1C002004
+#define GPIO2_DIR		0x1C002008
+
+/* determine which ports are visible via MPORT regs (0=vis 1=masked) */
+#define GPIO0_MASK		0x1C002080
+#define GPIO1_MASK		0x1C002084
+#define GPIO2_MASK		0x1C002088
+
+/* raw access, read returns gpio status, write sets status */
+#define GPIO0_PORT		0x1C002100
+#define GPIO1_PORT		0x1C002104
+#define GPIO2_PORT		0x1C002108
+
+/* masked access */
+#define GPIO0_MPORT		0x1C002180
+#define GPIO1_MPORT		0x1C002184
+#define GPIO2_MPORT		0x1C002188
+
+/* set/clear/toggle registers - write 1 to take action, 0 is no-op */
+#define GPIO0_SET		0x1C002200
+#define GPIO1_SET		0x1C002204
+#define GPIO2_SET		0x1C002208
+#define GPIO0_CLR		0x1C002280
+#define GPIO1_CLR		0x1C002284
+#define GPIO2_CLR		0x1C002288
+#define GPIO0_TGL		0x1C002300
+#define GPIO1_TGL		0x1C002304
+#define GPIO2_TGL		0x1C002308
+
 #endif