]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
ARM: add basic support for the Broadcom BCM2835 SoC
authorStephen Warren <swarren@wwwdotorg.org>
Sun, 5 Aug 2012 16:07:21 +0000 (16:07 +0000)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Sat, 1 Sep 2012 12:58:21 +0000 (14:58 +0200)
This SoC is used in the Raspberry Pi, for example.

For more details, see:
http://www.broadcom.com/products/BCM2835
http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf.

Initial support is enough to boot to a serial console, execute a minimal
set of U-Boot commands, download data over a serial port, and boot a
Linux kernel. No storage or network drivers are implemented.

GPIO driver originally by Vikram Narayanan <vikram186@gmail.com>
with many fixes from myself.

Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
arch/arm/cpu/arm1176/bcm2835/Makefile [new file with mode: 0644]
arch/arm/cpu/arm1176/bcm2835/config.mk [new file with mode: 0644]
arch/arm/cpu/arm1176/bcm2835/lowlevel_init.S [new file with mode: 0644]
arch/arm/cpu/arm1176/bcm2835/reset.c [new file with mode: 0644]
arch/arm/cpu/arm1176/bcm2835/timer.c [new file with mode: 0644]
arch/arm/include/asm/arch-bcm2835/gpio.h [new file with mode: 0644]
arch/arm/include/asm/arch-bcm2835/timer.h [new file with mode: 0644]
arch/arm/include/asm/arch-bcm2835/wdog.h [new file with mode: 0644]
drivers/gpio/Makefile
drivers/gpio/bcm2835_gpio.c [new file with mode: 0644]

diff --git a/arch/arm/cpu/arm1176/bcm2835/Makefile b/arch/arm/cpu/arm1176/bcm2835/Makefile
new file mode 100644 (file)
index 0000000..4ea6d6b
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = $(obj)lib$(SOC).o
+
+SOBJS  := lowlevel_init.o
+COBJS  := reset.o timer.o
+
+SRCS   := $(SOBJS:.o=.c) $(COBJS:.o=.c)
+OBJS   := $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+all:   $(obj).depend $(LIB)
+
+$(LIB):        $(OBJS)
+       $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/arm/cpu/arm1176/bcm2835/config.mk b/arch/arm/cpu/arm1176/bcm2835/config.mk
new file mode 100644 (file)
index 0000000..b87ce24
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# (C) Copyright 2012 Stephen Warren
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# Don't attempt to override the target CPU/ABI options;
+# the Raspberry Pi toolchain does the right thing by default.
+PLATFORM_RELFLAGS := $(filter-out -msoft-float,$(PLATFORM_RELFLAGS))
+PLATFORM_CPPFLAGS := $(filter-out -march=armv5t,$(PLATFORM_CPPFLAGS))
diff --git a/arch/arm/cpu/arm1176/bcm2835/lowlevel_init.S b/arch/arm/cpu/arm1176/bcm2835/lowlevel_init.S
new file mode 100644 (file)
index 0000000..c7b0843
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+.globl lowlevel_init
+lowlevel_init:
+       mov     pc, lr
diff --git a/arch/arm/cpu/arm1176/bcm2835/reset.c b/arch/arm/cpu/arm1176/bcm2835/reset.c
new file mode 100644 (file)
index 0000000..8c37ad9
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/wdog.h>
+
+#define RESET_TIMEOUT 10
+
+void reset_cpu(ulong addr)
+{
+       struct bcm2835_wdog_regs *regs =
+               (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR;
+       uint32_t rstc;
+
+       rstc = readl(&regs->rstc);
+       rstc &= ~BCM2835_WDOG_RSTC_WRCFG_MASK;
+       rstc |= BCM2835_WDOG_RSTC_WRCFG_FULL_RESET;
+
+       writel(BCM2835_WDOG_PASSWORD | RESET_TIMEOUT, &regs->wdog);
+       writel(BCM2835_WDOG_PASSWORD | rstc, &regs->rstc);
+}
diff --git a/arch/arm/cpu/arm1176/bcm2835/timer.c b/arch/arm/cpu/arm1176/bcm2835/timer.c
new file mode 100644 (file)
index 0000000..d232d7e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/timer.h>
+
+int timer_init(void)
+{
+       return 0;
+}
+
+ulong get_timer(ulong base)
+{
+       struct bcm2835_timer_regs *regs =
+               (struct bcm2835_timer_regs *)BCM2835_TIMER_PHYSADDR;
+
+       return readl(&regs->clo) - base;
+}
+
+unsigned long long get_ticks(void)
+{
+       return get_timer(0);
+}
+
+ulong get_tbclk(void)
+{
+       return CONFIG_SYS_HZ;
+}
+
+void __udelay(unsigned long usec)
+{
+       ulong endtime;
+       signed long diff;
+
+       endtime = get_timer(0) + usec;
+
+       do {
+               ulong now = get_timer(0);
+               diff = endtime - now;
+       } while (diff >= 0);
+}
diff --git a/arch/arm/include/asm/arch-bcm2835/gpio.h b/arch/arm/include/asm/arch-bcm2835/gpio.h
new file mode 100644 (file)
index 0000000..0e70856
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Vikram Narayananan
+ * <vikram186@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _BCM2835_GPIO_H_
+#define _BCM2835_GPIO_H_
+
+#define BCM2835_GPIO_BASE              0x20200000
+#define BCM2835_GPIO_COUNT             54
+
+#define BCM2835_GPIO_FSEL_MASK         0x7
+#define BCM2835_GPIO_INPUT             0x0
+#define BCM2835_GPIO_OUTPUT            0x1
+#define BCM2835_GPIO_ALT0              0x4
+#define BCM2835_GPIO_ALT1              0x5
+#define BCM2835_GPIO_ALT2              0x6
+#define BCM2835_GPIO_ALT3              0x7
+#define BCM2835_GPIO_ALT4              0x3
+#define BCM2835_GPIO_ALT5              0x2
+
+#define BCM2835_GPIO_COMMON_BANK(gpio) ((gpio < 32) ? 0 : 1)
+#define BCM2835_GPIO_COMMON_SHIFT(gpio)        (gpio & 0x1f)
+
+#define BCM2835_GPIO_FSEL_BANK(gpio)   (gpio / 10)
+#define BCM2835_GPIO_FSEL_SHIFT(gpio)  ((gpio % 10) * 3)
+
+struct bcm2835_gpio_regs {
+       u32 gpfsel[6];
+       u32 reserved1;
+       u32 gpset[2];
+       u32 reserved2;
+       u32 gpclr[2];
+       u32 reserved3;
+       u32 gplev[2];
+       u32 reserved4;
+       u32 gpeds[2];
+       u32 reserved5;
+       u32 gpren[2];
+       u32 reserved6;
+       u32 gpfen[2];
+       u32 reserved7;
+       u32 gphen[2];
+       u32 reserved8;
+       u32 gplen[2];
+       u32 reserved9;
+       u32 gparen[2];
+       u32 reserved10;
+       u32 gppud;
+       u32 gppudclk[2];
+};
+
+#endif /* _BCM2835_GPIO_H_ */
diff --git a/arch/arm/include/asm/arch-bcm2835/timer.h b/arch/arm/include/asm/arch-bcm2835/timer.h
new file mode 100644 (file)
index 0000000..30c70e0
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _BCM2835_TIMER_H
+#define _BCM2835_TIMER_H
+
+#define BCM2835_TIMER_PHYSADDR 0x20003000
+
+struct bcm2835_timer_regs {
+       u32 cs;
+       u32 clo;
+       u32 chi;
+       u32 c0;
+       u32 c1;
+       u32 c2;
+       u32 c3;
+};
+
+#define BCM2835_TIMER_CS_M3    (1 << 3)
+#define BCM2835_TIMER_CS_M2    (1 << 2)
+#define BCM2835_TIMER_CS_M1    (1 << 1)
+#define BCM2835_TIMER_CS_M0    (1 << 0)
+
+#endif
diff --git a/arch/arm/include/asm/arch-bcm2835/wdog.h b/arch/arm/include/asm/arch-bcm2835/wdog.h
new file mode 100644 (file)
index 0000000..303a65f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2012 Stephen Warren
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _BCM2835_TIMER_H
+#define _BCM2835_TIMER_H
+
+#define BCM2835_WDOG_PHYSADDR                  0x20100000
+
+struct bcm2835_wdog_regs {
+       u32 unknown0[7];
+       u32 rstc;
+       u32 unknown1;
+       u32 wdog;
+};
+
+#define BCM2835_WDOG_PASSWORD                  0x5a000000
+
+#define BCM2835_WDOG_RSTC_WRCFG_MASK           0x00000030
+#define BCM2835_WDOG_RSTC_WRCFG_FULL_RESET     0x00000020
+
+#define BCM2835_WDOG_WDOG_TIMEOUT_MASK         0x0000ffff
+
+#endif
index 3c67599880885302c3950cf90f185f9c9f2279b2..17f4b739a92a974356ec09d5d2538d34857c362d 100644 (file)
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_MPC83XX_GPIO)  += mpc83xx_gpio.o
 COBJS-$(CONFIG_SH_GPIO_PFC)    += sh_pfc.o
 COBJS-$(CONFIG_OMAP_GPIO)      += omap_gpio.o
 COBJS-$(CONFIG_DB8500_GPIO)    += db8500_gpio.o
