diff options
Diffstat (limited to 'arch/arm/mach-ks8695')
| -rw-r--r-- | arch/arm/mach-ks8695/Kconfig | 13 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/Makefile | 15 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/Makefile.boot | 8 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/board-micrel.c | 60 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/cpu.c | 73 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/devices.c | 191 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/generic.h | 15 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/irq.c | 175 | ||||
| -rw-r--r-- | arch/arm/mach-ks8695/time.c | 114 |
9 files changed, 664 insertions, 0 deletions
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig new file mode 100644 index 0000000000..ce1cf8de2b --- /dev/null +++ b/arch/arm/mach-ks8695/Kconfig | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | if ARCH_KS8695 | ||
| 2 | |||
| 3 | menu "Kendin/Micrel KS8695 Implementations" | ||
| 4 | |||
| 5 | config MACH_KS8695 | ||
| 6 | bool "KS8695 development board" | ||
| 7 | help | ||
| 8 | Say 'Y' here if you want your kernel to run on the original | ||
| 9 | Kendin-Micrel KS8695 development board. | ||
| 10 | |||
| 11 | endmenu | ||
| 12 | |||
| 13 | endif | ||
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile new file mode 100644 index 0000000000..56b7d33733 --- /dev/null +++ b/arch/arm/mach-ks8695/Makefile | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | # arch/arm/mach-ks8695/Makefile | ||
| 2 | # | ||
| 3 | # Makefile for KS8695 architecture support | ||
| 4 | # | ||
| 5 | |||
| 6 | obj-y := cpu.o irq.o time.o devices.o | ||
| 7 | obj-m := | ||
| 8 | obj-n := | ||
| 9 | obj- := | ||
| 10 | |||
| 11 | # PCI support is optional | ||
| 12 | #obj-$(CONFIG_PCI) += pci.o | ||
| 13 | |||
| 14 | # Board-specific support | ||
| 15 | obj-$(CONFIG_MACH_KS8695) += board-micrel.o | ||
diff --git a/arch/arm/mach-ks8695/Makefile.boot b/arch/arm/mach-ks8695/Makefile.boot new file mode 100644 index 0000000000..48eb2cb3ac --- /dev/null +++ b/arch/arm/mach-ks8695/Makefile.boot | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # Note: the following conditions must always be true: | ||
| 2 | # ZRELADDR == virt_to_phys(TEXTADDR) | ||
| 3 | # PARAMS_PHYS must be within 4MB of ZRELADDR | ||
| 4 | # INITRD_PHYS must be in RAM | ||
| 5 | |||
| 6 | zreladdr-y := 0x00008000 | ||
| 7 | params_phys-y := 0x00000100 | ||
| 8 | initrd_phys-y := 0x00800000 | ||
diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c new file mode 100644 index 0000000000..8fc0edb521 --- /dev/null +++ b/arch/arm/mach-ks8695/board-micrel.c | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ks8695/board-micrel.c | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/types.h> | ||
| 11 | #include <linux/interrupt.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | |||
| 15 | #include <asm/mach-types.h> | ||
| 16 | |||
| 17 | #include <asm/mach/arch.h> | ||
| 18 | #include <asm/mach/map.h> | ||
| 19 | #include <asm/mach/irq.h> | ||
| 20 | |||
| 21 | #include <asm/arch/devices.h> | ||
| 22 | |||
| 23 | #include "generic.h" | ||
| 24 | |||
| 25 | #ifdef CONFIG_PCI | ||
| 26 | static int __init micrel_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
| 27 | { | ||
| 28 | return KS8695_IRQ_EXTERN0; | ||
| 29 | } | ||
| 30 | |||
| 31 | static struct ks8695_pci_cfg micrel_pci = { | ||
| 32 | .mode = KS8695_MODE_MINIPCI, | ||
| 33 | .map_irq = micrel_pci_map_irq, | ||
| 34 | }; | ||
| 35 | #endif | ||
| 36 | |||
| 37 | |||
| 38 | static void micrel_init(void) | ||
| 39 | { | ||
| 40 | printk(KERN_INFO "Micrel KS8695 Development Board initializing\n"); | ||
| 41 | |||
| 42 | #ifdef CONFIG_PCI | ||
| 43 | ks8695_init_pci(&micrel_pci); | ||
| 44 | #endif | ||
| 45 | |||
| 46 | /* Add devices */ | ||
| 47 | ks8695_add_device_wan(); /* eth0 = WAN */ | ||
| 48 | ks8695_add_device_lan(); /* eth1 = LAN */ | ||
| 49 | } | ||
| 50 | |||
| 51 | MACHINE_START(KS8695, "KS8695 Centaur Development Board") | ||
| 52 | /* Maintainer: Micrel Semiconductor Inc. */ | ||
| 53 | .phys_io = KS8695_IO_PA, | ||
| 54 | .io_pg_offst = (KS8695_IO_VA >> 18) & 0xfffc, | ||
| 55 | .boot_params = KS8695_SDRAM_PA + 0x100, | ||
| 56 | .map_io = ks8695_map_io, | ||
| 57 | .init_irq = ks8695_init_irq, | ||
| 58 | .init_machine = micrel_init, | ||
| 59 | .timer = &ks8695_timer, | ||
| 60 | MACHINE_END | ||
diff --git a/arch/arm/mach-ks8695/cpu.c b/arch/arm/mach-ks8695/cpu.c new file mode 100644 index 0000000000..407d255e42 --- /dev/null +++ b/arch/arm/mach-ks8695/cpu.c | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ks8695/cpu.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk> | ||
| 5 | * Copyright (C) 2006 Simtec Electronics | ||
| 6 | * | ||
| 7 | * KS8695 CPU support | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | |||
| 28 | #include <asm/hardware.h> | ||
| 29 | #include <asm/io.h> | ||
| 30 | #include <asm/mach/arch.h> | ||
| 31 | #include <asm/mach/map.h> | ||
| 32 | |||
| 33 | #include <asm/arch/regs-sys.h> | ||
| 34 | #include <asm/arch/regs-misc.h> | ||
| 35 | |||
| 36 | |||
| 37 | static struct __initdata map_desc ks8695_io_desc[] = { | ||
| 38 | { | ||
| 39 | .virtual = KS8695_IO_VA, | ||
| 40 | .pfn = __phys_to_pfn(KS8695_IO_PA), | ||
| 41 | .length = KS8695_IO_SIZE, | ||
| 42 | .type = MT_DEVICE, | ||
| 43 | } | ||
| 44 | }; | ||
| 45 | |||
| 46 | static void __init ks8695_processor_info(void) | ||
| 47 | { | ||
| 48 | unsigned long id, rev; | ||
| 49 | |||
| 50 | id = __raw_readl(KS8695_MISC_VA + KS8695_DID); | ||
| 51 | rev = __raw_readl(KS8695_MISC_VA + KS8695_RID); | ||
| 52 | |||
| 53 | printk("KS8695 ID=%04lx SubID=%02lx Revision=%02lx\n", (id & DID_ID), (rev & RID_SUBID), (rev & RID_REVISION)); | ||
| 54 | } | ||
| 55 | |||
| 56 | static unsigned int sysclk[8] = { 125000000, 100000000, 62500000, 50000000, 41700000, 33300000, 31300000, 25000000 }; | ||
| 57 | static unsigned int cpuclk[8] = { 166000000, 166000000, 83000000, 83000000, 55300000, 55300000, 41500000, 41500000 }; | ||
| 58 | |||
| 59 | static void __init ks8695_clock_info(void) | ||
| 60 | { | ||
| 61 | unsigned int scdc = __raw_readl(KS8695_SYS_VA + KS8695_CLKCON) & CLKCON_SCDC; | ||
| 62 | |||
| 63 | printk("Clocks: System %u MHz, CPU %u MHz\n", | ||
| 64 | sysclk[scdc] / 1000000, cpuclk[scdc] / 1000000); | ||
| 65 | } | ||
| 66 | |||
| 67 | void __init ks8695_map_io(void) | ||
| 68 | { | ||
| 69 | iotable_init(ks8695_io_desc, ARRAY_SIZE(ks8695_io_desc)); | ||
| 70 | |||
| 71 | ks8695_processor_info(); | ||
| 72 | ks8695_clock_info(); | ||
| 73 | } | ||
diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c new file mode 100644 index 0000000000..386593f8ac --- /dev/null +++ b/arch/arm/mach-ks8695/devices.c | |||
| @@ -0,0 +1,191 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ks8695/devices.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Andrew Victor | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <asm/mach/arch.h> | ||
| 21 | #include <asm/mach/map.h> | ||
| 22 | |||
| 23 | #include <linux/platform_device.h> | ||
| 24 | |||
| 25 | #include <asm/arch/regs-wan.h> | ||
| 26 | #include <asm/arch/regs-lan.h> | ||
| 27 | #include <asm/arch/regs-hpna.h> | ||
| 28 | |||
| 29 | |||
| 30 | /* -------------------------------------------------------------------- | ||
| 31 | * Ethernet | ||
| 32 | * -------------------------------------------------------------------- */ | ||
| 33 | |||
| 34 | #if defined(CONFIG_ARM_KS8695_ETHER) || defined(CONFIG_ARM_KS8695_ETHER_MODULE) | ||
| 35 | static u64 eth_dmamask = 0xffffffffUL; | ||
| 36 | |||
| 37 | static struct resource ks8695_wan_resources[] = { | ||
| 38 | [0] = { | ||
| 39 | .start = KS8695_WAN_VA, | ||
| 40 | .end = KS8695_WAN_VA + 0x00ff, | ||
| 41 | .flags = IORESOURCE_MEM, | ||
| 42 | }, | ||
| 43 | [1] = { | ||
| 44 | .name = "WAN RX", | ||
| 45 | .start = KS8695_IRQ_WAN_RX_STATUS, | ||
| 46 | .end = KS8695_IRQ_WAN_RX_STATUS, | ||
| 47 | .flags = IORESOURCE_IRQ, | ||
| 48 | }, | ||
| 49 | [2] = { | ||
| 50 | .name = "WAN TX", | ||
| 51 | .start = KS8695_IRQ_WAN_TX_STATUS, | ||
| 52 | .end = KS8695_IRQ_WAN_TX_STATUS, | ||
| 53 | .flags = IORESOURCE_IRQ, | ||
| 54 | }, | ||
| 55 | [3] = { | ||
| 56 | .name = "WAN Link", | ||
| 57 | .start = KS8695_IRQ_WAN_LINK, | ||
| 58 | .end = KS8695_IRQ_WAN_LINK, | ||
| 59 | .flags = IORESOURCE_IRQ, | ||
| 60 | }, | ||
| 61 | }; | ||
| 62 | |||
| 63 | static struct platform_device ks8695_wan_device = { | ||
| 64 | .name = "ks8695_ether", | ||
| 65 | .id = 0, | ||
| 66 | .dev = { | ||
| 67 | .dma_mask = ð_dmamask, | ||
| 68 | .coherent_dma_mask = 0xffffffff, | ||
| 69 | }, | ||
| 70 | .resource = ks8695_wan_resources, | ||
| 71 | .num_resources = ARRAY_SIZE(ks8695_wan_resources), | ||
| 72 | }; | ||
| 73 | |||
| 74 | |||
| 75 | static struct resource ks8695_lan_resources[] = { | ||
| 76 | [0] = { | ||
| 77 | .start = KS8695_LAN_VA, | ||
| 78 | .end = KS8695_LAN_VA + 0x00ff, | ||
| 79 | .flags = IORESOURCE_MEM, | ||
| 80 | }, | ||
| 81 | [1] = { | ||
| 82 | .name = "LAN RX", | ||
| 83 | .start = KS8695_IRQ_LAN_RX_STATUS, | ||
| 84 | .end = KS8695_IRQ_LAN_RX_STATUS, | ||
| 85 | .flags = IORESOURCE_IRQ, | ||
| 86 | }, | ||
| 87 | [2] = { | ||
| 88 | .name = "LAN TX", | ||
| 89 | .start = KS8695_IRQ_LAN_TX_STATUS, | ||
| 90 | .end = KS8695_IRQ_LAN_TX_STATUS, | ||
| 91 | .flags = IORESOURCE_IRQ, | ||
| 92 | }, | ||
| 93 | }; | ||
| 94 | |||
| 95 | static struct platform_device ks8695_lan_device = { | ||
| 96 | .name = "ks8695_ether", | ||
| 97 | .id = 1, | ||
| 98 | .dev = { | ||
| 99 | .dma_mask = ð_dmamask, | ||
| 100 | .coherent_dma_mask = 0xffffffff, | ||
| 101 | }, | ||
| 102 | .resource = ks8695_lan_resources, | ||
| 103 | .num_resources = ARRAY_SIZE(ks8695_lan_resources), | ||
| 104 | }; | ||
| 105 | |||
| 106 | |||
| 107 | static struct resource ks8695_hpna_resources[] = { | ||
| 108 | [0] = { | ||
| 109 | .start = KS8695_HPNA_VA, | ||
| 110 | .end = KS8695_HPNA_VA + 0x00ff, | ||
| 111 | .flags = IORESOURCE_MEM, | ||
| 112 | }, | ||
| 113 | [1] = { | ||
| 114 | .name = "HPNA RX", | ||
| 115 | .start = KS8695_IRQ_HPNA_RX_STATUS, | ||
| 116 | .end = KS8695_IRQ_HPNA_RX_STATUS, | ||
| 117 | .flags = IORESOURCE_IRQ, | ||
| 118 | }, | ||
| 119 | [2] = { | ||
| 120 | .name = "HPNA TX", | ||
| 121 | .start = KS8695_IRQ_HPNA_TX_STATUS, | ||
| 122 | .end = KS8695_IRQ_HPNA_TX_STATUS, | ||
| 123 | .flags = IORESOURCE_IRQ, | ||
| 124 | }, | ||
| 125 | }; | ||
| 126 | |||
| 127 | static struct platform_device ks8695_hpna_device = { | ||
| 128 | .name = "ks8695_ether", | ||
| 129 | .id = 2, | ||
| 130 | .dev = { | ||
| 131 | .dma_mask = ð_dmamask, | ||
| 132 | .coherent_dma_mask = 0xffffffff, | ||
| 133 | }, | ||
| 134 | .resource = ks8695_hpna_resources, | ||
| 135 | .num_resources = ARRAY_SIZE(ks8695_hpna_resources), | ||
| 136 | }; | ||
| 137 | |||
| 138 | void __init ks8695_add_device_wan(void) | ||
| 139 | { | ||
| 140 | platform_device_register(&ks8695_wan_device); | ||
| 141 | } | ||
| 142 | |||
| 143 | void __init ks8695_add_device_lan(void) | ||
| 144 | { | ||
| 145 | platform_device_register(&ks8695_lan_device); | ||
| 146 | } | ||
| 147 | |||
| 148 | void __init ks8696_add_device_hpna(void) | ||
| 149 | { | ||
| 150 | platform_device_register(&ks8695_hpna_device); | ||
| 151 | } | ||
| 152 | #else | ||
| 153 | void __init ks8695_add_device_wan(void) {} | ||
| 154 | void __init ks8695_add_device_lan(void) {} | ||
| 155 | void __init ks8696_add_device_hpna(void) {} | ||
| 156 | #endif | ||
| 157 | |||
| 158 | |||
| 159 | /* -------------------------------------------------------------------- | ||
| 160 | * Watchdog | ||
| 161 | * -------------------------------------------------------------------- */ | ||
| 162 | |||
| 163 | #if defined(CONFIG_KS8695_WATCHDOG) || defined(CONFIG_KS8695_WATCHDOG_MODULE) | ||
| 164 | static struct platform_device ks8695_wdt_device = { | ||
| 165 | .name = "ks8695_wdt", | ||
| 166 | .id = -1, | ||
| 167 | .num_resources = 0, | ||
| 168 | }; | ||
| 169 | |||
| 170 | static void __init ks8695_add_device_watchdog(void) | ||
| 171 | { | ||
| 172 | platform_device_register(&ks8695_wdt_device); | ||
| 173 | } | ||
| 174 | #else | ||
| 175 | static void __init ks8695_add_device_watchdog(void) {} | ||
| 176 | #endif | ||
| 177 | |||
| 178 | |||
| 179 | /* -------------------------------------------------------------------- */ | ||
| 180 | |||
| 181 | /* | ||
| 182 | * These devices are always present and don't need any board-specific | ||
| 183 | * setup. | ||
| 184 | */ | ||
| 185 | static int __init ks8695_add_standard_devices(void) | ||
| 186 | { | ||
| 187 | ks8695_add_device_watchdog(); | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | arch_initcall(ks8695_add_standard_devices); | ||
diff --git a/arch/arm/mach-ks8695/generic.h b/arch/arm/mach-ks8695/generic.h new file mode 100644 index 0000000000..2fbfab8d5f --- /dev/null +++ b/arch/arm/mach-ks8695/generic.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ks8695/generic.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk> | ||
| 5 | * Copyright (C) 2006 Simtec Electronics | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | extern __init void ks8695_map_io(void); | ||
| 14 | extern __init void ks8695_init_irq(void); | ||
| 15 | extern struct sys_timer ks8695_timer; | ||
diff --git a/arch/arm/mach-ks8695/irq.c b/arch/arm/mach-ks8695/irq.c new file mode 100644 index 0000000000..2407bba005 --- /dev/null +++ b/arch/arm/mach-ks8695/irq.c | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ks8695/irq.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk> | ||
| 5 | * Copyright (C) 2006 Simtec Electronics | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/ioport.h> | ||
| 26 | #include <linux/ptrace.h> | ||
| 27 | #include <linux/sysdev.h> | ||
| 28 | |||
| 29 | #include <asm/hardware.h> | ||
| 30 | #include <asm/irq.h> | ||
| 31 | #include <asm/io.h> | ||
| 32 | |||
| 33 | #include <asm/mach/irq.h> | ||
| 34 | |||
| 35 | #include <asm/arch/regs-irq.h> | ||
| 36 | #include <asm/arch/regs-gpio.h> | ||
| 37 | |||
| 38 | static void ks8695_irq_mask(unsigned int irqno) | ||
| 39 | { | ||
| 40 | unsigned long inten; | ||
| 41 | |||
| 42 | inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN); | ||
| 43 | inten &= ~(1 << irqno); | ||
| 44 | |||
| 45 | __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN); | ||
| 46 | } | ||
| 47 | |||
| 48 | static void ks8695_irq_unmask(unsigned int irqno) | ||
| 49 | { | ||
| 50 | unsigned long inten; | ||
| 51 | |||
| 52 | inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN); | ||
| 53 | inten |= (1 << irqno); | ||
| 54 | |||
| 55 | __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN); | ||
| 56 | } | ||
| 57 | |||
| 58 | static void ks8695_irq_ack(unsigned int irqno) | ||
| 59 | { | ||
| 60 | __raw_writel((1 << irqno), KS8695_IRQ_VA + KS8695_INTST); | ||
| 61 | } | ||
| 62 | |||
| 63 | |||
| 64 | static struct irq_chip ks8695_irq_level_chip; | ||
| 65 | static struct irq_chip ks8695_irq_edge_chip; | ||
| 66 | |||
| 67 | |||
| 68 | static int ks8695_irq_set_type(unsigned int irqno, unsigned int type) | ||
| 69 | { | ||
| 70 | unsigned long ctrl, mode; | ||
| 71 | unsigned short level_triggered = 0; | ||
| 72 | |||
| 73 | ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); | ||
| 74 | |||
| 75 | switch (type) { | ||
| 76 | case IRQT_HIGH: | ||
| 77 | mode = IOPC_TM_HIGH; | ||
| 78 | level_triggered = 1; | ||
| 79 | break; | ||
| 80 | case IRQT_LOW: | ||
| 81 | mode = IOPC_TM_LOW; | ||
| 82 | level_triggered = 1; | ||
| 83 | break; | ||
| 84 | case IRQT_RISING: | ||
| 85 | mode = IOPC_TM_RISING; | ||
| 86 | break; | ||
| 87 | case IRQT_FALLING: | ||
| 88 | mode = IOPC_TM_FALLING; | ||
| 89 | break; | ||
| 90 | case IRQT_BOTHEDGE: | ||
| 91 | mode = IOPC_TM_EDGE; | ||
| 92 | break; | ||
| 93 | default: | ||
| 94 | return -EINVAL; | ||
| 95 | } | ||
| 96 | |||
| 97 | switch (irqno) { | ||
| 98 | case KS8695_IRQ_EXTERN0: | ||
| 99 | ctrl &= ~IOPC_IOEINT0TM; | ||
| 100 | ctrl |= IOPC_IOEINT0_MODE(mode); | ||
| 101 | break; | ||
| 102 | case KS8695_IRQ_EXTERN1: | ||
| 103 | ctrl &= ~IOPC_IOEINT1TM; | ||
| 104 | ctrl |= IOPC_IOEINT1_MODE(mode); | ||
| 105 | break; | ||
| 106 | case KS8695_IRQ_EXTERN2: | ||
| 107 | ctrl &= ~IOPC_IOEINT2TM; | ||
| 108 | ctrl |= IOPC_IOEINT2_MODE(mode); | ||
| 109 | break; | ||
| 110 | case KS8695_IRQ_EXTERN3: | ||
| 111 | ctrl &= ~IOPC_IOEINT3TM; | ||
| 112 | ctrl |= IOPC_IOEINT3_MODE(mode); | ||
| 113 | break; | ||
| 114 | default: | ||
| 115 | return -EINVAL; | ||
| 116 | } | ||
| 117 | |||
| 118 | if (level_triggered) { | ||
| 119 | set_irq_chip(irqno, &ks8695_irq_level_chip); | ||
| 120 | set_irq_handler(irqno, handle_level_irq); | ||
| 121 | } | ||
| 122 | else { | ||
| 123 | set_irq_chip(irqno, &ks8695_irq_edge_chip); | ||
| 124 | set_irq_handler(irqno, handle_edge_irq); | ||
| 125 | } | ||
| 126 | |||
| 127 | __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC); | ||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static struct irq_chip ks8695_irq_level_chip = { | ||
| 132 | .ack = ks8695_irq_mask, | ||
| 133 | .mask = ks8695_irq_mask, | ||
| 134 | .unmask = ks8695_irq_unmask, | ||
| 135 | .set_type = ks8695_irq_set_type, | ||
| 136 | }; | ||
| 137 | |||
| 138 | static struct irq_chip ks8695_irq_edge_chip = { | ||
| 139 | .ack = ks8695_irq_ack, | ||
| 140 | .mask = ks8695_irq_mask, | ||
| 141 | .unmask = ks8695_irq_unmask, | ||
| 142 | .set_type = ks8695_irq_set_type, | ||
| 143 | }; | ||
| 144 | |||
| 145 | void __init ks8695_init_irq(void) | ||
| 146 | { | ||
| 147 | unsigned int irq; | ||
| 148 | |||
| 149 | /* Disable all interrupts initially */ | ||
| 150 | __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC); | ||
| 151 | __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN); | ||
| 152 | |||
| 153 | for (irq = 0; irq < NR_IRQS; irq++) { | ||
| 154 | switch (irq) { | ||
| 155 | /* Level-triggered interrupts */ | ||
| 156 | case KS8695_IRQ_BUS_ERROR: | ||
| 157 | case KS8695_IRQ_UART_MODEM_STATUS: | ||
| 158 | case KS8695_IRQ_UART_LINE_STATUS: | ||
| 159 | case KS8695_IRQ_UART_RX: | ||
| 160 | case KS8695_IRQ_COMM_TX: | ||
| 161 | case KS8695_IRQ_COMM_RX: | ||
| 162 | set_irq_chip(irq, &ks8695_irq_level_chip); | ||
| 163 | set_irq_handler(irq, handle_level_irq); | ||
| 164 | break; | ||
| 165 | |||
| 166 | /* Edge-triggered interrupts */ | ||
| 167 | default: | ||
| 168 | ks8695_irq_ack(irq); /* clear pending bit */ | ||
| 169 | set_irq_chip(irq, &ks8695_irq_edge_chip); | ||
| 170 | set_irq_handler(irq, handle_edge_irq); | ||
| 171 | } | ||
| 172 | |||
| 173 | set_irq_flags(irq, IRQF_VALID); | ||
| 174 | } | ||
| 175 | } | ||
diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c new file mode 100644 index 0000000000..d2c86e4a72 --- /dev/null +++ b/arch/arm/mach-ks8695/time.c | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ks8695/time.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk> | ||
| 5 | * Copyright (C) 2006 Simtec Electronics | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/irq.h> | ||
| 25 | #include <linux/kernel.h> | ||
| 26 | #include <linux/sched.h> | ||
| 27 | |||
| 28 | #include <asm/io.h> | ||
| 29 | #include <asm/mach/time.h> | ||
| 30 | |||
| 31 | #include <asm/arch/regs-timer.h> | ||
| 32 | #include <asm/arch/regs-irq.h> | ||
| 33 | |||
| 34 | #include "generic.h" | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Returns number of ms since last clock interrupt. Note that interrupts | ||
| 38 | * will have been disabled by do_gettimeoffset() | ||
| 39 | */ | ||
| 40 | static unsigned long ks8695_gettimeoffset (void) | ||
| 41 | { | ||
| 42 | unsigned long elapsed, tick2, intpending; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Get the current number of ticks. Note that there is a race | ||
| 46 | * condition between us reading the timer and checking for an | ||
| 47 | * interrupt. We solve this by ensuring that the counter has not | ||
| 48 | * reloaded between our two reads. | ||
| 49 | */ | ||
| 50 | elapsed = __raw_readl(KS8695_TMR_VA + KS8695_T1TC) + __raw_readl(KS8695_TMR_VA + KS8695_T1PD); | ||
| 51 | do { | ||
| 52 | tick2 = elapsed; | ||
| 53 | intpending = __raw_readl(KS8695_IRQ_VA + KS8695_INTST) & (1 << KS8695_IRQ_TIMER1); | ||
| 54 | elapsed = __raw_readl(KS8695_TMR_VA + KS8695_T1TC) + __raw_readl(KS8695_TMR_VA + KS8695_T1PD); | ||
| 55 | } while (elapsed > tick2); | ||
| 56 | |||
| 57 | /* Convert to number of ticks expired (not remaining) */ | ||
| 58 | elapsed = (CLOCK_TICK_RATE / HZ) - elapsed; | ||
| 59 | |||
| 60 | /* Is interrupt pending? If so, then timer has been reloaded already. */ | ||
| 61 | if (intpending) | ||
| 62 | elapsed += (CLOCK_TICK_RATE / HZ); | ||
| 63 | |||
| 64 | /* Convert ticks to usecs */ | ||
| 65 | return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* | ||
| 69 | * IRQ handler for the timer. | ||
| 70 | */ | ||
| 71 | static irqreturn_t ks8695_timer_interrupt(int irq, void *dev_id) | ||
| 72 | { | ||
| 73 | write_seqlock(&xtime_lock); | ||
| 74 | timer_tick(); | ||
| 75 | write_sequnlock(&xtime_lock); | ||
| 76 | |||
| 77 | return IRQ_HANDLED; | ||
| 78 | } | ||
| 79 | |||
| 80 | static struct irqaction ks8695_timer_irq = { | ||
| 81 | .name = "ks8695_tick", | ||
| 82 | .flags = IRQF_DISABLED | IRQF_TIMER, | ||
| 83 | .handler = ks8695_timer_interrupt, | ||
| 84 | }; | ||
| 85 | |||
| 86 | static void ks8695_timer_setup(void) | ||
| 87 | { | ||
| 88 | unsigned long tmout = CLOCK_TICK_RATE / HZ; | ||
| 89 | unsigned long tmcon; | ||
| 90 | |||
| 91 | /* disable timer1 */ | ||
| 92 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | ||
| 93 | __raw_writel(tmcon & ~TMCON_T1EN, KS8695_TMR_VA + KS8695_TMCON); | ||
| 94 | |||
| 95 | __raw_writel(tmout / 2, KS8695_TMR_VA + KS8695_T1TC); | ||
| 96 | __raw_writel(tmout / 2, KS8695_TMR_VA + KS8695_T1PD); | ||
| 97 | |||
| 98 | /* re-enable timer1 */ | ||
| 99 | __raw_writel(tmcon | TMCON_T1EN, KS8695_TMR_VA + KS8695_TMCON); | ||
| 100 | } | ||
| 101 | |||
| 102 | static void __init ks8695_timer_init (void) | ||
| 103 | { | ||
| 104 | ks8695_timer_setup(); | ||
| 105 | |||
| 106 | /* Enable timer interrupts */ | ||
| 107 | setup_irq(KS8695_IRQ_TIMER1, &ks8695_timer_irq); | ||
| 108 | } | ||
| 109 | |||
| 110 | struct sys_timer ks8695_timer = { | ||
| 111 | .init = ks8695_timer_init, | ||
| 112 | .offset = ks8695_gettimeoffset, | ||
| 113 | .resume = ks8695_timer_setup, | ||
| 114 | }; | ||
