aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-ks8695
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ks8695')
-rw-r--r--arch/arm/mach-ks8695/Kconfig8
-rw-r--r--arch/arm/mach-ks8695/Makefile14
-rw-r--r--arch/arm/mach-ks8695/Makefile.boot8
-rw-r--r--arch/arm/mach-ks8695/cpu.c73
-rw-r--r--arch/arm/mach-ks8695/devices.c191
-rw-r--r--arch/arm/mach-ks8695/generic.h15
-rw-r--r--arch/arm/mach-ks8695/irq.c175
-rw-r--r--arch/arm/mach-ks8695/time.c114
8 files changed, 598 insertions, 0 deletions
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig
new file mode 100644
index 000000000000..44d14aa0baa7
--- /dev/null
+++ b/arch/arm/mach-ks8695/Kconfig
@@ -0,0 +1,8 @@
1if ARCH_KS8695
2
3menu "Kendin/Micrel KS8695 Implementations"
4
5
6endmenu
7
8endif
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
new file mode 100644
index 000000000000..0a0f496e8ccf
--- /dev/null
+++ b/arch/arm/mach-ks8695/Makefile
@@ -0,0 +1,14 @@
1# arch/arm/mach-ks8695/Makefile
2#
3# Makefile for KS8695 architecture support
4#
5
6obj-y := cpu.o irq.o time.o devices.o
7obj-m :=
8obj-n :=
9obj- :=
10
11# PCI support is optional
12#obj-$(CONFIG_PCI) += pci.o
13
14# Board-specific support
diff --git a/arch/arm/mach-ks8695/Makefile.boot b/arch/arm/mach-ks8695/Makefile.boot
new file mode 100644
index 000000000000..48eb2cb3ac77
--- /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
7params_phys-y := 0x00000100
8initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-ks8695/cpu.c b/arch/arm/mach-ks8695/cpu.c
new file mode 100644
index 000000000000..407d255e42bf
--- /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
37static 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
46static 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
56static unsigned int sysclk[8] = { 125000000, 100000000, 62500000, 50000000, 41700000, 33300000, 31300000, 25000000 };
57static unsigned int cpuclk[8] = { 166000000, 166000000, 83000000, 83000000, 55300000, 55300000, 41500000, 41500000 };
58
59static 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
67void __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 000000000000..386593f8ac65
--- /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)
35static u64 eth_dmamask = 0xffffffffUL;
36
37static 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
63static struct platform_device ks8695_wan_device = {
64 .name = "ks8695_ether",
65 .id = 0,
66 .dev = {
67 .dma_mask = &eth_dmamask,
68 .coherent_dma_mask = 0xffffffff,
69 },
70 .resource = ks8695_wan_resources,
71 .num_resources = ARRAY_SIZE(ks8695_wan_resources),
72};
73
74
75static 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
95static struct platform_device ks8695_lan_device = {
96 .name = "ks8695_ether",
97 .id = 1,
98 .dev = {
99 .dma_mask = &eth_dmamask,
100 .coherent_dma_mask = 0xffffffff,
101 },
102 .resource = ks8695_lan_resources,
103 .num_resources = ARRAY_SIZE(ks8695_lan_resources),
104};
105
106
107static 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
127static struct platform_device ks8695_hpna_device = {
128 .name = "ks8695_ether",
129 .id = 2,
130 .dev = {
131 .dma_mask = &eth_dmamask,
132 .coherent_dma_mask = 0xffffffff,
133 },
134 .resource = ks8695_hpna_resources,
135 .num_resources = ARRAY_SIZE(ks8695_hpna_resources),
136};
137
138void __init ks8695_add_device_wan(void)
139{
140 platform_device_register(&ks8695_wan_device);
141}
142
143void __init ks8695_add_device_lan(void)
144{
145 platform_device_register(&ks8695_lan_device);
146}
147
148void __init ks8696_add_device_hpna(void)
149{
150 platform_device_register(&ks8695_hpna_device);
151}
152#else
153void __init ks8695_add_device_wan(void) {}
154void __init ks8695_add_device_lan(void) {}
155void __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)
164static struct platform_device ks8695_wdt_device = {
165 .name = "ks8695_wdt",
166 .id = -1,
167 .num_resources = 0,
168};
169
170static void __init ks8695_add_device_watchdog(void)
171{
172 platform_device_register(&ks8695_wdt_device);
173}
174#else
175static 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 */
185static int __init ks8695_add_standard_devices(void)
186{
187 ks8695_add_device_watchdog();
188 return 0;
189}
190
191arch_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 000000000000..2fbfab8d5fae
--- /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
13extern __init void ks8695_map_io(void);
14extern __init void ks8695_init_irq(void);
15extern 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 000000000000..2407bba00547
--- /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
38static 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
48static 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
58static void ks8695_irq_ack(unsigned int irqno)
59{
60 __raw_writel((1 << irqno), KS8695_IRQ_VA + KS8695_INTST);
61}
62
63
64static struct irq_chip ks8695_irq_level_chip;
65static struct irq_chip ks8695_irq_edge_chip;
66
67
68static 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
131static 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
138static 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
145void __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 000000000000..d2c86e4a72eb
--- /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 */
40static 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 */
71static 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
80static struct irqaction ks8695_timer_irq = {
81 .name = "ks8695_tick",
82 .flags = IRQF_DISABLED | IRQF_TIMER,
83 .handler = ks8695_timer_interrupt,
84};
85
86static 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
102static 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
110struct sys_timer ks8695_timer = {
111 .init = ks8695_timer_init,
112 .offset = ks8695_gettimeoffset,
113 .resume = ks8695_timer_setup,
114};