summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig12
-rw-r--r--arch/arm/Makefile2
-rw-r--r--arch/arm/boards/raspberry-pi/Makefile1
-rw-r--r--arch/arm/boards/raspberry-pi/config.h4
-rw-r--r--arch/arm/boards/raspberry-pi/env/init/bootargs-base8
-rw-r--r--arch/arm/boards/raspberry-pi/env/init/hostname8
-rw-r--r--arch/arm/boards/raspberry-pi/rpi.c44
-rw-r--r--arch/arm/configs/rpi_defconfig41
-rw-r--r--arch/arm/configs/versatilepb_defconfig2
-rw-r--r--arch/arm/cpu/Kconfig5
-rw-r--r--arch/arm/mach-bcm2835/Kconfig18
-rw-r--r--arch/arm/mach-bcm2835/Makefile1
-rw-r--r--arch/arm/mach-bcm2835/core.c101
-rw-r--r--arch/arm/mach-bcm2835/include/mach/clkdev.h7
-rw-r--r--arch/arm/mach-bcm2835/include/mach/core.h22
-rw-r--r--arch/arm/mach-bcm2835/include/mach/gpio.h1
-rw-r--r--arch/arm/mach-bcm2835/include/mach/platform.h50
-rw-r--r--arch/arm/mach-bcm2835/include/mach/wd.h47
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gpio.h27
-rw-r--r--arch/arm/mach-imx/include/mach/gpio.h7
-rw-r--r--arch/arm/mach-mxs/include/mach/gpio.h6
-rw-r--r--arch/arm/mach-nomadik/8815.c5
-rw-r--r--arch/arm/mach-nomadik/include/mach/mtu.h46
-rw-r--r--arch/arm/mach-nomadik/include/mach/timex.h6
-rw-r--r--arch/arm/mach-nomadik/timer.c54
-rw-r--r--arch/arm/mach-omap/include/mach/gpio.h43
-rw-r--r--arch/arm/mach-samsung/include/mach/gpio.h6
-rw-r--r--arch/arm/mach-versatile/core.c10
-rw-r--r--arch/arm/mach-versatile/include/mach/gpio.h1
-rw-r--r--drivers/Kconfig1
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/clk/clkdev.c21
-rw-r--r--drivers/clocksource/Kconfig11
-rw-r--r--drivers/clocksource/Makefile3
-rw-r--r--drivers/clocksource/arm_smp_twd.c101
-rw-r--r--drivers/clocksource/bcm2835.c90
-rw-r--r--drivers/clocksource/nomadik.c147
-rw-r--r--drivers/gpio/Kconfig11
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/gpio-bcm2835.c158
-rw-r--r--drivers/gpio/gpio-pl061.c158
-rw-r--r--include/asm-generic/gpio.h10
-rw-r--r--include/linux/amba/pl061.h12
-rw-r--r--include/linux/clkdev.h1
44 files changed, 1128 insertions, 184 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 57b3ca7551..82284325e8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -31,6 +31,15 @@ config ARCH_AT91
select HAS_DEBUG_LL
select HAVE_MACH_ARM_HEAD
+config ARCH_BCM2835
+ bool "Broadcom BCM2835 boards"
+ select GPIOLIB
+ select CPU_ARM1176
+ select CLKDEV_LOOKUP
+ select COMMON_CLK
+ select CLOCKSOURCE_BCM2835
+ select ARM_AMBA
+
config ARCH_EP93XX
bool "Cirrus Logic EP93xx"
select CPU_ARM920T
@@ -54,6 +63,7 @@ config ARCH_NETX
config ARCH_NOMADIK
bool "STMicroelectronics Nomadik"
select CPU_ARM926T
+ select CLOCKSOURCE_NOMADIK
help
Support for the Nomadik platform by ST-Ericsson
@@ -87,6 +97,7 @@ config ARCH_S3C64xx
config ARCH_VERSATILE
bool "ARM Versatile boards (ARM926EJ-S)"
select CPU_ARM926T
+ select GPIOLIB
config ARCH_TEGRA
bool "Nvidia Tegra-based boards"
@@ -97,6 +108,7 @@ endchoice
source arch/arm/cpu/Kconfig
source arch/arm/mach-at91/Kconfig
+source arch/arm/mach-bcm2835/Kconfig
source arch/arm/mach-ep93xx/Kconfig
source arch/arm/mach-imx/Kconfig
source arch/arm/mach-mxs/Kconfig
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 855043aedf..5e8f5099f5 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -52,6 +52,7 @@ AFLAGS += -include asm/unified.h -msoft-float $(AFLAGS_THUMB2)
# Machine directory name. This list is sorted alphanumerically
# by CONFIG_* macro name.
machine-$(CONFIG_ARCH_AT91) := at91
+machine-$(CONFIG_ARCH_BCM2835) := bcm2835
machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_IMX) := imx
machine-$(CONFIG_ARCH_MXS) := mxs
@@ -112,6 +113,7 @@ board-$(CONFIG_MACH_PCM043) := pcm043
board-$(CONFIG_MACH_PM9261) := pm9261
board-$(CONFIG_MACH_PM9263) := pm9263
board-$(CONFIG_MACH_PM9G45) := pm9g45
+board-$(CONFIG_MACH_RPI) := raspberry-pi
board-$(CONFIG_MACH_SCB9328) := scb9328
board-$(CONFIG_MACH_NESO) := guf-neso
board-$(CONFIG_MACH_MX23EVK) := freescale-mx23-evk
diff --git a/arch/arm/boards/raspberry-pi/Makefile b/arch/arm/boards/raspberry-pi/Makefile
new file mode 100644
index 0000000000..6ce5edeb27
--- /dev/null
+++ b/arch/arm/boards/raspberry-pi/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_MACH_RPI) += rpi.o
diff --git a/arch/arm/boards/raspberry-pi/config.h b/arch/arm/boards/raspberry-pi/config.h
new file mode 100644
index 0000000000..ca15136817
--- /dev/null
+++ b/arch/arm/boards/raspberry-pi/config.h
@@ -0,0 +1,4 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#endif /* __CONFIG_H */
diff --git a/arch/arm/boards/raspberry-pi/env/init/bootargs-base b/arch/arm/boards/raspberry-pi/env/init/bootargs-base
new file mode 100644
index 0000000000..d86975406e
--- /dev/null
+++ b/arch/arm/boards/raspberry-pi/env/init/bootargs-base
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+ init-menu-add-entry "$0" "Base bootargs"
+ exit
+fi
+
+global.linux.bootargs.base="console=ttymxc0,115200"
diff --git a/arch/arm/boards/raspberry-pi/env/init/hostname b/arch/arm/boards/raspberry-pi/env/init/hostname
new file mode 100644
index 0000000000..7e8f294357
--- /dev/null
+++ b/arch/arm/boards/raspberry-pi/env/init/hostname
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+if [ "$1" = menu ]; then
+ init-menu-add-entry "$0" "hostname"
+ exit
+fi
+
+global.hostname=Raspberry-Pi
diff --git a/arch/arm/boards/raspberry-pi/rpi.c b/arch/arm/boards/raspberry-pi/rpi.c
new file mode 100644
index 0000000000..3be95ae5c4
--- /dev/null
+++ b/arch/arm/boards/raspberry-pi/rpi.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Carlo Caione <carlo@carlocaione.org>
+ *
+ * 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 <init.h>
+#include <asm/armlinux.h>
+#include <generated/mach-types.h>
+
+#include <mach/core.h>
+
+static int rpi_mem_init(void)
+{
+ bcm2835_add_device_sdram(0);
+ return 0;
+}
+mem_initcall(rpi_mem_init);
+
+static int rpi_console_init(void)
+{
+ bcm2835_register_uart();
+ return 0;
+}
+console_initcall(rpi_console_init);
+
+static int rpi_devices_init(void)
+{
+ armlinux_set_architecture(MACH_TYPE_BCM2708);
+ armlinux_set_bootparams((void *)(0x00000100));
+ return 0;
+}
+
+device_initcall(rpi_devices_init);
diff --git a/arch/arm/configs/rpi_defconfig b/arch/arm/configs/rpi_defconfig
new file mode 100644
index 0000000000..014e28c73d
--- /dev/null
+++ b/arch/arm/configs/rpi_defconfig
@@ -0,0 +1,41 @@
+CONFIG_ARCH_BCM2835=y
+CONFIG_GPIO_BCM2835=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_PROMPT="R-Pi> "
+CONFIG_LONGHELP=y
+CONFIG_GLOB=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/raspberry-pi/env"
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_PASSWD=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MTEST=y
+CONFIG_CMD_MTEST_ALTERNATIVE=y
+CONFIG_CMD_BOOTM_ZLIB=y
+CONFIG_CMD_BOOTM_BZLIB=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_GPIO=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SHA1=y
+CONFIG_SHA256=y
diff --git a/arch/arm/configs/versatilepb_defconfig b/arch/arm/configs/versatilepb_defconfig
index eb29a22ad7..8daf9ae72f 100644
--- a/arch/arm/configs/versatilepb_defconfig
+++ b/arch/arm/configs/versatilepb_defconfig
@@ -32,6 +32,7 @@ CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_CMD_I2C=y
CONFIG_NET=y
@@ -44,6 +45,7 @@ CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_DRIVER_NET_SMC91111=y
+CONFIG_GPIO_PL061=y
CONFIG_I2C=y
CONFIG_I2C_VERSATILE=y
CONFIG_FS_CRAMFS=y
diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig
index 2ed678961d..d8a5fb1734 100644
--- a/arch/arm/cpu/Kconfig
+++ b/arch/arm/cpu/Kconfig
@@ -8,6 +8,11 @@ config CPU_32
# which CPUs we support in the kernel image, and the compiler instruction
# optimiser behaviour.
+# ARM1176
+config CPU_ARM1176
+ bool
+ select CPU_V6
+
# ARM920T
config CPU_ARM920T
bool
diff --git a/arch/arm/mach-bcm2835/Kconfig b/arch/arm/mach-bcm2835/Kconfig
new file mode 100644
index 0000000000..9d97aea2b8
--- /dev/null
+++ b/arch/arm/mach-bcm2835/Kconfig
@@ -0,0 +1,18 @@
+if ARCH_BCM2835
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x04000000 if MACH_RPI
+
+config BOARDINFO
+ default "RaspberryPi (BCM2835/ARM1176JZF-S)" if MACH_RPI
+
+choice
+ prompt "Broadcom Board type"
+
+config MACH_RPI
+ bool "RaspberryPi (BCM2835/ARM1176JZF-S)"
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-bcm2835/Makefile b/arch/arm/mach-bcm2835/Makefile
new file mode 100644
index 0000000000..820eb10ac2
--- /dev/null
+++ b/arch/arm/mach-bcm2835/Makefile
@@ -0,0 +1 @@
+obj-y += core.o
diff --git a/arch/arm/mach-bcm2835/core.c b/arch/arm/mach-bcm2835/core.c
new file mode 100644
index 0000000000..b0fec8b008
--- /dev/null
+++ b/arch/arm/mach-bcm2835/core.c
@@ -0,0 +1,101 @@
+/*
+ * Author: Carlo Caione <carlo@carlocaione.org>
+ *
+ * Based on mach-nomadik
+ * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * 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 <init.h>
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+
+#include <io.h>
+#include <asm/armlinux.h>
+#include <sizes.h>
+
+#include <mach/platform.h>
+#include <mach/wd.h>
+#include <mach/core.h>
+#include <linux/amba/bus.h>
+
+enum brcm_clks {
+ dummy, clk_ref_3, clk_ref_1, clks_max
+};
+
+static struct clk *clks[clks_max];
+
+static int bcm2835_clk_init(void)
+{
+ int ret;
+
+ clks[dummy] = clk_fixed("dummy", 0);
+ clks[clk_ref_3] = clk_fixed("ref3", 3 * 1000 * 1000);
+ clks[clk_ref_1] = clk_fixed("ref1", 1 * 1000 * 1000);
+
+ ret = clk_register_clkdev(clks[dummy], "apb_pclk", NULL);
+ if (ret)
+ goto clk_err;
+
+ ret = clk_register_clkdev(clks[clk_ref_3], NULL, "uart0-pl0110");
+ if (ret)
+ goto clk_err;
+
+ ret = clk_register_clkdev(clks[clk_ref_1], NULL, "bcm2835-cs");
+ if (ret)
+ goto clk_err;
+
+ return 0;
+
+clk_err:
+ return ret;
+
+}
+postcore_initcall(bcm2835_clk_init);
+
+static int bcm2835_dev_init(void)
+{
+ add_generic_device("bcm2835-gpio", 0, NULL, BCM2835_GPIO_BASE, 0xB0, IORESOURCE_MEM, NULL);
+ add_generic_device("bcm2835-cs", DEVICE_ID_SINGLE, NULL, BCM2835_ST_BASE, 0x1C, IORESOURCE_MEM, NULL);
+ return 0;
+}
+coredevice_initcall(bcm2835_dev_init);
+
+void bcm2835_register_uart(void)
+{
+ amba_apb_device_add(NULL, "uart0-pl011", 0, BCM2835_UART0_BASE, 4096, NULL, 0);
+}
+
+void bcm2835_add_device_sdram(u32 size)
+{
+ if (!size)
+ size = get_ram_size((ulong *) BCM2835_SDRAM_BASE, SZ_128M);
+
+ arm_add_mem_device("ram0", BCM2835_SDRAM_BASE, size);
+}
+#define RESET_TIMEOUT 10
+
+void __noreturn reset_cpu (unsigned long addr)
+{
+ uint32_t rstc;
+
+ rstc = readl(PM_RSTC);
+ rstc &= ~PM_RSTC_WRCFG_SET;
+ rstc |= PM_RSTC_WRCFG_FULL_RESET;
+ writel(PM_PASSWORD | RESET_TIMEOUT, PM_WDOG);
+ writel(PM_PASSWORD | rstc, PM_RSTC);
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-bcm2835/include/mach/clkdev.h b/arch/arm/mach-bcm2835/include/mach/clkdev.h
new file mode 100644
index 0000000000..04b37a8980
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/clkdev.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-bcm2835/include/mach/core.h b/arch/arm/mach-bcm2835/include/mach/core.h
new file mode 100644
index 0000000000..9379af209b
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/core.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2009 Carlo Caione <carlo@carlocaione.org>
+ *
+ * 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_CORE_H__
+#define __BCM2835_CORE_H__
+
+void bcm2835_register_uart(void);
+void bcm2835_add_device_sdram(u32 size);
+
+#endif
diff --git a/arch/arm/mach-bcm2835/include/mach/gpio.h b/arch/arm/mach-bcm2835/include/mach/gpio.h
new file mode 100644
index 0000000000..306ab4c9f2
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/gpio.h
@@ -0,0 +1 @@
+#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-bcm2835/include/mach/platform.h b/arch/arm/mach-bcm2835/include/mach/platform.h
new file mode 100644
index 0000000000..e55085a75b
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/platform.h
@@ -0,0 +1,50 @@
+/*
+ * Extract from arch/arm/mach-bcm2708/include/mach/platform.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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_PLATFORM_H
+#define _BCM2835_PLATFORM_H
+
+/*
+ * SDRAM
+ */
+#define BCM2835_SDRAM_BASE 0x00000000
+
+/*
+ * Definitions and addresses for the ARM CONTROL logic
+ * This file is manually generated.
+ */
+
+#define BCM2835_PERI_BASE 0x20000000
+#define BCM2835_ST_BASE (BCM2835_PERI_BASE + 0x3000) /* System Timer */
+#define BCM2835_DMA_BASE (BCM2835_PERI_BASE + 0x7000) /* DMA controller */
+#define BCM2835_ARM_BASE (BCM2835_PERI_BASE + 0xB000) /* BCM2708 ARM control block */
+#define BCM2835_PM_BASE (BCM2835_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */
+#define BCM2835_GPIO_BASE (BCM2835_PERI_BASE + 0x200000) /* GPIO */
+#define BCM2835_UART0_BASE (BCM2835_PERI_BASE + 0x201000) /* Uart 0 */
+#define BCM2835_MMCI0_BASE (BCM2835_PERI_BASE + 0x202000) /* MMC interface */
+#define BCM2835_SPI0_BASE (BCM2835_PERI_BASE + 0x204000) /* SPI0 */
+#define BCM2835_BSC0_BASE (BCM2835_PERI_BASE + 0x205000) /* BSC0 I2C/TWI */
+#define BCM2835_UART1_BASE (BCM2835_PERI_BASE + 0x215000) /* Uart 1 */
+#define BCM2835_EMMC_BASE (BCM2835_PERI_BASE + 0x300000) /* eMMC interface */
+#define BCM2835_SMI_BASE (BCM2835_PERI_BASE + 0x600000) /* SMI */
+#define BCM2835_BSC1_BASE (BCM2835_PERI_BASE + 0x804000) /* BSC1 I2C/TWI */
+#define BCM2835_USB_BASE (BCM2835_PERI_BASE + 0x980000) /* DTC_OTG USB controller */
+#define BCM2835_MCORE_BASE (BCM2835_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/
+
+#endif
+
+/* END */
diff --git a/arch/arm/mach-bcm2835/include/mach/wd.h b/arch/arm/mach-bcm2835/include/mach/wd.h
new file mode 100644
index 0000000000..ad8b762d96
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/wd.h
@@ -0,0 +1,47 @@
+/*
+ * Extract from arch/arm/mach-bcm2708/include/mach/platform.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * 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 _WD_H
+#define _WD_H
+
+/*
+ * Watchdog
+ */
+#define PM_RSTC (BCM2835_PM_BASE+0x1c)
+#define PM_RSTS (BCM2835_PM_BASE+0x20)
+#define PM_WDOG (BCM2835_PM_BASE+0x24)
+
+#define PM_WDOG_RESET 0000000000
+#define PM_PASSWORD 0x5a000000
+#define PM_WDOG_TIME_SET 0x000fffff
+#define PM_RSTC_WRCFG_CLR 0xffffffcf
+#define PM_RSTC_WRCFG_SET 0x00000030
+#define PM_RSTC_WRCFG_FULL_RESET 0x00000020
+#define PM_RSTC_RESET 0x00000102
+
+#define PM_RSTS_HADPOR_SET 0x00001000
+#define PM_RSTS_HADSRH_SET 0x00000400
+#define PM_RSTS_HADSRF_SET 0x00000200
+#define PM_RSTS_HADSRQ_SET 0x00000100
+#define PM_RSTS_HADWRH_SET 0x00000040
+#define PM_RSTS_HADWRF_SET 0x00000020
+#define PM_RSTS_HADWRQ_SET 0x00000010
+#define PM_RSTS_HADDRH_SET 0x00000004
+#define PM_RSTS_HADDRF_SET 0x00000002
+#define PM_RSTS_HADDRQ_SET 0x00000001
+
+#endif
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h
index 5f1b4bc001..306ab4c9f2 100644
--- a/arch/arm/mach-ep93xx/include/mach/gpio.h
+++ b/arch/arm/mach-ep93xx/include/mach/gpio.h
@@ -1,26 +1 @@
-/*
- * Copyright (C) 2010 Matthias Kaehlcke <matthias@kaehlcke.net>
- *
- * 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 __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-void gpio_set_value(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_direction_input(unsigned gpio);
-
-#endif /* __ASM_ARCH_GPIO_H */
-
+#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-imx/include/mach/gpio.h b/arch/arm/mach-imx/include/mach/gpio.h
index 0ebc3f939f..489ae2cf09 100644
--- a/arch/arm/mach-imx/include/mach/gpio.h
+++ b/arch/arm/mach-imx/include/mach/gpio.h
@@ -1,11 +1,8 @@
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H
+#include <asm-generic/gpio.h>
+
void imx_gpio_mode(int gpio_mode);
-void gpio_set_value(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_direction_input(unsigned gpio);
#endif /* __ASM_ARCH_GPIO_H */
-
diff --git a/arch/arm/mach-mxs/include/mach/gpio.h b/arch/arm/mach-mxs/include/mach/gpio.h
index 1e575fa0c4..4e7c8fe87e 100644
--- a/arch/arm/mach-mxs/include/mach/gpio.h
+++ b/arch/arm/mach-mxs/include/mach/gpio.h
@@ -25,10 +25,8 @@
# include <mach/iomux-imx28.h>
#endif
+#include <asm-generic/gpio.h>
+
void imx_gpio_mode(uint32_t);
-void gpio_set_value(unsigned, int);
-int gpio_direction_input(unsigned);
-int gpio_direction_output(unsigned, int);
-int gpio_get_value(unsigned);
#endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-nomadik/8815.c b/arch/arm/mach-nomadik/8815.c
index 81c5ce16d8..c5cac580d2 100644
--- a/arch/arm/mach-nomadik/8815.c
+++ b/arch/arm/mach-nomadik/8815.c
@@ -29,6 +29,10 @@ static struct clk st8815_clk_48 = {
.rate = 48 * 1000 * 1000,
};
+static struct clk st8815_clk_2_4 = {
+ .rate = 2400000,
+};
+
static struct clk st8815_dummy;
void st8815_add_device_sdram(u32 size)
@@ -38,6 +42,7 @@ void st8815_add_device_sdram(u32 size)
static struct clk_lookup clocks_lookups[] = {
CLKDEV_CON_ID("apb_pclk", &st8815_dummy),
+ CLKDEV_CON_ID("nomadik_mtu", &st8815_clk_2_4),
CLKDEV_DEV_ID("uart-pl0110", &st8815_clk_48),
CLKDEV_DEV_ID("uart-pl0111", &st8815_clk_48),
};
diff --git a/arch/arm/mach-nomadik/include/mach/mtu.h b/arch/arm/mach-nomadik/include/mach/mtu.h
deleted file mode 100644
index 9095d86a5a..0000000000
--- a/arch/arm/mach-nomadik/include/mach/mtu.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __ASM_ARCH_MTU_H
-#define __ASM_ARCH_MTU_H
-
-/*
- * The MTU device hosts four different counters, with 4 set of
- * registers. These are register names.
- */
-
-#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
-#define MTU_RIS 0x04 /* Raw interrupt status */
-#define MTU_MIS 0x08 /* Masked interrupt status */
-#define MTU_ICR 0x0C /* Interrupt clear register */
-
-/* per-timer registers take 0..3 as argument */
-#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
-#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
-
-#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
-#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
-
-
-/* bits for the control register */
-#define MTU_CRn_ENA 0x80
-#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
-#define MTU_CRn_PRESCALE_MASK 0x0c
-#define MTU_CRn_PRESCALE_1 0x00
-#define MTU_CRn_PRESCALE_16 0x04
-#define MTU_CRn_PRESCALE_256 0x08
-#define MTU_CRn_32BITS 0x02
-#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
-
-/* Other registers are usual amba/primecell registers, currently not used */
-#define MTU_ITCR 0xff0
-#define MTU_ITOP 0xff4
-
-#define MTU_PERIPH_ID0 0xfe0
-#define MTU_PERIPH_ID1 0xfe4
-#define MTU_PERIPH_ID2 0xfe8
-#define MTU_PERIPH_ID3 0xfeC
-
-#define MTU_PCELL0 0xff0
-#define MTU_PCELL1 0xff4
-#define MTU_PCELL2 0xff8
-#define MTU_PCELL3 0xffC
-
-#endif /* __ASM_ARCH_MTU_H */
diff --git a/arch/arm/mach-nomadik/include/mach/timex.h b/arch/arm/mach-nomadik/include/mach/timex.h
deleted file mode 100644
index b2b41faa1b..0000000000
--- a/arch/arm/mach-nomadik/include/mach/timex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE 2400000
-
-#endif
diff --git a/arch/arm/mach-nomadik/timer.c b/arch/arm/mach-nomadik/timer.c
index becd36357a..0b8dc866eb 100644
--- a/arch/arm/mach-nomadik/timer.c
+++ b/arch/arm/mach-nomadik/timer.c
@@ -10,55 +10,16 @@
*/
#include <common.h>
#include <init.h>
-#include <clock.h>
#include <io.h>
#include <mach/hardware.h>
-#include <mach/mtu.h>
-#include <mach/timex.h>
/* Initial value for SRC control register: all timers use MXTAL/8 source */
#define SRC_CR_INIT_MASK 0x00007fff
#define SRC_CR_INIT_VAL 0x2aaa8000
-static u32 nmdk_cycle; /* write-once */
-static __iomem void *mtu_base;
-
-/*
- * clocksource: the MTU device is a decrementing counters, so we negate
- * the value being read.
- */
-static uint64_t nmdk_read_timer(void)
-{
- return nmdk_cycle - readl(mtu_base + MTU_VAL(0));
-}
-
-static struct clocksource nmdk_clksrc = {
- .read = nmdk_read_timer,
- .shift = 20,
- .mask = CLOCKSOURCE_MASK(32),
-};
-
-static void nmdk_timer_reset(void)
-{
- u32 cr;
-
- writel(0, mtu_base + MTU_CR(0)); /* off */
-
- /* configure load and background-load, and fire it up */
- writel(nmdk_cycle, mtu_base + MTU_LR(0));
- writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
- cr = MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS;
- writel(cr, mtu_base + MTU_CR(0));
- writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
-}
-
-static int nmdk_timer_init(void)
+static int st8815_timer_init(void)
{
u32 src_cr;
- unsigned long rate;
-
- rate = CLOCK_TICK_RATE; /* 2.4MHz */
- nmdk_cycle = (rate + 1000 / 2) / 1000;
/* Configure timer sources in "system reset controller" ctrl reg */
src_cr = readl(NOMADIK_SRC_BASE);
@@ -66,16 +27,7 @@ static int nmdk_timer_init(void)
src_cr |= SRC_CR_INIT_VAL;
writel(src_cr, NOMADIK_SRC_BASE);
- /* Save global pointer to mtu, used by functions above */
- mtu_base = (void *)NOMADIK_MTU0_BASE;
-
- /* Init the timer and register clocksource */
- nmdk_timer_reset();
-
- nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift);
-
- init_clock(&nmdk_clksrc);
-
+ add_generic_device("nomadik_mtu", DEVICE_ID_SINGLE, NULL, NOMADIK_MTU0_BASE, 0x1000, IORESOURCE_MEM, NULL);
return 0;
}
-core_initcall(nmdk_timer_init);
+coredevice_initcall(st8815_timer_init);
diff --git a/arch/arm/mach-omap/include/mach/gpio.h b/arch/arm/mach-omap/include/mach/gpio.h
index 79bf4485b9..306ab4c9f2 100644
--- a/arch/arm/mach-omap/include/mach/gpio.h
+++ b/arch/arm/mach-omap/include/mach/gpio.h
@@ -1,42 +1 @@
-/*
- * Copyright (c) 2009 Wind River Systems, Inc.
- * Tom Rix <Tom.Rix@windriver.com>
- *
- * 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.
- *
- *
- * This work is derived from the linux 2.6.27 kernel source
- * To fetch, use the kernel repository
- * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
- * Use the v2.6.27 tag.
- *
- * Below is the original's header including its copyright
- *
- * linux/arch/arm/plat-omap/gpio.c
- *
- * Support functions for OMAP GPIO
- *
- * Copyright (C) 2003-2005 Nokia Corporation
- * Written by Juha Yrjölä <juha.yrjola@nokia.com>
- *
- * 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.
- */
-#ifndef _GPIO_H
-#define _GPIO_H
-
-void gpio_set_value(unsigned gpio, int value);
-int gpio_get_value(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
-int gpio_direction_input(unsigned gpio);
-
-#endif /* _GPIO_H_ */
+#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-samsung/include/mach/gpio.h b/arch/arm/mach-samsung/include/mach/gpio.h
index 2b4569547e..9e64a841b6 100644
--- a/arch/arm/mach-samsung/include/mach/gpio.h
+++ b/arch/arm/mach-samsung/include/mach/gpio.h
@@ -23,10 +23,8 @@
# include <mach/iomux-s5pcxx.h>
#endif
-void gpio_set_value(unsigned, int);
-int gpio_direction_input(unsigned);
-int gpio_direction_output(unsigned, int);
-int gpio_get_value(unsigned);
+#include <asm-generic/gpio.h>
+
void s3c_gpio_mode(unsigned);
#endif /* __ASM_MACH_GPIO_H */
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 853437991a..8aca2a19e3 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -203,3 +203,13 @@ void __noreturn reset_cpu (unsigned long ignored)
while(1);
}
EXPORT_SYMBOL(reset_cpu);
+
+static int versatile_init(void)
+{
+ amba_apb_device_add(NULL, "pl061_gpio", 0, 0x101e4000, 4096, NULL, 0);
+ amba_apb_device_add(NULL, "pl061_gpio", 1, 0x101e5000, 4096, NULL, 0);
+ amba_apb_device_add(NULL, "pl061_gpio", 2, 0x101e6000, 4096, NULL, 0);
+ amba_apb_device_add(NULL, "pl061_gpio", 3, 0x101e7000, 4096, NULL, 0);
+ return 0;
+}
+coredevice_initcall(versatile_init);
diff --git a/arch/arm/mach-versatile/include/mach/gpio.h b/arch/arm/mach-versatile/include/mach/gpio.h
new file mode 100644
index 0000000000..306ab4c9f2
--- /dev/null
+++ b/arch/arm/mach-versatile/include/mach/gpio.h
@@ -0,0 +1 @@
+#include <asm-generic/gpio.h>
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 945fe02327..f6446e8413 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -11,6 +11,7 @@ source "drivers/usb/Kconfig"
source "drivers/video/Kconfig"
source "drivers/mci/Kconfig"
source "drivers/clk/Kconfig"
+source "drivers/clocksource/Kconfig"
source "drivers/mfd/Kconfig"
source "drivers/misc/Kconfig"
source "drivers/led/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index e6cdf399e6..1fddee0dd4 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_MCI) += mci/
obj-$(CONFIG_VIDEO) += video/
obj-y += clk/
+obj-y += clocksource/
obj-y += mfd/
obj-$(CONFIG_LED) += led/
obj-y += eeprom/
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 1ae822ffa6..5441eeb8dc 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -178,6 +178,27 @@ struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
}
EXPORT_SYMBOL(clkdev_alloc);
+int clk_register_clkdev(struct clk *clk, const char *con_id,
+ const char *dev_fmt, ...)
+{
+ struct clk_lookup *cl;
+ va_list ap;
+
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ va_start(ap, dev_fmt);
+ cl = clkdev_alloc(clk, con_id, dev_fmt, ap);
+ va_end(ap);
+
+ if (!cl)
+ return -ENOMEM;
+
+ clkdev_add(cl);
+
+ return 0;
+}
+
int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
struct device_d *dev)
{
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
new file mode 100644
index 0000000000..09acdd74c5
--- /dev/null
+++ b/drivers/clocksource/Kconfig
@@ -0,0 +1,11 @@
+config ARM_SMP_TWD
+ bool
+ depends on ARM && CPU_V7
+
+config CLOCKSOURCE_BCM2835
+ bool
+ depends on ARCH_BCM2835
+
+config CLOCKSOURCE_NOMADIK
+ bool
+ depends on ARM
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
new file mode 100644
index 0000000000..92d7c1344a
--- /dev/null
+++ b/drivers/clocksource/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
+obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o
+obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
diff --git a/drivers/clocksource/arm_smp_twd.c b/drivers/clocksource/arm_smp_twd.c
new file mode 100644
index 0000000000..746d566441
--- /dev/null
+++ b/drivers/clocksource/arm_smp_twd.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPL v2
+ */
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <io.h>
+#include <driver.h>
+#include <errno.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#define TWD_TIMER_LOAD 0x00
+#define TWD_TIMER_COUNTER 0x04
+#define TWD_TIMER_CONTROL 0x08
+#define TWD_TIMER_INTSTAT 0x0C
+
+#define TWD_TIMER_CONTROL_ENABLE (1 << 0)
+#define TWD_TIMER_CONTROL_ONESHOT (0 << 1)
+#define TWD_TIMER_CONTROL_PERIODIC (1 << 1)
+#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2)
+
+#define TWD_TIMER_CONTROL_PRESC(x) (((x) & 0xff) << 8)
+
+static __iomem void *twd_base;
+static struct clk *twd_clk;
+
+static uint64_t smp_twd_read(void)
+{
+ return ~readl(twd_base + TWD_TIMER_COUNTER);
+}
+
+static struct clocksource smp_twd_clksrc = {
+ .read = smp_twd_read,
+ .shift = 20,
+ .mask = CLOCKSOURCE_MASK(32),
+};
+
+#define SMP_TWD_MAX_FREQ (25 *1000 * 1000)
+
+static int smp_twd_probe(struct device_d *dev)
+{
+ u32 tick_rate;
+ u32 val;
+ int ret;
+ u32 presc = 0;
+
+ twd_clk = clk_get(dev, NULL);
+ if (IS_ERR(twd_clk)) {
+ ret = PTR_ERR(twd_clk);
+ dev_err(dev, "clock not found: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(twd_clk);
+ if (ret < 0) {
+ dev_err(dev, "clock failed to enable: %d\n", ret);
+ clk_put(twd_clk);
+ return ret;
+ }
+
+ twd_base = dev_request_mem_region(dev, 0);
+
+ tick_rate = clk_get_rate(twd_clk);
+ if (tick_rate > SMP_TWD_MAX_FREQ) {
+ presc = tick_rate / SMP_TWD_MAX_FREQ;
+ if (presc)
+ presc--;
+ presc = min((u32)0xff, presc);
+ tick_rate /= presc + 1;
+ }
+
+ val = TWD_TIMER_CONTROL_PRESC(presc) |
+ TWD_TIMER_CONTROL_PERIODIC;
+ writel(val, twd_base + TWD_TIMER_CONTROL);
+
+ writel(0xffffffff, twd_base + TWD_TIMER_LOAD);
+
+ val = readl(twd_base + TWD_TIMER_CONTROL);
+ val |= TWD_TIMER_CONTROL_ENABLE;
+ writel(val, twd_base + TWD_TIMER_CONTROL);
+
+ smp_twd_clksrc.mult = clocksource_hz2mult(tick_rate, smp_twd_clksrc.shift);
+
+ init_clock(&smp_twd_clksrc);
+
+ return 0;
+}
+
+static struct driver_d smp_twd_driver = {
+ .name = "smp_twd",
+ .probe = smp_twd_probe,
+};
+
+static int smp_twd_init(void)
+{
+ return platform_driver_register(&smp_twd_driver);
+}
+coredevice_initcall(smp_twd_init);
diff --git a/drivers/clocksource/bcm2835.c b/drivers/clocksource/bcm2835.c
new file mode 100644
index 0000000000..d5fe0f03a2
--- /dev/null
+++ b/drivers/clocksource/bcm2835.c
@@ -0,0 +1,90 @@
+/*
+ * Author: Carlo Caione <carlo@carlocaione.org>
+ *
+ * Based on clocksource for nomadik
+ *
+ * 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 <clock.h>
+#include <io.h>
+#include <init.h>
+#include <driver.h>
+#include <errno.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+/* Registers */
+#define ST_CLO 0x04
+
+static __iomem void *stc_base;
+
+static uint64_t stc_read_cycles(void)
+{
+ return readl(stc_base + ST_CLO);
+}
+
+static struct clocksource bcm2835_stc = {
+ .read = stc_read_cycles,
+ .mask = CLOCKSOURCE_MASK(32),
+};
+
+static int bcm2835_cs_probe(struct device_d *dev)
+{
+ static struct clk *stc_clk;
+ u32 rate;
+ int ret;
+
+ stc_clk = clk_get(dev, NULL);
+ if (IS_ERR(stc_clk)) {
+ ret = PTR_ERR(stc_clk);
+ dev_err(dev, "clock not found: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(stc_clk);
+ if (ret) {
+ dev_err(dev, "clock failed to enable: %d\n", ret);
+ clk_put(stc_clk);
+ return ret;
+ }
+
+ rate = clk_get_rate(stc_clk);
+ stc_base = dev_request_mem_region(dev, 0);
+
+ clocks_calc_mult_shift(&bcm2835_stc.mult, &bcm2835_stc.shift, rate, NSEC_PER_SEC, 60);
+ init_clock(&bcm2835_stc);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id bcm2835_cs_dt_ids[] = {
+ {
+ .compatible = "brcm,bcm2835-system-timer",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d bcm2835_cs_driver = {
+ .name = "bcm2835-cs",
+ .probe = bcm2835_cs_probe,
+ .of_compatible = DRV_OF_COMPAT(bcm2835_cs_dt_ids),
+};
+
+static int bcm2835_cs_init(void)
+{
+ return platform_driver_register(&bcm2835_cs_driver);
+}
+coredevice_initcall(bcm2835_cs_init);
diff --git a/drivers/clocksource/nomadik.c b/drivers/clocksource/nomadik.c
new file mode 100644
index 0000000000..8a3e6d930e
--- /dev/null
+++ b/drivers/clocksource/nomadik.c
@@ -0,0 +1,147 @@
+/*
+ * linux/arch/arm/mach-nomadik/timer.c
+ *
+ * Copyright (C) 2008 STMicroelectronics
+ * Copyright (C) 2009 Alessandro Rubini, somewhat based on at91sam926x
+ *
+ * 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.
+ */
+#include <common.h>
+#include <clock.h>
+#include <io.h>
+#include <init.h>
+#include <driver.h>
+#include <errno.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+/*
+ * The MTU device hosts four different counters, with 4 set of
+ * registers. These are register names.
+ */
+
+#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
+#define MTU_RIS 0x04 /* Raw interrupt status */
+#define MTU_MIS 0x08 /* Masked interrupt status */
+#define MTU_ICR 0x0C /* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
+#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
+#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
+#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA 0x80
+#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */
+#define MTU_CRn_PRESCALE_MASK 0x0c
+#define MTU_CRn_PRESCALE_1 0x00
+#define MTU_CRn_PRESCALE_16 0x04
+#define MTU_CRn_PRESCALE_256 0x08
+#define MTU_CRn_32BITS 0x02
+#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR 0xff0
+#define MTU_ITOP 0xff4
+
+#define MTU_PERIPH_ID0 0xfe0
+#define MTU_PERIPH_ID1 0xfe4
+#define MTU_PERIPH_ID2 0xfe8
+#define MTU_PERIPH_ID3 0xfeC
+
+#define MTU_PCELL0 0xff0
+#define MTU_PCELL1 0xff4
+#define MTU_PCELL2 0xff8
+#define MTU_PCELL3 0xffC
+
+static __iomem void *mtu_base;
+static u32 clk_prescale;
+static u32 nmdk_cycle; /* write-once */
+
+/*
+ * clocksource: the MTU device is a decrementing counters, so we negate
+ * the value being read.
+ */
+static uint64_t nmdk_read_timer(void)
+{
+ return nmdk_cycle - readl(mtu_base + MTU_VAL(0));
+}
+
+static struct clocksource nmdk_clksrc = {
+ .read = nmdk_read_timer,
+ .shift = 20,
+ .mask = CLOCKSOURCE_MASK(32),
+};
+
+static void nmdk_timer_reset(void)
+{
+ u32 cr;
+
+ /* Disable */
+ writel(0, mtu_base + MTU_CR(0)); /* off */
+
+ /* configure load and background-load, and fire it up */
+ writel(nmdk_cycle, mtu_base + MTU_LR(0));
+ writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+ cr = clk_prescale | MTU_CRn_32BITS;
+ writel(cr, mtu_base + MTU_CR(0));
+ writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
+}
+
+static int nmdk_mtu_probe(struct device_d *dev)
+{
+ static struct clk *mtu_clk;
+ u32 rate;
+ int ret;
+
+ mtu_clk = clk_get(dev, NULL);
+ if (IS_ERR(mtu_clk)) {
+ ret = PTR_ERR(mtu_clk);
+ dev_err(dev, "clock not found: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(mtu_clk);
+ if (ret < 0) {
+ dev_err(dev, "clock failed to enable: %d\n", ret);
+ clk_put(mtu_clk);
+ return ret;
+ }
+
+ rate = clk_get_rate(mtu_clk);
+ if (rate > 32000000) {
+ rate /= 16;
+ clk_prescale = MTU_CRn_PRESCALE_16;
+ } else {
+ clk_prescale = MTU_CRn_PRESCALE_1;
+ }
+
+ nmdk_cycle = (rate + 1000 / 2) / 1000;
+
+ /* Save global pointer to mtu, used by functions above */
+ mtu_base = dev_request_mem_region(dev, 0);
+
+ /* Init the timer and register clocksource */
+ nmdk_timer_reset();
+
+ nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift);
+
+ init_clock(&nmdk_clksrc);
+
+ return 0;
+}
+
+static struct driver_d nmdk_mtu_driver = {
+ .name = "nomadik_mtu",
+ .probe = nmdk_mtu_probe,
+};
+
+static int nmdk_mtu_init(void)
+{
+ return platform_driver_register(&nmdk_mtu_driver);
+}
+coredevice_initcall(nmdk_mtu_init);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 022a30988e..e8eeb6d4c3 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1,10 +1,21 @@
config GPIOLIB
bool
+ select GENERIC_GPIO
if GPIOLIB
menu "GPIO "
+config GPIO_BCM2835
+ bool "GPIO support for BCM2835"
+ depends on ARCH_BCM2835
+
+config GPIO_PL061
+ bool "PrimeCell PL061 GPIO support"
+ depends on ARM_AMBA
+ help
+ Say yes here to support the PrimeCell PL061 GPIO device
+
config GPIO_STMPE
depends on I2C_STMPE
bool "STMPE GPIO Expander"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 945122b083..993ab89596 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,2 +1,4 @@
obj-$(CONFIG_GPIOLIB) += gpio.o
+obj-$(CONFIG_GPIO_BCM2835) += gpio-bcm2835.o
+obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
diff --git a/drivers/gpio/gpio-bcm2835.c b/drivers/gpio/gpio-bcm2835.c
new file mode 100644
index 0000000000..cec15c98b1
--- /dev/null
+++ b/drivers/gpio/gpio-bcm2835.c
@@ -0,0 +1,158 @@
+/*
+ * Author: Carlo Caione <carlo@carlocaione.org>
+ *
+ * Based on linux/arch/arm/mach-bcm2708/bcm2708_gpio.c
+ *
+ * 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 <errno.h>
+#include <malloc.h>
+#include <io.h>
+#include <gpio.h>
+#include <init.h>
+
+#define GPIOFSEL(x) (0x00+(x)*4)
+#define GPIOSET(x) (0x1c+(x)*4)
+#define GPIOCLR(x) (0x28+(x)*4)
+#define GPIOLEV(x) (0x34+(x)*4)
+#define GPIOEDS(x) (0x40+(x)*4)
+#define GPIOREN(x) (0x4c+(x)*4)
+#define GPIOFEN(x) (0x58+(x)*4)
+#define GPIOHEN(x) (0x64+(x)*4)
+#define GPIOLEN(x) (0x70+(x)*4)
+#define GPIOAREN(x) (0x7c+(x)*4)
+#define GPIOAFEN(x) (0x88+(x)*4)
+#define GPIOUD(x) (0x94+(x)*4)
+#define GPIOUDCLK(x) (0x98+(x)*4)
+
+enum {
+ GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT,
+ GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4,
+ GPIO_FSEL_ALT0, GPIO_FSEL_ALT1,
+ GPIO_FSEL_ALT2, GPIO_FSEL_ALT3,
+};
+
+struct bcm2835_gpio_chip {
+ void __iomem *base;
+ struct gpio_chip chip;
+};
+
+static int bcm2835_set_function(struct gpio_chip *chip, unsigned gpio, int function)
+{
+ struct bcm2835_gpio_chip *bcmgpio = container_of(chip, struct bcm2835_gpio_chip, chip);
+ void __iomem *base = bcmgpio->base;
+ unsigned gpiodir;
+ unsigned gpio_bank = gpio / 10;
+ unsigned gpio_field_offset = (gpio - 10 * gpio_bank) * 3;
+
+ gpiodir = readl(base + GPIOFSEL(gpio_bank));
+ gpiodir &= ~(7 << gpio_field_offset);
+ gpiodir |= function << gpio_field_offset;
+ writel(gpiodir, base + GPIOFSEL(gpio_bank));
+ gpiodir = readl(base + GPIOFSEL(gpio_bank));
+
+ return 0;
+}
+
+static void bcm2835_gpio_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ struct bcm2835_gpio_chip *bcmgpio = container_of(chip, struct bcm2835_gpio_chip, chip);
+ void __iomem *base = bcmgpio->base;
+ unsigned gpio_bank = gpio / 32;
+ unsigned gpio_field_offset = gpio % 32;
+
+ if (value)
+ writel(1 << gpio_field_offset, base + GPIOSET(gpio_bank));
+ else
+ writel(1 << gpio_field_offset, base + GPIOCLR(gpio_bank));
+}
+
+static int bcm2835_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+ struct bcm2835_gpio_chip *bcmgpio = container_of(chip, struct bcm2835_gpio_chip, chip);
+ void __iomem *base = bcmgpio->base;
+ unsigned gpio_bank = gpio / 32;
+ unsigned gpio_field_offset = gpio % 32;
+ unsigned lev;
+
+ lev = readl(base + GPIOLEV(gpio_bank));
+ return 0x1 & (lev >> gpio_field_offset);
+}
+
+static int bcm2835_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ return bcm2835_set_function(chip, gpio, GPIO_FSEL_INPUT);
+}
+
+static int bcm2835_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ bcm2835_set_function(chip, gpio, GPIO_FSEL_OUTPUT);
+ bcm2835_gpio_set_value(chip, gpio, value);
+
+ return 0;
+}
+
+static struct gpio_ops bcm2835_gpio_ops = {
+ .direction_input = bcm2835_gpio_direction_input,
+ .direction_output = bcm2835_gpio_direction_output,
+ .get = bcm2835_gpio_get_value,
+ .set = bcm2835_gpio_set_value,
+};
+
+static int bcm2835_gpio_probe(struct device_d *dev)
+{
+ struct bcm2835_gpio_chip *bcmgpio;
+ int ret;
+
+ bcmgpio = xzalloc(sizeof(*bcmgpio));
+ bcmgpio->base = dev_request_mem_region(dev, 0);
+ bcmgpio->chip.ops = &bcm2835_gpio_ops;
+ bcmgpio->chip.base = 0;
+ bcmgpio->chip.ngpio = 54;
+ bcmgpio->chip.dev = dev;
+
+ ret = gpiochip_add(&bcmgpio->chip);
+ if (ret) {
+ dev_err(dev, "couldn't add gpiochip, ret = %d\n", ret);
+ goto err;
+ }
+ dev_info(dev, "probed gpiochip%d with base %d\n", dev->id, bcmgpio->chip.base);
+
+ return 0;
+
+err:
+ kfree(bcmgpio);
+
+ return ret;
+}
+
+static __maybe_unused struct of_device_id bcm2835_gpio_dt_ids[] = {
+ {
+ .compatible = "brcm,bcm2835-gpio",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d bcm2835_gpio_driver = {
+ .name = "bcm2835-gpio",
+ .probe = bcm2835_gpio_probe,
+ .of_compatible = DRV_OF_COMPAT(bcm2835_gpio_dt_ids),
+};
+
+static int bcm2835_gpio_add(void)
+{
+ return platform_driver_register(&bcm2835_gpio_driver);
+}
+coredevice_initcall(bcm2835_gpio_add);
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
new file mode 100644
index 0000000000..f34aba9da9
--- /dev/null
+++ b/drivers/gpio/gpio-pl061.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2008, 2009 Provigent Ltd.
+ *
+ * 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.
+ *
+ * Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061)
+ *
+ * Data sheet: ARM DDI 0190B, September 2000
+ */
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <io.h>
+#include <gpio.h>
+#include <init.h>
+
+#include <linux/amba/bus.h>
+#include <linux/amba/pl061.h>
+
+#define GPIODIR 0x400
+#define GPIOIS 0x404
+#define GPIOIBE 0x408
+#define GPIOIEV 0x40C
+#define GPIOIE 0x410
+#define GPIORIS 0x414
+#define GPIOMIS 0x418
+#define GPIOIC 0x41C
+
+#define PL061_GPIO_NR 8
+
+struct pl061_gpio {
+ void __iomem *base;
+ struct gpio_chip gc;
+};
+
+static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+ struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+ unsigned char gpiodir;
+
+ if (offset >= gc->ngpio)
+ return -EINVAL;
+
+ gpiodir = readb(chip->base + GPIODIR);
+ gpiodir &= ~(1 << offset);
+ writeb(gpiodir, chip->base + GPIODIR);
+
+ return 0;
+}
+
+static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
+ int value)
+{
+ struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+ unsigned char gpiodir;
+
+ if (offset >= gc->ngpio)
+ return -EINVAL;
+
+ writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+ gpiodir = readb(chip->base + GPIODIR);
+ gpiodir |= 1 << offset;
+ writeb(gpiodir, chip->base + GPIODIR);
+
+ /*
+ * gpio value is set again, because pl061 doesn't allow to set value of
+ * a gpio pin before configuring it in OUT mode.
+ */
+ writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+
+ return 0;
+}
+
+static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
+{
+ struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+ return !!readb(chip->base + (1 << (offset + 2)));
+}
+
+static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
+{
+ struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+ writeb(!!value << offset, chip->base + (1 << (offset + 2)));
+}
+
+static struct gpio_ops pl061_gpio_ops = {
+ .direction_input = pl061_direction_input,
+ .direction_output = pl061_direction_output,
+ .get = pl061_get_value,
+ .set = pl061_set_value,
+};
+
+static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
+{
+ struct pl061_platform_data *pdata;
+ struct pl061_gpio *chip;
+ int ret;
+
+ chip = xzalloc(sizeof(*chip));
+
+ pdata = dev->dev.platform_data;
+ if (pdata) {
+ chip->gc.base = pdata->gpio_base;
+ } else {
+ chip->gc.base = -1;
+ }
+
+ chip->base = amba_get_mem_region(dev);
+
+ chip->gc.ops = &pl061_gpio_ops;
+ chip->gc.ngpio = PL061_GPIO_NR;
+ chip->gc.dev = &dev->dev;
+
+ ret = gpiochip_add(&chip->gc);
+ if (ret) {
+ dev_err(&dev->dev, "couldn't add gpiochip, ret = %d\n", ret);
+ goto free_mem;
+ }
+
+ writeb(0, chip->base + GPIOIE); /* disable irqs */
+
+ return 0;
+
+free_mem:
+ kfree(chip);
+
+ return ret;
+}
+
+static struct amba_id pl061_ids[] = {
+ {
+ .id = 0x00041061,
+ .mask = 0x000fffff,
+ },
+ { 0, 0 },
+};
+
+static struct amba_driver pl061_gpio_driver = {
+ .drv = {
+ .name = "pl061_gpio",
+ },
+ .id_table = pl061_ids,
+ .probe = pl061_probe,
+};
+
+static int __init pl061_gpio_init(void)
+{
+ return amba_driver_register(&pl061_gpio_driver);
+}
+coredevice_initcall(pl061_gpio_init);
+
+MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
+MODULE_DESCRIPTION("PL061 GPIO driver");
+MODULE_LICENSE("GPL");
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
new file mode 100644
index 0000000000..1997888bbb
--- /dev/null
+++ b/include/asm-generic/gpio.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_GENERIC_GPIO_H
+#define __ASM_GENERIC_GPIO_H
+
+void gpio_set_value(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_direction_input(unsigned gpio);
+
+#endif /* __ASM_GENERIC_GPIO_H */
+
diff --git a/include/linux/amba/pl061.h b/include/linux/amba/pl061.h
new file mode 100644
index 0000000000..d498cd7a8c
--- /dev/null
+++ b/include/linux/amba/pl061.h
@@ -0,0 +1,12 @@
+#ifndef __AMBA_PL061_H__
+#define __AMBA_PL061_H__
+
+#include <linux/types.h>
+
+/* platform data for the PL061 GPIO driver */
+
+struct pl061_platform_data {
+ /* number of the first GPIO */
+ unsigned gpio_base;
+};
+#endif /* __AMBA_PL061_H__ */
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index d2f0d8972e..1fc0ab9973 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -33,6 +33,7 @@ void clkdev_drop(struct clk_lookup *cl);
void clkdev_add_table(struct clk_lookup *, size_t);
int clk_add_alias(const char *, const char *, char *, struct device_d *);
+int clk_register_clkdev(struct clk *, const char *, const char *, ...);
int clkdev_add_physbase(struct clk *clk, unsigned long base, const char *id);