From 28ad94ec61dc60207dbffdb95ff870c617fbb832 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Thu, 2 Jul 2009 19:06:47 +0100 Subject: [ARM] 5590/1: Add basic support for ST Nomadik 8815 SoC and evaluation board This patch adds the basic infrastructure for the Nomadik 8815 CPU and the "Nomadik Hardware Kit" NHK8815. This patch only includes the serial console and core stuff, no drivers. Signed-off-by: Alessandro Rubini Acked-by: Andrea Gallo Signed-off-by: Russell King --- arch/arm/mach-nomadik/Kconfig | 14 ++ arch/arm/mach-nomadik/Makefile | 16 +++ arch/arm/mach-nomadik/Makefile.boot | 4 + arch/arm/mach-nomadik/board-nhk8815.c | 75 +++++++++++ arch/arm/mach-nomadik/clock.c | 45 +++++++ arch/arm/mach-nomadik/clock.h | 14 ++ arch/arm/mach-nomadik/cpu-8815.c | 58 ++++++++ arch/arm/mach-nomadik/include/mach/clkdev.h | 7 + arch/arm/mach-nomadik/include/mach/debug-macro.S | 22 +++ arch/arm/mach-nomadik/include/mach/entry-macro.S | 43 ++++++ arch/arm/mach-nomadik/include/mach/hardware.h | 90 +++++++++++++ arch/arm/mach-nomadik/include/mach/io.h | 22 +++ arch/arm/mach-nomadik/include/mach/irqs.h | 82 ++++++++++++ arch/arm/mach-nomadik/include/mach/memory.h | 28 ++++ arch/arm/mach-nomadik/include/mach/mtu.h | 45 +++++++ arch/arm/mach-nomadik/include/mach/setup.h | 22 +++ arch/arm/mach-nomadik/include/mach/system.h | 45 +++++++ arch/arm/mach-nomadik/include/mach/timex.h | 6 + arch/arm/mach-nomadik/include/mach/uncompress.h | 63 +++++++++ arch/arm/mach-nomadik/include/mach/vmalloc.h | 2 + arch/arm/mach-nomadik/timer.c | 164 +++++++++++++++++++++++ 21 files changed, 867 insertions(+) create mode 100644 arch/arm/mach-nomadik/Kconfig create mode 100644 arch/arm/mach-nomadik/Makefile create mode 100644 arch/arm/mach-nomadik/Makefile.boot create mode 100644 arch/arm/mach-nomadik/board-nhk8815.c create mode 100644 arch/arm/mach-nomadik/clock.c create mode 100644 arch/arm/mach-nomadik/clock.h create mode 100644 arch/arm/mach-nomadik/cpu-8815.c create mode 100644 arch/arm/mach-nomadik/include/mach/clkdev.h create mode 100644 arch/arm/mach-nomadik/include/mach/debug-macro.S create mode 100644 arch/arm/mach-nomadik/include/mach/entry-macro.S create mode 100644 arch/arm/mach-nomadik/include/mach/hardware.h create mode 100644 arch/arm/mach-nomadik/include/mach/io.h create mode 100644 arch/arm/mach-nomadik/include/mach/irqs.h create mode 100644 arch/arm/mach-nomadik/include/mach/memory.h create mode 100644 arch/arm/mach-nomadik/include/mach/mtu.h create mode 100644 arch/arm/mach-nomadik/include/mach/setup.h create mode 100644 arch/arm/mach-nomadik/include/mach/system.h create mode 100644 arch/arm/mach-nomadik/include/mach/timex.h create mode 100644 arch/arm/mach-nomadik/include/mach/uncompress.h create mode 100644 arch/arm/mach-nomadik/include/mach/vmalloc.h create mode 100644 arch/arm/mach-nomadik/timer.c (limited to 'arch/arm/mach-nomadik') diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig new file mode 100644 index 000000000000..abce23461061 --- /dev/null +++ b/arch/arm/mach-nomadik/Kconfig @@ -0,0 +1,14 @@ +if ARCH_NOMADIK + +menu "Nomadik boards" + +config MACH_NOMADIK_8815NHK + bool "ST 8815 Nomadik Hardware Kit (evaluation board)" + select NOMADIK_8815 + +endmenu + +config NOMADIK_8815 + bool + +endif diff --git a/arch/arm/mach-nomadik/Makefile b/arch/arm/mach-nomadik/Makefile new file mode 100644 index 000000000000..fa97769fe707 --- /dev/null +++ b/arch/arm/mach-nomadik/Makefile @@ -0,0 +1,16 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +# Object file lists. + +obj-y += clock.o timer.o + +# Cpu revision +obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o + +# Specific board support +obj-$(CONFIG_MACH_NOMADIK_8815NHK) += board-nhk8815.o diff --git a/arch/arm/mach-nomadik/Makefile.boot b/arch/arm/mach-nomadik/Makefile.boot new file mode 100644 index 000000000000..c7e75acfe6c9 --- /dev/null +++ b/arch/arm/mach-nomadik/Makefile.boot @@ -0,0 +1,4 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 + diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c new file mode 100644 index 000000000000..eebca614d36b --- /dev/null +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -0,0 +1,75 @@ +/* + * linux/arch/arm/mach-nomadik/board-8815nhk.c + * + * Copyright (C) STMicroelectronics + * + * 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. + * + * NHK15 board specifc driver definition + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clock.h" + +#define __MEM_4K_RESOURCE(x) \ + .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} + +static struct amba_device uart0_device = { + .dev = { .init_name = "uart0" }, + __MEM_4K_RESOURCE(NOMADIK_UART0_BASE), + .irq = {IRQ_UART0, NO_IRQ}, +}; + +static struct amba_device uart1_device = { + .dev = { .init_name = "uart1" }, + __MEM_4K_RESOURCE(NOMADIK_UART1_BASE), + .irq = {IRQ_UART1, NO_IRQ}, +}; + +static struct amba_device *amba_devs[] __initdata = { + &uart0_device, + &uart1_device, +}; + +/* We have a fixed clock alone, by now */ +static struct clk nhk8815_clk_48 = { + .rate = 48*1000*1000, +}; + +static struct platform_device *nhk8815_platform_devices[] __initdata = { + /* currently empty, will add keypad, touchscreen etc */ +}; + +static void __init nhk8815_platform_init(void) +{ + int i; + + cpu8815_platform_init(); + platform_add_devices(nhk8815_platform_devices, + ARRAY_SIZE(nhk8815_platform_devices)); + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + nmdk_clk_create(&nhk8815_clk_48, amba_devs[i]->dev.init_name); + amba_device_register(amba_devs[i], &iomem_resource); + } +} + +MACHINE_START(NOMADIK, "NHK8815") + /* Maintainer: ST MicroElectronics */ + .phys_io = NOMADIK_UART0_BASE, + .io_pg_offst = (IO_ADDRESS(NOMADIK_UART0_BASE) >> 18) & 0xfffc, + .boot_params = 0x100, + .map_io = cpu8815_map_io, + .init_irq = cpu8815_init_irq, + .timer = &nomadik_timer, + .init_machine = nhk8815_platform_init, +MACHINE_END diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c new file mode 100644 index 000000000000..9f92502a0083 --- /dev/null +++ b/arch/arm/mach-nomadik/clock.c @@ -0,0 +1,45 @@ +/* + * linux/arch/arm/mach-nomadik/clock.c + * + * Copyright (C) 2009 Alessandro Rubini + */ +#include +#include +#include +#include +#include +#include "clock.h" + +/* + * The nomadik board uses generic clocks, but the serial pl011 file + * calls clk_enable(), clk_disable(), clk_get_rate(), so we provide them + */ +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +/* enable and disable do nothing */ +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +/* Create a clock structure with the given name */ +int nmdk_clk_create(struct clk *clk, const char *dev_id) +{ + struct clk_lookup *clkdev; + + clkdev = clkdev_alloc(clk, NULL, dev_id); + if (!clkdev) + return -ENOMEM; + clkdev_add(clkdev); + return 0; +} diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h new file mode 100644 index 000000000000..235faec7f627 --- /dev/null +++ b/arch/arm/mach-nomadik/clock.h @@ -0,0 +1,14 @@ + +/* + * linux/arch/arm/mach-nomadik/clock.h + * + * Copyright (C) 2009 Alessandro Rubini + * + * 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. + */ +struct clk { + unsigned long rate; +}; +extern int nmdk_clk_create(struct clk *clk, const char *dev_id); diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c new file mode 100644 index 000000000000..dec42da6956a --- /dev/null +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -0,0 +1,58 @@ +/* + * Copyright STMicroelectronics, 2007. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + +#include +#include +#include +#include + +/* All SoC devices live in the same area (see hardware.h) */ +static struct map_desc nomadik_io_desc[] __initdata = { + { + .virtual = NOMADIK_IO_VIRTUAL, + .pfn = __phys_to_pfn(NOMADIK_IO_PHYSICAL), + .length = NOMADIK_IO_SIZE, + .type = MT_DEVICE, + } + /* static ram and secured ram may be added later */ +}; + +void __init cpu8815_map_io(void) +{ + iotable_init(nomadik_io_desc, ARRAY_SIZE(nomadik_io_desc)); +} + +void __init cpu8815_init_irq(void) +{ + /* This modified VIC cell has two register blocks, at 0 and 0x20 */ + vic_init(io_p2v(NOMADIK_IC_BASE + 0x00), IRQ_VIC_START + 0, ~0, 0); + vic_init(io_p2v(NOMADIK_IC_BASE + 0x20), IRQ_VIC_START + 32, ~0, 0); +} + +/* + * This function is called from the board init ("init_machine"). + * Currently nothing is done as we can't register amba devs so early. + */ + void __init cpu8815_platform_init(void) +{ + return; +} diff --git a/arch/arm/mach-nomadik/include/mach/clkdev.h b/arch/arm/mach-nomadik/include/mach/clkdev.h new file mode 100644 index 000000000000..04b37a89801c --- /dev/null +++ b/arch/arm/mach-nomadik/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-nomadik/include/mach/debug-macro.S b/arch/arm/mach-nomadik/include/mach/debug-macro.S new file mode 100644 index 000000000000..e876990e1569 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/debug-macro.S @@ -0,0 +1,22 @@ +/* + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * 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. + * +*/ + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x10000000 @ physical base address + movne \rx, #0xf0000000 @ virtual base + add \rx, \rx, #0x00100000 + add \rx, \rx, #0x000fb000 + .endm + +#include diff --git a/arch/arm/mach-nomadik/include/mach/entry-macro.S b/arch/arm/mach-nomadik/include/mach/entry-macro.S new file mode 100644 index 000000000000..49f1aa3bb420 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/entry-macro.S @@ -0,0 +1,43 @@ +/* + * Low-level IRQ helper macros for Nomadik platforms + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =IO_ADDRESS(NOMADIK_IC_BASE) + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + /* This stanza gets the irq mask from one of two status registers */ + mov \irqnr, #0 + ldr \irqstat, [\base, #VIC_REG_IRQSR0] @ get masked status + cmp \irqstat, #0 + bne 1001f + add \irqnr, \irqnr, #32 + ldr \irqstat, [\base, #VIC_REG_IRQSR1] @ get masked status + +1001: tst \irqstat, #15 + bne 1002f + add \irqnr, \irqnr, #4 + movs \irqstat, \irqstat, lsr #4 + bne 1001b +1002: tst \irqstat, #1 + bne 1003f + add \irqnr, \irqnr, #1 + movs \irqstat, \irqstat, lsr #1 + bne 1002b +1003: /* EQ will be set if no irqs pending */ + .endm diff --git a/arch/arm/mach-nomadik/include/mach/hardware.h b/arch/arm/mach-nomadik/include/mach/hardware.h new file mode 100644 index 000000000000..6316dba3bfc8 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/hardware.h @@ -0,0 +1,90 @@ +/* + * This file contains the hardware definitions of the 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. + * + * YOU should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* Nomadik registers live from 0x1000.0000 to 0x1023.0000 -- currently */ +#define NOMADIK_IO_VIRTUAL 0xF0000000 /* VA of IO */ +#define NOMADIK_IO_PHYSICAL 0x10000000 /* PA of IO */ +#define NOMADIK_IO_SIZE 0x00300000 /* 3MB for all regs */ + +/* used in C code, so cast to proper type */ +#define io_p2v(x) ((void __iomem *)(x) \ + - NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL) +#define io_v2p(x) ((unsigned long)(x) \ + - NOMADIK_IO_VIRTUAL + NOMADIK_IO_PHYSICAL) + +/* used in asm code, so no casts */ +#define IO_ADDRESS(x) ((x) - NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL) + +/* + * Base address defination for Nomadik Onchip Logic Block + */ +#define NOMADIK_FSMC_BASE 0x10100000 /* FSMC registers */ +#define NOMADIK_SDRAMC_BASE 0x10110000 /* SDRAM Controller */ +#define NOMADIK_CLCDC_BASE 0x10120000 /* CLCD Controller */ +#define NOMADIK_MDIF_BASE 0x10120000 /* MDIF */ +#define NOMADIK_DMA0_BASE 0x10130000 /* DMA0 Controller */ +#define NOMADIK_IC_BASE 0x10140000 /* Vectored Irq Controller */ +#define NOMADIK_DMA1_BASE 0x10150000 /* DMA1 Controller */ +#define NOMADIK_USB_BASE 0x10170000 /* USB-OTG conf reg base */ +#define NOMADIK_CRYP_BASE 0x10180000 /* Crypto processor */ +#define NOMADIK_SHA1_BASE 0x10190000 /* SHA-1 Processor */ +#define NOMADIK_XTI_BASE 0x101A0000 /* XTI */ +#define NOMADIK_RNG_BASE 0x101B0000 /* Random number generator */ +#define NOMADIK_SRC_BASE 0x101E0000 /* SRC base */ +#define NOMADIK_WDOG_BASE 0x101E1000 /* Watchdog */ +#define NOMADIK_MTU0_BASE 0x101E2000 /* Multiple Timer 0 */ +#define NOMADIK_MTU1_BASE 0x101E3000 /* Multiple Timer 1 */ +#define NOMADIK_GPIO0_BASE 0x101E4000 /* GPIO0 */ +#define NOMADIK_GPIO1_BASE 0x101E5000 /* GPIO1 */ +#define NOMADIK_GPIO2_BASE 0x101E6000 /* GPIO2 */ +#define NOMADIK_GPIO3_BASE 0x101E7000 /* GPIO3 */ +#define NOMADIK_RTC_BASE 0x101E8000 /* Real Time Clock base */ +#define NOMADIK_PMU_BASE 0x101E9000 /* Power Management Unit */ +#define NOMADIK_OWM_BASE 0x101EA000 /* One wire master */ +#define NOMADIK_SCR_BASE 0x101EF000 /* Secure Control registers */ +#define NOMADIK_MSP2_BASE 0x101F0000 /* MSP 2 interface */ +#define NOMADIK_MSP1_BASE 0x101F1000 /* MSP 1 interface */ +#define NOMADIK_UART2_BASE 0x101F2000 /* UART 2 interface */ +#define NOMADIK_SSIRx_BASE 0x101F3000 /* SSI 8-ch rx interface */ +#define NOMADIK_SSITx_BASE 0x101F4000 /* SSI 8-ch tx interface */ +#define NOMADIK_MSHC_BASE 0x101F5000 /* Memory Stick(Pro) Host */ +#define NOMADIK_SDI_BASE 0x101F6000 /* SD-card/MM-Card */ +#define NOMADIK_I2C1_BASE 0x101F7000 /* I2C1 interface */ +#define NOMADIK_I2C0_BASE 0x101F8000 /* I2C0 interface */ +#define NOMADIK_MSP0_BASE 0x101F9000 /* MSP 0 interface */ +#define NOMADIK_FIRDA_BASE 0x101FA000 /* FIrDA interface */ +#define NOMADIK_UART1_BASE 0x101FB000 /* UART 1 interface */ +#define NOMADIK_SSP_BASE 0x101FC000 /* SSP interface */ +#define NOMADIK_UART0_BASE 0x101FD000 /* UART 0 interface */ +#define NOMADIK_SGA_BASE 0x101FE000 /* SGA interface */ +#define NOMADIK_L2CC_BASE 0x10210000 /* L2 Cache controller */ + +/* Other ranges, not for p2v/v2p */ +#define NOMADIK_BACKUP_RAM 0x80010000 +#define NOMADIK_EBROM 0x80000000 /* Embedded boot ROM */ +#define NOMADIK_HAMACV_DMEM_BASE 0xA0100000 /* HAMACV Data Memory Start */ +#define NOMADIK_HAMACV_DMEM_END 0xA01FFFFF /* HAMACV Data Memory End */ +#define NOMADIK_HAMACA_DMEM 0xA0200000 /* HAMACA Data Memory Space */ + +#define NOMADIK_FSMC_VA IO_ADDRESS(NOMADIK_FSMC_BASE) +#define NOMADIK_MTU0_VA IO_ADDRESS(NOMADIK_MTU0_BASE) +#define NOMADIK_MTU1_VA IO_ADDRESS(NOMADIK_MTU1_BASE) + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-nomadik/include/mach/io.h b/arch/arm/mach-nomadik/include/mach/io.h new file mode 100644 index 000000000000..2e1eca1b8243 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/io.h @@ -0,0 +1,22 @@ +/* + * arch/arm/mach-nomadik/include/mach/io.h (copied from mach-sa1100) + * + * Copyright (C) 1997-1999 Russell King + * + * Modifications: + * 06-12-1997 RMK Created. + * 07-04-1999 RMK Major cleanup + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +/* + * We don't actually have real ISA nor PCI buses, but there is so many + * drivers out there that might just work if we fake them... + */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/irqs.h b/arch/arm/mach-nomadik/include/mach/irqs.h new file mode 100644 index 000000000000..8faabc560398 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/irqs.h @@ -0,0 +1,82 @@ +/* + * mach-nomadik/include/mach/irqs.h + * + * Copyright (C) ST Microelectronics + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#include + +#define IRQ_VIC_START 0 /* first VIC interrupt is 0 */ + +/* + * Interrupt numbers generic for all Nomadik Chip cuts + */ +#define IRQ_WATCHDOG 0 +#define IRQ_SOFTINT 1 +#define IRQ_CRYPTO 2 +#define IRQ_OWM 3 +#define IRQ_MTU0 4 +#define IRQ_MTU1 5 +#define IRQ_GPIO0 6 +#define IRQ_GPIO1 7 +#define IRQ_GPIO2 8 +#define IRQ_GPIO3 9 +#define IRQ_RTC_RTT 10 +#define IRQ_SSP 11 +#define IRQ_UART0 12 +#define IRQ_DMA1 13 +#define IRQ_CLCD_MDIF 14 +#define IRQ_DMA0 15 +#define IRQ_PWRFAIL 16 +#define IRQ_UART1 17 +#define IRQ_FIRDA 18 +#define IRQ_MSP0 19 +#define IRQ_I2C0 20 +#define IRQ_I2C1 21 +#define IRQ_SDMMC 22 +#define IRQ_USBOTG 23 +#define IRQ_SVA_IT0 24 +#define IRQ_SVA_IT1 25 +#define IRQ_SAA_IT0 26 +#define IRQ_SAA_IT1 27 +#define IRQ_UART2 28 +#define IRQ_MSP2 31 +#define IRQ_L2CC 48 +#define IRQ_HPI 49 +#define IRQ_SKE 50 +#define IRQ_KP 51 +#define IRQ_MEMST 54 +#define IRQ_SGA_IT 58 +#define IRQ_USBM 60 +#define IRQ_MSP1 62 + +#define NOMADIK_SOC_NR_IRQS 64 + +/* After chip-specific IRQ numbers we have the GPIO ones */ +#define NOMADIK_NR_GPIO 128 /* last 4 not wired to pins */ +#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + NOMADIK_SOC_NR_IRQS) +#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - NOMADIK_SOC_NR_IRQS) +#define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) + +/* Following two are used by entry_macro.S, to access our dual-vic */ +#define VIC_REG_IRQSR0 0 +#define VIC_REG_IRQSR1 0x20 + +#endif /* __ASM_ARCH_IRQS_H */ + diff --git a/arch/arm/mach-nomadik/include/mach/memory.h b/arch/arm/mach-nomadik/include/mach/memory.h new file mode 100644 index 000000000000..1e5689d98ecd --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/memory.h @@ -0,0 +1,28 @@ +/* + * mach-nomadik/include/mach/memory.h + * + * Copyright (C) 1999 ARM Limited + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* + * Physical DRAM offset. + */ +#define PHYS_OFFSET UL(0x00000000) + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/mtu.h b/arch/arm/mach-nomadik/include/mach/mtu.h new file mode 100644 index 000000000000..76da7f085330 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/mtu.h @@ -0,0 +1,45 @@ +#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/setup.h b/arch/arm/mach-nomadik/include/mach/setup.h new file mode 100644 index 000000000000..a4e468cf63da --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/setup.h @@ -0,0 +1,22 @@ + +/* + * These symbols are needed for board-specific files to call their + * own cpu-specific files + */ + +#ifndef __ASM_ARCH_SETUP_H +#define __ASM_ARCH_SETUP_H + +#include +#include + +#ifdef CONFIG_NOMADIK_8815 + +extern void cpu8815_map_io(void); +extern void cpu8815_platform_init(void); +extern void cpu8815_init_irq(void); +extern struct sys_timer nomadik_timer; + +#endif /* NOMADIK_8815 */ + +#endif /* __ASM_ARCH_SETUP_H */ diff --git a/arch/arm/mach-nomadik/include/mach/system.h b/arch/arm/mach-nomadik/include/mach/system.h new file mode 100644 index 000000000000..7119f688116e --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/system.h @@ -0,0 +1,45 @@ +/* + * mach-nomadik/include/mach/system.h + * + * Copyright (C) 2008 STMicroelectronics + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include +#include + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ + void __iomem *src_rstsr = io_p2v(NOMADIK_SRC_BASE + 0x18); + + /* FIXME: use egpio when implemented */ + + /* Write anything to Reset status register */ + writel(1, src_rstsr); +} + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/timex.h b/arch/arm/mach-nomadik/include/mach/timex.h new file mode 100644 index 000000000000..318b8896ce96 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/timex.h @@ -0,0 +1,6 @@ +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +#define CLOCK_TICK_RATE 2400000 + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/uncompress.h b/arch/arm/mach-nomadik/include/mach/uncompress.h new file mode 100644 index 000000000000..071003bc8456 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/uncompress.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 STMicroelectronics + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include +#include +#include + +/* we need the constants in amba/serial.h, but it refers to amba_device */ +struct amba_device; +#include + +#define NOMADIK_UART_DR 0x101FB000 +#define NOMADIK_UART_LCRH 0x101FB02c +#define NOMADIK_UART_CR 0x101FB030 +#define NOMADIK_UART_FR 0x101FB018 + +static void putc(const char c) +{ + /* Do nothing if the UART is not enabled. */ + if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN)) + return; + + if (c == '\n') + putc('\r'); + + while (readb(NOMADIK_UART_FR) & UART01x_FR_TXFF) + barrier(); + writeb(c, NOMADIK_UART_DR); +} + +static void flush(void) +{ + if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN)) + return; + while (readb(NOMADIK_UART_FR) & UART01x_FR_BUSY) + barrier(); +} + +static inline void arch_decomp_setup(void) +{ +} + +#define arch_decomp_wdog() /* nothing to do here */ + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-nomadik/include/mach/vmalloc.h b/arch/arm/mach-nomadik/include/mach/vmalloc.h new file mode 100644 index 000000000000..be12e31ea528 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/vmalloc.h @@ -0,0 +1,2 @@ + +#define VMALLOC_END 0xe8000000 diff --git a/arch/arm/mach-nomadik/timer.c b/arch/arm/mach-nomadik/timer.c new file mode 100644 index 000000000000..d1738e7061d4 --- /dev/null +++ b/arch/arm/mach-nomadik/timer.c @@ -0,0 +1,164 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_CTRL 0x80 /* No divisor */ +#define TIMER_PERIODIC 0x40 +#define TIMER_SZ32BIT 0x02 + +/* 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_count; /* accumulated count */ +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 cycle_t nmdk_read_timer(struct clocksource *cs) +{ + u32 count = readl(mtu_base + MTU_VAL(0)); + return nmdk_count + nmdk_cycle - count; + +} + +static struct clocksource nmdk_clksrc = { + .name = "mtu_0", + .rating = 120, + .read = nmdk_read_timer, + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +/* + * Clockevent device: currently only periodic mode is supported + */ +static void nmdk_clkevt_mode(enum clock_event_mode mode, + struct clock_event_device *dev) +{ + unsigned long flags; + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* enable interrupts -- and count current value? */ + raw_local_irq_save(flags); + writel(readl(mtu_base + MTU_IMSC) | 1, mtu_base + MTU_IMSC); + raw_local_irq_restore(flags); + break; + case CLOCK_EVT_MODE_ONESHOT: + BUG(); /* Not supported, yet */ + /* FALLTHROUGH */ + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + /* disable irq */ + raw_local_irq_save(flags); + writel(readl(mtu_base + MTU_IMSC) & ~1, mtu_base + MTU_IMSC); + raw_local_irq_restore(flags); + break; + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device nmdk_clkevt = { + .name = "mtu_0", + .features = CLOCK_EVT_FEAT_PERIODIC, + .shift = 32, + .rating = 100, + .set_mode = nmdk_clkevt_mode, +}; + +/* + * IRQ Handler for the timer 0 of the MTU block. The irq is not shared + * as we are the only users of mtu0 by now. + */ +static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id) +{ + /* ack: "interrupt clear register" */ + writel( 1 << 0, mtu_base + MTU_ICR); + + /* we can't count lost ticks, unfortunately */ + nmdk_count += nmdk_cycle; + nmdk_clkevt.event_handler(&nmdk_clkevt); + + return IRQ_HANDLED; +} + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +static struct irqaction nmdk_timer_irq = { + .name = "Nomadik Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = nmdk_timer_interrupt, +}; + +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_PERIODIC | 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 void __init nmdk_timer_init(void) +{ + u32 src_cr; + unsigned long rate; + int bits; + + rate = CLOCK_TICK_RATE; /* 2.4MHz */ + nmdk_cycle = (rate + HZ/2) / HZ; + + /* Configure timer sources in "system reset controller" ctrl reg */ + src_cr = readl(io_p2v(NOMADIK_SRC_BASE)); + src_cr &= SRC_CR_INIT_MASK; + src_cr |= SRC_CR_INIT_VAL; + writel(src_cr, io_p2v(NOMADIK_SRC_BASE)); + + /* Save global pointer to mtu, used by functions above */ + mtu_base = io_p2v(NOMADIK_MTU0_BASE); + + /* Init the timer and register clocksource */ + nmdk_timer_reset(); + + nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift); + bits = 8*sizeof(nmdk_count); + nmdk_clksrc.mask = CLOCKSOURCE_MASK(bits); + + clocksource_register(&nmdk_clksrc); + + /* Register irq and clockevents */ + setup_irq(IRQ_MTU0, &nmdk_timer_irq); + nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift); + nmdk_clkevt.cpumask = cpumask_of(0); + clockevents_register_device(&nmdk_clkevt); +} + +struct sys_timer nomadik_timer = { + .init = nmdk_timer_init, +}; -- cgit v1.2.3 From 2ec1d3594563e0283873e24bb5d100dffee5d568 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Thu, 2 Jul 2009 15:29:12 +0100 Subject: [ARM] 5584/1: nomadik: add gpio driver and devices Signed-off-by: Alessandro Rubini Acked-by: Andrea Gallo Signed-off-by: Russell King --- arch/arm/mach-nomadik/Makefile | 2 +- arch/arm/mach-nomadik/cpu-8815.c | 75 ++++++ arch/arm/mach-nomadik/gpio.c | 396 ++++++++++++++++++++++++++++++ arch/arm/mach-nomadik/include/mach/gpio.h | 71 ++++++ 4 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-nomadik/gpio.c create mode 100644 arch/arm/mach-nomadik/include/mach/gpio.h (limited to 'arch/arm/mach-nomadik') diff --git a/arch/arm/mach-nomadik/Makefile b/arch/arm/mach-nomadik/Makefile index fa97769fe707..3fc43543e6e7 100644 --- a/arch/arm/mach-nomadik/Makefile +++ b/arch/arm/mach-nomadik/Makefile @@ -7,7 +7,7 @@ # Object file lists. -obj-y += clock.o timer.o +obj-y += clock.o timer.o gpio.o # Cpu revision obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index dec42da6956a..9917a9abdb52 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -19,12 +19,87 @@ #include #include #include +#include +#include #include #include #include #include +/* The 8815 has 4 GPIO blocks, let's register them immediately */ +static struct nmk_gpio_platform_data cpu8815_gpio[] = { + { + .name = "GPIO-0-31", + .first_gpio = 0, + .first_irq = NOMADIK_GPIO_TO_IRQ(0), + .parent_irq = IRQ_GPIO0, + }, { + .name = "GPIO-32-63", + .first_gpio = 32, + .first_irq = NOMADIK_GPIO_TO_IRQ(32), + .parent_irq = IRQ_GPIO1, + }, { + .name = "GPIO-64-95", + .first_gpio = 64, + .first_irq = NOMADIK_GPIO_TO_IRQ(64), + .parent_irq = IRQ_GPIO2, + }, { + .name = "GPIO-96-127", /* 124..127 not routed to pin */ + .first_gpio = 96, + .first_irq = NOMADIK_GPIO_TO_IRQ(96), + .parent_irq = IRQ_GPIO3, + } +}; + +#define __MEM_4K_RESOURCE(x) \ + .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} + +static struct amba_device cpu8815_amba_gpio[] = { + { + .dev = { + .init_name = "gpio0", + .platform_data = cpu8815_gpio + 0, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO0_BASE), + }, { + .dev = { + .init_name = "gpio1", + .platform_data = cpu8815_gpio + 1, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO1_BASE), + }, { + .dev = { + .init_name = "gpio2", + .platform_data = cpu8815_gpio + 2, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO2_BASE), + }, { + .dev = { + .init_name = "gpio3", + .platform_data = cpu8815_gpio + 3, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO3_BASE), + }, +}; + +static struct amba_device *amba_devs[] __initdata = { + cpu8815_amba_gpio + 0, + cpu8815_amba_gpio + 1, + cpu8815_amba_gpio + 2, + cpu8815_amba_gpio + 3, +}; + +static int __init cpu8815_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) + amba_device_register(amba_devs[i], &iomem_resource); + return 0; +} +arch_initcall(cpu8815_init); + /* All SoC devices live in the same area (see hardware.h) */ static struct map_desc nomadik_io_desc[] __initdata = { { diff --git a/arch/arm/mach-nomadik/gpio.c b/arch/arm/mach-nomadik/gpio.c new file mode 100644 index 000000000000..9a09b2791e03 --- /dev/null +++ b/arch/arm/mach-nomadik/gpio.c @@ -0,0 +1,396 @@ +/* + * Generic GPIO driver for logic cells found in the Nomadik SoC + * + * Copyright (C) 2008,2009 STMicroelectronics + * Copyright (C) 2009 Alessandro Rubini + * Rewritten based on work by Prafulla WADASKAR + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * The GPIO module in the Nomadik family of Systems-on-Chip is an + * AMBA device, managing 32 pins and alternate functions. The logic block + * is currently only used in the Nomadik. + * + * Symbols in this file are called "nmk_gpio" for "nomadik gpio" + */ + +#define NMK_GPIO_PER_CHIP 32 +struct nmk_gpio_chip { + struct gpio_chip chip; + void __iomem *addr; + unsigned int parent_irq; + spinlock_t *lock; + /* Keep track of configured edges */ + u32 edge_rising; + u32 edge_falling; +}; + +/* Mode functions */ +int nmk_gpio_set_mode(int gpio, int gpio_mode) +{ + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 afunc, bfunc, bit; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + bit = 1 << (gpio - nmk_chip->chip.base); + + spin_lock_irqsave(&nmk_chip->lock, flags); + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; + if (gpio_mode & NMK_GPIO_ALT_A) + afunc |= bit; + if (gpio_mode & NMK_GPIO_ALT_B) + bfunc |= bit; + writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); + writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; +} +EXPORT_SYMBOL(nmk_gpio_set_mode); + +int nmk_gpio_get_mode(int gpio) +{ + struct nmk_gpio_chip *nmk_chip; + u32 afunc, bfunc, bit; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + bit = 1 << (gpio - nmk_chip->chip.base); + + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; + + return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); +} +EXPORT_SYMBOL(nmk_gpio_get_mode); + + +/* IRQ functions */ +static inline int nmk_gpio_get_bitmask(int gpio) +{ + return 1 << (gpio % 32); +} + +static void nmk_gpio_irq_ack(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + if (!nmk_chip) + return; + writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); +} + +static void nmk_gpio_irq_mask(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask, reg; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return; + + /* we must individually clear the two edges */ + spin_lock_irqsave(&nmk_chip->lock, flags); + if (nmk_chip->edge_rising & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg &= ~bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + } + if (nmk_chip->edge_falling & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg &= ~bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + } + spin_unlock_irqrestore(&nmk_chip->lock, flags); +}; + +static void nmk_gpio_irq_unmask(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask, reg; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return; + + /* we must individually set the two edges */ + spin_lock_irqsave(&nmk_chip->lock, flags); + if (nmk_chip->edge_rising & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg |= bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + } + if (nmk_chip->edge_falling & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg |= bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + } + spin_unlock_irqrestore(&nmk_chip->lock, flags); +} + +static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return -EINVAL; + + if (type & IRQ_TYPE_LEVEL_HIGH) + return -EINVAL; + if (type & IRQ_TYPE_LEVEL_LOW) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); + + nmk_chip->edge_rising &= ~bitmask; + if (type & IRQ_TYPE_EDGE_RISING) + nmk_chip->edge_rising |= bitmask; + writel(nmk_chip->edge_rising, nmk_chip->addr + NMK_GPIO_RIMSC); + + nmk_chip->edge_falling &= ~bitmask; + if (type & IRQ_TYPE_EDGE_FALLING) + nmk_chip->edge_falling |= bitmask; + writel(nmk_chip->edge_falling, nmk_chip->addr + NMK_GPIO_FIMSC); + + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + nmk_gpio_irq_unmask(irq); + + return 0; +} + +static struct irq_chip nmk_gpio_irq_chip = { + .name = "Nomadik-GPIO", + .ack = nmk_gpio_irq_ack, + .mask = nmk_gpio_irq_mask, + .unmask = nmk_gpio_irq_unmask, + .set_type = nmk_gpio_irq_set_type, +}; + +static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct nmk_gpio_chip *nmk_chip; + struct irq_chip *host_chip; + unsigned int gpio_irq; + u32 pending; + unsigned int first_irq; + + nmk_chip = get_irq_data(irq); + first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); + while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { + gpio_irq = first_irq + __ffs(pending); + generic_handle_irq(gpio_irq); + } + if (0) {/* don't ack parent irq, as ack == disable */ + host_chip = get_irq_chip(irq); + host_chip->ack(irq); + } +} + +static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) +{ + unsigned int first_irq; + int i; + + first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); + for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) { + set_irq_chip(i, &nmk_gpio_irq_chip); + set_irq_handler(i, handle_edge_irq); + set_irq_flags(i, IRQF_VALID); + set_irq_chip_data(i, nmk_chip); + } + set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); + set_irq_data(nmk_chip->parent_irq, nmk_chip); + return 0; +} + +/* I/O Functions */ +static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); + return 0; +} + +static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); + return 0; +} + +static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + u32 bit = 1 << offset; + + return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; +} + +static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + u32 bit = 1 << offset; + + if (val) + writel(bit, nmk_chip->addr + NMK_GPIO_DATS); + else + writel(bit, nmk_chip->addr + NMK_GPIO_DATC); +} + +/* This structure is replicated for each GPIO block allocated at probe time */ +static struct gpio_chip nmk_gpio_template = { + .direction_input = nmk_gpio_make_input, + .get = nmk_gpio_get_input, + .direction_output = nmk_gpio_make_output, + .set = nmk_gpio_set_output, + .ngpio = NMK_GPIO_PER_CHIP, + .can_sleep = 0, +}; + +static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) +{ + struct nmk_gpio_platform_data *pdata; + struct nmk_gpio_chip *nmk_chip; + struct gpio_chip *chip; + int ret; + + pdata = dev->dev.platform_data; + ret = amba_request_regions(dev, pdata->name); + if (ret) + return ret; + + nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); + if (!nmk_chip) { + ret = -ENOMEM; + goto out_amba; + } + /* + * The virt address in nmk_chip->addr is in the nomadik register space, + * so we can simply convert the resource address, without remapping + */ + nmk_chip->addr = io_p2v(dev->res.start); + nmk_chip->chip = nmk_gpio_template; + nmk_chip->parent_irq = pdata->parent_irq; + + chip = &nmk_chip->chip; + chip->base = pdata->first_gpio; + chip->label = pdata->name; + chip->dev = &dev->dev; + chip->owner = THIS_MODULE; + + ret = gpiochip_add(&nmk_chip->chip); + if (ret) + goto out_free; + + amba_set_drvdata(dev, nmk_chip); + + nmk_gpio_init_irq(nmk_chip); + + dev_info(&dev->dev, "Bits %i-%i at address %p\n", + nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); + return 0; + + out_free: + kfree(nmk_chip); + out_amba: + amba_release_regions(dev); + dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, + pdata->first_gpio, pdata->first_gpio+31); + return ret; +} + +static int nmk_gpio_remove(struct amba_device *dev) +{ + struct nmk_gpio_chip *nmk_chip; + + nmk_chip = amba_get_drvdata(dev); + gpiochip_remove(&nmk_chip->chip); + kfree(nmk_chip); + amba_release_regions(dev); + return 0; +} + + +/* We have 0x1f080060 and 0x1f180060, accept both using the mask */ +static struct amba_id nmk_gpio_ids[] = { + { + .id = 0x1f080060, + .mask = 0xffefffff, + }, + {0, 0}, +}; + +static struct amba_driver nmk_gpio_driver = { + .drv = { + .owner = THIS_MODULE, + .name = "gpio", + }, + .probe = nmk_gpio_probe, + .remove = nmk_gpio_remove, + .suspend = NULL, /* to be done */ + .resume = NULL, + .id_table = nmk_gpio_ids, +}; + +static int __init nmk_gpio_init(void) +{ + return amba_driver_register(&nmk_gpio_driver); +} + +arch_initcall(nmk_gpio_init); + +MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); +MODULE_DESCRIPTION("Nomadik GPIO Driver"); +MODULE_LICENSE("GPL"); + + diff --git a/arch/arm/mach-nomadik/include/mach/gpio.h b/arch/arm/mach-nomadik/include/mach/gpio.h new file mode 100644 index 000000000000..61577c9f9a7d --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/gpio.h @@ -0,0 +1,71 @@ +/* + * Structures and registers for GPIO access in the Nomadik SoC + * + * Copyright (C) 2008 STMicroelectronics + * Author: Prafulla WADASKAR + * Copyright (C) 2009 Alessandro Rubini + * + * 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 __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#include + +/* + * These currently cause a function call to happen, they may be optimized + * if needed by adding cpu-specific defines to identify blocks + * (see mach-pxa/include/mach/gpio.h as an example using GPLR etc) + */ +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +extern int nmk_gpio_set_mode(int gpio, int gpio_mode); +extern int nmk_gpio_get_mode(int gpio); + +/* + * Platform data to register a block: only the initial gpio/irq number. + */ +struct nmk_gpio_platform_data { + char *name; + int first_gpio; + int first_irq; + int parent_irq; +}; + +#endif /* __ASM_ARCH_GPIO_H */ -- cgit v1.2.3 From 63796b740b888b396eb0cc78917d755693cc224c Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Thu, 2 Jul 2009 15:29:22 +0100 Subject: [ARM] 5585/1: nomadik: add gpio-i2c devices Signed-off-by: Alessandro Rubini Acked-by: Andrea Gallo Signed-off-by: Russell King --- arch/arm/mach-nomadik/Kconfig | 7 ++++ arch/arm/mach-nomadik/Makefile | 3 ++ arch/arm/mach-nomadik/i2c-8815nhk.c | 65 +++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 arch/arm/mach-nomadik/i2c-8815nhk.c (limited to 'arch/arm/mach-nomadik') diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig index abce23461061..2a02b49c40f0 100644 --- a/arch/arm/mach-nomadik/Kconfig +++ b/arch/arm/mach-nomadik/Kconfig @@ -11,4 +11,11 @@ endmenu config NOMADIK_8815 bool + +config I2C_BITBANG_8815NHK + tristate "Driver for bit-bang busses found on the 8815 NHK" + depends on I2C && MACH_NOMADIK_8815NHK + select I2C_ALGOBIT + default y + endif diff --git a/arch/arm/mach-nomadik/Makefile b/arch/arm/mach-nomadik/Makefile index 3fc43543e6e7..412040982a40 100644 --- a/arch/arm/mach-nomadik/Makefile +++ b/arch/arm/mach-nomadik/Makefile @@ -14,3 +14,6 @@ obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o # Specific board support obj-$(CONFIG_MACH_NOMADIK_8815NHK) += board-nhk8815.o + +# Nomadik extra devices +obj-$(CONFIG_I2C_BITBANG_8815NHK) += i2c-8815nhk.o diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c new file mode 100644 index 000000000000..abfe25a08d6b --- /dev/null +++ b/arch/arm/mach-nomadik/i2c-8815nhk.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * There are two busses in the 8815NHK. + * They could, in theory, be driven by the hardware component, but we + * use bit-bang through GPIO by now, to keep things simple + */ + +static struct i2c_gpio_platform_data nhk8815_i2c_data0 = { + /* keep defaults for timeouts; pins are push-pull bidirectional */ + .scl_pin = 62, + .sda_pin = 63, +}; + +static struct i2c_gpio_platform_data nhk8815_i2c_data1 = { + /* keep defaults for timeouts; pins are push-pull bidirectional */ + .scl_pin = 53, + .sda_pin = 54, +}; + +/* first bus: GPIO XX and YY */ +static struct platform_device nhk8815_i2c_dev0 = { + .name = "i2c-gpio", + .id = 0, + .dev = { + .platform_data = &nhk8815_i2c_data0, + }, +}; +/* second bus: GPIO XX and YY */ +static struct platform_device nhk8815_i2c_dev1 = { + .name = "i2c-gpio", + .id = 1, + .dev = { + .platform_data = &nhk8815_i2c_data1, + }, +}; + +static int __init nhk8815_i2c_init(void) +{ + nmk_gpio_set_mode(nhk8815_i2c_data0.scl_pin, NMK_GPIO_ALT_GPIO); + nmk_gpio_set_mode(nhk8815_i2c_data0.sda_pin, NMK_GPIO_ALT_GPIO); + platform_device_register(&nhk8815_i2c_dev0); + + nmk_gpio_set_mode(nhk8815_i2c_data1.scl_pin, NMK_GPIO_ALT_GPIO); + nmk_gpio_set_mode(nhk8815_i2c_data1.sda_pin, NMK_GPIO_ALT_GPIO); + platform_device_register(&nhk8815_i2c_dev1); + + return 0; +} + +static void __exit nhk8815_i2c_exit(void) +{ + platform_device_unregister(&nhk8815_i2c_dev0); + platform_device_unregister(&nhk8815_i2c_dev1); + return; +} + +module_init(nhk8815_i2c_init); +module_exit(nhk8815_i2c_exit); -- cgit v1.2.3 From 725b1f9d86822246e5a1237bf97d2783857d8a3a Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Thu, 2 Jul 2009 15:29:32 +0100 Subject: [ARM] 5586/1: nomadik board: added ethernet Signed-off-by: Alessandro Rubini Acked-by: Andrea Gallo Signed-off-by: Russell King --- arch/arm/mach-nomadik/board-nhk8815.c | 38 ++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-nomadik') diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index eebca614d36b..79bdea943eb4 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -45,8 +47,42 @@ static struct clk nhk8815_clk_48 = { .rate = 48*1000*1000, }; +static struct resource nhk8815_eth_resources[] = { + { + .name = "smc91x-regs", + .start = 0x34000000 + 0x300, + .end = 0x34000000 + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = NOMADIK_GPIO_TO_IRQ(115), + .end = NOMADIK_GPIO_TO_IRQ(115), + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING, + } +}; + +static struct platform_device nhk8815_eth_device = { + .name = "smc91x", + .resource = nhk8815_eth_resources, + .num_resources = ARRAY_SIZE(nhk8815_eth_resources), +}; + +static int __init nhk8815_eth_init(void) +{ + int gpio_nr = 115; /* hardwired in the board */ + int err; + + err = gpio_request(gpio_nr, "eth_irq"); + if (!err) err = nmk_gpio_set_mode(gpio_nr, NMK_GPIO_ALT_GPIO); + if (!err) err = gpio_direction_input(gpio_nr); + if (err) + pr_err("Error %i in %s\n", err, __func__); + return err; +} +device_initcall(nhk8815_eth_init); + static struct platform_device *nhk8815_platform_devices[] __initdata = { - /* currently empty, will add keypad, touchscreen etc */ + &nhk8815_eth_device, + /* will add more devices */ }; static void __init nhk8815_platform_init(void) -- cgit v1.2.3 From 0b260fd4b0eb7c90f9258bfa6317ae553319b5da Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Thu, 2 Jul 2009 15:29:43 +0100 Subject: [ARM] 5587/1: nomadik: add l2cc Signed-off-by: Alessandro Rubini Acked-by: Andrea Gallo Signed-off-by: Russell King --- arch/arm/mach-nomadik/cpu-8815.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-nomadik') diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 9917a9abdb52..f93c59634191 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -27,6 +27,9 @@ #include #include +#include +#include + /* The 8815 has 4 GPIO blocks, let's register them immediately */ static struct nmk_gpio_platform_data cpu8815_gpio[] = { { @@ -125,9 +128,12 @@ void __init cpu8815_init_irq(void) /* * This function is called from the board init ("init_machine"). - * Currently nothing is done as we can't register amba devs so early. */ void __init cpu8815_platform_init(void) { +#ifdef CONFIG_CACHE_L2X0 + /* At full speed latency must be >=2, so 0x249 in low bits */ + l2x0_init(io_p2v(NOMADIK_L2CC_BASE), 0x00730249, 0xfe000fff); +#endif return; } -- cgit v1.2.3