+COBJS-$(CONFIG_BCM2835_GPIO)   += bcm2835_gpio.o
 
 COBJS  := $(COBJS-y)
 SRCS   := $(COBJS:.o=.c)
diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c
new file mode 100644 (file)
index 0000000..1d50dbd
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 Vikram Narayananan
+ * <vikram186@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+inline int gpio_is_valid(unsigned gpio)
+{
+       return (gpio < BCM2835_GPIO_COUNT);
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+       return !gpio_is_valid(gpio);
+}
+
+int gpio_free(unsigned gpio)
+{
+       return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+       struct bcm2835_gpio_regs *reg =
+               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+       unsigned val;
+
+       val = readl(&reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+       val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
+       val |= (BCM2835_GPIO_INPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
+       writel(val, &reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+
+       return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       struct bcm2835_gpio_regs *reg =
+               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+       unsigned val;
+
+       gpio_set_value(gpio, value);
+
+       val = readl(&reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+       val &= ~(BCM2835_GPIO_FSEL_MASK << BCM2835_GPIO_FSEL_SHIFT(gpio));
+       val |= (BCM2835_GPIO_OUTPUT << BCM2835_GPIO_FSEL_SHIFT(gpio));
+       writel(val, &reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]);
+
+       return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+       struct bcm2835_gpio_regs *reg =
+               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+       unsigned val;
+
+       val = readl(&reg->gplev[BCM2835_GPIO_COMMON_BANK(gpio)]);
+
+       return (val >> BCM2835_GPIO_COMMON_SHIFT(gpio)) & 0x1;
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+       struct bcm2835_gpio_regs *reg =
+               (struct bcm2835_gpio_regs *)BCM2835_GPIO_BASE;
+       u32 *output_reg = value ? reg->gpset : reg->gpclr;
+
+       writel(1 << BCM2835_GPIO_COMMON_SHIFT(gpio),
+                               &output_reg[BCM2835_GPIO_COMMON_BANK(gpio)]);
+
+       return 0;
+}