diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/txx9 | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/txx9')
34 files changed, 6152 insertions, 0 deletions
diff --git a/arch/mips/txx9/Kconfig b/arch/mips/txx9/Kconfig new file mode 100644 index 000000000..85c4c121c --- /dev/null +++ b/arch/mips/txx9/Kconfig | |||
@@ -0,0 +1,128 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | config MACH_TX39XX | ||
3 | bool | ||
4 | select MACH_TXX9 | ||
5 | select SYS_HAS_CPU_TX39XX | ||
6 | |||
7 | config MACH_TX49XX | ||
8 | bool | ||
9 | select MACH_TXX9 | ||
10 | select CEVT_R4K | ||
11 | select CSRC_R4K | ||
12 | select IRQ_MIPS_CPU | ||
13 | select SYS_HAS_CPU_TX49XX | ||
14 | select SYS_SUPPORTS_64BIT_KERNEL | ||
15 | |||
16 | config MACH_TXX9 | ||
17 | bool | ||
18 | select DMA_NONCOHERENT | ||
19 | select SWAP_IO_SPACE | ||
20 | select SYS_HAS_EARLY_PRINTK | ||
21 | select SYS_SUPPORTS_32BIT_KERNEL | ||
22 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
23 | select SYS_SUPPORTS_BIG_ENDIAN | ||
24 | select COMMON_CLK | ||
25 | |||
26 | config TOSHIBA_JMR3927 | ||
27 | bool "Toshiba JMR-TX3927 board" | ||
28 | depends on MACH_TX39XX | ||
29 | select SOC_TX3927 | ||
30 | |||
31 | config TOSHIBA_RBTX4927 | ||
32 | bool "Toshiba RBTX49[23]7 board" | ||
33 | depends on MACH_TX49XX | ||
34 | select SOC_TX4927 | ||
35 | # TX4937 is subset of TX4938 | ||
36 | select SOC_TX4938 | ||
37 | help | ||
38 | This Toshiba board is based on the TX4927 processor. Say Y here to | ||
39 | support this machine type | ||
40 | |||
41 | config TOSHIBA_RBTX4938 | ||
42 | bool "Toshiba RBTX4938 board" | ||
43 | depends on MACH_TX49XX | ||
44 | select SOC_TX4938 | ||
45 | help | ||
46 | This Toshiba board is based on the TX4938 processor. Say Y here to | ||
47 | support this machine type | ||
48 | |||
49 | config TOSHIBA_RBTX4939 | ||
50 | bool "Toshiba RBTX4939 board" | ||
51 | depends on MACH_TX49XX | ||
52 | select SOC_TX4939 | ||
53 | select TXX9_7SEGLED | ||
54 | help | ||
55 | This Toshiba board is based on the TX4939 processor. Say Y here to | ||
56 | support this machine type | ||
57 | |||
58 | config SOC_TX3927 | ||
59 | bool | ||
60 | select CEVT_TXX9 | ||
61 | imply HAS_TXX9_SERIAL | ||
62 | select HAVE_PCI | ||
63 | select IRQ_TXX9 | ||
64 | select GPIO_TXX9 | ||
65 | |||
66 | config SOC_TX4927 | ||
67 | bool | ||
68 | select CEVT_TXX9 | ||
69 | imply HAS_TXX9_SERIAL | ||
70 | select HAVE_PCI | ||
71 | select IRQ_TXX9 | ||
72 | select PCI_TX4927 | ||
73 | select GPIO_TXX9 | ||
74 | imply HAS_TXX9_ACLC | ||
75 | |||
76 | config SOC_TX4938 | ||
77 | bool | ||
78 | select CEVT_TXX9 | ||
79 | imply HAS_TXX9_SERIAL | ||
80 | select HAVE_PCI | ||
81 | select IRQ_TXX9 | ||
82 | select PCI_TX4927 | ||
83 | select GPIO_TXX9 | ||
84 | imply HAS_TXX9_ACLC | ||
85 | |||
86 | config SOC_TX4939 | ||
87 | bool | ||
88 | select CEVT_TXX9 | ||
89 | imply HAS_TXX9_SERIAL | ||
90 | select HAVE_PCI | ||
91 | select PCI_TX4927 | ||
92 | imply HAS_TXX9_ACLC | ||
93 | |||
94 | config TXX9_7SEGLED | ||
95 | bool | ||
96 | |||
97 | config TOSHIBA_FPCIB0 | ||
98 | bool "FPCIB0 Backplane Support" | ||
99 | depends on PCI && MACH_TXX9 | ||
100 | select I8259 | ||
101 | |||
102 | config PICMG_PCI_BACKPLANE_DEFAULT | ||
103 | bool "Support for PICMG PCI Backplane" | ||
104 | depends on PCI && MACH_TXX9 | ||
105 | default y if !TOSHIBA_FPCIB0 | ||
106 | |||
107 | if TOSHIBA_RBTX4938 | ||
108 | |||
109 | comment "Multiplex Pin Select" | ||
110 | choice | ||
111 | prompt "PIO[58:61]" | ||
112 | default TOSHIBA_RBTX4938_MPLEX_PIO58_61 | ||
113 | |||
114 | config TOSHIBA_RBTX4938_MPLEX_PIO58_61 | ||
115 | bool "PIO" | ||
116 | config TOSHIBA_RBTX4938_MPLEX_NAND | ||
117 | bool "NAND" | ||
118 | config TOSHIBA_RBTX4938_MPLEX_ATA | ||
119 | bool "ATA" | ||
120 | config TOSHIBA_RBTX4938_MPLEX_KEEP | ||
121 | bool "Keep firmware settings" | ||
122 | |||
123 | endchoice | ||
124 | |||
125 | endif | ||
126 | |||
127 | config PCI_TX4927 | ||
128 | bool | ||
diff --git a/arch/mips/txx9/Makefile b/arch/mips/txx9/Makefile new file mode 100644 index 000000000..195295937 --- /dev/null +++ b/arch/mips/txx9/Makefile | |||
@@ -0,0 +1,18 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | # | ||
3 | # Common TXx9 | ||
4 | # | ||
5 | obj-$(CONFIG_MACH_TX39XX) += generic/ | ||
6 | obj-$(CONFIG_MACH_TX49XX) += generic/ | ||
7 | |||
8 | # | ||
9 | # Toshiba JMR-TX3927 board | ||
10 | # | ||
11 | obj-$(CONFIG_TOSHIBA_JMR3927) += jmr3927/ | ||
12 | |||
13 | # | ||
14 | # Toshiba RBTX49XX boards | ||
15 | # | ||
16 | obj-$(CONFIG_TOSHIBA_RBTX4927) += rbtx4927/ | ||
17 | obj-$(CONFIG_TOSHIBA_RBTX4938) += rbtx4938/ | ||
18 | obj-$(CONFIG_TOSHIBA_RBTX4939) += rbtx4939/ | ||
diff --git a/arch/mips/txx9/Platform b/arch/mips/txx9/Platform new file mode 100644 index 000000000..7f4429ba2 --- /dev/null +++ b/arch/mips/txx9/Platform | |||
@@ -0,0 +1,7 @@ | |||
1 | cflags-$(CONFIG_MACH_TX39XX) += \ | ||
2 | -I$(srctree)/arch/mips/include/asm/mach-tx39xx | ||
3 | cflags-$(CONFIG_MACH_TX49XX) += \ | ||
4 | -I$(srctree)/arch/mips/include/asm/mach-tx49xx | ||
5 | |||
6 | load-$(CONFIG_MACH_TX39XX) += 0xffffffff80050000 | ||
7 | load-$(CONFIG_MACH_TX49XX) += 0xffffffff80100000 | ||
diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c new file mode 100644 index 000000000..2203c2548 --- /dev/null +++ b/arch/mips/txx9/generic/7segled.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * 7 Segment LED routines | ||
3 | * Based on RBTX49xx patch from CELF patch archive. | ||
4 | * | ||
5 | * This file is subject to the terms and conditions of the GNU General Public | ||
6 | * License. See the file "COPYING" in the main directory of this archive | ||
7 | * for more details. | ||
8 | * | ||
9 | * (C) Copyright TOSHIBA CORPORATION 2005-2007 | ||
10 | * All Rights Reserved. | ||
11 | */ | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/map_to_7segment.h> | ||
15 | #include <asm/txx9/generic.h> | ||
16 | |||
17 | static unsigned int tx_7segled_num; | ||
18 | static void (*tx_7segled_putc)(unsigned int pos, unsigned char val); | ||
19 | |||
20 | void __init txx9_7segled_init(unsigned int num, | ||
21 | void (*putc)(unsigned int pos, unsigned char val)) | ||
22 | { | ||
23 | tx_7segled_num = num; | ||
24 | tx_7segled_putc = putc; | ||
25 | } | ||
26 | |||
27 | static SEG7_CONVERSION_MAP(txx9_seg7map, MAP_ASCII7SEG_ALPHANUM_LC); | ||
28 | |||
29 | int txx9_7segled_putc(unsigned int pos, char c) | ||
30 | { | ||
31 | if (pos >= tx_7segled_num) | ||
32 | return -EINVAL; | ||
33 | c = map_to_seg7(&txx9_seg7map, c); | ||
34 | if (c < 0) | ||
35 | return c; | ||
36 | tx_7segled_putc(pos, c); | ||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | static ssize_t ascii_store(struct device *dev, | ||
41 | struct device_attribute *attr, | ||
42 | const char *buf, size_t size) | ||
43 | { | ||
44 | unsigned int ch = dev->id; | ||
45 | txx9_7segled_putc(ch, buf[0]); | ||
46 | return size; | ||
47 | } | ||
48 | |||
49 | static ssize_t raw_store(struct device *dev, | ||
50 | struct device_attribute *attr, | ||
51 | const char *buf, size_t size) | ||
52 | { | ||
53 | unsigned int ch = dev->id; | ||
54 | tx_7segled_putc(ch, buf[0]); | ||
55 | return size; | ||
56 | } | ||
57 | |||
58 | static DEVICE_ATTR_WO(ascii); | ||
59 | static DEVICE_ATTR_WO(raw); | ||
60 | |||
61 | static ssize_t map_seg7_show(struct device *dev, | ||
62 | struct device_attribute *attr, | ||
63 | char *buf) | ||
64 | { | ||
65 | memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map)); | ||
66 | return sizeof(txx9_seg7map); | ||
67 | } | ||
68 | |||
69 | static ssize_t map_seg7_store(struct device *dev, | ||
70 | struct device_attribute *attr, | ||
71 | const char *buf, size_t size) | ||
72 | { | ||
73 | if (size != sizeof(txx9_seg7map)) | ||
74 | return -EINVAL; | ||
75 | memcpy(&txx9_seg7map, buf, size); | ||
76 | return size; | ||
77 | } | ||
78 | |||
79 | static DEVICE_ATTR(map_seg7, 0600, map_seg7_show, map_seg7_store); | ||
80 | |||
81 | static struct bus_type tx_7segled_subsys = { | ||
82 | .name = "7segled", | ||
83 | .dev_name = "7segled", | ||
84 | }; | ||
85 | |||
86 | static void tx_7segled_release(struct device *dev) | ||
87 | { | ||
88 | kfree(dev); | ||
89 | } | ||
90 | |||
91 | static int __init tx_7segled_init_sysfs(void) | ||
92 | { | ||
93 | int error, i; | ||
94 | if (!tx_7segled_num) | ||
95 | return -ENODEV; | ||
96 | error = subsys_system_register(&tx_7segled_subsys, NULL); | ||
97 | if (error) | ||
98 | return error; | ||
99 | error = device_create_file(tx_7segled_subsys.dev_root, &dev_attr_map_seg7); | ||
100 | if (error) | ||
101 | return error; | ||
102 | for (i = 0; i < tx_7segled_num; i++) { | ||
103 | struct device *dev; | ||
104 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
105 | if (!dev) { | ||
106 | error = -ENODEV; | ||
107 | break; | ||
108 | } | ||
109 | dev->id = i; | ||
110 | dev->bus = &tx_7segled_subsys; | ||
111 | dev->release = &tx_7segled_release; | ||
112 | error = device_register(dev); | ||
113 | if (error) { | ||
114 | put_device(dev); | ||
115 | return error; | ||
116 | } | ||
117 | device_create_file(dev, &dev_attr_ascii); | ||
118 | device_create_file(dev, &dev_attr_raw); | ||
119 | } | ||
120 | return error; | ||
121 | } | ||
122 | |||
123 | device_initcall(tx_7segled_init_sysfs); | ||
diff --git a/arch/mips/txx9/generic/Makefile b/arch/mips/txx9/generic/Makefile new file mode 100644 index 000000000..6d00580fc --- /dev/null +++ b/arch/mips/txx9/generic/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | # | ||
3 | # Makefile for common code for TXx9 based systems | ||
4 | # | ||
5 | |||
6 | obj-y += setup.o | ||
7 | obj-$(CONFIG_PCI) += pci.o | ||
8 | obj-$(CONFIG_SOC_TX3927) += setup_tx3927.o irq_tx3927.o | ||
9 | obj-$(CONFIG_SOC_TX4927) += mem_tx4927.o setup_tx4927.o irq_tx4927.o | ||
10 | obj-$(CONFIG_SOC_TX4938) += mem_tx4927.o setup_tx4938.o irq_tx4938.o | ||
11 | obj-$(CONFIG_SOC_TX4939) += setup_tx4939.o irq_tx4939.o | ||
12 | obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o | ||
13 | obj-$(CONFIG_SPI) += spi_eeprom.o | ||
14 | obj-$(CONFIG_TXX9_7SEGLED) += 7segled.o | ||
diff --git a/arch/mips/txx9/generic/irq_tx3927.c b/arch/mips/txx9/generic/irq_tx3927.c new file mode 100644 index 000000000..c683f593e --- /dev/null +++ b/arch/mips/txx9/generic/irq_tx3927.c | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Common tx3927 irq handler | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright 2001 MontaVista Software Inc. | ||
9 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <asm/txx9irq.h> | ||
13 | #include <asm/txx9/tx3927.h> | ||
14 | |||
15 | void __init tx3927_irq_init(void) | ||
16 | { | ||
17 | int i; | ||
18 | |||
19 | txx9_irq_init(TX3927_IRC_REG); | ||
20 | /* raise priority for timers, sio */ | ||
21 | for (i = 0; i < TX3927_NR_TMR; i++) | ||
22 | txx9_irq_set_pri(TX3927_IR_TMR(i), 6); | ||
23 | for (i = 0; i < TX3927_NR_SIO; i++) | ||
24 | txx9_irq_set_pri(TX3927_IR_SIO(i), 7); | ||
25 | } | ||
diff --git a/arch/mips/txx9/generic/irq_tx4927.c b/arch/mips/txx9/generic/irq_tx4927.c new file mode 100644 index 000000000..ed8e702d4 --- /dev/null +++ b/arch/mips/txx9/generic/irq_tx4927.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * Common tx4927 irq handler | ||
3 | * | ||
4 | * Author: MontaVista Software, Inc. | ||
5 | * source@mvista.com | ||
6 | * | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
12 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
13 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
14 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
15 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
16 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
17 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
18 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
19 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
20 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <asm/irq_cpu.h> | ||
30 | #include <asm/txx9/tx4927.h> | ||
31 | |||
32 | void __init tx4927_irq_init(void) | ||
33 | { | ||
34 | int i; | ||
35 | |||
36 | mips_cpu_irq_init(); | ||
37 | txx9_irq_init(TX4927_IRC_REG & 0xfffffffffULL); | ||
38 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT, | ||
39 | handle_simple_irq); | ||
40 | /* raise priority for errors, timers, SIO */ | ||
41 | txx9_irq_set_pri(TX4927_IR_ECCERR, 7); | ||
42 | txx9_irq_set_pri(TX4927_IR_WTOERR, 7); | ||
43 | txx9_irq_set_pri(TX4927_IR_PCIERR, 7); | ||
44 | txx9_irq_set_pri(TX4927_IR_PCIPME, 7); | ||
45 | for (i = 0; i < TX4927_NUM_IR_TMR; i++) | ||
46 | txx9_irq_set_pri(TX4927_IR_TMR(i), 6); | ||
47 | for (i = 0; i < TX4927_NUM_IR_SIO; i++) | ||
48 | txx9_irq_set_pri(TX4927_IR_SIO(i), 5); | ||
49 | } | ||
diff --git a/arch/mips/txx9/generic/irq_tx4938.c b/arch/mips/txx9/generic/irq_tx4938.c new file mode 100644 index 000000000..aace85653 --- /dev/null +++ b/arch/mips/txx9/generic/irq_tx4938.c | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/tx4938/common/irq.c | ||
3 | * | ||
4 | * Common tx4938 irq handler | ||
5 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
6 | * | ||
7 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | * | ||
12 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
13 | */ | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <asm/irq_cpu.h> | ||
18 | #include <asm/txx9/tx4938.h> | ||
19 | |||
20 | void __init tx4938_irq_init(void) | ||
21 | { | ||
22 | int i; | ||
23 | |||
24 | mips_cpu_irq_init(); | ||
25 | txx9_irq_init(TX4938_IRC_REG & 0xfffffffffULL); | ||
26 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT, | ||
27 | handle_simple_irq); | ||
28 | /* raise priority for errors, timers, SIO */ | ||
29 | txx9_irq_set_pri(TX4938_IR_ECCERR, 7); | ||
30 | txx9_irq_set_pri(TX4938_IR_WTOERR, 7); | ||
31 | txx9_irq_set_pri(TX4938_IR_PCIERR, 7); | ||
32 | txx9_irq_set_pri(TX4938_IR_PCIPME, 7); | ||
33 | for (i = 0; i < TX4938_NUM_IR_TMR; i++) | ||
34 | txx9_irq_set_pri(TX4938_IR_TMR(i), 6); | ||
35 | for (i = 0; i < TX4938_NUM_IR_SIO; i++) | ||
36 | txx9_irq_set_pri(TX4938_IR_SIO(i), 5); | ||
37 | } | ||
diff --git a/arch/mips/txx9/generic/irq_tx4939.c b/arch/mips/txx9/generic/irq_tx4939.c new file mode 100644 index 000000000..0d7267e81 --- /dev/null +++ b/arch/mips/txx9/generic/irq_tx4939.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* | ||
2 | * TX4939 irq routines | ||
3 | * Based on linux/arch/mips/kernel/irq_txx9.c, | ||
4 | * and RBTX49xx patch from CELF patch archive. | ||
5 | * | ||
6 | * Copyright 2001, 2003-2005 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ahennessy@mvista.com | ||
9 | * source@mvista.com | ||
10 | * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation | ||
11 | * | ||
12 | * This file is subject to the terms and conditions of the GNU General Public | ||
13 | * License. See the file "COPYING" in the main directory of this archive | ||
14 | * for more details. | ||
15 | */ | ||
16 | /* | ||
17 | * TX4939 defines 64 IRQs. | ||
18 | * Similer to irq_txx9.c but different register layouts. | ||
19 | */ | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <asm/irq_cpu.h> | ||
25 | #include <asm/txx9irq.h> | ||
26 | #include <asm/txx9/tx4939.h> | ||
27 | |||
28 | /* IRCER : Int. Control Enable */ | ||
29 | #define TXx9_IRCER_ICE 0x00000001 | ||
30 | |||
31 | /* IRCR : Int. Control */ | ||
32 | #define TXx9_IRCR_LOW 0x00000000 | ||
33 | #define TXx9_IRCR_HIGH 0x00000001 | ||
34 | #define TXx9_IRCR_DOWN 0x00000002 | ||
35 | #define TXx9_IRCR_UP 0x00000003 | ||
36 | #define TXx9_IRCR_EDGE(cr) ((cr) & 0x00000002) | ||
37 | |||
38 | /* IRSCR : Int. Status Control */ | ||
39 | #define TXx9_IRSCR_EIClrE 0x00000100 | ||
40 | #define TXx9_IRSCR_EIClr_MASK 0x0000000f | ||
41 | |||
42 | /* IRCSR : Int. Current Status */ | ||
43 | #define TXx9_IRCSR_IF 0x00010000 | ||
44 | |||
45 | #define irc_dlevel 0 | ||
46 | #define irc_elevel 1 | ||
47 | |||
48 | static struct { | ||
49 | unsigned char level; | ||
50 | unsigned char mode; | ||
51 | } tx4939irq[TX4939_NUM_IR] __read_mostly; | ||
52 | |||
53 | static void tx4939_irq_unmask(struct irq_data *d) | ||
54 | { | ||
55 | unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; | ||
56 | u32 __iomem *lvlp; | ||
57 | int ofs; | ||
58 | if (irq_nr < 32) { | ||
59 | irq_nr--; | ||
60 | lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; | ||
61 | } else { | ||
62 | irq_nr -= 32; | ||
63 | lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; | ||
64 | } | ||
65 | ofs = (irq_nr & 16) + (irq_nr & 1) * 8; | ||
66 | __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) | ||
67 | | (tx4939irq[irq_nr].level << ofs), | ||
68 | lvlp); | ||
69 | } | ||
70 | |||
71 | static inline void tx4939_irq_mask(struct irq_data *d) | ||
72 | { | ||
73 | unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; | ||
74 | u32 __iomem *lvlp; | ||
75 | int ofs; | ||
76 | if (irq_nr < 32) { | ||
77 | irq_nr--; | ||
78 | lvlp = &tx4939_ircptr->lvl[(irq_nr % 16) / 2].r; | ||
79 | } else { | ||
80 | irq_nr -= 32; | ||
81 | lvlp = &tx4939_ircptr->lvl[8 + (irq_nr % 16) / 2].r; | ||
82 | } | ||
83 | ofs = (irq_nr & 16) + (irq_nr & 1) * 8; | ||
84 | __raw_writel((__raw_readl(lvlp) & ~(0xff << ofs)) | ||
85 | | (irc_dlevel << ofs), | ||
86 | lvlp); | ||
87 | mmiowb(); | ||
88 | } | ||
89 | |||
90 | static void tx4939_irq_mask_ack(struct irq_data *d) | ||
91 | { | ||
92 | unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; | ||
93 | |||
94 | tx4939_irq_mask(d); | ||
95 | if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) { | ||
96 | irq_nr--; | ||
97 | /* clear edge detection */ | ||
98 | __raw_writel((TXx9_IRSCR_EIClrE | (irq_nr & 0xf)) | ||
99 | << (irq_nr & 0x10), | ||
100 | &tx4939_ircptr->edc.r); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static int tx4939_irq_set_type(struct irq_data *d, unsigned int flow_type) | ||
105 | { | ||
106 | unsigned int irq_nr = d->irq - TXX9_IRQ_BASE; | ||
107 | u32 cr; | ||
108 | u32 __iomem *crp; | ||
109 | int ofs; | ||
110 | int mode; | ||
111 | |||
112 | if (flow_type & IRQF_TRIGGER_PROBE) | ||
113 | return 0; | ||
114 | switch (flow_type & IRQF_TRIGGER_MASK) { | ||
115 | case IRQF_TRIGGER_RISING: | ||
116 | mode = TXx9_IRCR_UP; | ||
117 | break; | ||
118 | case IRQF_TRIGGER_FALLING: | ||
119 | mode = TXx9_IRCR_DOWN; | ||
120 | break; | ||
121 | case IRQF_TRIGGER_HIGH: | ||
122 | mode = TXx9_IRCR_HIGH; | ||
123 | break; | ||
124 | case IRQF_TRIGGER_LOW: | ||
125 | mode = TXx9_IRCR_LOW; | ||
126 | break; | ||
127 | default: | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | if (irq_nr < 32) { | ||
131 | irq_nr--; | ||
132 | crp = &tx4939_ircptr->dm[(irq_nr & 8) >> 3].r; | ||
133 | } else { | ||
134 | irq_nr -= 32; | ||
135 | crp = &tx4939_ircptr->dm2[((irq_nr & 8) >> 3)].r; | ||
136 | } | ||
137 | ofs = (((irq_nr & 16) >> 1) | (irq_nr & (8 - 1))) * 2; | ||
138 | cr = __raw_readl(crp); | ||
139 | cr &= ~(0x3 << ofs); | ||
140 | cr |= (mode & 0x3) << ofs; | ||
141 | __raw_writel(cr, crp); | ||
142 | tx4939irq[irq_nr].mode = mode; | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static struct irq_chip tx4939_irq_chip = { | ||
147 | .name = "TX4939", | ||
148 | .irq_ack = tx4939_irq_mask_ack, | ||
149 | .irq_mask = tx4939_irq_mask, | ||
150 | .irq_mask_ack = tx4939_irq_mask_ack, | ||
151 | .irq_unmask = tx4939_irq_unmask, | ||
152 | .irq_set_type = tx4939_irq_set_type, | ||
153 | }; | ||
154 | |||
155 | static int tx4939_irq_set_pri(int irc_irq, int new_pri) | ||
156 | { | ||
157 | int old_pri; | ||
158 | |||
159 | if ((unsigned int)irc_irq >= TX4939_NUM_IR) | ||
160 | return 0; | ||
161 | old_pri = tx4939irq[irc_irq].level; | ||
162 | tx4939irq[irc_irq].level = new_pri; | ||
163 | return old_pri; | ||
164 | } | ||
165 | |||
166 | void __init tx4939_irq_init(void) | ||
167 | { | ||
168 | int i; | ||
169 | |||
170 | mips_cpu_irq_init(); | ||
171 | /* disable interrupt control */ | ||
172 | __raw_writel(0, &tx4939_ircptr->den.r); | ||
173 | __raw_writel(0, &tx4939_ircptr->maskint.r); | ||
174 | __raw_writel(0, &tx4939_ircptr->maskext.r); | ||
175 | /* irq_base + 0 is not used */ | ||
176 | for (i = 1; i < TX4939_NUM_IR; i++) { | ||
177 | tx4939irq[i].level = 4; /* middle level */ | ||
178 | tx4939irq[i].mode = TXx9_IRCR_LOW; | ||
179 | irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &tx4939_irq_chip, | ||
180 | handle_level_irq); | ||
181 | } | ||
182 | |||
183 | /* mask all IRC interrupts */ | ||
184 | __raw_writel(0, &tx4939_ircptr->msk.r); | ||
185 | for (i = 0; i < 16; i++) | ||
186 | __raw_writel(0, &tx4939_ircptr->lvl[i].r); | ||
187 | /* setup IRC interrupt mode (Low Active) */ | ||
188 | for (i = 0; i < 2; i++) | ||
189 | __raw_writel(0, &tx4939_ircptr->dm[i].r); | ||
190 | for (i = 0; i < 2; i++) | ||
191 | __raw_writel(0, &tx4939_ircptr->dm2[i].r); | ||
192 | /* enable interrupt control */ | ||
193 | __raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r); | ||
194 | __raw_writel(irc_elevel, &tx4939_ircptr->msk.r); | ||
195 | |||
196 | irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT, | ||
197 | handle_simple_irq); | ||
198 | |||
199 | /* raise priority for errors, timers, sio */ | ||
200 | tx4939_irq_set_pri(TX4939_IR_WTOERR, 7); | ||
201 | tx4939_irq_set_pri(TX4939_IR_PCIERR, 7); | ||
202 | tx4939_irq_set_pri(TX4939_IR_PCIPME, 7); | ||
203 | for (i = 0; i < TX4939_NUM_IR_TMR; i++) | ||
204 | tx4939_irq_set_pri(TX4939_IR_TMR(i), 6); | ||
205 | for (i = 0; i < TX4939_NUM_IR_SIO; i++) | ||
206 | tx4939_irq_set_pri(TX4939_IR_SIO(i), 5); | ||
207 | } | ||
208 | |||
209 | int tx4939_irq(void) | ||
210 | { | ||
211 | u32 csr = __raw_readl(&tx4939_ircptr->cs.r); | ||
212 | |||
213 | if (likely(!(csr & TXx9_IRCSR_IF))) | ||
214 | return TXX9_IRQ_BASE + (csr & (TX4939_NUM_IR - 1)); | ||
215 | return -1; | ||
216 | } | ||
diff --git a/arch/mips/txx9/generic/mem_tx4927.c b/arch/mips/txx9/generic/mem_tx4927.c new file mode 100644 index 000000000..deea2ceae --- /dev/null +++ b/arch/mips/txx9/generic/mem_tx4927.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * common tx4927 memory interface | ||
3 | * | ||
4 | * Author: MontaVista Software, Inc. | ||
5 | * source@mvista.com | ||
6 | * | ||
7 | * Copyright 2001-2002 MontaVista Software Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
19 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
20 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
22 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
23 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | |||
30 | #include <linux/init.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/io.h> | ||
33 | #include <asm/txx9/tx4927.h> | ||
34 | |||
35 | static unsigned int __init tx4927_process_sdccr(u64 __iomem *addr) | ||
36 | { | ||
37 | u64 val; | ||
38 | unsigned int sdccr_ce; | ||
39 | unsigned int sdccr_bs; | ||
40 | unsigned int sdccr_rs; | ||
41 | unsigned int sdccr_cs; | ||
42 | unsigned int sdccr_mw; | ||
43 | unsigned int bs = 0; | ||
44 | unsigned int rs = 0; | ||
45 | unsigned int cs = 0; | ||
46 | unsigned int mw = 0; | ||
47 | |||
48 | val = __raw_readq(addr); | ||
49 | |||
50 | /* MVMCP -- need #defs for these bits masks */ | ||
51 | sdccr_ce = ((val & (1 << 10)) >> 10); | ||
52 | sdccr_bs = ((val & (1 << 8)) >> 8); | ||
53 | sdccr_rs = ((val & (3 << 5)) >> 5); | ||
54 | sdccr_cs = ((val & (7 << 2)) >> 2); | ||
55 | sdccr_mw = ((val & (1 << 0)) >> 0); | ||
56 | |||
57 | if (sdccr_ce) { | ||
58 | bs = 2 << sdccr_bs; | ||
59 | rs = 2048 << sdccr_rs; | ||
60 | cs = 256 << sdccr_cs; | ||
61 | mw = 8 >> sdccr_mw; | ||
62 | } | ||
63 | |||
64 | return rs * cs * mw * bs; | ||
65 | } | ||
66 | |||
67 | unsigned int __init tx4927_get_mem_size(void) | ||
68 | { | ||
69 | unsigned int total = 0; | ||
70 | int i; | ||
71 | |||
72 | for (i = 0; i < ARRAY_SIZE(tx4927_sdramcptr->cr); i++) | ||
73 | total += tx4927_process_sdccr(&tx4927_sdramcptr->cr[i]); | ||
74 | return total; | ||
75 | } | ||
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c new file mode 100644 index 000000000..fb998726b --- /dev/null +++ b/arch/mips/txx9/generic/pci.c | |||
@@ -0,0 +1,432 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/txx9/pci.c | ||
3 | * | ||
4 | * Based on linux/arch/mips/txx9/rbtx4927/setup.c, | ||
5 | * linux/arch/mips/txx9/rbtx4938/setup.c, | ||
6 | * and RBTX49xx patch from CELF patch archive. | ||
7 | * | ||
8 | * Copyright 2001-2005 MontaVista Software Inc. | ||
9 | * Copyright (C) 1996, 97, 2001, 04 Ralf Baechle (ralf@linux-mips.org) | ||
10 | * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 | ||
11 | * | ||
12 | * This file is subject to the terms and conditions of the GNU General Public | ||
13 | * License. See the file "COPYING" in the main directory of this archive | ||
14 | * for more details. | ||
15 | */ | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/jiffies.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <asm/txx9/generic.h> | ||
20 | #include <asm/txx9/pci.h> | ||
21 | #ifdef CONFIG_TOSHIBA_FPCIB0 | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <asm/i8259.h> | ||
25 | #include <asm/txx9/smsc_fdc37m81x.h> | ||
26 | #endif | ||
27 | |||
28 | static int __init | ||
29 | early_read_config_word(struct pci_controller *hose, | ||
30 | int top_bus, int bus, int devfn, int offset, u16 *value) | ||
31 | { | ||
32 | struct pci_bus fake_bus; | ||
33 | |||
34 | fake_bus.number = bus; | ||
35 | fake_bus.sysdata = hose; | ||
36 | fake_bus.ops = hose->pci_ops; | ||
37 | |||
38 | if (bus != top_bus) | ||
39 | /* Fake a parent bus structure. */ | ||
40 | fake_bus.parent = &fake_bus; | ||
41 | else | ||
42 | fake_bus.parent = NULL; | ||
43 | |||
44 | return pci_bus_read_config_word(&fake_bus, devfn, offset, value); | ||
45 | } | ||
46 | |||
47 | int __init txx9_pci66_check(struct pci_controller *hose, int top_bus, | ||
48 | int current_bus) | ||
49 | { | ||
50 | u32 pci_devfn; | ||
51 | unsigned short vid; | ||
52 | int cap66 = -1; | ||
53 | u16 stat; | ||
54 | |||
55 | /* It seems SLC90E66 needs some time after PCI reset... */ | ||
56 | mdelay(80); | ||
57 | |||
58 | pr_info("PCI: Checking 66MHz capabilities...\n"); | ||
59 | |||
60 | for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) { | ||
61 | if (PCI_FUNC(pci_devfn)) | ||
62 | continue; | ||
63 | if (early_read_config_word(hose, top_bus, current_bus, | ||
64 | pci_devfn, PCI_VENDOR_ID, &vid) != | ||
65 | PCIBIOS_SUCCESSFUL) | ||
66 | continue; | ||
67 | if (vid == 0xffff) | ||
68 | continue; | ||
69 | |||
70 | /* check 66MHz capability */ | ||
71 | if (cap66 < 0) | ||
72 | cap66 = 1; | ||
73 | if (cap66) { | ||
74 | early_read_config_word(hose, top_bus, current_bus, | ||
75 | pci_devfn, PCI_STATUS, &stat); | ||
76 | if (!(stat & PCI_STATUS_66MHZ)) { | ||
77 | pr_debug("PCI: %02x:%02x not 66MHz capable.\n", | ||
78 | current_bus, pci_devfn); | ||
79 | cap66 = 0; | ||
80 | break; | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | return cap66 > 0; | ||
85 | } | ||
86 | |||
87 | static struct resource primary_pci_mem_res[2] = { | ||
88 | { .name = "PCI MEM" }, | ||
89 | { .name = "PCI MMIO" }, | ||
90 | }; | ||
91 | static struct resource primary_pci_io_res = { .name = "PCI IO" }; | ||
92 | struct pci_controller txx9_primary_pcic = { | ||
93 | .mem_resource = &primary_pci_mem_res[0], | ||
94 | .io_resource = &primary_pci_io_res, | ||
95 | }; | ||
96 | |||
97 | #ifdef CONFIG_64BIT | ||
98 | int txx9_pci_mem_high __initdata = 1; | ||
99 | #else | ||
100 | int txx9_pci_mem_high __initdata; | ||
101 | #endif | ||
102 | |||
103 | /* | ||
104 | * allocate pci_controller and resources. | ||
105 | * mem_base, io_base: physical address. 0 for auto assignment. | ||
106 | * mem_size and io_size means max size on auto assignment. | ||
107 | * pcic must be &txx9_primary_pcic or NULL. | ||
108 | */ | ||
109 | struct pci_controller *__init | ||
110 | txx9_alloc_pci_controller(struct pci_controller *pcic, | ||
111 | unsigned long mem_base, unsigned long mem_size, | ||
112 | unsigned long io_base, unsigned long io_size) | ||
113 | { | ||
114 | struct pcic { | ||
115 | struct pci_controller c; | ||
116 | struct resource r_mem[2]; | ||
117 | struct resource r_io; | ||
118 | } *new = NULL; | ||
119 | int min_size = 0x10000; | ||
120 | |||
121 | if (!pcic) { | ||
122 | new = kzalloc(sizeof(*new), GFP_KERNEL); | ||
123 | if (!new) | ||
124 | return NULL; | ||
125 | new->r_mem[0].name = "PCI mem"; | ||
126 | new->r_mem[1].name = "PCI mmio"; | ||
127 | new->r_io.name = "PCI io"; | ||
128 | new->c.mem_resource = new->r_mem; | ||
129 | new->c.io_resource = &new->r_io; | ||
130 | pcic = &new->c; | ||
131 | } else | ||
132 | BUG_ON(pcic != &txx9_primary_pcic); | ||
133 | pcic->io_resource->flags = IORESOURCE_IO; | ||
134 | |||
135 | /* | ||
136 | * for auto assignment, first search a (big) region for PCI | ||
137 | * MEM, then search a region for PCI IO. | ||
138 | */ | ||
139 | if (mem_base) { | ||
140 | pcic->mem_resource[0].start = mem_base; | ||
141 | pcic->mem_resource[0].end = mem_base + mem_size - 1; | ||
142 | if (request_resource(&iomem_resource, &pcic->mem_resource[0])) | ||
143 | goto free_and_exit; | ||
144 | } else { | ||
145 | unsigned long min = 0, max = 0x20000000; /* low 512MB */ | ||
146 | if (!mem_size) { | ||
147 | /* default size for auto assignment */ | ||
148 | if (txx9_pci_mem_high) | ||
149 | mem_size = 0x20000000; /* mem:512M(max) */ | ||
150 | else | ||
151 | mem_size = 0x08000000; /* mem:128M(max) */ | ||
152 | } | ||
153 | if (txx9_pci_mem_high) { | ||
154 | min = 0x20000000; | ||
155 | max = 0xe0000000; | ||
156 | } | ||
157 | /* search free region for PCI MEM */ | ||
158 | for (; mem_size >= min_size; mem_size /= 2) { | ||
159 | if (allocate_resource(&iomem_resource, | ||
160 | &pcic->mem_resource[0], | ||
161 | mem_size, min, max, | ||
162 | mem_size, NULL, NULL) == 0) | ||
163 | break; | ||
164 | } | ||
165 | if (mem_size < min_size) | ||
166 | goto free_and_exit; | ||
167 | } | ||
168 | |||
169 | pcic->mem_resource[1].flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
170 | if (io_base) { | ||
171 | pcic->mem_resource[1].start = io_base; | ||
172 | pcic->mem_resource[1].end = io_base + io_size - 1; | ||
173 | if (request_resource(&iomem_resource, &pcic->mem_resource[1])) | ||
174 | goto release_and_exit; | ||
175 | } else { | ||
176 | if (!io_size) | ||
177 | /* default size for auto assignment */ | ||
178 | io_size = 0x01000000; /* io:16M(max) */ | ||
179 | /* search free region for PCI IO in low 512MB */ | ||
180 | for (; io_size >= min_size; io_size /= 2) { | ||
181 | if (allocate_resource(&iomem_resource, | ||
182 | &pcic->mem_resource[1], | ||
183 | io_size, 0, 0x20000000, | ||
184 | io_size, NULL, NULL) == 0) | ||
185 | break; | ||
186 | } | ||
187 | if (io_size < min_size) | ||
188 | goto release_and_exit; | ||
189 | io_base = pcic->mem_resource[1].start; | ||
190 | } | ||
191 | |||
192 | pcic->mem_resource[0].flags = IORESOURCE_MEM; | ||
193 | if (pcic == &txx9_primary_pcic && | ||
194 | mips_io_port_base == (unsigned long)-1) { | ||
195 | /* map ioport 0 to PCI I/O space address 0 */ | ||
196 | set_io_port_base(IO_BASE + pcic->mem_resource[1].start); | ||
197 | pcic->io_resource->start = 0; | ||
198 | pcic->io_offset = 0; /* busaddr == ioaddr */ | ||
199 | pcic->io_map_base = IO_BASE + pcic->mem_resource[1].start; | ||
200 | } else { | ||
201 | /* physaddr to ioaddr */ | ||
202 | pcic->io_resource->start = | ||
203 | io_base - (mips_io_port_base - IO_BASE); | ||
204 | pcic->io_offset = io_base - (mips_io_port_base - IO_BASE); | ||
205 | pcic->io_map_base = mips_io_port_base; | ||
206 | } | ||
207 | pcic->io_resource->end = pcic->io_resource->start + io_size - 1; | ||
208 | |||
209 | pcic->mem_offset = 0; /* busaddr == physaddr */ | ||
210 | |||
211 | pr_info("PCI: IO %pR MEM %pR\n", &pcic->mem_resource[1], | ||
212 | &pcic->mem_resource[0]); | ||
213 | |||
214 | /* register_pci_controller() will request MEM resource */ | ||
215 | release_resource(&pcic->mem_resource[0]); | ||
216 | return pcic; | ||
217 | release_and_exit: | ||
218 | release_resource(&pcic->mem_resource[0]); | ||
219 | free_and_exit: | ||
220 | kfree(new); | ||
221 | pr_err("PCI: Failed to allocate resources.\n"); | ||
222 | return NULL; | ||
223 | } | ||
224 | |||
225 | static int __init | ||
226 | txx9_arch_pci_init(void) | ||
227 | { | ||
228 | PCIBIOS_MIN_IO = 0x8000; /* reseve legacy I/O space */ | ||
229 | return 0; | ||
230 | } | ||
231 | arch_initcall(txx9_arch_pci_init); | ||
232 | |||
233 | /* IRQ/IDSEL mapping */ | ||
234 | int txx9_pci_option = | ||
235 | #ifdef CONFIG_PICMG_PCI_BACKPLANE_DEFAULT | ||
236 | TXX9_PCI_OPT_PICMG | | ||
237 | #endif | ||
238 | TXX9_PCI_OPT_CLK_AUTO; | ||
239 | |||
240 | enum txx9_pci_err_action txx9_pci_err_action = TXX9_PCI_ERR_REPORT; | ||
241 | |||
242 | #ifdef CONFIG_TOSHIBA_FPCIB0 | ||
243 | static irqreturn_t i8259_interrupt(int irq, void *dev_id) | ||
244 | { | ||
245 | int isairq; | ||
246 | |||
247 | isairq = i8259_irq(); | ||
248 | if (unlikely(isairq <= I8259A_IRQ_BASE)) | ||
249 | return IRQ_NONE; | ||
250 | generic_handle_irq(isairq); | ||
251 | return IRQ_HANDLED; | ||
252 | } | ||
253 | |||
254 | static int txx9_i8259_irq_setup(int irq) | ||
255 | { | ||
256 | int err; | ||
257 | |||
258 | init_i8259_irqs(); | ||
259 | err = request_irq(irq, &i8259_interrupt, IRQF_SHARED, | ||
260 | "cascade(i8259)", (void *)(long)irq); | ||
261 | if (!err) | ||
262 | pr_info("PCI-ISA bridge PIC (irq %d)\n", irq); | ||
263 | return err; | ||
264 | } | ||
265 | |||
266 | static void __ref quirk_slc90e66_bridge(struct pci_dev *dev) | ||
267 | { | ||
268 | int irq; /* PCI/ISA Bridge interrupt */ | ||
269 | u8 reg_64; | ||
270 | u32 reg_b0; | ||
271 | u8 reg_e1; | ||
272 | irq = pcibios_map_irq(dev, PCI_SLOT(dev->devfn), 1); /* INTA */ | ||
273 | if (!irq) | ||
274 | return; | ||
275 | txx9_i8259_irq_setup(irq); | ||
276 | pci_read_config_byte(dev, 0x64, ®_64); | ||
277 | pci_read_config_dword(dev, 0xb0, ®_b0); | ||
278 | pci_read_config_byte(dev, 0xe1, ®_e1); | ||
279 | /* serial irq control */ | ||
280 | reg_64 = 0xd0; | ||
281 | /* serial irq pin */ | ||
282 | reg_b0 |= 0x00010000; | ||
283 | /* ide irq on isa14 */ | ||
284 | reg_e1 &= 0xf0; | ||
285 | reg_e1 |= 0x0d; | ||
286 | pci_write_config_byte(dev, 0x64, reg_64); | ||
287 | pci_write_config_dword(dev, 0xb0, reg_b0); | ||
288 | pci_write_config_byte(dev, 0xe1, reg_e1); | ||
289 | |||
290 | smsc_fdc37m81x_init(0x3f0); | ||
291 | smsc_fdc37m81x_config_beg(); | ||
292 | smsc_fdc37m81x_config_set(SMSC_FDC37M81X_DNUM, | ||
293 | SMSC_FDC37M81X_KBD); | ||
294 | smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT, 1); | ||
295 | smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT2, 12); | ||
296 | smsc_fdc37m81x_config_set(SMSC_FDC37M81X_ACTIVE, | ||
297 | 1); | ||
298 | smsc_fdc37m81x_config_end(); | ||
299 | } | ||
300 | |||
301 | static void quirk_slc90e66_ide(struct pci_dev *dev) | ||
302 | { | ||
303 | unsigned char dat; | ||
304 | int regs[2] = {0x41, 0x43}; | ||
305 | int i; | ||
306 | |||
307 | /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */ | ||
308 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 14); | ||
309 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &dat); | ||
310 | pr_info("PCI: %s: IRQ %02x", pci_name(dev), dat); | ||
311 | /* enable SMSC SLC90E66 IDE */ | ||
312 | for (i = 0; i < ARRAY_SIZE(regs); i++) { | ||
313 | pci_read_config_byte(dev, regs[i], &dat); | ||
314 | pci_write_config_byte(dev, regs[i], dat | 0x80); | ||
315 | pci_read_config_byte(dev, regs[i], &dat); | ||
316 | pr_cont(" IDETIM%d %02x", i, dat); | ||
317 | } | ||
318 | pci_read_config_byte(dev, 0x5c, &dat); | ||
319 | /* | ||
320 | * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!! | ||
321 | * | ||
322 | * This line of code is intended to provide the user with a work | ||
323 | * around solution to the anomalies cited in SMSC's anomaly sheet | ||
324 | * entitled, "SLC90E66 Functional Rev.J_0.1 Anomalies"". | ||
325 | * | ||
326 | * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!! | ||
327 | */ | ||
328 | dat |= 0x01; | ||
329 | pci_write_config_byte(dev, 0x5c, dat); | ||
330 | pci_read_config_byte(dev, 0x5c, &dat); | ||
331 | pr_cont(" REG5C %02x\n", dat); | ||
332 | } | ||
333 | #endif /* CONFIG_TOSHIBA_FPCIB0 */ | ||
334 | |||
335 | static void tc35815_fixup(struct pci_dev *dev) | ||
336 | { | ||
337 | /* This device may have PM registers but not they are not supported. */ | ||
338 | if (dev->pm_cap) { | ||
339 | dev_info(&dev->dev, "PM disabled\n"); | ||
340 | dev->pm_cap = 0; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | static void final_fixup(struct pci_dev *dev) | ||
345 | { | ||
346 | unsigned char bist; | ||
347 | |||
348 | /* Do build-in self test */ | ||
349 | if (pci_read_config_byte(dev, PCI_BIST, &bist) == PCIBIOS_SUCCESSFUL && | ||
350 | (bist & PCI_BIST_CAPABLE)) { | ||
351 | unsigned long timeout; | ||
352 | pci_set_power_state(dev, PCI_D0); | ||
353 | pr_info("PCI: %s BIST...", pci_name(dev)); | ||
354 | pci_write_config_byte(dev, PCI_BIST, PCI_BIST_START); | ||
355 | timeout = jiffies + HZ * 2; /* timeout after 2 sec */ | ||
356 | do { | ||
357 | pci_read_config_byte(dev, PCI_BIST, &bist); | ||
358 | if (time_after(jiffies, timeout)) | ||
359 | break; | ||
360 | } while (bist & PCI_BIST_START); | ||
361 | if (bist & (PCI_BIST_CODE_MASK | PCI_BIST_START)) | ||
362 | pr_cont("failed. (0x%x)\n", bist); | ||
363 | else | ||
364 | pr_cont("OK.\n"); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | #ifdef CONFIG_TOSHIBA_FPCIB0 | ||
369 | #define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460 | ||
370 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_0, | ||
371 | quirk_slc90e66_bridge); | ||
372 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, | ||
373 | quirk_slc90e66_ide); | ||
374 | DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, | ||
375 | quirk_slc90e66_ide); | ||
376 | #endif | ||
377 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2, | ||
378 | PCI_DEVICE_ID_TOSHIBA_TC35815_NWU, tc35815_fixup); | ||
379 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TOSHIBA_2, | ||
380 | PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939, tc35815_fixup); | ||
381 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, final_fixup); | ||
382 | DECLARE_PCI_FIXUP_RESUME(PCI_ANY_ID, PCI_ANY_ID, final_fixup); | ||
383 | |||
384 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
385 | { | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int (*txx9_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); | ||
390 | int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
391 | { | ||
392 | return txx9_pci_map_irq(dev, slot, pin); | ||
393 | } | ||
394 | |||
395 | char * (*txx9_board_pcibios_setup)(char *str) __initdata; | ||
396 | |||
397 | char *__init txx9_pcibios_setup(char *str) | ||
398 | { | ||
399 | if (txx9_board_pcibios_setup && !txx9_board_pcibios_setup(str)) | ||
400 | return NULL; | ||
401 | if (!strcmp(str, "picmg")) { | ||
402 | /* PICMG compliant backplane (TOSHIBA JMB-PICMG-ATX | ||
403 | (5V or 3.3V), JMB-PICMG-L2 (5V only), etc.) */ | ||
404 | txx9_pci_option |= TXX9_PCI_OPT_PICMG; | ||
405 | return NULL; | ||
406 | } else if (!strcmp(str, "nopicmg")) { | ||
407 | /* non-PICMG compliant backplane (TOSHIBA | ||
408 | RBHBK4100,RBHBK4200, Interface PCM-PCM05, etc.) */ | ||
409 | txx9_pci_option &= ~TXX9_PCI_OPT_PICMG; | ||
410 | return NULL; | ||
411 | } else if (!strncmp(str, "clk=", 4)) { | ||
412 | char *val = str + 4; | ||
413 | txx9_pci_option &= ~TXX9_PCI_OPT_CLK_MASK; | ||
414 | if (strcmp(val, "33") == 0) | ||
415 | txx9_pci_option |= TXX9_PCI_OPT_CLK_33; | ||
416 | else if (strcmp(val, "66") == 0) | ||
417 | txx9_pci_option |= TXX9_PCI_OPT_CLK_66; | ||
418 | else /* "auto" */ | ||
419 | txx9_pci_option |= TXX9_PCI_OPT_CLK_AUTO; | ||
420 | return NULL; | ||
421 | } else if (!strncmp(str, "err=", 4)) { | ||
422 | if (!strcmp(str + 4, "panic")) | ||
423 | txx9_pci_err_action = TXX9_PCI_ERR_PANIC; | ||
424 | else if (!strcmp(str + 4, "ignore")) | ||
425 | txx9_pci_err_action = TXX9_PCI_ERR_IGNORE; | ||
426 | return NULL; | ||
427 | } | ||
428 | |||
429 | txx9_pci_map_irq = txx9_board_vec->pci_map_irq; | ||
430 | |||
431 | return str; | ||
432 | } | ||
diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c new file mode 100644 index 000000000..6d0fd0e05 --- /dev/null +++ b/arch/mips/txx9/generic/setup.c | |||
@@ -0,0 +1,965 @@ | |||
1 | /* | ||
2 | * Based on linux/arch/mips/txx9/rbtx4938/setup.c, | ||
3 | * and RBTX49xx patch from CELF patch archive. | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. | ||
6 | * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/export.h> | ||
18 | #include <linux/clk-provider.h> | ||
19 | #include <linux/clkdev.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/gpio/driver.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/platform_data/txx9/ndfmc.h> | ||
24 | #include <linux/serial_core.h> | ||
25 | #include <linux/mtd/physmap.h> | ||
26 | #include <linux/leds.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/irq.h> | ||
31 | #include <asm/bootinfo.h> | ||
32 | #include <asm/idle.h> | ||
33 | #include <asm/time.h> | ||
34 | #include <asm/reboot.h> | ||
35 | #include <asm/r4kcache.h> | ||
36 | #include <asm/setup.h> | ||
37 | #include <asm/txx9/generic.h> | ||
38 | #include <asm/txx9/pci.h> | ||
39 | #include <asm/txx9tmr.h> | ||
40 | #include <asm/txx9/dmac.h> | ||
41 | #ifdef CONFIG_CPU_TX49XX | ||
42 | #include <asm/txx9/tx4938.h> | ||
43 | #endif | ||
44 | |||
45 | /* EBUSC settings of TX4927, etc. */ | ||
46 | struct resource txx9_ce_res[8]; | ||
47 | static char txx9_ce_res_name[8][4]; /* "CEn" */ | ||
48 | |||
49 | /* pcode, internal register */ | ||
50 | unsigned int txx9_pcode; | ||
51 | char txx9_pcode_str[8]; | ||
52 | static struct resource txx9_reg_res = { | ||
53 | .name = txx9_pcode_str, | ||
54 | .flags = IORESOURCE_MEM, | ||
55 | }; | ||
56 | void __init | ||
57 | txx9_reg_res_init(unsigned int pcode, unsigned long base, unsigned long size) | ||
58 | { | ||
59 | int i; | ||
60 | |||
61 | for (i = 0; i < ARRAY_SIZE(txx9_ce_res); i++) { | ||
62 | sprintf(txx9_ce_res_name[i], "CE%d", i); | ||
63 | txx9_ce_res[i].flags = IORESOURCE_MEM; | ||
64 | txx9_ce_res[i].name = txx9_ce_res_name[i]; | ||
65 | } | ||
66 | |||
67 | txx9_pcode = pcode; | ||
68 | sprintf(txx9_pcode_str, "TX%x", pcode); | ||
69 | if (base) { | ||
70 | txx9_reg_res.start = base & 0xfffffffffULL; | ||
71 | txx9_reg_res.end = (base & 0xfffffffffULL) + (size - 1); | ||
72 | request_resource(&iomem_resource, &txx9_reg_res); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* clocks */ | ||
77 | unsigned int txx9_master_clock; | ||
78 | unsigned int txx9_cpu_clock; | ||
79 | unsigned int txx9_gbus_clock; | ||
80 | |||
81 | #ifdef CONFIG_CPU_TX39XX | ||
82 | /* don't enable by default - see errata */ | ||
83 | int txx9_ccfg_toeon __initdata; | ||
84 | #else | ||
85 | int txx9_ccfg_toeon __initdata = 1; | ||
86 | #endif | ||
87 | |||
88 | #define BOARD_VEC(board) extern struct txx9_board_vec board; | ||
89 | #include <asm/txx9/boards.h> | ||
90 | #undef BOARD_VEC | ||
91 | |||
92 | struct txx9_board_vec *txx9_board_vec __initdata; | ||
93 | static char txx9_system_type[32]; | ||
94 | |||
95 | static struct txx9_board_vec *board_vecs[] __initdata = { | ||
96 | #define BOARD_VEC(board) &board, | ||
97 | #include <asm/txx9/boards.h> | ||
98 | #undef BOARD_VEC | ||
99 | }; | ||
100 | |||
101 | static struct txx9_board_vec *__init find_board_byname(const char *name) | ||
102 | { | ||
103 | int i; | ||
104 | |||
105 | /* search board_vecs table */ | ||
106 | for (i = 0; i < ARRAY_SIZE(board_vecs); i++) { | ||
107 | if (strstr(board_vecs[i]->system, name)) | ||
108 | return board_vecs[i]; | ||
109 | } | ||
110 | return NULL; | ||
111 | } | ||
112 | |||
113 | static void __init prom_init_cmdline(void) | ||
114 | { | ||
115 | int argc; | ||
116 | int *argv32; | ||
117 | int i; /* Always ignore the "-c" at argv[0] */ | ||
118 | |||
119 | if (fw_arg0 >= CKSEG0 || fw_arg1 < CKSEG0) { | ||
120 | /* | ||
121 | * argc is not a valid number, or argv32 is not a valid | ||
122 | * pointer | ||
123 | */ | ||
124 | argc = 0; | ||
125 | argv32 = NULL; | ||
126 | } else { | ||
127 | argc = (int)fw_arg0; | ||
128 | argv32 = (int *)fw_arg1; | ||
129 | } | ||
130 | |||
131 | arcs_cmdline[0] = '\0'; | ||
132 | |||
133 | for (i = 1; i < argc; i++) { | ||
134 | char *str = (char *)(long)argv32[i]; | ||
135 | if (i != 1) | ||
136 | strcat(arcs_cmdline, " "); | ||
137 | if (strchr(str, ' ')) { | ||
138 | strcat(arcs_cmdline, "\""); | ||
139 | strcat(arcs_cmdline, str); | ||
140 | strcat(arcs_cmdline, "\""); | ||
141 | } else | ||
142 | strcat(arcs_cmdline, str); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | static int txx9_ic_disable __initdata; | ||
147 | static int txx9_dc_disable __initdata; | ||
148 | |||
149 | #if defined(CONFIG_CPU_TX49XX) | ||
150 | /* flush all cache on very early stage (before 4k_cache_init) */ | ||
151 | static void __init early_flush_dcache(void) | ||
152 | { | ||
153 | unsigned int conf = read_c0_config(); | ||
154 | unsigned int dc_size = 1 << (12 + ((conf & CONF_DC) >> 6)); | ||
155 | unsigned int linesz = 32; | ||
156 | unsigned long addr, end; | ||
157 | |||
158 | end = INDEX_BASE + dc_size / 4; | ||
159 | /* 4way, waybit=0 */ | ||
160 | for (addr = INDEX_BASE; addr < end; addr += linesz) { | ||
161 | cache_op(Index_Writeback_Inv_D, addr | 0); | ||
162 | cache_op(Index_Writeback_Inv_D, addr | 1); | ||
163 | cache_op(Index_Writeback_Inv_D, addr | 2); | ||
164 | cache_op(Index_Writeback_Inv_D, addr | 3); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static void __init txx9_cache_fixup(void) | ||
169 | { | ||
170 | unsigned int conf; | ||
171 | |||
172 | conf = read_c0_config(); | ||
173 | /* flush and disable */ | ||
174 | if (txx9_ic_disable) { | ||
175 | conf |= TX49_CONF_IC; | ||
176 | write_c0_config(conf); | ||
177 | } | ||
178 | if (txx9_dc_disable) { | ||
179 | early_flush_dcache(); | ||
180 | conf |= TX49_CONF_DC; | ||
181 | write_c0_config(conf); | ||
182 | } | ||
183 | |||
184 | /* enable cache */ | ||
185 | conf = read_c0_config(); | ||
186 | if (!txx9_ic_disable) | ||
187 | conf &= ~TX49_CONF_IC; | ||
188 | if (!txx9_dc_disable) | ||
189 | conf &= ~TX49_CONF_DC; | ||
190 | write_c0_config(conf); | ||
191 | |||
192 | if (conf & TX49_CONF_IC) | ||
193 | pr_info("TX49XX I-Cache disabled.\n"); | ||
194 | if (conf & TX49_CONF_DC) | ||
195 | pr_info("TX49XX D-Cache disabled.\n"); | ||
196 | } | ||
197 | #elif defined(CONFIG_CPU_TX39XX) | ||
198 | /* flush all cache on very early stage (before tx39_cache_init) */ | ||
199 | static void __init early_flush_dcache(void) | ||
200 | { | ||
201 | unsigned int conf = read_c0_config(); | ||
202 | unsigned int dc_size = 1 << (10 + ((conf & TX39_CONF_DCS_MASK) >> | ||
203 | TX39_CONF_DCS_SHIFT)); | ||
204 | unsigned int linesz = 16; | ||
205 | unsigned long addr, end; | ||
206 | |||
207 | end = INDEX_BASE + dc_size / 2; | ||
208 | /* 2way, waybit=0 */ | ||
209 | for (addr = INDEX_BASE; addr < end; addr += linesz) { | ||
210 | cache_op(Index_Writeback_Inv_D, addr | 0); | ||
211 | cache_op(Index_Writeback_Inv_D, addr | 1); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static void __init txx9_cache_fixup(void) | ||
216 | { | ||
217 | unsigned int conf; | ||
218 | |||
219 | conf = read_c0_config(); | ||
220 | /* flush and disable */ | ||
221 | if (txx9_ic_disable) { | ||
222 | conf &= ~TX39_CONF_ICE; | ||
223 | write_c0_config(conf); | ||
224 | } | ||
225 | if (txx9_dc_disable) { | ||
226 | early_flush_dcache(); | ||
227 | conf &= ~TX39_CONF_DCE; | ||
228 | write_c0_config(conf); | ||
229 | } | ||
230 | |||
231 | /* enable cache */ | ||
232 | conf = read_c0_config(); | ||
233 | if (!txx9_ic_disable) | ||
234 | conf |= TX39_CONF_ICE; | ||
235 | if (!txx9_dc_disable) | ||
236 | conf |= TX39_CONF_DCE; | ||
237 | write_c0_config(conf); | ||
238 | |||
239 | if (!(conf & TX39_CONF_ICE)) | ||
240 | pr_info("TX39XX I-Cache disabled.\n"); | ||
241 | if (!(conf & TX39_CONF_DCE)) | ||
242 | pr_info("TX39XX D-Cache disabled.\n"); | ||
243 | } | ||
244 | #else | ||
245 | static inline void txx9_cache_fixup(void) | ||
246 | { | ||
247 | } | ||
248 | #endif | ||
249 | |||
250 | static void __init preprocess_cmdline(void) | ||
251 | { | ||
252 | static char cmdline[COMMAND_LINE_SIZE] __initdata; | ||
253 | char *s; | ||
254 | |||
255 | strcpy(cmdline, arcs_cmdline); | ||
256 | s = cmdline; | ||
257 | arcs_cmdline[0] = '\0'; | ||
258 | while (s && *s) { | ||
259 | char *str = strsep(&s, " "); | ||
260 | if (strncmp(str, "board=", 6) == 0) { | ||
261 | txx9_board_vec = find_board_byname(str + 6); | ||
262 | continue; | ||
263 | } else if (strncmp(str, "masterclk=", 10) == 0) { | ||
264 | unsigned int val; | ||
265 | if (kstrtouint(str + 10, 10, &val) == 0) | ||
266 | txx9_master_clock = val; | ||
267 | continue; | ||
268 | } else if (strcmp(str, "icdisable") == 0) { | ||
269 | txx9_ic_disable = 1; | ||
270 | continue; | ||
271 | } else if (strcmp(str, "dcdisable") == 0) { | ||
272 | txx9_dc_disable = 1; | ||
273 | continue; | ||
274 | } else if (strcmp(str, "toeoff") == 0) { | ||
275 | txx9_ccfg_toeon = 0; | ||
276 | continue; | ||
277 | } else if (strcmp(str, "toeon") == 0) { | ||
278 | txx9_ccfg_toeon = 1; | ||
279 | continue; | ||
280 | } | ||
281 | if (arcs_cmdline[0]) | ||
282 | strcat(arcs_cmdline, " "); | ||
283 | strcat(arcs_cmdline, str); | ||
284 | } | ||
285 | |||
286 | txx9_cache_fixup(); | ||
287 | } | ||
288 | |||
289 | static void __init select_board(void) | ||
290 | { | ||
291 | const char *envstr; | ||
292 | |||
293 | /* first, determine by "board=" argument in preprocess_cmdline() */ | ||
294 | if (txx9_board_vec) | ||
295 | return; | ||
296 | /* next, determine by "board" envvar */ | ||
297 | envstr = prom_getenv("board"); | ||
298 | if (envstr) { | ||
299 | txx9_board_vec = find_board_byname(envstr); | ||
300 | if (txx9_board_vec) | ||
301 | return; | ||
302 | } | ||
303 | |||
304 | /* select "default" board */ | ||
305 | #ifdef CONFIG_TOSHIBA_JMR3927 | ||
306 | txx9_board_vec = &jmr3927_vec; | ||
307 | #endif | ||
308 | #ifdef CONFIG_CPU_TX49XX | ||
309 | switch (TX4938_REV_PCODE()) { | ||
310 | #ifdef CONFIG_TOSHIBA_RBTX4927 | ||
311 | case 0x4927: | ||
312 | txx9_board_vec = &rbtx4927_vec; | ||
313 | break; | ||
314 | case 0x4937: | ||
315 | txx9_board_vec = &rbtx4937_vec; | ||
316 | break; | ||
317 | #endif | ||
318 | #ifdef CONFIG_TOSHIBA_RBTX4938 | ||
319 | case 0x4938: | ||
320 | txx9_board_vec = &rbtx4938_vec; | ||
321 | break; | ||
322 | #endif | ||
323 | #ifdef CONFIG_TOSHIBA_RBTX4939 | ||
324 | case 0x4939: | ||
325 | txx9_board_vec = &rbtx4939_vec; | ||
326 | break; | ||
327 | #endif | ||
328 | } | ||
329 | #endif | ||
330 | } | ||
331 | |||
332 | void __init prom_init(void) | ||
333 | { | ||
334 | prom_init_cmdline(); | ||
335 | preprocess_cmdline(); | ||
336 | select_board(); | ||
337 | |||
338 | strcpy(txx9_system_type, txx9_board_vec->system); | ||
339 | |||
340 | txx9_board_vec->prom_init(); | ||
341 | } | ||
342 | |||
343 | void __init prom_free_prom_memory(void) | ||
344 | { | ||
345 | } | ||
346 | |||
347 | const char *get_system_type(void) | ||
348 | { | ||
349 | return txx9_system_type; | ||
350 | } | ||
351 | |||
352 | const char *__init prom_getenv(const char *name) | ||
353 | { | ||
354 | const s32 *str; | ||
355 | |||
356 | if (fw_arg2 < CKSEG0) | ||
357 | return NULL; | ||
358 | |||
359 | str = (const s32 *)fw_arg2; | ||
360 | /* YAMON style ("name", "value" pairs) */ | ||
361 | while (str[0] && str[1]) { | ||
362 | if (!strcmp((const char *)(unsigned long)str[0], name)) | ||
363 | return (const char *)(unsigned long)str[1]; | ||
364 | str += 2; | ||
365 | } | ||
366 | return NULL; | ||
367 | } | ||
368 | |||
369 | static void __noreturn txx9_machine_halt(void) | ||
370 | { | ||
371 | local_irq_disable(); | ||
372 | clear_c0_status(ST0_IM); | ||
373 | while (1) { | ||
374 | if (cpu_wait) { | ||
375 | (*cpu_wait)(); | ||
376 | if (cpu_has_counter) { | ||
377 | /* | ||
378 | * Clear counter interrupt while it | ||
379 | * breaks WAIT instruction even if | ||
380 | * masked. | ||
381 | */ | ||
382 | write_c0_compare(0); | ||
383 | } | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | |||
388 | /* Watchdog support */ | ||
389 | void __init txx9_wdt_init(unsigned long base) | ||
390 | { | ||
391 | struct resource res = { | ||
392 | .start = base, | ||
393 | .end = base + 0x100 - 1, | ||
394 | .flags = IORESOURCE_MEM, | ||
395 | }; | ||
396 | platform_device_register_simple("txx9wdt", -1, &res, 1); | ||
397 | } | ||
398 | |||
399 | void txx9_wdt_now(unsigned long base) | ||
400 | { | ||
401 | struct txx9_tmr_reg __iomem *tmrptr = | ||
402 | ioremap(base, sizeof(struct txx9_tmr_reg)); | ||
403 | /* disable watch dog timer */ | ||
404 | __raw_writel(TXx9_TMWTMR_WDIS | TXx9_TMWTMR_TWC, &tmrptr->wtmr); | ||
405 | __raw_writel(0, &tmrptr->tcr); | ||
406 | /* kick watchdog */ | ||
407 | __raw_writel(TXx9_TMWTMR_TWIE, &tmrptr->wtmr); | ||
408 | __raw_writel(1, &tmrptr->cpra); /* immediate */ | ||
409 | __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, | ||
410 | &tmrptr->tcr); | ||
411 | } | ||
412 | |||
413 | /* SPI support */ | ||
414 | void __init txx9_spi_init(int busid, unsigned long base, int irq) | ||
415 | { | ||
416 | struct resource res[] = { | ||
417 | { | ||
418 | .start = base, | ||
419 | .end = base + 0x20 - 1, | ||
420 | .flags = IORESOURCE_MEM, | ||
421 | }, { | ||
422 | .start = irq, | ||
423 | .flags = IORESOURCE_IRQ, | ||
424 | }, | ||
425 | }; | ||
426 | platform_device_register_simple("spi_txx9", busid, | ||
427 | res, ARRAY_SIZE(res)); | ||
428 | } | ||
429 | |||
430 | void __init txx9_ethaddr_init(unsigned int id, unsigned char *ethaddr) | ||
431 | { | ||
432 | struct platform_device *pdev = | ||
433 | platform_device_alloc("tc35815-mac", id); | ||
434 | if (!pdev || | ||
435 | platform_device_add_data(pdev, ethaddr, 6) || | ||
436 | platform_device_add(pdev)) | ||
437 | platform_device_put(pdev); | ||
438 | } | ||
439 | |||
440 | void __init txx9_sio_init(unsigned long baseaddr, int irq, | ||
441 | unsigned int line, unsigned int sclk, int nocts) | ||
442 | { | ||
443 | #ifdef CONFIG_SERIAL_TXX9 | ||
444 | struct uart_port req; | ||
445 | |||
446 | memset(&req, 0, sizeof(req)); | ||
447 | req.line = line; | ||
448 | req.iotype = UPIO_MEM; | ||
449 | req.membase = ioremap(baseaddr, 0x24); | ||
450 | req.mapbase = baseaddr; | ||
451 | req.irq = irq; | ||
452 | if (!nocts) | ||
453 | req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/; | ||
454 | if (sclk) { | ||
455 | req.flags |= UPF_MAGIC_MULTIPLIER /*USE_SCLK*/; | ||
456 | req.uartclk = sclk; | ||
457 | } else | ||
458 | req.uartclk = TXX9_IMCLK; | ||
459 | early_serial_txx9_setup(&req); | ||
460 | #endif /* CONFIG_SERIAL_TXX9 */ | ||
461 | } | ||
462 | |||
463 | #ifdef CONFIG_EARLY_PRINTK | ||
464 | static void null_prom_putchar(char c) | ||
465 | { | ||
466 | } | ||
467 | void (*txx9_prom_putchar)(char c) = null_prom_putchar; | ||
468 | |||
469 | void prom_putchar(char c) | ||
470 | { | ||
471 | txx9_prom_putchar(c); | ||
472 | } | ||
473 | |||
474 | static void __iomem *early_txx9_sio_port; | ||
475 | |||
476 | static void early_txx9_sio_putchar(char c) | ||
477 | { | ||
478 | #define TXX9_SICISR 0x0c | ||
479 | #define TXX9_SITFIFO 0x1c | ||
480 | #define TXX9_SICISR_TXALS 0x00000002 | ||
481 | while (!(__raw_readl(early_txx9_sio_port + TXX9_SICISR) & | ||
482 | TXX9_SICISR_TXALS)) | ||
483 | ; | ||
484 | __raw_writel(c, early_txx9_sio_port + TXX9_SITFIFO); | ||
485 | } | ||
486 | |||
487 | void __init txx9_sio_putchar_init(unsigned long baseaddr) | ||
488 | { | ||
489 | early_txx9_sio_port = ioremap(baseaddr, 0x24); | ||
490 | txx9_prom_putchar = early_txx9_sio_putchar; | ||
491 | } | ||
492 | #endif /* CONFIG_EARLY_PRINTK */ | ||
493 | |||
494 | /* wrappers */ | ||
495 | void __init plat_mem_setup(void) | ||
496 | { | ||
497 | ioport_resource.start = 0; | ||
498 | ioport_resource.end = ~0UL; /* no limit */ | ||
499 | iomem_resource.start = 0; | ||
500 | iomem_resource.end = ~0UL; /* no limit */ | ||
501 | |||
502 | /* fallback restart/halt routines */ | ||
503 | _machine_restart = (void (*)(char *))txx9_machine_halt; | ||
504 | _machine_halt = txx9_machine_halt; | ||
505 | pm_power_off = txx9_machine_halt; | ||
506 | |||
507 | #ifdef CONFIG_PCI | ||
508 | pcibios_plat_setup = txx9_pcibios_setup; | ||
509 | #endif | ||
510 | txx9_board_vec->mem_setup(); | ||
511 | } | ||
512 | |||
513 | void __init arch_init_irq(void) | ||
514 | { | ||
515 | txx9_board_vec->irq_setup(); | ||
516 | } | ||
517 | |||
518 | void __init plat_time_init(void) | ||
519 | { | ||
520 | #ifdef CONFIG_CPU_TX49XX | ||
521 | mips_hpt_frequency = txx9_cpu_clock / 2; | ||
522 | #endif | ||
523 | txx9_board_vec->time_init(); | ||
524 | } | ||
525 | |||
526 | static void txx9_clk_init(void) | ||
527 | { | ||
528 | struct clk_hw *hw; | ||
529 | int error; | ||
530 | |||
531 | hw = clk_hw_register_fixed_rate(NULL, "gbus", NULL, 0, txx9_gbus_clock); | ||
532 | if (IS_ERR(hw)) { | ||
533 | error = PTR_ERR(hw); | ||
534 | goto fail; | ||
535 | } | ||
536 | |||
537 | hw = clk_hw_register_fixed_factor(NULL, "imbus", "gbus", 0, 1, 2); | ||
538 | error = clk_hw_register_clkdev(hw, "imbus_clk", NULL); | ||
539 | if (error) | ||
540 | goto fail; | ||
541 | |||
542 | #ifdef CONFIG_CPU_TX49XX | ||
543 | if (TX4938_REV_PCODE() == 0x4938) { | ||
544 | hw = clk_hw_register_fixed_factor(NULL, "spi", "gbus", 0, 1, 4); | ||
545 | error = clk_hw_register_clkdev(hw, "spi-baseclk", NULL); | ||
546 | if (error) | ||
547 | goto fail; | ||
548 | } | ||
549 | #endif | ||
550 | |||
551 | return; | ||
552 | |||
553 | fail: | ||
554 | pr_err("Failed to register clocks: %d\n", error); | ||
555 | } | ||
556 | |||
557 | static int __init _txx9_arch_init(void) | ||
558 | { | ||
559 | txx9_clk_init(); | ||
560 | |||
561 | if (txx9_board_vec->arch_init) | ||
562 | txx9_board_vec->arch_init(); | ||
563 | return 0; | ||
564 | } | ||
565 | arch_initcall(_txx9_arch_init); | ||
566 | |||
567 | static int __init _txx9_device_init(void) | ||
568 | { | ||
569 | if (txx9_board_vec->device_init) | ||
570 | txx9_board_vec->device_init(); | ||
571 | return 0; | ||
572 | } | ||
573 | device_initcall(_txx9_device_init); | ||
574 | |||
575 | int (*txx9_irq_dispatch)(int pending); | ||
576 | asmlinkage void plat_irq_dispatch(void) | ||
577 | { | ||
578 | int pending = read_c0_status() & read_c0_cause() & ST0_IM; | ||
579 | int irq = txx9_irq_dispatch(pending); | ||
580 | |||
581 | if (likely(irq >= 0)) | ||
582 | do_IRQ(irq); | ||
583 | else | ||
584 | spurious_interrupt(); | ||
585 | } | ||
586 | |||
587 | /* see include/asm-mips/mach-tx39xx/mangle-port.h, for example. */ | ||
588 | #ifdef NEEDS_TXX9_SWIZZLE_ADDR_B | ||
589 | static unsigned long __swizzle_addr_none(unsigned long port) | ||
590 | { | ||
591 | return port; | ||
592 | } | ||
593 | unsigned long (*__swizzle_addr_b)(unsigned long port) = __swizzle_addr_none; | ||
594 | EXPORT_SYMBOL(__swizzle_addr_b); | ||
595 | #endif | ||
596 | |||
597 | #ifdef NEEDS_TXX9_IOSWABW | ||
598 | static u16 ioswabw_default(volatile u16 *a, u16 x) | ||
599 | { | ||
600 | return le16_to_cpu(x); | ||
601 | } | ||
602 | static u16 __mem_ioswabw_default(volatile u16 *a, u16 x) | ||
603 | { | ||
604 | return x; | ||
605 | } | ||
606 | u16 (*ioswabw)(volatile u16 *a, u16 x) = ioswabw_default; | ||
607 | EXPORT_SYMBOL(ioswabw); | ||
608 | u16 (*__mem_ioswabw)(volatile u16 *a, u16 x) = __mem_ioswabw_default; | ||
609 | EXPORT_SYMBOL(__mem_ioswabw); | ||
610 | #endif | ||
611 | |||
612 | void __init txx9_physmap_flash_init(int no, unsigned long addr, | ||
613 | unsigned long size, | ||
614 | const struct physmap_flash_data *pdata) | ||
615 | { | ||
616 | #if IS_ENABLED(CONFIG_MTD_PHYSMAP) | ||
617 | struct resource res = { | ||
618 | .start = addr, | ||
619 | .end = addr + size - 1, | ||
620 | .flags = IORESOURCE_MEM, | ||
621 | }; | ||
622 | struct platform_device *pdev; | ||
623 | static struct mtd_partition parts[2]; | ||
624 | struct physmap_flash_data pdata_part; | ||
625 | |||
626 | /* If this area contained boot area, make separate partition */ | ||
627 | if (pdata->nr_parts == 0 && !pdata->parts && | ||
628 | addr < 0x1fc00000 && addr + size > 0x1fc00000 && | ||
629 | !parts[0].name) { | ||
630 | parts[0].name = "boot"; | ||
631 | parts[0].offset = 0x1fc00000 - addr; | ||
632 | parts[0].size = addr + size - 0x1fc00000; | ||
633 | parts[1].name = "user"; | ||
634 | parts[1].offset = 0; | ||
635 | parts[1].size = 0x1fc00000 - addr; | ||
636 | pdata_part = *pdata; | ||
637 | pdata_part.nr_parts = ARRAY_SIZE(parts); | ||
638 | pdata_part.parts = parts; | ||
639 | pdata = &pdata_part; | ||
640 | } | ||
641 | |||
642 | pdev = platform_device_alloc("physmap-flash", no); | ||
643 | if (!pdev || | ||
644 | platform_device_add_resources(pdev, &res, 1) || | ||
645 | platform_device_add_data(pdev, pdata, sizeof(*pdata)) || | ||
646 | platform_device_add(pdev)) | ||
647 | platform_device_put(pdev); | ||
648 | #endif | ||
649 | } | ||
650 | |||
651 | void __init txx9_ndfmc_init(unsigned long baseaddr, | ||
652 | const struct txx9ndfmc_platform_data *pdata) | ||
653 | { | ||
654 | #if IS_ENABLED(CONFIG_MTD_NAND_TXX9NDFMC) | ||
655 | struct resource res = { | ||
656 | .start = baseaddr, | ||
657 | .end = baseaddr + 0x1000 - 1, | ||
658 | .flags = IORESOURCE_MEM, | ||
659 | }; | ||
660 | struct platform_device *pdev = platform_device_alloc("txx9ndfmc", -1); | ||
661 | |||
662 | if (!pdev || | ||
663 | platform_device_add_resources(pdev, &res, 1) || | ||
664 | platform_device_add_data(pdev, pdata, sizeof(*pdata)) || | ||
665 | platform_device_add(pdev)) | ||
666 | platform_device_put(pdev); | ||
667 | #endif | ||
668 | } | ||
669 | |||
670 | #if IS_ENABLED(CONFIG_LEDS_GPIO) | ||
671 | static DEFINE_SPINLOCK(txx9_iocled_lock); | ||
672 | |||
673 | #define TXX9_IOCLED_MAXLEDS 8 | ||
674 | |||
675 | struct txx9_iocled_data { | ||
676 | struct gpio_chip chip; | ||
677 | u8 cur_val; | ||
678 | void __iomem *mmioaddr; | ||
679 | struct gpio_led_platform_data pdata; | ||
680 | struct gpio_led leds[TXX9_IOCLED_MAXLEDS]; | ||
681 | char names[TXX9_IOCLED_MAXLEDS][32]; | ||
682 | }; | ||
683 | |||
684 | static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset) | ||
685 | { | ||
686 | struct txx9_iocled_data *data = gpiochip_get_data(chip); | ||
687 | return !!(data->cur_val & (1 << offset)); | ||
688 | } | ||
689 | |||
690 | static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset, | ||
691 | int value) | ||
692 | { | ||
693 | struct txx9_iocled_data *data = gpiochip_get_data(chip); | ||
694 | unsigned long flags; | ||
695 | spin_lock_irqsave(&txx9_iocled_lock, flags); | ||
696 | if (value) | ||
697 | data->cur_val |= 1 << offset; | ||
698 | else | ||
699 | data->cur_val &= ~(1 << offset); | ||
700 | writeb(data->cur_val, data->mmioaddr); | ||
701 | mmiowb(); | ||
702 | spin_unlock_irqrestore(&txx9_iocled_lock, flags); | ||
703 | } | ||
704 | |||
705 | static int txx9_iocled_dir_in(struct gpio_chip *chip, unsigned int offset) | ||
706 | { | ||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | static int txx9_iocled_dir_out(struct gpio_chip *chip, unsigned int offset, | ||
711 | int value) | ||
712 | { | ||
713 | txx9_iocled_set(chip, offset, value); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | void __init txx9_iocled_init(unsigned long baseaddr, | ||
718 | int basenum, unsigned int num, int lowactive, | ||
719 | const char *color, char **deftriggers) | ||
720 | { | ||
721 | struct txx9_iocled_data *iocled; | ||
722 | struct platform_device *pdev; | ||
723 | int i; | ||
724 | static char *default_triggers[] __initdata = { | ||
725 | "heartbeat", | ||
726 | "disk-activity", | ||
727 | "nand-disk", | ||
728 | NULL, | ||
729 | }; | ||
730 | |||
731 | if (!deftriggers) | ||
732 | deftriggers = default_triggers; | ||
733 | iocled = kzalloc(sizeof(*iocled), GFP_KERNEL); | ||
734 | if (!iocled) | ||
735 | return; | ||
736 | iocled->mmioaddr = ioremap(baseaddr, 1); | ||
737 | if (!iocled->mmioaddr) | ||
738 | goto out_free; | ||
739 | iocled->chip.get = txx9_iocled_get; | ||
740 | iocled->chip.set = txx9_iocled_set; | ||
741 | iocled->chip.direction_input = txx9_iocled_dir_in; | ||
742 | iocled->chip.direction_output = txx9_iocled_dir_out; | ||
743 | iocled->chip.label = "iocled"; | ||
744 | iocled->chip.base = basenum; | ||
745 | iocled->chip.ngpio = num; | ||
746 | if (gpiochip_add_data(&iocled->chip, iocled)) | ||
747 | goto out_unmap; | ||
748 | if (basenum < 0) | ||
749 | basenum = iocled->chip.base; | ||
750 | |||
751 | pdev = platform_device_alloc("leds-gpio", basenum); | ||
752 | if (!pdev) | ||
753 | goto out_gpio; | ||
754 | iocled->pdata.num_leds = num; | ||
755 | iocled->pdata.leds = iocled->leds; | ||
756 | for (i = 0; i < num; i++) { | ||
757 | struct gpio_led *led = &iocled->leds[i]; | ||
758 | snprintf(iocled->names[i], sizeof(iocled->names[i]), | ||
759 | "iocled:%s:%u", color, i); | ||
760 | led->name = iocled->names[i]; | ||
761 | led->gpio = basenum + i; | ||
762 | led->active_low = lowactive; | ||
763 | if (deftriggers && *deftriggers) | ||
764 | led->default_trigger = *deftriggers++; | ||
765 | } | ||
766 | pdev->dev.platform_data = &iocled->pdata; | ||
767 | if (platform_device_add(pdev)) | ||
768 | goto out_pdev; | ||
769 | return; | ||
770 | |||
771 | out_pdev: | ||
772 | platform_device_put(pdev); | ||
773 | out_gpio: | ||
774 | gpiochip_remove(&iocled->chip); | ||
775 | out_unmap: | ||
776 | iounmap(iocled->mmioaddr); | ||
777 | out_free: | ||
778 | kfree(iocled); | ||
779 | } | ||
780 | #else /* CONFIG_LEDS_GPIO */ | ||
781 | void __init txx9_iocled_init(unsigned long baseaddr, | ||
782 | int basenum, unsigned int num, int lowactive, | ||
783 | const char *color, char **deftriggers) | ||
784 | { | ||
785 | } | ||
786 | #endif /* CONFIG_LEDS_GPIO */ | ||
787 | |||
788 | void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq, | ||
789 | const struct txx9dmac_platform_data *pdata) | ||
790 | { | ||
791 | #if IS_ENABLED(CONFIG_TXX9_DMAC) | ||
792 | struct resource res[] = { | ||
793 | { | ||
794 | .start = baseaddr, | ||
795 | .end = baseaddr + 0x800 - 1, | ||
796 | .flags = IORESOURCE_MEM, | ||
797 | #ifndef CONFIG_MACH_TX49XX | ||
798 | }, { | ||
799 | .start = irq, | ||
800 | .flags = IORESOURCE_IRQ, | ||
801 | #endif | ||
802 | } | ||
803 | }; | ||
804 | #ifdef CONFIG_MACH_TX49XX | ||
805 | struct resource chan_res[] = { | ||
806 | { | ||
807 | .flags = IORESOURCE_IRQ, | ||
808 | } | ||
809 | }; | ||
810 | #endif | ||
811 | struct platform_device *pdev = platform_device_alloc("txx9dmac", id); | ||
812 | struct txx9dmac_chan_platform_data cpdata; | ||
813 | int i; | ||
814 | |||
815 | if (!pdev || | ||
816 | platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) || | ||
817 | platform_device_add_data(pdev, pdata, sizeof(*pdata)) || | ||
818 | platform_device_add(pdev)) { | ||
819 | platform_device_put(pdev); | ||
820 | return; | ||
821 | } | ||
822 | memset(&cpdata, 0, sizeof(cpdata)); | ||
823 | cpdata.dmac_dev = pdev; | ||
824 | for (i = 0; i < TXX9_DMA_MAX_NR_CHANNELS; i++) { | ||
825 | #ifdef CONFIG_MACH_TX49XX | ||
826 | chan_res[0].start = irq + i; | ||
827 | #endif | ||
828 | pdev = platform_device_alloc("txx9dmac-chan", | ||
829 | id * TXX9_DMA_MAX_NR_CHANNELS + i); | ||
830 | if (!pdev || | ||
831 | #ifdef CONFIG_MACH_TX49XX | ||
832 | platform_device_add_resources(pdev, chan_res, | ||
833 | ARRAY_SIZE(chan_res)) || | ||
834 | #endif | ||
835 | platform_device_add_data(pdev, &cpdata, sizeof(cpdata)) || | ||
836 | platform_device_add(pdev)) | ||
837 | platform_device_put(pdev); | ||
838 | } | ||
839 | #endif | ||
840 | } | ||
841 | |||
842 | void __init txx9_aclc_init(unsigned long baseaddr, int irq, | ||
843 | unsigned int dmac_id, | ||
844 | unsigned int dma_chan_out, | ||
845 | unsigned int dma_chan_in) | ||
846 | { | ||
847 | #if IS_ENABLED(CONFIG_SND_SOC_TXX9ACLC) | ||
848 | unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS; | ||
849 | struct resource res[] = { | ||
850 | { | ||
851 | .start = baseaddr, | ||
852 | .end = baseaddr + 0x100 - 1, | ||
853 | .flags = IORESOURCE_MEM, | ||
854 | }, { | ||
855 | .start = irq, | ||
856 | .flags = IORESOURCE_IRQ, | ||
857 | }, { | ||
858 | .name = "txx9dmac-chan", | ||
859 | .start = dma_base + dma_chan_out, | ||
860 | .flags = IORESOURCE_DMA, | ||
861 | }, { | ||
862 | .name = "txx9dmac-chan", | ||
863 | .start = dma_base + dma_chan_in, | ||
864 | .flags = IORESOURCE_DMA, | ||
865 | } | ||
866 | }; | ||
867 | struct platform_device *pdev = | ||
868 | platform_device_alloc("txx9aclc-ac97", -1); | ||
869 | |||
870 | if (!pdev || | ||
871 | platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) || | ||
872 | platform_device_add(pdev)) | ||
873 | platform_device_put(pdev); | ||
874 | #endif | ||
875 | } | ||
876 | |||
877 | static struct bus_type txx9_sramc_subsys = { | ||
878 | .name = "txx9_sram", | ||
879 | .dev_name = "txx9_sram", | ||
880 | }; | ||
881 | |||
882 | struct txx9_sramc_dev { | ||
883 | struct device dev; | ||
884 | struct bin_attribute bindata_attr; | ||
885 | void __iomem *base; | ||
886 | }; | ||
887 | |||
888 | static ssize_t txx9_sram_read(struct file *filp, struct kobject *kobj, | ||
889 | struct bin_attribute *bin_attr, | ||
890 | char *buf, loff_t pos, size_t size) | ||
891 | { | ||
892 | struct txx9_sramc_dev *dev = bin_attr->private; | ||
893 | size_t ramsize = bin_attr->size; | ||
894 | |||
895 | if (pos >= ramsize) | ||
896 | return 0; | ||
897 | if (pos + size > ramsize) | ||
898 | size = ramsize - pos; | ||
899 | memcpy_fromio(buf, dev->base + pos, size); | ||
900 | return size; | ||
901 | } | ||
902 | |||
903 | static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj, | ||
904 | struct bin_attribute *bin_attr, | ||
905 | char *buf, loff_t pos, size_t size) | ||
906 | { | ||
907 | struct txx9_sramc_dev *dev = bin_attr->private; | ||
908 | size_t ramsize = bin_attr->size; | ||
909 | |||
910 | if (pos >= ramsize) | ||
911 | return 0; | ||
912 | if (pos + size > ramsize) | ||
913 | size = ramsize - pos; | ||
914 | memcpy_toio(dev->base + pos, buf, size); | ||
915 | return size; | ||
916 | } | ||
917 | |||
918 | static void txx9_device_release(struct device *dev) | ||
919 | { | ||
920 | struct txx9_sramc_dev *tdev; | ||
921 | |||
922 | tdev = container_of(dev, struct txx9_sramc_dev, dev); | ||
923 | kfree(tdev); | ||
924 | } | ||
925 | |||
926 | void __init txx9_sramc_init(struct resource *r) | ||
927 | { | ||
928 | struct txx9_sramc_dev *dev; | ||
929 | size_t size; | ||
930 | int err; | ||
931 | |||
932 | err = subsys_system_register(&txx9_sramc_subsys, NULL); | ||
933 | if (err) | ||
934 | return; | ||
935 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
936 | if (!dev) | ||
937 | return; | ||
938 | size = resource_size(r); | ||
939 | dev->base = ioremap(r->start, size); | ||
940 | if (!dev->base) { | ||
941 | kfree(dev); | ||
942 | return; | ||
943 | } | ||
944 | dev->dev.release = &txx9_device_release; | ||
945 | dev->dev.bus = &txx9_sramc_subsys; | ||
946 | sysfs_bin_attr_init(&dev->bindata_attr); | ||
947 | dev->bindata_attr.attr.name = "bindata"; | ||
948 | dev->bindata_attr.attr.mode = S_IRUSR | S_IWUSR; | ||
949 | dev->bindata_attr.read = txx9_sram_read; | ||
950 | dev->bindata_attr.write = txx9_sram_write; | ||
951 | dev->bindata_attr.size = size; | ||
952 | dev->bindata_attr.private = dev; | ||
953 | err = device_register(&dev->dev); | ||
954 | if (err) | ||
955 | goto exit_put; | ||
956 | err = sysfs_create_bin_file(&dev->dev.kobj, &dev->bindata_attr); | ||
957 | if (err) { | ||
958 | iounmap(dev->base); | ||
959 | device_unregister(&dev->dev); | ||
960 | } | ||
961 | return; | ||
962 | exit_put: | ||
963 | iounmap(dev->base); | ||
964 | put_device(&dev->dev); | ||
965 | } | ||
diff --git a/arch/mips/txx9/generic/setup_tx3927.c b/arch/mips/txx9/generic/setup_tx3927.c new file mode 100644 index 000000000..33f7a7253 --- /dev/null +++ b/arch/mips/txx9/generic/setup_tx3927.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * TX3927 setup routines | ||
3 | * Based on linux/arch/mips/txx9/jmr3927/setup.c | ||
4 | * | ||
5 | * Copyright 2001 MontaVista Software Inc. | ||
6 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
7 | * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/ioport.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/param.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/mtd/physmap.h> | ||
19 | #include <asm/mipsregs.h> | ||
20 | #include <asm/txx9irq.h> | ||
21 | #include <asm/txx9tmr.h> | ||
22 | #include <asm/txx9pio.h> | ||
23 | #include <asm/txx9/generic.h> | ||
24 | #include <asm/txx9/tx3927.h> | ||
25 | |||
26 | void __init tx3927_wdt_init(void) | ||
27 | { | ||
28 | txx9_wdt_init(TX3927_TMR_REG(2)); | ||
29 | } | ||
30 | |||
31 | void __init tx3927_setup(void) | ||
32 | { | ||
33 | int i; | ||
34 | unsigned int conf; | ||
35 | |||
36 | txx9_reg_res_init(TX3927_REV_PCODE(), TX3927_REG_BASE, | ||
37 | TX3927_REG_SIZE); | ||
38 | |||
39 | /* SDRAMC,ROMC are configured by PROM */ | ||
40 | for (i = 0; i < 8; i++) { | ||
41 | if (!(tx3927_romcptr->cr[i] & 0x8)) | ||
42 | continue; /* disabled */ | ||
43 | txx9_ce_res[i].start = (unsigned long)TX3927_ROMC_BA(i); | ||
44 | txx9_ce_res[i].end = | ||
45 | txx9_ce_res[i].start + TX3927_ROMC_SIZE(i) - 1; | ||
46 | request_resource(&iomem_resource, &txx9_ce_res[i]); | ||
47 | } | ||
48 | |||
49 | /* clocks */ | ||
50 | txx9_gbus_clock = txx9_cpu_clock / 2; | ||
51 | /* change default value to udelay/mdelay take reasonable time */ | ||
52 | loops_per_jiffy = txx9_cpu_clock / HZ / 2; | ||
53 | |||
54 | /* CCFG */ | ||
55 | /* enable Timeout BusError */ | ||
56 | if (txx9_ccfg_toeon) | ||
57 | tx3927_ccfgptr->ccfg |= TX3927_CCFG_TOE; | ||
58 | |||
59 | /* clear BusErrorOnWrite flag */ | ||
60 | tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_BEOW; | ||
61 | if (read_c0_conf() & TX39_CONF_WBON) | ||
62 | /* Disable PCI snoop */ | ||
63 | tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_PSNP; | ||
64 | else | ||
65 | /* Enable PCI SNOOP - with write through only */ | ||
66 | tx3927_ccfgptr->ccfg |= TX3927_CCFG_PSNP; | ||
67 | /* do reset on watchdog */ | ||
68 | tx3927_ccfgptr->ccfg |= TX3927_CCFG_WR; | ||
69 | |||
70 | pr_info("TX3927 -- CRIR:%08lx CCFG:%08lx PCFG:%08lx\n", | ||
71 | tx3927_ccfgptr->crir, tx3927_ccfgptr->ccfg, | ||
72 | tx3927_ccfgptr->pcfg); | ||
73 | |||
74 | /* TMR */ | ||
75 | for (i = 0; i < TX3927_NR_TMR; i++) | ||
76 | txx9_tmr_init(TX3927_TMR_REG(i)); | ||
77 | |||
78 | /* DMA */ | ||
79 | tx3927_dmaptr->mcr = 0; | ||
80 | for (i = 0; i < ARRAY_SIZE(tx3927_dmaptr->ch); i++) { | ||
81 | /* reset channel */ | ||
82 | tx3927_dmaptr->ch[i].ccr = TX3927_DMA_CCR_CHRST; | ||
83 | tx3927_dmaptr->ch[i].ccr = 0; | ||
84 | } | ||
85 | /* enable DMA */ | ||
86 | #ifdef __BIG_ENDIAN | ||
87 | tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN; | ||
88 | #else | ||
89 | tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN | TX3927_DMA_MCR_LE; | ||
90 | #endif | ||
91 | |||
92 | /* PIO */ | ||
93 | __raw_writel(0, &tx3927_pioptr->maskcpu); | ||
94 | __raw_writel(0, &tx3927_pioptr->maskext); | ||
95 | |||
96 | conf = read_c0_conf(); | ||
97 | if (conf & TX39_CONF_DCE) { | ||
98 | if (!(conf & TX39_CONF_WBON)) | ||
99 | pr_info("TX3927 D-Cache WriteThrough.\n"); | ||
100 | else if (!(conf & TX39_CONF_CWFON)) | ||
101 | pr_info("TX3927 D-Cache WriteBack.\n"); | ||
102 | else | ||
103 | pr_info("TX3927 D-Cache WriteBack (CWF) .\n"); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | void __init tx3927_time_init(unsigned int evt_tmrnr, unsigned int src_tmrnr) | ||
108 | { | ||
109 | txx9_clockevent_init(TX3927_TMR_REG(evt_tmrnr), | ||
110 | TXX9_IRQ_BASE + TX3927_IR_TMR(evt_tmrnr), | ||
111 | TXX9_IMCLK); | ||
112 | txx9_clocksource_init(TX3927_TMR_REG(src_tmrnr), TXX9_IMCLK); | ||
113 | } | ||
114 | |||
115 | void __init tx3927_sio_init(unsigned int sclk, unsigned int cts_mask) | ||
116 | { | ||
117 | int i; | ||
118 | |||
119 | for (i = 0; i < 2; i++) | ||
120 | txx9_sio_init(TX3927_SIO_REG(i), | ||
121 | TXX9_IRQ_BASE + TX3927_IR_SIO(i), | ||
122 | i, sclk, (1 << i) & cts_mask); | ||
123 | } | ||
124 | |||
125 | void __init tx3927_mtd_init(int ch) | ||
126 | { | ||
127 | struct physmap_flash_data pdata = { | ||
128 | .width = TX3927_ROMC_WIDTH(ch) / 8, | ||
129 | }; | ||
130 | unsigned long start = txx9_ce_res[ch].start; | ||
131 | unsigned long size = txx9_ce_res[ch].end - start + 1; | ||
132 | |||
133 | if (!(tx3927_romcptr->cr[ch] & 0x8)) | ||
134 | return; /* disabled */ | ||
135 | txx9_physmap_flash_init(ch, start, size, &pdata); | ||
136 | } | ||
diff --git a/arch/mips/txx9/generic/setup_tx4927.c b/arch/mips/txx9/generic/setup_tx4927.c new file mode 100644 index 000000000..46e9c4101 --- /dev/null +++ b/arch/mips/txx9/generic/setup_tx4927.c | |||
@@ -0,0 +1,337 @@ | |||
1 | /* | ||
2 | * TX4927 setup routines | ||
3 | * Based on linux/arch/mips/txx9/rbtx4938/setup.c, | ||
4 | * and RBTX49xx patch from CELF patch archive. | ||
5 | * | ||
6 | * 2003-2005 (c) MontaVista Software, Inc. | ||
7 | * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/ioport.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/param.h> | ||
17 | #include <linux/ptrace.h> | ||
18 | #include <linux/mtd/physmap.h> | ||
19 | #include <asm/reboot.h> | ||
20 | #include <asm/traps.h> | ||
21 | #include <asm/txx9irq.h> | ||
22 | #include <asm/txx9tmr.h> | ||
23 | #include <asm/txx9pio.h> | ||
24 | #include <asm/txx9/generic.h> | ||
25 | #include <asm/txx9/dmac.h> | ||
26 | #include <asm/txx9/tx4927.h> | ||
27 | |||
28 | static void __init tx4927_wdr_init(void) | ||
29 | { | ||
30 | /* report watchdog reset status */ | ||
31 | if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST) | ||
32 | pr_warn("Watchdog reset detected at 0x%lx\n", | ||
33 | read_c0_errorepc()); | ||
34 | /* clear WatchDogReset (W1C) */ | ||
35 | tx4927_ccfg_set(TX4927_CCFG_WDRST); | ||
36 | /* do reset on watchdog */ | ||
37 | tx4927_ccfg_set(TX4927_CCFG_WR); | ||
38 | } | ||
39 | |||
40 | void __init tx4927_wdt_init(void) | ||
41 | { | ||
42 | txx9_wdt_init(TX4927_TMR_REG(2) & 0xfffffffffULL); | ||
43 | } | ||
44 | |||
45 | static void tx4927_machine_restart(char *command) | ||
46 | { | ||
47 | local_irq_disable(); | ||
48 | pr_emerg("Rebooting (with %s watchdog reset)...\n", | ||
49 | (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) ? | ||
50 | "external" : "internal"); | ||
51 | /* clear watchdog status */ | ||
52 | tx4927_ccfg_set(TX4927_CCFG_WDRST); /* W1C */ | ||
53 | txx9_wdt_now(TX4927_TMR_REG(2) & 0xfffffffffULL); | ||
54 | while (!(____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDRST)) | ||
55 | ; | ||
56 | mdelay(10); | ||
57 | if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_WDREXEN) { | ||
58 | pr_emerg("Rebooting (with internal watchdog reset)...\n"); | ||
59 | /* External WDRST failed. Do internal watchdog reset */ | ||
60 | tx4927_ccfg_clear(TX4927_CCFG_WDREXEN); | ||
61 | } | ||
62 | /* fallback */ | ||
63 | (*_machine_halt)(); | ||
64 | } | ||
65 | |||
66 | void show_registers(struct pt_regs *regs); | ||
67 | static int tx4927_be_handler(struct pt_regs *regs, int is_fixup) | ||
68 | { | ||
69 | int data = regs->cp0_cause & 4; | ||
70 | console_verbose(); | ||
71 | pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc); | ||
72 | pr_err("ccfg:%llx, toea:%llx\n", | ||
73 | (unsigned long long)____raw_readq(&tx4927_ccfgptr->ccfg), | ||
74 | (unsigned long long)____raw_readq(&tx4927_ccfgptr->toea)); | ||
75 | #ifdef CONFIG_PCI | ||
76 | tx4927_report_pcic_status(); | ||
77 | #endif | ||
78 | show_registers(regs); | ||
79 | panic("BusError!"); | ||
80 | } | ||
81 | static void __init tx4927_be_init(void) | ||
82 | { | ||
83 | board_be_handler = tx4927_be_handler; | ||
84 | } | ||
85 | |||
86 | static struct resource tx4927_sdram_resource[4]; | ||
87 | |||
88 | void __init tx4927_setup(void) | ||
89 | { | ||
90 | int i; | ||
91 | __u32 divmode; | ||
92 | unsigned int cpuclk = 0; | ||
93 | u64 ccfg; | ||
94 | |||
95 | txx9_reg_res_init(TX4927_REV_PCODE(), TX4927_REG_BASE, | ||
96 | TX4927_REG_SIZE); | ||
97 | set_c0_config(TX49_CONF_CWFON); | ||
98 | |||
99 | /* SDRAMC,EBUSC are configured by PROM */ | ||
100 | for (i = 0; i < 8; i++) { | ||
101 | if (!(TX4927_EBUSC_CR(i) & 0x8)) | ||
102 | continue; /* disabled */ | ||
103 | txx9_ce_res[i].start = (unsigned long)TX4927_EBUSC_BA(i); | ||
104 | txx9_ce_res[i].end = | ||
105 | txx9_ce_res[i].start + TX4927_EBUSC_SIZE(i) - 1; | ||
106 | request_resource(&iomem_resource, &txx9_ce_res[i]); | ||
107 | } | ||
108 | |||
109 | /* clocks */ | ||
110 | ccfg = ____raw_readq(&tx4927_ccfgptr->ccfg); | ||
111 | if (txx9_master_clock) { | ||
112 | /* calculate gbus_clock and cpu_clock from master_clock */ | ||
113 | divmode = (__u32)ccfg & TX4927_CCFG_DIVMODE_MASK; | ||
114 | switch (divmode) { | ||
115 | case TX4927_CCFG_DIVMODE_8: | ||
116 | case TX4927_CCFG_DIVMODE_10: | ||
117 | case TX4927_CCFG_DIVMODE_12: | ||
118 | case TX4927_CCFG_DIVMODE_16: | ||
119 | txx9_gbus_clock = txx9_master_clock * 4; break; | ||
120 | default: | ||
121 | txx9_gbus_clock = txx9_master_clock; | ||
122 | } | ||
123 | switch (divmode) { | ||
124 | case TX4927_CCFG_DIVMODE_2: | ||
125 | case TX4927_CCFG_DIVMODE_8: | ||
126 | cpuclk = txx9_gbus_clock * 2; break; | ||
127 | case TX4927_CCFG_DIVMODE_2_5: | ||
128 | case TX4927_CCFG_DIVMODE_10: | ||
129 | cpuclk = txx9_gbus_clock * 5 / 2; break; | ||
130 | case TX4927_CCFG_DIVMODE_3: | ||
131 | case TX4927_CCFG_DIVMODE_12: | ||
132 | cpuclk = txx9_gbus_clock * 3; break; | ||
133 | case TX4927_CCFG_DIVMODE_4: | ||
134 | case TX4927_CCFG_DIVMODE_16: | ||
135 | cpuclk = txx9_gbus_clock * 4; break; | ||
136 | } | ||
137 | txx9_cpu_clock = cpuclk; | ||
138 | } else { | ||
139 | if (txx9_cpu_clock == 0) | ||
140 | txx9_cpu_clock = 200000000; /* 200MHz */ | ||
141 | /* calculate gbus_clock and master_clock from cpu_clock */ | ||
142 | cpuclk = txx9_cpu_clock; | ||
143 | divmode = (__u32)ccfg & TX4927_CCFG_DIVMODE_MASK; | ||
144 | switch (divmode) { | ||
145 | case TX4927_CCFG_DIVMODE_2: | ||
146 | case TX4927_CCFG_DIVMODE_8: | ||
147 | txx9_gbus_clock = cpuclk / 2; break; | ||
148 | case TX4927_CCFG_DIVMODE_2_5: | ||
149 | case TX4927_CCFG_DIVMODE_10: | ||
150 | txx9_gbus_clock = cpuclk * 2 / 5; break; | ||
151 | case TX4927_CCFG_DIVMODE_3: | ||
152 | case TX4927_CCFG_DIVMODE_12: | ||
153 | txx9_gbus_clock = cpuclk / 3; break; | ||
154 | case TX4927_CCFG_DIVMODE_4: | ||
155 | case TX4927_CCFG_DIVMODE_16: | ||
156 | txx9_gbus_clock = cpuclk / 4; break; | ||
157 | } | ||
158 | switch (divmode) { | ||
159 | case TX4927_CCFG_DIVMODE_8: | ||
160 | case TX4927_CCFG_DIVMODE_10: | ||
161 | case TX4927_CCFG_DIVMODE_12: | ||
162 | case TX4927_CCFG_DIVMODE_16: | ||
163 | txx9_master_clock = txx9_gbus_clock / 4; break; | ||
164 | default: | ||
165 | txx9_master_clock = txx9_gbus_clock; | ||
166 | } | ||
167 | } | ||
168 | /* change default value to udelay/mdelay take reasonable time */ | ||
169 | loops_per_jiffy = txx9_cpu_clock / HZ / 2; | ||
170 | |||
171 | /* CCFG */ | ||
172 | tx4927_wdr_init(); | ||
173 | /* clear BusErrorOnWrite flag (W1C) */ | ||
174 | tx4927_ccfg_set(TX4927_CCFG_BEOW); | ||
175 | /* enable Timeout BusError */ | ||
176 | if (txx9_ccfg_toeon) | ||
177 | tx4927_ccfg_set(TX4927_CCFG_TOE); | ||
178 | |||
179 | /* DMA selection */ | ||
180 | txx9_clear64(&tx4927_ccfgptr->pcfg, TX4927_PCFG_DMASEL_ALL); | ||
181 | |||
182 | /* Use external clock for external arbiter */ | ||
183 | if (!(____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCIARB)) | ||
184 | txx9_clear64(&tx4927_ccfgptr->pcfg, TX4927_PCFG_PCICLKEN_ALL); | ||
185 | |||
186 | pr_info("%s -- %dMHz(M%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n", | ||
187 | txx9_pcode_str, (cpuclk + 500000) / 1000000, | ||
188 | (txx9_master_clock + 500000) / 1000000, | ||
189 | (__u32)____raw_readq(&tx4927_ccfgptr->crir), | ||
190 | ____raw_readq(&tx4927_ccfgptr->ccfg), | ||
191 | ____raw_readq(&tx4927_ccfgptr->pcfg)); | ||
192 | |||
193 | pr_info("%s SDRAMC --", txx9_pcode_str); | ||
194 | for (i = 0; i < 4; i++) { | ||
195 | __u64 cr = TX4927_SDRAMC_CR(i); | ||
196 | unsigned long base, size; | ||
197 | if (!((__u32)cr & 0x00000400)) | ||
198 | continue; /* disabled */ | ||
199 | base = (unsigned long)(cr >> 49) << 21; | ||
200 | size = (((unsigned long)(cr >> 33) & 0x7fff) + 1) << 21; | ||
201 | pr_cont(" CR%d:%016llx", i, cr); | ||
202 | tx4927_sdram_resource[i].name = "SDRAM"; | ||
203 | tx4927_sdram_resource[i].start = base; | ||
204 | tx4927_sdram_resource[i].end = base + size - 1; | ||
205 | tx4927_sdram_resource[i].flags = IORESOURCE_MEM; | ||
206 | request_resource(&iomem_resource, &tx4927_sdram_resource[i]); | ||
207 | } | ||
208 | pr_cont(" TR:%09llx\n", ____raw_readq(&tx4927_sdramcptr->tr)); | ||
209 | |||
210 | /* TMR */ | ||
211 | /* disable all timers */ | ||
212 | for (i = 0; i < TX4927_NR_TMR; i++) | ||
213 | txx9_tmr_init(TX4927_TMR_REG(i) & 0xfffffffffULL); | ||
214 | |||
215 | /* PIO */ | ||
216 | __raw_writel(0, &tx4927_pioptr->maskcpu); | ||
217 | __raw_writel(0, &tx4927_pioptr->maskext); | ||
218 | |||
219 | _machine_restart = tx4927_machine_restart; | ||
220 | board_be_init = tx4927_be_init; | ||
221 | } | ||
222 | |||
223 | void __init tx4927_time_init(unsigned int tmrnr) | ||
224 | { | ||
225 | if (____raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_TINTDIS) | ||
226 | txx9_clockevent_init(TX4927_TMR_REG(tmrnr) & 0xfffffffffULL, | ||
227 | TXX9_IRQ_BASE + TX4927_IR_TMR(tmrnr), | ||
228 | TXX9_IMCLK); | ||
229 | } | ||
230 | |||
231 | void __init tx4927_sio_init(unsigned int sclk, unsigned int cts_mask) | ||
232 | { | ||
233 | int i; | ||
234 | |||
235 | for (i = 0; i < 2; i++) | ||
236 | txx9_sio_init(TX4927_SIO_REG(i) & 0xfffffffffULL, | ||
237 | TXX9_IRQ_BASE + TX4927_IR_SIO(i), | ||
238 | i, sclk, (1 << i) & cts_mask); | ||
239 | } | ||
240 | |||
241 | void __init tx4927_mtd_init(int ch) | ||
242 | { | ||
243 | struct physmap_flash_data pdata = { | ||
244 | .width = TX4927_EBUSC_WIDTH(ch) / 8, | ||
245 | }; | ||
246 | unsigned long start = txx9_ce_res[ch].start; | ||
247 | unsigned long size = txx9_ce_res[ch].end - start + 1; | ||
248 | |||
249 | if (!(TX4927_EBUSC_CR(ch) & 0x8)) | ||
250 | return; /* disabled */ | ||
251 | txx9_physmap_flash_init(ch, start, size, &pdata); | ||
252 | } | ||
253 | |||
254 | void __init tx4927_dmac_init(int memcpy_chan) | ||
255 | { | ||
256 | struct txx9dmac_platform_data plat_data = { | ||
257 | .memcpy_chan = memcpy_chan, | ||
258 | .have_64bit_regs = true, | ||
259 | }; | ||
260 | |||
261 | txx9_dmac_init(0, TX4927_DMA_REG & 0xfffffffffULL, | ||
262 | TXX9_IRQ_BASE + TX4927_IR_DMA(0), &plat_data); | ||
263 | } | ||
264 | |||
265 | void __init tx4927_aclc_init(unsigned int dma_chan_out, | ||
266 | unsigned int dma_chan_in) | ||
267 | { | ||
268 | u64 pcfg = __raw_readq(&tx4927_ccfgptr->pcfg); | ||
269 | __u64 dmasel_mask = 0, dmasel = 0; | ||
270 | unsigned long flags; | ||
271 | |||
272 | if (!(pcfg & TX4927_PCFG_SEL2)) | ||
273 | return; | ||
274 | /* setup DMASEL (playback:ACLC ch0, capture:ACLC ch1) */ | ||
275 | switch (dma_chan_out) { | ||
276 | case 0: | ||
277 | dmasel_mask |= TX4927_PCFG_DMASEL0_MASK; | ||
278 | dmasel |= TX4927_PCFG_DMASEL0_ACL0; | ||
279 | break; | ||
280 | case 2: | ||
281 | dmasel_mask |= TX4927_PCFG_DMASEL2_MASK; | ||
282 | dmasel |= TX4927_PCFG_DMASEL2_ACL0; | ||
283 | break; | ||
284 | default: | ||
285 | return; | ||
286 | } | ||
287 | switch (dma_chan_in) { | ||
288 | case 1: | ||
289 | dmasel_mask |= TX4927_PCFG_DMASEL1_MASK; | ||
290 | dmasel |= TX4927_PCFG_DMASEL1_ACL1; | ||
291 | break; | ||
292 | case 3: | ||
293 | dmasel_mask |= TX4927_PCFG_DMASEL3_MASK; | ||
294 | dmasel |= TX4927_PCFG_DMASEL3_ACL1; | ||
295 | break; | ||
296 | default: | ||
297 | return; | ||
298 | } | ||
299 | local_irq_save(flags); | ||
300 | txx9_clear64(&tx4927_ccfgptr->pcfg, dmasel_mask); | ||
301 | txx9_set64(&tx4927_ccfgptr->pcfg, dmasel); | ||
302 | local_irq_restore(flags); | ||
303 | txx9_aclc_init(TX4927_ACLC_REG & 0xfffffffffULL, | ||
304 | TXX9_IRQ_BASE + TX4927_IR_ACLC, | ||
305 | 0, dma_chan_out, dma_chan_in); | ||
306 | } | ||
307 | |||
308 | static void __init tx4927_stop_unused_modules(void) | ||
309 | { | ||
310 | __u64 pcfg, rst = 0, ckd = 0; | ||
311 | char buf[128]; | ||
312 | |||
313 | buf[0] = '\0'; | ||
314 | local_irq_disable(); | ||
315 | pcfg = ____raw_readq(&tx4927_ccfgptr->pcfg); | ||
316 | if (!(pcfg & TX4927_PCFG_SEL2)) { | ||
317 | rst |= TX4927_CLKCTR_ACLRST; | ||
318 | ckd |= TX4927_CLKCTR_ACLCKD; | ||
319 | strcat(buf, " ACLC"); | ||
320 | } | ||
321 | if (rst | ckd) { | ||
322 | txx9_set64(&tx4927_ccfgptr->clkctr, rst); | ||
323 | txx9_set64(&tx4927_ccfgptr->clkctr, ckd); | ||
324 | } | ||
325 | local_irq_enable(); | ||
326 | if (buf[0]) | ||
327 | pr_info("%s: stop%s\n", txx9_pcode_str, buf); | ||
328 | } | ||
329 | |||
330 | static int __init tx4927_late_init(void) | ||
331 | { | ||
332 | if (txx9_pcode != 0x4927) | ||
333 | return -ENODEV; | ||
334 | tx4927_stop_unused_modules(); | ||
335 | return 0; | ||
336 | } | ||
337 | late_initcall(tx4927_late_init); | ||
diff --git a/arch/mips/txx9/generic/setup_tx4938.c b/arch/mips/txx9/generic/setup_tx4938.c new file mode 100644 index 000000000..17395d5d1 --- /dev/null +++ b/arch/mips/txx9/generic/setup_tx4938.c | |||
@@ -0,0 +1,485 @@ | |||
1 | /* | ||
2 | * TX4938/4937 setup routines | ||
3 | * Based on linux/arch/mips/txx9/rbtx4938/setup.c, | ||
4 | * and RBTX49xx patch from CELF patch archive. | ||
5 | * | ||
6 | * 2003-2005 (c) MontaVista Software, Inc. | ||
7 | * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/ioport.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/param.h> | ||
17 | #include <linux/ptrace.h> | ||
18 | #include <linux/mtd/physmap.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/platform_data/txx9/ndfmc.h> | ||
21 | #include <asm/reboot.h> | ||
22 | #include <asm/traps.h> | ||
23 | #include <asm/txx9irq.h> | ||
24 | #include <asm/txx9tmr.h> | ||
25 | #include <asm/txx9pio.h> | ||
26 | #include <asm/txx9/generic.h> | ||
27 | #include <asm/txx9/dmac.h> | ||
28 | #include <asm/txx9/tx4938.h> | ||
29 | |||
30 | static void __init tx4938_wdr_init(void) | ||
31 | { | ||
32 | /* report watchdog reset status */ | ||
33 | if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST) | ||
34 | pr_warn("Watchdog reset detected at 0x%lx\n", | ||
35 | read_c0_errorepc()); | ||
36 | /* clear WatchDogReset (W1C) */ | ||
37 | tx4938_ccfg_set(TX4938_CCFG_WDRST); | ||
38 | /* do reset on watchdog */ | ||
39 | tx4938_ccfg_set(TX4938_CCFG_WR); | ||
40 | } | ||
41 | |||
42 | void __init tx4938_wdt_init(void) | ||
43 | { | ||
44 | txx9_wdt_init(TX4938_TMR_REG(2) & 0xfffffffffULL); | ||
45 | } | ||
46 | |||
47 | static void tx4938_machine_restart(char *command) | ||
48 | { | ||
49 | local_irq_disable(); | ||
50 | pr_emerg("Rebooting (with %s watchdog reset)...\n", | ||
51 | (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) ? | ||
52 | "external" : "internal"); | ||
53 | /* clear watchdog status */ | ||
54 | tx4938_ccfg_set(TX4938_CCFG_WDRST); /* W1C */ | ||
55 | txx9_wdt_now(TX4938_TMR_REG(2) & 0xfffffffffULL); | ||
56 | while (!(____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDRST)) | ||
57 | ; | ||
58 | mdelay(10); | ||
59 | if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_WDREXEN) { | ||
60 | pr_emerg("Rebooting (with internal watchdog reset)...\n"); | ||
61 | /* External WDRST failed. Do internal watchdog reset */ | ||
62 | tx4938_ccfg_clear(TX4938_CCFG_WDREXEN); | ||
63 | } | ||
64 | /* fallback */ | ||
65 | (*_machine_halt)(); | ||
66 | } | ||
67 | |||
68 | void show_registers(struct pt_regs *regs); | ||
69 | static int tx4938_be_handler(struct pt_regs *regs, int is_fixup) | ||
70 | { | ||
71 | int data = regs->cp0_cause & 4; | ||
72 | console_verbose(); | ||
73 | pr_err("%cBE exception at %#lx\n", data ? 'D' : 'I', regs->cp0_epc); | ||
74 | pr_err("ccfg:%llx, toea:%llx\n", | ||
75 | (unsigned long long)____raw_readq(&tx4938_ccfgptr->ccfg), | ||
76 | (unsigned long long)____raw_readq(&tx4938_ccfgptr->toea)); | ||
77 | #ifdef CONFIG_PCI | ||
78 | tx4927_report_pcic_status(); | ||
79 | #endif | ||
80 | show_registers(regs); | ||
81 | panic("BusError!"); | ||
82 | } | ||
83 | static void __init tx4938_be_init(void) | ||
84 | { | ||
85 | board_be_handler = tx4938_be_handler; | ||
86 | } | ||
87 | |||
88 | static struct resource tx4938_sdram_resource[4]; | ||
89 | static struct resource tx4938_sram_resource; | ||
90 | |||
91 | #define TX4938_SRAM_SIZE 0x800 | ||
92 | |||
93 | void __init tx4938_setup(void) | ||
94 | { | ||
95 | int i; | ||
96 | __u32 divmode; | ||
97 | unsigned int cpuclk = 0; | ||
98 | u64 ccfg; | ||
99 | |||
100 | txx9_reg_res_init(TX4938_REV_PCODE(), TX4938_REG_BASE, | ||
101 | TX4938_REG_SIZE); | ||
102 | set_c0_config(TX49_CONF_CWFON); | ||
103 | |||
104 | /* SDRAMC,EBUSC are configured by PROM */ | ||
105 | for (i = 0; i < 8; i++) { | ||
106 | if (!(TX4938_EBUSC_CR(i) & 0x8)) | ||
107 | continue; /* disabled */ | ||
108 | txx9_ce_res[i].start = (unsigned long)TX4938_EBUSC_BA(i); | ||
109 | txx9_ce_res[i].end = | ||
110 | txx9_ce_res[i].start + TX4938_EBUSC_SIZE(i) - 1; | ||
111 | request_resource(&iomem_resource, &txx9_ce_res[i]); | ||
112 | } | ||
113 | |||
114 | /* clocks */ | ||
115 | ccfg = ____raw_readq(&tx4938_ccfgptr->ccfg); | ||
116 | if (txx9_master_clock) { | ||
117 | /* calculate gbus_clock and cpu_clock from master_clock */ | ||
118 | divmode = (__u32)ccfg & TX4938_CCFG_DIVMODE_MASK; | ||
119 | switch (divmode) { | ||
120 | case TX4938_CCFG_DIVMODE_8: | ||
121 | case TX4938_CCFG_DIVMODE_10: | ||
122 | case TX4938_CCFG_DIVMODE_12: | ||
123 | case TX4938_CCFG_DIVMODE_16: | ||
124 | case TX4938_CCFG_DIVMODE_18: | ||
125 | txx9_gbus_clock = txx9_master_clock * 4; break; | ||
126 | default: | ||
127 | txx9_gbus_clock = txx9_master_clock; | ||
128 | } | ||
129 | switch (divmode) { | ||
130 | case TX4938_CCFG_DIVMODE_2: | ||
131 | case TX4938_CCFG_DIVMODE_8: | ||
132 | cpuclk = txx9_gbus_clock * 2; break; | ||
133 | case TX4938_CCFG_DIVMODE_2_5: | ||
134 | case TX4938_CCFG_DIVMODE_10: | ||
135 | cpuclk = txx9_gbus_clock * 5 / 2; break; | ||
136 | case TX4938_CCFG_DIVMODE_3: | ||
137 | case TX4938_CCFG_DIVMODE_12: | ||
138 | cpuclk = txx9_gbus_clock * 3; break; | ||
139 | case TX4938_CCFG_DIVMODE_4: | ||
140 | case TX4938_CCFG_DIVMODE_16: | ||
141 | cpuclk = txx9_gbus_clock * 4; break; | ||
142 | case TX4938_CCFG_DIVMODE_4_5: | ||
143 | case TX4938_CCFG_DIVMODE_18: | ||
144 | cpuclk = txx9_gbus_clock * 9 / 2; break; | ||
145 | } | ||
146 | txx9_cpu_clock = cpuclk; | ||
147 | } else { | ||
148 | if (txx9_cpu_clock == 0) | ||
149 | txx9_cpu_clock = 300000000; /* 300MHz */ | ||
150 | /* calculate gbus_clock and master_clock from cpu_clock */ | ||
151 | cpuclk = txx9_cpu_clock; | ||
152 | divmode = (__u32)ccfg & TX4938_CCFG_DIVMODE_MASK; | ||
153 | switch (divmode) { | ||
154 | case TX4938_CCFG_DIVMODE_2: | ||
155 | case TX4938_CCFG_DIVMODE_8: | ||
156 | txx9_gbus_clock = cpuclk / 2; break; | ||
157 | case TX4938_CCFG_DIVMODE_2_5: | ||
158 | case TX4938_CCFG_DIVMODE_10: | ||
159 | txx9_gbus_clock = cpuclk * 2 / 5; break; | ||
160 | case TX4938_CCFG_DIVMODE_3: | ||
161 | case TX4938_CCFG_DIVMODE_12: | ||
162 | txx9_gbus_clock = cpuclk / 3; break; | ||
163 | case TX4938_CCFG_DIVMODE_4: | ||
164 | case TX4938_CCFG_DIVMODE_16: | ||
165 | txx9_gbus_clock = cpuclk / 4; break; | ||
166 | case TX4938_CCFG_DIVMODE_4_5: | ||
167 | case TX4938_CCFG_DIVMODE_18: | ||
168 | txx9_gbus_clock = cpuclk * 2 / 9; break; | ||
169 | } | ||
170 | switch (divmode) { | ||
171 | case TX4938_CCFG_DIVMODE_8: | ||
172 | case TX4938_CCFG_DIVMODE_10: | ||
173 | case TX4938_CCFG_DIVMODE_12: | ||
174 | case TX4938_CCFG_DIVMODE_16: | ||
175 | case TX4938_CCFG_DIVMODE_18: | ||
176 | txx9_master_clock = txx9_gbus_clock / 4; break; | ||
177 | default: | ||
178 | txx9_master_clock = txx9_gbus_clock; | ||
179 | } | ||
180 | } | ||
181 | /* change default value to udelay/mdelay take reasonable time */ | ||
182 | loops_per_jiffy = txx9_cpu_clock / HZ / 2; | ||
183 | |||
184 | /* CCFG */ | ||
185 | tx4938_wdr_init(); | ||
186 | /* clear BusErrorOnWrite flag (W1C) */ | ||
187 | tx4938_ccfg_set(TX4938_CCFG_BEOW); | ||
188 | /* enable Timeout BusError */ | ||
189 | if (txx9_ccfg_toeon) | ||
190 | tx4938_ccfg_set(TX4938_CCFG_TOE); | ||
191 | |||
192 | /* DMA selection */ | ||
193 | txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_DMASEL_ALL); | ||
194 | |||
195 | /* Use external clock for external arbiter */ | ||
196 | if (!(____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCIARB)) | ||
197 | txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_PCICLKEN_ALL); | ||
198 | |||
199 | pr_info("%s -- %dMHz(M%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n", | ||
200 | txx9_pcode_str, (cpuclk + 500000) / 1000000, | ||
201 | (txx9_master_clock + 500000) / 1000000, | ||
202 | (__u32)____raw_readq(&tx4938_ccfgptr->crir), | ||
203 | ____raw_readq(&tx4938_ccfgptr->ccfg), | ||
204 | ____raw_readq(&tx4938_ccfgptr->pcfg)); | ||
205 | |||
206 | pr_info("%s SDRAMC --", txx9_pcode_str); | ||
207 | for (i = 0; i < 4; i++) { | ||
208 | __u64 cr = TX4938_SDRAMC_CR(i); | ||
209 | unsigned long base, size; | ||
210 | if (!((__u32)cr & 0x00000400)) | ||
211 | continue; /* disabled */ | ||
212 | base = (unsigned long)(cr >> 49) << 21; | ||
213 | size = (((unsigned long)(cr >> 33) & 0x7fff) + 1) << 21; | ||
214 | pr_cont(" CR%d:%016llx", i, cr); | ||
215 | tx4938_sdram_resource[i].name = "SDRAM"; | ||
216 | tx4938_sdram_resource[i].start = base; | ||
217 | tx4938_sdram_resource[i].end = base + size - 1; | ||
218 | tx4938_sdram_resource[i].flags = IORESOURCE_MEM; | ||
219 | request_resource(&iomem_resource, &tx4938_sdram_resource[i]); | ||
220 | } | ||
221 | pr_cont(" TR:%09llx\n", ____raw_readq(&tx4938_sdramcptr->tr)); | ||
222 | |||
223 | /* SRAM */ | ||
224 | if (txx9_pcode == 0x4938 && ____raw_readq(&tx4938_sramcptr->cr) & 1) { | ||
225 | unsigned int size = TX4938_SRAM_SIZE; | ||
226 | tx4938_sram_resource.name = "SRAM"; | ||
227 | tx4938_sram_resource.start = | ||
228 | (____raw_readq(&tx4938_sramcptr->cr) >> (39-11)) | ||
229 | & ~(size - 1); | ||
230 | tx4938_sram_resource.end = | ||
231 | tx4938_sram_resource.start + TX4938_SRAM_SIZE - 1; | ||
232 | tx4938_sram_resource.flags = IORESOURCE_MEM; | ||
233 | request_resource(&iomem_resource, &tx4938_sram_resource); | ||
234 | } | ||
235 | |||
236 | /* TMR */ | ||
237 | /* disable all timers */ | ||
238 | for (i = 0; i < TX4938_NR_TMR; i++) | ||
239 | txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL); | ||
240 | |||
241 | /* PIO */ | ||
242 | __raw_writel(0, &tx4938_pioptr->maskcpu); | ||
243 | __raw_writel(0, &tx4938_pioptr->maskext); | ||
244 | |||
245 | if (txx9_pcode == 0x4938) { | ||
246 | __u64 pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); | ||
247 | /* set PCIC1 reset */ | ||
248 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST); | ||
249 | if (pcfg & (TX4938_PCFG_ETH0_SEL | TX4938_PCFG_ETH1_SEL)) { | ||
250 | mdelay(1); /* at least 128 cpu clock */ | ||
251 | /* clear PCIC1 reset */ | ||
252 | txx9_clear64(&tx4938_ccfgptr->clkctr, | ||
253 | TX4938_CLKCTR_PCIC1RST); | ||
254 | } else { | ||
255 | pr_info("%s: stop PCIC1\n", txx9_pcode_str); | ||
256 | /* stop PCIC1 */ | ||
257 | txx9_set64(&tx4938_ccfgptr->clkctr, | ||
258 | TX4938_CLKCTR_PCIC1CKD); | ||
259 | } | ||
260 | if (!(pcfg & TX4938_PCFG_ETH0_SEL)) { | ||
261 | pr_info("%s: stop ETH0\n", txx9_pcode_str); | ||
262 | txx9_set64(&tx4938_ccfgptr->clkctr, | ||
263 | TX4938_CLKCTR_ETH0RST); | ||
264 | txx9_set64(&tx4938_ccfgptr->clkctr, | ||
265 | TX4938_CLKCTR_ETH0CKD); | ||
266 | } | ||
267 | if (!(pcfg & TX4938_PCFG_ETH1_SEL)) { | ||
268 | pr_info("%s: stop ETH1\n", txx9_pcode_str); | ||
269 | txx9_set64(&tx4938_ccfgptr->clkctr, | ||
270 | TX4938_CLKCTR_ETH1RST); | ||
271 | txx9_set64(&tx4938_ccfgptr->clkctr, | ||
272 | TX4938_CLKCTR_ETH1CKD); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | _machine_restart = tx4938_machine_restart; | ||
277 | board_be_init = tx4938_be_init; | ||
278 | } | ||
279 | |||
280 | void __init tx4938_time_init(unsigned int tmrnr) | ||
281 | { | ||
282 | if (____raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_TINTDIS) | ||
283 | txx9_clockevent_init(TX4938_TMR_REG(tmrnr) & 0xfffffffffULL, | ||
284 | TXX9_IRQ_BASE + TX4938_IR_TMR(tmrnr), | ||
285 | TXX9_IMCLK); | ||
286 | } | ||
287 | |||
288 | void __init tx4938_sio_init(unsigned int sclk, unsigned int cts_mask) | ||
289 | { | ||
290 | int i; | ||
291 | unsigned int ch_mask = 0; | ||
292 | |||
293 | if (__raw_readq(&tx4938_ccfgptr->pcfg) & TX4938_PCFG_ETH0_SEL) | ||
294 | ch_mask |= 1 << 1; /* disable SIO1 by PCFG setting */ | ||
295 | for (i = 0; i < 2; i++) { | ||
296 | if ((1 << i) & ch_mask) | ||
297 | continue; | ||
298 | txx9_sio_init(TX4938_SIO_REG(i) & 0xfffffffffULL, | ||
299 | TXX9_IRQ_BASE + TX4938_IR_SIO(i), | ||
300 | i, sclk, (1 << i) & cts_mask); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | void __init tx4938_spi_init(int busid) | ||
305 | { | ||
306 | txx9_spi_init(busid, TX4938_SPI_REG & 0xfffffffffULL, | ||
307 | TXX9_IRQ_BASE + TX4938_IR_SPI); | ||
308 | } | ||
309 | |||
310 | void __init tx4938_ethaddr_init(unsigned char *addr0, unsigned char *addr1) | ||
311 | { | ||
312 | u64 pcfg = __raw_readq(&tx4938_ccfgptr->pcfg); | ||
313 | |||
314 | if (addr0 && (pcfg & TX4938_PCFG_ETH0_SEL)) | ||
315 | txx9_ethaddr_init(TXX9_IRQ_BASE + TX4938_IR_ETH0, addr0); | ||
316 | if (addr1 && (pcfg & TX4938_PCFG_ETH1_SEL)) | ||
317 | txx9_ethaddr_init(TXX9_IRQ_BASE + TX4938_IR_ETH1, addr1); | ||
318 | } | ||
319 | |||
320 | void __init tx4938_mtd_init(int ch) | ||
321 | { | ||
322 | struct physmap_flash_data pdata = { | ||
323 | .width = TX4938_EBUSC_WIDTH(ch) / 8, | ||
324 | }; | ||
325 | unsigned long start = txx9_ce_res[ch].start; | ||
326 | unsigned long size = txx9_ce_res[ch].end - start + 1; | ||
327 | |||
328 | if (!(TX4938_EBUSC_CR(ch) & 0x8)) | ||
329 | return; /* disabled */ | ||
330 | txx9_physmap_flash_init(ch, start, size, &pdata); | ||
331 | } | ||
332 | |||
333 | void __init tx4938_ata_init(unsigned int irq, unsigned int shift, int tune) | ||
334 | { | ||
335 | struct platform_device *pdev; | ||
336 | struct resource res[] = { | ||
337 | { | ||
338 | /* .start and .end are filled in later */ | ||
339 | .flags = IORESOURCE_MEM, | ||
340 | }, { | ||
341 | .start = irq, | ||
342 | .flags = IORESOURCE_IRQ, | ||
343 | }, | ||
344 | }; | ||
345 | struct tx4938ide_platform_info pdata = { | ||
346 | .ioport_shift = shift, | ||
347 | /* | ||
348 | * The IDE driver should not change bus timings if other ISA | ||
349 | * devices existed. | ||
350 | */ | ||
351 | .gbus_clock = tune ? txx9_gbus_clock : 0, | ||
352 | }; | ||
353 | u64 ebccr; | ||
354 | int i; | ||
355 | |||
356 | if ((__raw_readq(&tx4938_ccfgptr->pcfg) & | ||
357 | (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) | ||
358 | != TX4938_PCFG_ATA_SEL) | ||
359 | return; | ||
360 | for (i = 0; i < 8; i++) { | ||
361 | /* check EBCCRn.ISA, EBCCRn.BSZ, EBCCRn.ME */ | ||
362 | ebccr = __raw_readq(&tx4938_ebuscptr->cr[i]); | ||
363 | if ((ebccr & 0x00f00008) == 0x00e00008) | ||
364 | break; | ||
365 | } | ||
366 | if (i == 8) | ||
367 | return; | ||
368 | pdata.ebus_ch = i; | ||
369 | res[0].start = ((ebccr >> 48) << 20) + 0x10000; | ||
370 | res[0].end = res[0].start + 0x20000 - 1; | ||
371 | pdev = platform_device_alloc("tx4938ide", -1); | ||
372 | if (!pdev || | ||
373 | platform_device_add_resources(pdev, res, ARRAY_SIZE(res)) || | ||
374 | platform_device_add_data(pdev, &pdata, sizeof(pdata)) || | ||
375 | platform_device_add(pdev)) | ||
376 | platform_device_put(pdev); | ||
377 | } | ||
378 | |||
379 | void __init tx4938_ndfmc_init(unsigned int hold, unsigned int spw) | ||
380 | { | ||
381 | struct txx9ndfmc_platform_data plat_data = { | ||
382 | .shift = 1, | ||
383 | .gbus_clock = txx9_gbus_clock, | ||
384 | .hold = hold, | ||
385 | .spw = spw, | ||
386 | .ch_mask = 1, | ||
387 | }; | ||
388 | unsigned long baseaddr = TX4938_NDFMC_REG & 0xfffffffffULL; | ||
389 | |||
390 | #ifdef __BIG_ENDIAN | ||
391 | baseaddr += 4; | ||
392 | #endif | ||
393 | if ((__raw_readq(&tx4938_ccfgptr->pcfg) & | ||
394 | (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL)) == | ||
395 | TX4938_PCFG_NDF_SEL) | ||
396 | txx9_ndfmc_init(baseaddr, &plat_data); | ||
397 | } | ||
398 | |||
399 | void __init tx4938_dmac_init(int memcpy_chan0, int memcpy_chan1) | ||
400 | { | ||
401 | struct txx9dmac_platform_data plat_data = { | ||
402 | .have_64bit_regs = true, | ||
403 | }; | ||
404 | int i; | ||
405 | |||
406 | for (i = 0; i < 2; i++) { | ||
407 | plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0; | ||
408 | txx9_dmac_init(i, TX4938_DMA_REG(i) & 0xfffffffffULL, | ||
409 | TXX9_IRQ_BASE + TX4938_IR_DMA(i, 0), | ||
410 | &plat_data); | ||
411 | } | ||
412 | } | ||
413 | |||
414 | void __init tx4938_aclc_init(void) | ||
415 | { | ||
416 | u64 pcfg = __raw_readq(&tx4938_ccfgptr->pcfg); | ||
417 | |||
418 | if ((pcfg & TX4938_PCFG_SEL2) && | ||
419 | !(pcfg & TX4938_PCFG_ETH0_SEL)) | ||
420 | txx9_aclc_init(TX4938_ACLC_REG & 0xfffffffffULL, | ||
421 | TXX9_IRQ_BASE + TX4938_IR_ACLC, | ||
422 | 1, 0, 1); | ||
423 | } | ||
424 | |||
425 | void __init tx4938_sramc_init(void) | ||
426 | { | ||
427 | if (tx4938_sram_resource.start) | ||
428 | txx9_sramc_init(&tx4938_sram_resource); | ||
429 | } | ||
430 | |||
431 | static void __init tx4938_stop_unused_modules(void) | ||
432 | { | ||
433 | __u64 pcfg, rst = 0, ckd = 0; | ||
434 | char buf[128]; | ||
435 | |||
436 | buf[0] = '\0'; | ||
437 | local_irq_disable(); | ||
438 | pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); | ||
439 | switch (txx9_pcode) { | ||
440 | case 0x4937: | ||
441 | if (!(pcfg & TX4938_PCFG_SEL2)) { | ||
442 | rst |= TX4938_CLKCTR_ACLRST; | ||
443 | ckd |= TX4938_CLKCTR_ACLCKD; | ||
444 | strcat(buf, " ACLC"); | ||
445 | } | ||
446 | break; | ||
447 | case 0x4938: | ||
448 | if (!(pcfg & TX4938_PCFG_SEL2) || | ||
449 | (pcfg & TX4938_PCFG_ETH0_SEL)) { | ||
450 | rst |= TX4938_CLKCTR_ACLRST; | ||
451 | ckd |= TX4938_CLKCTR_ACLCKD; | ||
452 | strcat(buf, " ACLC"); | ||
453 | } | ||
454 | if ((pcfg & | ||
455 | (TX4938_PCFG_ATA_SEL | TX4938_PCFG_ISA_SEL | | ||
456 | TX4938_PCFG_NDF_SEL)) | ||
457 | != TX4938_PCFG_NDF_SEL) { | ||
458 | rst |= TX4938_CLKCTR_NDFRST; | ||
459 | ckd |= TX4938_CLKCTR_NDFCKD; | ||
460 | strcat(buf, " NDFMC"); | ||
461 | } | ||
462 | if (!(pcfg & TX4938_PCFG_SPI_SEL)) { | ||
463 | rst |= TX4938_CLKCTR_SPIRST; | ||
464 | ckd |= TX4938_CLKCTR_SPICKD; | ||
465 | strcat(buf, " SPI"); | ||
466 | } | ||
467 | break; | ||
468 | } | ||
469 | if (rst | ckd) { | ||
470 | txx9_set64(&tx4938_ccfgptr->clkctr, rst); | ||
471 | txx9_set64(&tx4938_ccfgptr->clkctr, ckd); | ||
472 | } | ||
473 | local_irq_enable(); | ||
474 | if (buf[0]) | ||
475 | pr_info("%s: stop%s\n", txx9_pcode_str, buf); | ||
476 | } | ||
477 | |||
478 | static int __init tx4938_late_init(void) | ||
479 | { | ||
480 | if (txx9_pcode != 0x4937 && txx9_pcode != 0x4938) | ||
481 | return -ENODEV; | ||
482 | tx4938_stop_unused_modules(); | ||
483 | return 0; | ||
484 | } | ||
485 | late_initcall(tx4938_late_init); | ||
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c new file mode 100644 index 000000000..bf8a3cdab --- /dev/null +++ b/arch/mips/txx9/generic/setup_tx4939.c | |||
@@ -0,0 +1,568 @@ | |||
1 | /* | ||
2 | * TX4939 setup routines | ||
3 | * Based on linux/arch/mips/txx9/generic/setup_tx4938.c, | ||
4 | * and RBTX49xx patch from CELF patch archive. | ||
5 | * | ||
6 | * 2003-2005 (c) MontaVista Software, Inc. | ||
7 | * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 | ||
8 | * | ||
9 | * This file is subject to the terms and conditions of the GNU General Public | ||
10 | * License. See the file "COPYING" in the main directory of this archive | ||
11 | * for more details. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/ioport.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/netdevice.h> | ||
17 | #include <linux/notifier.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/ethtool.h> | ||
20 | #include <linux/param.h> | ||
21 | #include <linux/ptrace.h> | ||
22 | #include <linux/mtd/physmap.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/platform_data/txx9/ndfmc.h> | ||
25 | #include <asm/reboot.h> | ||
26 | #include <asm/traps.h> | ||
27 | #include <asm/txx9irq.h> | ||
28 | #include <asm/txx9tmr.h> | ||
29 | #include <asm/txx9/generic.h> | ||
30 | #include <asm/txx9/dmac.h> | ||
31 | #include <asm/txx9/tx4939.h> | ||
32 | |||
33 | static void __init tx4939_wdr_init(void) | ||
34 | { | ||
35 | /* report watchdog reset status */ | ||
36 | if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST) | ||
37 | pr_warn("Watchdog reset detected at 0x%lx\n", | ||
38 | read_c0_errorepc()); | ||
39 | /* clear WatchDogReset (W1C) */ | ||
40 | tx4939_ccfg_set(TX4939_CCFG_WDRST); | ||
41 | /* do reset on watchdog */ | ||
42 | tx4939_ccfg_set(TX4939_CCFG_WR); | ||
43 | } | ||
44 | |||
45 | void __init tx4939_wdt_init(void) | ||
46 | { | ||
47 | txx9_wdt_init(TX4939_TMR_REG(2) & 0xfffffffffULL); | ||
48 | } | ||
49 | |||
50 | static void tx4939_machine_restart(char *command) | ||
51 | { | ||
52 | local_irq_disable(); | ||
53 | pr_emerg("Rebooting (with %s watchdog reset)...\n", | ||
54 | (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) ? | ||
55 | "external" : "internal"); | ||
56 | /* clear watchdog status */ | ||
57 | tx4939_ccfg_set(TX4939_CCFG_WDRST); /* W1C */ | ||
58 | txx9_wdt_now(TX4939_TMR_REG(2) & 0xfffffffffULL); | ||
59 | while (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDRST)) | ||
60 | ; | ||
61 | mdelay(10); | ||
62 | if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_WDREXEN) { | ||
63 | pr_emerg("Rebooting (with internal watchdog reset)...\n"); | ||
64 | /* External WDRST failed. Do internal watchdog reset */ | ||
65 | tx4939_ccfg_clear(TX4939_CCFG_WDREXEN); | ||
66 | } | ||
67 | /* fallback */ | ||
68 | (*_machine_halt)(); | ||
69 | } | ||
70 | |||
71 | void show_registers(struct pt_regs *regs); | ||
72 | static int tx4939_be_handler(struct pt_regs *regs, int is_fixup) | ||
73 | { | ||
74 | int data = regs->cp0_cause & 4; | ||
75 | console_verbose(); | ||
76 | pr_err("%cBE exception at %#lx\n", | ||
77 | data ? 'D' : 'I', regs->cp0_epc); | ||
78 | pr_err("ccfg:%llx, toea:%llx\n", | ||
79 | (unsigned long long)____raw_readq(&tx4939_ccfgptr->ccfg), | ||
80 | (unsigned long long)____raw_readq(&tx4939_ccfgptr->toea)); | ||
81 | #ifdef CONFIG_PCI | ||
82 | tx4927_report_pcic_status(); | ||
83 | #endif | ||
84 | show_registers(regs); | ||
85 | panic("BusError!"); | ||
86 | } | ||
87 | static void __init tx4939_be_init(void) | ||
88 | { | ||
89 | board_be_handler = tx4939_be_handler; | ||
90 | } | ||
91 | |||
92 | static struct resource tx4939_sdram_resource[4]; | ||
93 | static struct resource tx4939_sram_resource; | ||
94 | #define TX4939_SRAM_SIZE 0x800 | ||
95 | |||
96 | void __init tx4939_setup(void) | ||
97 | { | ||
98 | int i; | ||
99 | __u32 divmode; | ||
100 | __u64 pcfg; | ||
101 | unsigned int cpuclk = 0; | ||
102 | |||
103 | txx9_reg_res_init(TX4939_REV_PCODE(), TX4939_REG_BASE, | ||
104 | TX4939_REG_SIZE); | ||
105 | set_c0_config(TX49_CONF_CWFON); | ||
106 | |||
107 | /* SDRAMC,EBUSC are configured by PROM */ | ||
108 | for (i = 0; i < 4; i++) { | ||
109 | if (!(TX4939_EBUSC_CR(i) & 0x8)) | ||
110 | continue; /* disabled */ | ||
111 | txx9_ce_res[i].start = (unsigned long)TX4939_EBUSC_BA(i); | ||
112 | txx9_ce_res[i].end = | ||
113 | txx9_ce_res[i].start + TX4939_EBUSC_SIZE(i) - 1; | ||
114 | request_resource(&iomem_resource, &txx9_ce_res[i]); | ||
115 | } | ||
116 | |||
117 | /* clocks */ | ||
118 | if (txx9_master_clock) { | ||
119 | /* calculate cpu_clock from master_clock */ | ||
120 | divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & | ||
121 | TX4939_CCFG_MULCLK_MASK; | ||
122 | cpuclk = txx9_master_clock * 20 / 2; | ||
123 | switch (divmode) { | ||
124 | case TX4939_CCFG_MULCLK_8: | ||
125 | cpuclk = cpuclk / 3 * 4 /* / 6 * 8 */; break; | ||
126 | case TX4939_CCFG_MULCLK_9: | ||
127 | cpuclk = cpuclk / 2 * 3 /* / 6 * 9 */; break; | ||
128 | case TX4939_CCFG_MULCLK_10: | ||
129 | cpuclk = cpuclk / 3 * 5 /* / 6 * 10 */; break; | ||
130 | case TX4939_CCFG_MULCLK_11: | ||
131 | cpuclk = cpuclk / 6 * 11; break; | ||
132 | case TX4939_CCFG_MULCLK_12: | ||
133 | cpuclk = cpuclk * 2 /* / 6 * 12 */; break; | ||
134 | case TX4939_CCFG_MULCLK_13: | ||
135 | cpuclk = cpuclk / 6 * 13; break; | ||
136 | case TX4939_CCFG_MULCLK_14: | ||
137 | cpuclk = cpuclk / 3 * 7 /* / 6 * 14 */; break; | ||
138 | case TX4939_CCFG_MULCLK_15: | ||
139 | cpuclk = cpuclk / 2 * 5 /* / 6 * 15 */; break; | ||
140 | } | ||
141 | txx9_cpu_clock = cpuclk; | ||
142 | } else { | ||
143 | if (txx9_cpu_clock == 0) | ||
144 | txx9_cpu_clock = 400000000; /* 400MHz */ | ||
145 | /* calculate master_clock from cpu_clock */ | ||
146 | cpuclk = txx9_cpu_clock; | ||
147 | divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & | ||
148 | TX4939_CCFG_MULCLK_MASK; | ||
149 | switch (divmode) { | ||
150 | case TX4939_CCFG_MULCLK_8: | ||
151 | txx9_master_clock = cpuclk * 6 / 8; break; | ||
152 | case TX4939_CCFG_MULCLK_9: | ||
153 | txx9_master_clock = cpuclk * 6 / 9; break; | ||
154 | case TX4939_CCFG_MULCLK_10: | ||
155 | txx9_master_clock = cpuclk * 6 / 10; break; | ||
156 | case TX4939_CCFG_MULCLK_11: | ||
157 | txx9_master_clock = cpuclk * 6 / 11; break; | ||
158 | case TX4939_CCFG_MULCLK_12: | ||
159 | txx9_master_clock = cpuclk * 6 / 12; break; | ||
160 | case TX4939_CCFG_MULCLK_13: | ||
161 | txx9_master_clock = cpuclk * 6 / 13; break; | ||
162 | case TX4939_CCFG_MULCLK_14: | ||
163 | txx9_master_clock = cpuclk * 6 / 14; break; | ||
164 | case TX4939_CCFG_MULCLK_15: | ||
165 | txx9_master_clock = cpuclk * 6 / 15; break; | ||
166 | } | ||
167 | txx9_master_clock /= 10; /* * 2 / 20 */ | ||
168 | } | ||
169 | /* calculate gbus_clock from cpu_clock */ | ||
170 | divmode = (__u32)____raw_readq(&tx4939_ccfgptr->ccfg) & | ||
171 | TX4939_CCFG_YDIVMODE_MASK; | ||
172 | txx9_gbus_clock = txx9_cpu_clock; | ||
173 | switch (divmode) { | ||
174 | case TX4939_CCFG_YDIVMODE_2: | ||
175 | txx9_gbus_clock /= 2; break; | ||
176 | case TX4939_CCFG_YDIVMODE_3: | ||
177 | txx9_gbus_clock /= 3; break; | ||
178 | case TX4939_CCFG_YDIVMODE_5: | ||
179 | txx9_gbus_clock /= 5; break; | ||
180 | case TX4939_CCFG_YDIVMODE_6: | ||
181 | txx9_gbus_clock /= 6; break; | ||
182 | } | ||
183 | /* change default value to udelay/mdelay take reasonable time */ | ||
184 | loops_per_jiffy = txx9_cpu_clock / HZ / 2; | ||
185 | |||
186 | /* CCFG */ | ||
187 | tx4939_wdr_init(); | ||
188 | /* clear BusErrorOnWrite flag (W1C) */ | ||
189 | tx4939_ccfg_set(TX4939_CCFG_WDRST | TX4939_CCFG_BEOW); | ||
190 | /* enable Timeout BusError */ | ||
191 | if (txx9_ccfg_toeon) | ||
192 | tx4939_ccfg_set(TX4939_CCFG_TOE); | ||
193 | |||
194 | /* DMA selection */ | ||
195 | txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_DMASEL_ALL); | ||
196 | |||
197 | /* Use external clock for external arbiter */ | ||
198 | if (!(____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB)) | ||
199 | txx9_clear64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_PCICLKEN_ALL); | ||
200 | |||
201 | pr_info("%s -- %dMHz(M%dMHz,G%dMHz) CRIR:%08x CCFG:%llx PCFG:%llx\n", | ||
202 | txx9_pcode_str, | ||
203 | (cpuclk + 500000) / 1000000, | ||
204 | (txx9_master_clock + 500000) / 1000000, | ||
205 | (txx9_gbus_clock + 500000) / 1000000, | ||
206 | (__u32)____raw_readq(&tx4939_ccfgptr->crir), | ||
207 | ____raw_readq(&tx4939_ccfgptr->ccfg), | ||
208 | ____raw_readq(&tx4939_ccfgptr->pcfg)); | ||
209 | |||
210 | pr_info("%s DDRC -- EN:%08x", txx9_pcode_str, | ||
211 | (__u32)____raw_readq(&tx4939_ddrcptr->winen)); | ||
212 | for (i = 0; i < 4; i++) { | ||
213 | __u64 win = ____raw_readq(&tx4939_ddrcptr->win[i]); | ||
214 | if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i))) | ||
215 | continue; /* disabled */ | ||
216 | pr_cont(" #%d:%016llx", i, win); | ||
217 | tx4939_sdram_resource[i].name = "DDR SDRAM"; | ||
218 | tx4939_sdram_resource[i].start = | ||
219 | (unsigned long)(win >> 48) << 20; | ||
220 | tx4939_sdram_resource[i].end = | ||
221 | ((((unsigned long)(win >> 32) & 0xffff) + 1) << | ||
222 | 20) - 1; | ||
223 | tx4939_sdram_resource[i].flags = IORESOURCE_MEM; | ||
224 | request_resource(&iomem_resource, &tx4939_sdram_resource[i]); | ||
225 | } | ||
226 | pr_cont("\n"); | ||
227 | |||
228 | /* SRAM */ | ||
229 | if (____raw_readq(&tx4939_sramcptr->cr) & 1) { | ||
230 | unsigned int size = TX4939_SRAM_SIZE; | ||
231 | tx4939_sram_resource.name = "SRAM"; | ||
232 | tx4939_sram_resource.start = | ||
233 | (____raw_readq(&tx4939_sramcptr->cr) >> (39-11)) | ||
234 | & ~(size - 1); | ||
235 | tx4939_sram_resource.end = | ||
236 | tx4939_sram_resource.start + TX4939_SRAM_SIZE - 1; | ||
237 | tx4939_sram_resource.flags = IORESOURCE_MEM; | ||
238 | request_resource(&iomem_resource, &tx4939_sram_resource); | ||
239 | } | ||
240 | |||
241 | /* TMR */ | ||
242 | /* disable all timers */ | ||
243 | for (i = 0; i < TX4939_NR_TMR; i++) | ||
244 | txx9_tmr_init(TX4939_TMR_REG(i) & 0xfffffffffULL); | ||
245 | |||
246 | /* set PCIC1 reset (required to prevent hangup on BIST) */ | ||
247 | txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST); | ||
248 | pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); | ||
249 | if (pcfg & (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE)) { | ||
250 | mdelay(1); /* at least 128 cpu clock */ | ||
251 | /* clear PCIC1 reset */ | ||
252 | txx9_clear64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1RST); | ||
253 | } else { | ||
254 | pr_info("%s: stop PCIC1\n", txx9_pcode_str); | ||
255 | /* stop PCIC1 */ | ||
256 | txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_PCI1CKD); | ||
257 | } | ||
258 | if (!(pcfg & TX4939_PCFG_ET0MODE)) { | ||
259 | pr_info("%s: stop ETH0\n", txx9_pcode_str); | ||
260 | txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0RST); | ||
261 | txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH0CKD); | ||
262 | } | ||
263 | if (!(pcfg & TX4939_PCFG_ET1MODE)) { | ||
264 | pr_info("%s: stop ETH1\n", txx9_pcode_str); | ||
265 | txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1RST); | ||
266 | txx9_set64(&tx4939_ccfgptr->clkctr, TX4939_CLKCTR_ETH1CKD); | ||
267 | } | ||
268 | |||
269 | _machine_restart = tx4939_machine_restart; | ||
270 | board_be_init = tx4939_be_init; | ||
271 | } | ||
272 | |||
273 | void __init tx4939_time_init(unsigned int tmrnr) | ||
274 | { | ||
275 | if (____raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_TINTDIS) | ||
276 | txx9_clockevent_init(TX4939_TMR_REG(tmrnr) & 0xfffffffffULL, | ||
277 | TXX9_IRQ_BASE + TX4939_IR_TMR(tmrnr), | ||
278 | TXX9_IMCLK); | ||
279 | } | ||
280 | |||
281 | void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) | ||
282 | { | ||
283 | int i; | ||
284 | unsigned int ch_mask = 0; | ||
285 | __u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); | ||
286 | |||
287 | cts_mask |= ~1; /* only SIO0 have RTS/CTS */ | ||
288 | if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO0) | ||
289 | cts_mask |= 1 << 0; /* disable SIO0 RTS/CTS by PCFG setting */ | ||
290 | if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2) | ||
291 | ch_mask |= 1 << 2; /* disable SIO2 by PCFG setting */ | ||
292 | if (pcfg & TX4939_PCFG_SIO3MODE) | ||
293 | ch_mask |= 1 << 3; /* disable SIO3 by PCFG setting */ | ||
294 | for (i = 0; i < 4; i++) { | ||
295 | if ((1 << i) & ch_mask) | ||
296 | continue; | ||
297 | txx9_sio_init(TX4939_SIO_REG(i) & 0xfffffffffULL, | ||
298 | TXX9_IRQ_BASE + TX4939_IR_SIO(i), | ||
299 | i, sclk, (1 << i) & cts_mask); | ||
300 | } | ||
301 | } | ||
302 | |||
303 | #if IS_ENABLED(CONFIG_TC35815) | ||
304 | static u32 tx4939_get_eth_speed(struct net_device *dev) | ||
305 | { | ||
306 | struct ethtool_link_ksettings cmd; | ||
307 | |||
308 | if (__ethtool_get_link_ksettings(dev, &cmd)) | ||
309 | return 100; /* default 100Mbps */ | ||
310 | |||
311 | return cmd.base.speed; | ||
312 | } | ||
313 | |||
314 | static int tx4939_netdev_event(struct notifier_block *this, | ||
315 | unsigned long event, | ||
316 | void *ptr) | ||
317 | { | ||
318 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | ||
319 | |||
320 | if (event == NETDEV_CHANGE && netif_carrier_ok(dev)) { | ||
321 | __u64 bit = 0; | ||
322 | if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(0)) | ||
323 | bit = TX4939_PCFG_SPEED0; | ||
324 | else if (dev->irq == TXX9_IRQ_BASE + TX4939_IR_ETH(1)) | ||
325 | bit = TX4939_PCFG_SPEED1; | ||
326 | if (bit) { | ||
327 | if (tx4939_get_eth_speed(dev) == 100) | ||
328 | txx9_set64(&tx4939_ccfgptr->pcfg, bit); | ||
329 | else | ||
330 | txx9_clear64(&tx4939_ccfgptr->pcfg, bit); | ||
331 | } | ||
332 | } | ||
333 | return NOTIFY_DONE; | ||
334 | } | ||
335 | |||
336 | static struct notifier_block tx4939_netdev_notifier = { | ||
337 | .notifier_call = tx4939_netdev_event, | ||
338 | .priority = 1, | ||
339 | }; | ||
340 | |||
341 | void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1) | ||
342 | { | ||
343 | u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); | ||
344 | |||
345 | if (addr0 && (pcfg & TX4939_PCFG_ET0MODE)) | ||
346 | txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(0), addr0); | ||
347 | if (addr1 && (pcfg & TX4939_PCFG_ET1MODE)) | ||
348 | txx9_ethaddr_init(TXX9_IRQ_BASE + TX4939_IR_ETH(1), addr1); | ||
349 | register_netdevice_notifier(&tx4939_netdev_notifier); | ||
350 | } | ||
351 | #else | ||
352 | void __init tx4939_ethaddr_init(unsigned char *addr0, unsigned char *addr1) | ||
353 | { | ||
354 | } | ||
355 | #endif | ||
356 | |||
357 | void __init tx4939_mtd_init(int ch) | ||
358 | { | ||
359 | struct physmap_flash_data pdata = { | ||
360 | .width = TX4939_EBUSC_WIDTH(ch) / 8, | ||
361 | }; | ||
362 | unsigned long start = txx9_ce_res[ch].start; | ||
363 | unsigned long size = txx9_ce_res[ch].end - start + 1; | ||
364 | |||
365 | if (!(TX4939_EBUSC_CR(ch) & 0x8)) | ||
366 | return; /* disabled */ | ||
367 | txx9_physmap_flash_init(ch, start, size, &pdata); | ||
368 | } | ||
369 | |||
370 | #define TX4939_ATA_REG_PHYS(ch) (TX4939_ATA_REG(ch) & 0xfffffffffULL) | ||
371 | void __init tx4939_ata_init(void) | ||
372 | { | ||
373 | static struct resource ata0_res[] = { | ||
374 | { | ||
375 | .start = TX4939_ATA_REG_PHYS(0), | ||
376 | .end = TX4939_ATA_REG_PHYS(0) + 0x1000 - 1, | ||
377 | .flags = IORESOURCE_MEM, | ||
378 | }, { | ||
379 | .start = TXX9_IRQ_BASE + TX4939_IR_ATA(0), | ||
380 | .flags = IORESOURCE_IRQ, | ||
381 | }, | ||
382 | }; | ||
383 | static struct resource ata1_res[] = { | ||
384 | { | ||
385 | .start = TX4939_ATA_REG_PHYS(1), | ||
386 | .end = TX4939_ATA_REG_PHYS(1) + 0x1000 - 1, | ||
387 | .flags = IORESOURCE_MEM, | ||
388 | }, { | ||
389 | .start = TXX9_IRQ_BASE + TX4939_IR_ATA(1), | ||
390 | .flags = IORESOURCE_IRQ, | ||
391 | }, | ||
392 | }; | ||
393 | static struct platform_device ata0_dev = { | ||
394 | .name = "tx4939ide", | ||
395 | .id = 0, | ||
396 | .num_resources = ARRAY_SIZE(ata0_res), | ||
397 | .resource = ata0_res, | ||
398 | }; | ||
399 | static struct platform_device ata1_dev = { | ||
400 | .name = "tx4939ide", | ||
401 | .id = 1, | ||
402 | .num_resources = ARRAY_SIZE(ata1_res), | ||
403 | .resource = ata1_res, | ||
404 | }; | ||
405 | __u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); | ||
406 | |||
407 | if (pcfg & TX4939_PCFG_ATA0MODE) | ||
408 | platform_device_register(&ata0_dev); | ||
409 | if ((pcfg & (TX4939_PCFG_ATA1MODE | | ||
410 | TX4939_PCFG_ET1MODE | | ||
411 | TX4939_PCFG_ET0MODE)) == TX4939_PCFG_ATA1MODE) | ||
412 | platform_device_register(&ata1_dev); | ||
413 | } | ||
414 | |||
415 | void __init tx4939_rtc_init(void) | ||
416 | { | ||
417 | static struct resource res[] = { | ||
418 | { | ||
419 | .start = TX4939_RTC_REG & 0xfffffffffULL, | ||
420 | .end = (TX4939_RTC_REG & 0xfffffffffULL) + 0x100 - 1, | ||
421 | .flags = IORESOURCE_MEM, | ||
422 | }, { | ||
423 | .start = TXX9_IRQ_BASE + TX4939_IR_RTC, | ||
424 | .flags = IORESOURCE_IRQ, | ||
425 | }, | ||
426 | }; | ||
427 | static struct platform_device rtc_dev = { | ||
428 | .name = "tx4939rtc", | ||
429 | .id = -1, | ||
430 | .num_resources = ARRAY_SIZE(res), | ||
431 | .resource = res, | ||
432 | }; | ||
433 | |||
434 | platform_device_register(&rtc_dev); | ||
435 | } | ||
436 | |||
437 | void __init tx4939_ndfmc_init(unsigned int hold, unsigned int spw, | ||
438 | unsigned char ch_mask, unsigned char wide_mask) | ||
439 | { | ||
440 | struct txx9ndfmc_platform_data plat_data = { | ||
441 | .shift = 1, | ||
442 | .gbus_clock = txx9_gbus_clock, | ||
443 | .hold = hold, | ||
444 | .spw = spw, | ||
445 | .flags = NDFMC_PLAT_FLAG_NO_RSTR | NDFMC_PLAT_FLAG_HOLDADD | | ||
446 | NDFMC_PLAT_FLAG_DUMMYWRITE, | ||
447 | .ch_mask = ch_mask, | ||
448 | .wide_mask = wide_mask, | ||
449 | }; | ||
450 | txx9_ndfmc_init(TX4939_NDFMC_REG & 0xfffffffffULL, &plat_data); | ||
451 | } | ||
452 | |||
453 | void __init tx4939_dmac_init(int memcpy_chan0, int memcpy_chan1) | ||
454 | { | ||
455 | struct txx9dmac_platform_data plat_data = { | ||
456 | .have_64bit_regs = true, | ||
457 | }; | ||
458 | int i; | ||
459 | |||
460 | for (i = 0; i < 2; i++) { | ||
461 | plat_data.memcpy_chan = i ? memcpy_chan1 : memcpy_chan0; | ||
462 | txx9_dmac_init(i, TX4939_DMA_REG(i) & 0xfffffffffULL, | ||
463 | TXX9_IRQ_BASE + TX4939_IR_DMA(i, 0), | ||
464 | &plat_data); | ||
465 | } | ||
466 | } | ||
467 | |||
468 | void __init tx4939_aclc_init(void) | ||
469 | { | ||
470 | u64 pcfg = __raw_readq(&tx4939_ccfgptr->pcfg); | ||
471 | |||
472 | if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_ACLC) | ||
473 | txx9_aclc_init(TX4939_ACLC_REG & 0xfffffffffULL, | ||
474 | TXX9_IRQ_BASE + TX4939_IR_ACLC, 1, 0, 1); | ||
475 | } | ||
476 | |||
477 | void __init tx4939_sramc_init(void) | ||
478 | { | ||
479 | if (tx4939_sram_resource.start) | ||
480 | txx9_sramc_init(&tx4939_sram_resource); | ||
481 | } | ||
482 | |||
483 | void __init tx4939_rng_init(void) | ||
484 | { | ||
485 | static struct resource res = { | ||
486 | .start = TX4939_RNG_REG & 0xfffffffffULL, | ||
487 | .end = (TX4939_RNG_REG & 0xfffffffffULL) + 0x30 - 1, | ||
488 | .flags = IORESOURCE_MEM, | ||
489 | }; | ||
490 | static struct platform_device pdev = { | ||
491 | .name = "tx4939-rng", | ||
492 | .id = -1, | ||
493 | .num_resources = 1, | ||
494 | .resource = &res, | ||
495 | }; | ||
496 | |||
497 | platform_device_register(&pdev); | ||
498 | } | ||
499 | |||
500 | static void __init tx4939_stop_unused_modules(void) | ||
501 | { | ||
502 | __u64 pcfg, rst = 0, ckd = 0; | ||
503 | char buf[128]; | ||
504 | |||
505 | buf[0] = '\0'; | ||
506 | local_irq_disable(); | ||
507 | pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); | ||
508 | if ((pcfg & TX4939_PCFG_I2SMODE_MASK) != | ||
509 | TX4939_PCFG_I2SMODE_ACLC) { | ||
510 | rst |= TX4939_CLKCTR_ACLRST; | ||
511 | ckd |= TX4939_CLKCTR_ACLCKD; | ||
512 | strcat(buf, " ACLC"); | ||
513 | } | ||
514 | if ((pcfg & TX4939_PCFG_I2SMODE_MASK) != | ||
515 | TX4939_PCFG_I2SMODE_I2S && | ||
516 | (pcfg & TX4939_PCFG_I2SMODE_MASK) != | ||
517 | TX4939_PCFG_I2SMODE_I2S_ALT) { | ||
518 | rst |= TX4939_CLKCTR_I2SRST; | ||
519 | ckd |= TX4939_CLKCTR_I2SCKD; | ||
520 | strcat(buf, " I2S"); | ||
521 | } | ||
522 | if (!(pcfg & TX4939_PCFG_ATA0MODE)) { | ||
523 | rst |= TX4939_CLKCTR_ATA0RST; | ||
524 | ckd |= TX4939_CLKCTR_ATA0CKD; | ||
525 | strcat(buf, " ATA0"); | ||
526 | } | ||
527 | if (!(pcfg & TX4939_PCFG_ATA1MODE)) { | ||
528 | rst |= TX4939_CLKCTR_ATA1RST; | ||
529 | ckd |= TX4939_CLKCTR_ATA1CKD; | ||
530 | strcat(buf, " ATA1"); | ||
531 | } | ||
532 | if (pcfg & TX4939_PCFG_SPIMODE) { | ||
533 | rst |= TX4939_CLKCTR_SPIRST; | ||
534 | ckd |= TX4939_CLKCTR_SPICKD; | ||
535 | strcat(buf, " SPI"); | ||
536 | } | ||
537 | if (!(pcfg & (TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE))) { | ||
538 | rst |= TX4939_CLKCTR_VPCRST; | ||
539 | ckd |= TX4939_CLKCTR_VPCCKD; | ||
540 | strcat(buf, " VPC"); | ||
541 | } | ||
542 | if ((pcfg & TX4939_PCFG_SIO2MODE_MASK) != TX4939_PCFG_SIO2MODE_SIO2) { | ||
543 | rst |= TX4939_CLKCTR_SIO2RST; | ||
544 | ckd |= TX4939_CLKCTR_SIO2CKD; | ||
545 | strcat(buf, " SIO2"); | ||
546 | } | ||
547 | if (pcfg & TX4939_PCFG_SIO3MODE) { | ||
548 | rst |= TX4939_CLKCTR_SIO3RST; | ||
549 | ckd |= TX4939_CLKCTR_SIO3CKD; | ||
550 | strcat(buf, " SIO3"); | ||
551 | } | ||
552 | if (rst | ckd) { | ||
553 | txx9_set64(&tx4939_ccfgptr->clkctr, rst); | ||
554 | txx9_set64(&tx4939_ccfgptr->clkctr, ckd); | ||
555 | } | ||
556 | local_irq_enable(); | ||
557 | if (buf[0]) | ||
558 | pr_info("%s: stop%s\n", txx9_pcode_str, buf); | ||
559 | } | ||
560 | |||
561 | static int __init tx4939_late_init(void) | ||
562 | { | ||
563 | if (txx9_pcode != 0x4939) | ||
564 | return -ENODEV; | ||
565 | tx4939_stop_unused_modules(); | ||
566 | return 0; | ||
567 | } | ||
568 | late_initcall(tx4939_late_init); | ||
diff --git a/arch/mips/txx9/generic/smsc_fdc37m81x.c b/arch/mips/txx9/generic/smsc_fdc37m81x.c new file mode 100644 index 000000000..40f4098d3 --- /dev/null +++ b/arch/mips/txx9/generic/smsc_fdc37m81x.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * Interface for smsc fdc48m81x Super IO chip | ||
3 | * | ||
4 | * Author: MontaVista Software, Inc. source@mvista.com | ||
5 | * | ||
6 | * 2001-2003 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | * Copyright 2004 (c) MontaVista Software, Inc. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <asm/io.h> | ||
16 | #include <asm/txx9/smsc_fdc37m81x.h> | ||
17 | |||
18 | /* Common Registers */ | ||
19 | #define SMSC_FDC37M81X_CONFIG_INDEX 0x00 | ||
20 | #define SMSC_FDC37M81X_CONFIG_DATA 0x01 | ||
21 | #define SMSC_FDC37M81X_CONF 0x02 | ||
22 | #define SMSC_FDC37M81X_INDEX 0x03 | ||
23 | #define SMSC_FDC37M81X_DNUM 0x07 | ||
24 | #define SMSC_FDC37M81X_DID 0x20 | ||
25 | #define SMSC_FDC37M81X_DREV 0x21 | ||
26 | #define SMSC_FDC37M81X_PCNT 0x22 | ||
27 | #define SMSC_FDC37M81X_PMGT 0x23 | ||
28 | #define SMSC_FDC37M81X_OSC 0x24 | ||
29 | #define SMSC_FDC37M81X_CONFPA0 0x26 | ||
30 | #define SMSC_FDC37M81X_CONFPA1 0x27 | ||
31 | #define SMSC_FDC37M81X_TEST4 0x2B | ||
32 | #define SMSC_FDC37M81X_TEST5 0x2C | ||
33 | #define SMSC_FDC37M81X_TEST1 0x2D | ||
34 | #define SMSC_FDC37M81X_TEST2 0x2E | ||
35 | #define SMSC_FDC37M81X_TEST3 0x2F | ||
36 | |||
37 | /* Logical device numbers */ | ||
38 | #define SMSC_FDC37M81X_FDD 0x00 | ||
39 | #define SMSC_FDC37M81X_SERIAL1 0x04 | ||
40 | #define SMSC_FDC37M81X_SERIAL2 0x05 | ||
41 | #define SMSC_FDC37M81X_KBD 0x07 | ||
42 | |||
43 | /* Logical device Config Registers */ | ||
44 | #define SMSC_FDC37M81X_ACTIVE 0x30 | ||
45 | #define SMSC_FDC37M81X_BASEADDR0 0x60 | ||
46 | #define SMSC_FDC37M81X_BASEADDR1 0x61 | ||
47 | #define SMSC_FDC37M81X_INT 0x70 | ||
48 | #define SMSC_FDC37M81X_INT2 0x72 | ||
49 | #define SMSC_FDC37M81X_MODE 0xF0 | ||
50 | |||
51 | /* Chip Config Values */ | ||
52 | #define SMSC_FDC37M81X_CONFIG_ENTER 0x55 | ||
53 | #define SMSC_FDC37M81X_CONFIG_EXIT 0xaa | ||
54 | #define SMSC_FDC37M81X_CHIP_ID 0x4d | ||
55 | |||
56 | static unsigned long g_smsc_fdc37m81x_base; | ||
57 | |||
58 | static inline unsigned char smsc_fdc37m81x_rd(unsigned char index) | ||
59 | { | ||
60 | outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); | ||
61 | |||
62 | return inb(g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA); | ||
63 | } | ||
64 | |||
65 | static inline void smsc_dc37m81x_wr(unsigned char index, unsigned char data) | ||
66 | { | ||
67 | outb(index, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); | ||
68 | outb(data, g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_DATA); | ||
69 | } | ||
70 | |||
71 | void smsc_fdc37m81x_config_beg(void) | ||
72 | { | ||
73 | if (g_smsc_fdc37m81x_base) { | ||
74 | outb(SMSC_FDC37M81X_CONFIG_ENTER, | ||
75 | g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | void smsc_fdc37m81x_config_end(void) | ||
80 | { | ||
81 | if (g_smsc_fdc37m81x_base) | ||
82 | outb(SMSC_FDC37M81X_CONFIG_EXIT, | ||
83 | g_smsc_fdc37m81x_base + SMSC_FDC37M81X_CONFIG_INDEX); | ||
84 | } | ||
85 | |||
86 | u8 smsc_fdc37m81x_config_get(u8 reg) | ||
87 | { | ||
88 | u8 val = 0; | ||
89 | |||
90 | if (g_smsc_fdc37m81x_base) | ||
91 | val = smsc_fdc37m81x_rd(reg); | ||
92 | |||
93 | return val; | ||
94 | } | ||
95 | |||
96 | void smsc_fdc37m81x_config_set(u8 reg, u8 val) | ||
97 | { | ||
98 | if (g_smsc_fdc37m81x_base) | ||
99 | smsc_dc37m81x_wr(reg, val); | ||
100 | } | ||
101 | |||
102 | unsigned long __init smsc_fdc37m81x_init(unsigned long port) | ||
103 | { | ||
104 | const int field = sizeof(unsigned long) * 2; | ||
105 | u8 chip_id; | ||
106 | |||
107 | if (g_smsc_fdc37m81x_base) | ||
108 | pr_warn("%s: stepping on old base=0x%0*lx\n", __func__, field, | ||
109 | g_smsc_fdc37m81x_base); | ||
110 | |||
111 | g_smsc_fdc37m81x_base = port; | ||
112 | |||
113 | smsc_fdc37m81x_config_beg(); | ||
114 | |||
115 | chip_id = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DID); | ||
116 | if (chip_id == SMSC_FDC37M81X_CHIP_ID) | ||
117 | smsc_fdc37m81x_config_end(); | ||
118 | else { | ||
119 | pr_warn("%s: unknown chip id 0x%02x\n", __func__, chip_id); | ||
120 | g_smsc_fdc37m81x_base = 0; | ||
121 | } | ||
122 | |||
123 | return g_smsc_fdc37m81x_base; | ||
124 | } | ||
125 | |||
126 | #ifdef DEBUG | ||
127 | static void smsc_fdc37m81x_config_dump_one(const char *key, u8 dev, u8 reg) | ||
128 | { | ||
129 | pr_info("%s: dev=0x%02x reg=0x%02x val=0x%02x\n", key, dev, reg, | ||
130 | smsc_fdc37m81x_rd(reg)); | ||
131 | } | ||
132 | |||
133 | void smsc_fdc37m81x_config_dump(void) | ||
134 | { | ||
135 | u8 orig; | ||
136 | const char *fname = __func__; | ||
137 | |||
138 | smsc_fdc37m81x_config_beg(); | ||
139 | |||
140 | orig = smsc_fdc37m81x_rd(SMSC_FDC37M81X_DNUM); | ||
141 | |||
142 | pr_info("%s: common\n", fname); | ||
143 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, | ||
144 | SMSC_FDC37M81X_DNUM); | ||
145 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, | ||
146 | SMSC_FDC37M81X_DID); | ||
147 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, | ||
148 | SMSC_FDC37M81X_DREV); | ||
149 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, | ||
150 | SMSC_FDC37M81X_PCNT); | ||
151 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_NONE, | ||
152 | SMSC_FDC37M81X_PMGT); | ||
153 | |||
154 | pr_info("%s: keyboard\n", fname); | ||
155 | smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, SMSC_FDC37M81X_KBD); | ||
156 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, | ||
157 | SMSC_FDC37M81X_ACTIVE); | ||
158 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, | ||
159 | SMSC_FDC37M81X_INT); | ||
160 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, | ||
161 | SMSC_FDC37M81X_INT2); | ||
162 | smsc_fdc37m81x_config_dump_one(fname, SMSC_FDC37M81X_KBD, | ||
163 | SMSC_FDC37M81X_LDCR_F0); | ||
164 | |||
165 | smsc_dc37m81x_wr(SMSC_FDC37M81X_DNUM, orig); | ||
166 | |||
167 | smsc_fdc37m81x_config_end(); | ||
168 | } | ||
169 | #endif | ||
diff --git a/arch/mips/txx9/generic/spi_eeprom.c b/arch/mips/txx9/generic/spi_eeprom.c new file mode 100644 index 000000000..d833dd2c9 --- /dev/null +++ b/arch/mips/txx9/generic/spi_eeprom.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * spi_eeprom.c | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/spi/spi.h> | ||
17 | #include <linux/spi/eeprom.h> | ||
18 | #include <asm/txx9/spi.h> | ||
19 | |||
20 | #define AT250X0_PAGE_SIZE 8 | ||
21 | |||
22 | /* register board information for at25 driver */ | ||
23 | int __init spi_eeprom_register(int busid, int chipid, int size) | ||
24 | { | ||
25 | struct spi_board_info info = { | ||
26 | .modalias = "at25", | ||
27 | .max_speed_hz = 1500000, /* 1.5Mbps */ | ||
28 | .bus_num = busid, | ||
29 | .chip_select = chipid, | ||
30 | /* Mode 0: High-Active, Sample-Then-Shift */ | ||
31 | }; | ||
32 | struct spi_eeprom *eeprom; | ||
33 | eeprom = kzalloc(sizeof(*eeprom), GFP_KERNEL); | ||
34 | if (!eeprom) | ||
35 | return -ENOMEM; | ||
36 | strcpy(eeprom->name, "at250x0"); | ||
37 | eeprom->byte_len = size; | ||
38 | eeprom->page_size = AT250X0_PAGE_SIZE; | ||
39 | eeprom->flags = EE_ADDR1; | ||
40 | info.platform_data = eeprom; | ||
41 | return spi_register_board_info(&info, 1); | ||
42 | } | ||
43 | |||
44 | /* simple temporary spi driver to provide early access to seeprom. */ | ||
45 | |||
46 | static struct read_param { | ||
47 | int busid; | ||
48 | int chipid; | ||
49 | int address; | ||
50 | unsigned char *buf; | ||
51 | int len; | ||
52 | } *read_param; | ||
53 | |||
54 | static int __init early_seeprom_probe(struct spi_device *spi) | ||
55 | { | ||
56 | int stat = 0; | ||
57 | u8 cmd[2]; | ||
58 | int len = read_param->len; | ||
59 | char *buf = read_param->buf; | ||
60 | int address = read_param->address; | ||
61 | |||
62 | dev_info(&spi->dev, "spiclk %u KHz.\n", | ||
63 | (spi->max_speed_hz + 500) / 1000); | ||
64 | if (read_param->busid != spi->master->bus_num || | ||
65 | read_param->chipid != spi->chip_select) | ||
66 | return -ENODEV; | ||
67 | while (len > 0) { | ||
68 | /* spi_write_then_read can only work with small chunk */ | ||
69 | int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE; | ||
70 | cmd[0] = 0x03; /* AT25_READ */ | ||
71 | cmd[1] = address; | ||
72 | stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c); | ||
73 | buf += c; | ||
74 | len -= c; | ||
75 | address += c; | ||
76 | } | ||
77 | return stat; | ||
78 | } | ||
79 | |||
80 | static struct spi_driver early_seeprom_driver __initdata = { | ||
81 | .driver = { | ||
82 | .name = "at25", | ||
83 | }, | ||
84 | .probe = early_seeprom_probe, | ||
85 | }; | ||
86 | |||
87 | int __init spi_eeprom_read(int busid, int chipid, int address, | ||
88 | unsigned char *buf, int len) | ||
89 | { | ||
90 | int ret; | ||
91 | struct read_param param = { | ||
92 | .busid = busid, | ||
93 | .chipid = chipid, | ||
94 | .address = address, | ||
95 | .buf = buf, | ||
96 | .len = len | ||
97 | }; | ||
98 | |||
99 | read_param = ¶m; | ||
100 | ret = spi_register_driver(&early_seeprom_driver); | ||
101 | if (!ret) | ||
102 | spi_unregister_driver(&early_seeprom_driver); | ||
103 | return ret; | ||
104 | } | ||
diff --git a/arch/mips/txx9/jmr3927/Makefile b/arch/mips/txx9/jmr3927/Makefile new file mode 100644 index 000000000..4bda0615d --- /dev/null +++ b/arch/mips/txx9/jmr3927/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | # | ||
3 | # Makefile for TOSHIBA JMR-TX3927 board | ||
4 | # | ||
5 | |||
6 | obj-y += prom.o irq.o setup.o | ||
diff --git a/arch/mips/txx9/jmr3927/irq.c b/arch/mips/txx9/jmr3927/irq.c new file mode 100644 index 000000000..c22c859a2 --- /dev/null +++ b/arch/mips/txx9/jmr3927/irq.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * Copyright 2001 MontaVista Software Inc. | ||
3 | * Author: MontaVista Software, Inc. | ||
4 | * ahennessy@mvista.com | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | * | ||
10 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
20 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
23 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
24 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License along | ||
29 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
30 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
31 | */ | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/types.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/irq.h> | ||
36 | |||
37 | #include <asm/io.h> | ||
38 | #include <asm/mipsregs.h> | ||
39 | #include <asm/txx9/generic.h> | ||
40 | #include <asm/txx9/jmr3927.h> | ||
41 | |||
42 | #if JMR3927_IRQ_END > NR_IRQS | ||
43 | #error JMR3927_IRQ_END > NR_IRQS | ||
44 | #endif | ||
45 | |||
46 | /* | ||
47 | * CP0_STATUS is a thread's resource (saved/restored on context switch). | ||
48 | * So disable_irq/enable_irq MUST handle IOC/IRC registers. | ||
49 | */ | ||
50 | static void mask_irq_ioc(struct irq_data *d) | ||
51 | { | ||
52 | /* 0: mask */ | ||
53 | unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC; | ||
54 | unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); | ||
55 | unsigned int bit = 1 << irq_nr; | ||
56 | jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR); | ||
57 | /* flush write buffer */ | ||
58 | (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); | ||
59 | } | ||
60 | static void unmask_irq_ioc(struct irq_data *d) | ||
61 | { | ||
62 | /* 0: mask */ | ||
63 | unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC; | ||
64 | unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); | ||
65 | unsigned int bit = 1 << irq_nr; | ||
66 | jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR); | ||
67 | /* flush write buffer */ | ||
68 | (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); | ||
69 | } | ||
70 | |||
71 | static int jmr3927_ioc_irqroute(void) | ||
72 | { | ||
73 | unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR); | ||
74 | int i; | ||
75 | |||
76 | for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) { | ||
77 | if (istat & (1 << i)) | ||
78 | return JMR3927_IRQ_IOC + i; | ||
79 | } | ||
80 | return -1; | ||
81 | } | ||
82 | |||
83 | static int jmr3927_irq_dispatch(int pending) | ||
84 | { | ||
85 | int irq; | ||
86 | |||
87 | if ((pending & CAUSEF_IP7) == 0) | ||
88 | return -1; | ||
89 | irq = (pending >> CAUSEB_IP2) & 0x0f; | ||
90 | irq += JMR3927_IRQ_IRC; | ||
91 | if (irq == JMR3927_IRQ_IOCINT) | ||
92 | irq = jmr3927_ioc_irqroute(); | ||
93 | return irq; | ||
94 | } | ||
95 | |||
96 | static struct irq_chip jmr3927_irq_ioc = { | ||
97 | .name = "jmr3927_ioc", | ||
98 | .irq_mask = mask_irq_ioc, | ||
99 | .irq_unmask = unmask_irq_ioc, | ||
100 | }; | ||
101 | |||
102 | void __init jmr3927_irq_setup(void) | ||
103 | { | ||
104 | int i; | ||
105 | |||
106 | txx9_irq_dispatch = jmr3927_irq_dispatch; | ||
107 | /* Now, interrupt control disabled, */ | ||
108 | /* all IRC interrupts are masked, */ | ||
109 | /* all IRC interrupt mode are Low Active. */ | ||
110 | |||
111 | /* mask all IOC interrupts */ | ||
112 | jmr3927_ioc_reg_out(0, JMR3927_IOC_INTM_ADDR); | ||
113 | /* setup IOC interrupt mode (SOFT:High Active, Others:Low Active) */ | ||
114 | jmr3927_ioc_reg_out(JMR3927_IOC_INTF_SOFT, JMR3927_IOC_INTP_ADDR); | ||
115 | |||
116 | /* clear PCI Soft interrupts */ | ||
117 | jmr3927_ioc_reg_out(0, JMR3927_IOC_INTS1_ADDR); | ||
118 | /* clear PCI Reset interrupts */ | ||
119 | jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); | ||
120 | |||
121 | tx3927_irq_init(); | ||
122 | for (i = JMR3927_IRQ_IOC; i < JMR3927_IRQ_IOC + JMR3927_NR_IRQ_IOC; i++) | ||
123 | irq_set_chip_and_handler(i, &jmr3927_irq_ioc, | ||
124 | handle_level_irq); | ||
125 | |||
126 | /* setup IOC interrupt 1 (PCI, MODEM) */ | ||
127 | irq_set_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq); | ||
128 | } | ||
diff --git a/arch/mips/txx9/jmr3927/prom.c b/arch/mips/txx9/jmr3927/prom.c new file mode 100644 index 000000000..53c68de54 --- /dev/null +++ b/arch/mips/txx9/jmr3927/prom.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * BRIEF MODULE DESCRIPTION | ||
3 | * PROM library initialisation code, assuming a version of | ||
4 | * pmon is the boot code. | ||
5 | * | ||
6 | * Copyright 2001 MontaVista Software Inc. | ||
7 | * Author: MontaVista Software, Inc. | ||
8 | * ahennessy@mvista.com | ||
9 | * | ||
10 | * Based on arch/mips/au1000/common/prom.c | ||
11 | * | ||
12 | * This file was derived from Carsten Langgaard's | ||
13 | * arch/mips/mips-boards/xx files. | ||
14 | * | ||
15 | * Carsten Langgaard, carstenl@mips.com | ||
16 | * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or modify it | ||
19 | * under the terms of the GNU General Public License as published by the | ||
20 | * Free Software Foundation; either version 2 of the License, or (at your | ||
21 | * option) any later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
24 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
26 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
29 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
30 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * You should have received a copy of the GNU General Public License along | ||
35 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
36 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
37 | */ | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/memblock.h> | ||
41 | #include <asm/txx9/generic.h> | ||
42 | #include <asm/txx9/jmr3927.h> | ||
43 | |||
44 | void __init jmr3927_prom_init(void) | ||
45 | { | ||
46 | /* CCFG */ | ||
47 | if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0) | ||
48 | pr_err("TX3927 TLB off\n"); | ||
49 | |||
50 | memblock_add(0, JMR3927_SDRAM_SIZE); | ||
51 | txx9_sio_putchar_init(TX3927_SIO_REG(1)); | ||
52 | } | ||
diff --git a/arch/mips/txx9/jmr3927/setup.c b/arch/mips/txx9/jmr3927/setup.c new file mode 100644 index 000000000..613943886 --- /dev/null +++ b/arch/mips/txx9/jmr3927/setup.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License as published by the | ||
4 | * Free Software Foundation; either version 2 of the License, or (at your | ||
5 | * option) any later version. | ||
6 | * | ||
7 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
8 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
9 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
10 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
11 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
12 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
13 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
14 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
15 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
16 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | * Copyright 2001 MontaVista Software Inc. | ||
23 | * Author: MontaVista Software, Inc. | ||
24 | * ahennessy@mvista.com | ||
25 | * | ||
26 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
27 | * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) | ||
28 | */ | ||
29 | |||
30 | #include <linux/init.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/ioport.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/gpio.h> | ||
37 | #include <asm/reboot.h> | ||
38 | #include <asm/txx9pio.h> | ||
39 | #include <asm/txx9/generic.h> | ||
40 | #include <asm/txx9/pci.h> | ||
41 | #include <asm/txx9/jmr3927.h> | ||
42 | #include <asm/mipsregs.h> | ||
43 | |||
44 | static void jmr3927_machine_restart(char *command) | ||
45 | { | ||
46 | local_irq_disable(); | ||
47 | #if 1 /* Resetting PCI bus */ | ||
48 | jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); | ||
49 | jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI, JMR3927_IOC_RESET_ADDR); | ||
50 | (void)jmr3927_ioc_reg_in(JMR3927_IOC_RESET_ADDR); /* flush WB */ | ||
51 | mdelay(1); | ||
52 | jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); | ||
53 | #endif | ||
54 | jmr3927_ioc_reg_out(JMR3927_IOC_RESET_CPU, JMR3927_IOC_RESET_ADDR); | ||
55 | /* fallback */ | ||
56 | (*_machine_halt)(); | ||
57 | } | ||
58 | |||
59 | static void __init jmr3927_time_init(void) | ||
60 | { | ||
61 | tx3927_time_init(0, 1); | ||
62 | } | ||
63 | |||
64 | #define DO_WRITE_THROUGH | ||
65 | |||
66 | static void jmr3927_board_init(void); | ||
67 | |||
68 | static void __init jmr3927_mem_setup(void) | ||
69 | { | ||
70 | set_io_port_base(JMR3927_PORT_BASE + JMR3927_PCIIO); | ||
71 | |||
72 | _machine_restart = jmr3927_machine_restart; | ||
73 | |||
74 | /* cache setup */ | ||
75 | { | ||
76 | unsigned int conf; | ||
77 | #ifdef DO_WRITE_THROUGH | ||
78 | int mips_config_cwfon = 0; | ||
79 | int mips_config_wbon = 0; | ||
80 | #else | ||
81 | int mips_config_cwfon = 1; | ||
82 | int mips_config_wbon = 1; | ||
83 | #endif | ||
84 | |||
85 | conf = read_c0_conf(); | ||
86 | conf &= ~(TX39_CONF_WBON | TX39_CONF_CWFON); | ||
87 | conf |= mips_config_wbon ? TX39_CONF_WBON : 0; | ||
88 | conf |= mips_config_cwfon ? TX39_CONF_CWFON : 0; | ||
89 | |||
90 | write_c0_conf(conf); | ||
91 | write_c0_cache(0); | ||
92 | } | ||
93 | |||
94 | /* initialize board */ | ||
95 | jmr3927_board_init(); | ||
96 | |||
97 | tx3927_sio_init(0, 1 << 1); /* ch1: noCTS */ | ||
98 | } | ||
99 | |||
100 | static void __init jmr3927_pci_setup(void) | ||
101 | { | ||
102 | #ifdef CONFIG_PCI | ||
103 | int extarb = !(tx3927_ccfgptr->ccfg & TX3927_CCFG_PCIXARB); | ||
104 | struct pci_controller *c; | ||
105 | |||
106 | c = txx9_alloc_pci_controller(&txx9_primary_pcic, | ||
107 | JMR3927_PCIMEM, JMR3927_PCIMEM_SIZE, | ||
108 | JMR3927_PCIIO, JMR3927_PCIIO_SIZE); | ||
109 | register_pci_controller(c); | ||
110 | if (!extarb) { | ||
111 | /* Reset PCI Bus */ | ||
112 | jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); | ||
113 | udelay(100); | ||
114 | jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI, | ||
115 | JMR3927_IOC_RESET_ADDR); | ||
116 | udelay(100); | ||
117 | jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); | ||
118 | } | ||
119 | tx3927_pcic_setup(c, JMR3927_SDRAM_SIZE, extarb); | ||
120 | tx3927_setup_pcierr_irq(); | ||
121 | #endif /* CONFIG_PCI */ | ||
122 | } | ||
123 | |||
124 | static void __init jmr3927_board_init(void) | ||
125 | { | ||
126 | txx9_cpu_clock = JMR3927_CORECLK; | ||
127 | /* SDRAMC are configured by PROM */ | ||
128 | |||
129 | /* ROMC */ | ||
130 | tx3927_romcptr->cr[1] = JMR3927_ROMCE1 | 0x00030048; | ||
131 | tx3927_romcptr->cr[2] = JMR3927_ROMCE2 | 0x000064c8; | ||
132 | tx3927_romcptr->cr[3] = JMR3927_ROMCE3 | 0x0003f698; | ||
133 | tx3927_romcptr->cr[5] = JMR3927_ROMCE5 | 0x0000f218; | ||
134 | |||
135 | /* Pin selection */ | ||
136 | tx3927_ccfgptr->pcfg &= ~TX3927_PCFG_SELALL; | ||
137 | tx3927_ccfgptr->pcfg |= | ||
138 | TX3927_PCFG_SELSIOC(0) | TX3927_PCFG_SELSIO_ALL | | ||
139 | (TX3927_PCFG_SELDMA_ALL & ~TX3927_PCFG_SELDMA(1)); | ||
140 | |||
141 | tx3927_setup(); | ||
142 | |||
143 | /* PIO[15:12] connected to LEDs */ | ||
144 | __raw_writel(0x0000f000, &tx3927_pioptr->dir); | ||
145 | |||
146 | jmr3927_pci_setup(); | ||
147 | |||
148 | /* SIO0 DTR on */ | ||
149 | jmr3927_ioc_reg_out(0, JMR3927_IOC_DTR_ADDR); | ||
150 | |||
151 | jmr3927_led_set(0); | ||
152 | |||
153 | pr_info("JMR-TX3927 (Rev %d) --- IOC(Rev %d) DIPSW:%d,%d,%d,%d\n", | ||
154 | jmr3927_ioc_reg_in(JMR3927_IOC_BREV_ADDR) & JMR3927_REV_MASK, | ||
155 | jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR) & JMR3927_REV_MASK, | ||
156 | jmr3927_dipsw1(), jmr3927_dipsw2(), | ||
157 | jmr3927_dipsw3(), jmr3927_dipsw4()); | ||
158 | } | ||
159 | |||
160 | /* This trick makes rtc-ds1742 driver usable as is. */ | ||
161 | static unsigned long jmr3927_swizzle_addr_b(unsigned long port) | ||
162 | { | ||
163 | if ((port & 0xffff0000) != JMR3927_IOC_NVRAMB_ADDR) | ||
164 | return port; | ||
165 | port = (port & 0xffff0000) | (port & 0x7fff << 1); | ||
166 | #ifdef __BIG_ENDIAN | ||
167 | return port; | ||
168 | #else | ||
169 | return port | 1; | ||
170 | #endif | ||
171 | } | ||
172 | |||
173 | static void __init jmr3927_rtc_init(void) | ||
174 | { | ||
175 | static struct resource __initdata res = { | ||
176 | .start = JMR3927_IOC_NVRAMB_ADDR - IO_BASE, | ||
177 | .end = JMR3927_IOC_NVRAMB_ADDR - IO_BASE + 0x800 - 1, | ||
178 | .flags = IORESOURCE_MEM, | ||
179 | }; | ||
180 | platform_device_register_simple("rtc-ds1742", -1, &res, 1); | ||
181 | } | ||
182 | |||
183 | static void __init jmr3927_mtd_init(void) | ||
184 | { | ||
185 | int i; | ||
186 | |||
187 | for (i = 0; i < 2; i++) | ||
188 | tx3927_mtd_init(i); | ||
189 | } | ||
190 | |||
191 | static void __init jmr3927_device_init(void) | ||
192 | { | ||
193 | unsigned long iocled_base = JMR3927_IOC_LED_ADDR - IO_BASE; | ||
194 | #ifdef __LITTLE_ENDIAN | ||
195 | iocled_base |= 1; | ||
196 | #endif | ||
197 | __swizzle_addr_b = jmr3927_swizzle_addr_b; | ||
198 | jmr3927_rtc_init(); | ||
199 | tx3927_wdt_init(); | ||
200 | jmr3927_mtd_init(); | ||
201 | txx9_iocled_init(iocled_base, -1, 8, 1, "green", NULL); | ||
202 | } | ||
203 | |||
204 | static void __init jmr3927_arch_init(void) | ||
205 | { | ||
206 | txx9_gpio_init(TX3927_PIO_REG, 0, 16); | ||
207 | |||
208 | gpio_request(11, "dipsw1"); | ||
209 | gpio_request(10, "dipsw2"); | ||
210 | } | ||
211 | |||
212 | struct txx9_board_vec jmr3927_vec __initdata = { | ||
213 | .system = "Toshiba JMR_TX3927", | ||
214 | .prom_init = jmr3927_prom_init, | ||
215 | .mem_setup = jmr3927_mem_setup, | ||
216 | .irq_setup = jmr3927_irq_setup, | ||
217 | .time_init = jmr3927_time_init, | ||
218 | .device_init = jmr3927_device_init, | ||
219 | .arch_init = jmr3927_arch_init, | ||
220 | #ifdef CONFIG_PCI | ||
221 | .pci_map_irq = jmr3927_pci_map_irq, | ||
222 | #endif | ||
223 | }; | ||
diff --git a/arch/mips/txx9/rbtx4927/Makefile b/arch/mips/txx9/rbtx4927/Makefile new file mode 100644 index 000000000..08a02aebd --- /dev/null +++ b/arch/mips/txx9/rbtx4927/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | obj-y += prom.o setup.o irq.o | ||
diff --git a/arch/mips/txx9/rbtx4927/irq.c b/arch/mips/txx9/rbtx4927/irq.c new file mode 100644 index 000000000..3f48292c9 --- /dev/null +++ b/arch/mips/txx9/rbtx4927/irq.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * Toshiba RBTX4927 specific interrupt handlers | ||
3 | * | ||
4 | * Author: MontaVista Software, Inc. | ||
5 | * source@mvista.com | ||
6 | * | ||
7 | * Copyright 2001-2002 MontaVista Software Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
19 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
20 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
22 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
23 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | /* | ||
30 | * I8259A_IRQ_BASE+00 | ||
31 | * I8259A_IRQ_BASE+01 PS2/Keyboard | ||
32 | * I8259A_IRQ_BASE+02 Cascade RBTX4927-ISA (irqs 8-15) | ||
33 | * I8259A_IRQ_BASE+03 | ||
34 | * I8259A_IRQ_BASE+04 | ||
35 | * I8259A_IRQ_BASE+05 | ||
36 | * I8259A_IRQ_BASE+06 | ||
37 | * I8259A_IRQ_BASE+07 | ||
38 | * I8259A_IRQ_BASE+08 | ||
39 | * I8259A_IRQ_BASE+09 | ||
40 | * I8259A_IRQ_BASE+10 | ||
41 | * I8259A_IRQ_BASE+11 | ||
42 | * I8259A_IRQ_BASE+12 PS2/Mouse (not supported at this time) | ||
43 | * I8259A_IRQ_BASE+13 | ||
44 | * I8259A_IRQ_BASE+14 IDE | ||
45 | * I8259A_IRQ_BASE+15 | ||
46 | * | ||
47 | * MIPS_CPU_IRQ_BASE+00 Software 0 | ||
48 | * MIPS_CPU_IRQ_BASE+01 Software 1 | ||
49 | * MIPS_CPU_IRQ_BASE+02 Cascade TX4927-CP0 | ||
50 | * MIPS_CPU_IRQ_BASE+03 Multiplexed -- do not use | ||
51 | * MIPS_CPU_IRQ_BASE+04 Multiplexed -- do not use | ||
52 | * MIPS_CPU_IRQ_BASE+05 Multiplexed -- do not use | ||
53 | * MIPS_CPU_IRQ_BASE+06 Multiplexed -- do not use | ||
54 | * MIPS_CPU_IRQ_BASE+07 CPU TIMER | ||
55 | * | ||
56 | * TXX9_IRQ_BASE+00 | ||
57 | * TXX9_IRQ_BASE+01 | ||
58 | * TXX9_IRQ_BASE+02 | ||
59 | * TXX9_IRQ_BASE+03 Cascade RBTX4927-IOC | ||
60 | * TXX9_IRQ_BASE+04 | ||
61 | * TXX9_IRQ_BASE+05 RBTX4927 RTL-8019AS ethernet | ||
62 | * TXX9_IRQ_BASE+06 | ||
63 | * TXX9_IRQ_BASE+07 | ||
64 | * TXX9_IRQ_BASE+08 TX4927 SerialIO Channel 0 | ||
65 | * TXX9_IRQ_BASE+09 TX4927 SerialIO Channel 1 | ||
66 | * TXX9_IRQ_BASE+10 | ||
67 | * TXX9_IRQ_BASE+11 | ||
68 | * TXX9_IRQ_BASE+12 | ||
69 | * TXX9_IRQ_BASE+13 | ||
70 | * TXX9_IRQ_BASE+14 | ||
71 | * TXX9_IRQ_BASE+15 | ||
72 | * TXX9_IRQ_BASE+16 TX4927 PCI PCI-C | ||
73 | * TXX9_IRQ_BASE+17 | ||
74 | * TXX9_IRQ_BASE+18 | ||
75 | * TXX9_IRQ_BASE+19 | ||
76 | * TXX9_IRQ_BASE+20 | ||
77 | * TXX9_IRQ_BASE+21 | ||
78 | * TXX9_IRQ_BASE+22 TX4927 PCI PCI-ERR | ||
79 | * TXX9_IRQ_BASE+23 TX4927 PCI PCI-PMA (not used) | ||
80 | * TXX9_IRQ_BASE+24 | ||
81 | * TXX9_IRQ_BASE+25 | ||
82 | * TXX9_IRQ_BASE+26 | ||
83 | * TXX9_IRQ_BASE+27 | ||
84 | * TXX9_IRQ_BASE+28 | ||
85 | * TXX9_IRQ_BASE+29 | ||
86 | * TXX9_IRQ_BASE+30 | ||
87 | * TXX9_IRQ_BASE+31 | ||
88 | * | ||
89 | * RBTX4927_IRQ_IOC+00 FPCIB0 PCI-D (SouthBridge) | ||
90 | * RBTX4927_IRQ_IOC+01 FPCIB0 PCI-C (SouthBridge) | ||
91 | * RBTX4927_IRQ_IOC+02 FPCIB0 PCI-B (SouthBridge/IDE/pin=1,INTR) | ||
92 | * RBTX4927_IRQ_IOC+03 FPCIB0 PCI-A (SouthBridge/USB/pin=4) | ||
93 | * RBTX4927_IRQ_IOC+04 | ||
94 | * RBTX4927_IRQ_IOC+05 | ||
95 | * RBTX4927_IRQ_IOC+06 | ||
96 | * RBTX4927_IRQ_IOC+07 | ||
97 | * | ||
98 | * NOTES: | ||
99 | * SouthBridge/INTR is mapped to SouthBridge/A=PCI-B/#58 | ||
100 | * SouthBridge/ISA/pin=0 no pci irq used by this device | ||
101 | * SouthBridge/IDE/pin=1 no pci irq used by this device, using INTR | ||
102 | * via ISA IRQ14 | ||
103 | * SouthBridge/USB/pin=4 using pci irq SouthBridge/D=PCI-A=#59 | ||
104 | * SouthBridge/PMC/pin=0 no pci irq used by this device | ||
105 | * SuperIO/PS2/Keyboard, using INTR via ISA IRQ1 | ||
106 | * SuperIO/PS2/Mouse, using INTR via ISA IRQ12 (mouse not currently supported) | ||
107 | * JP7 is not bus master -- do NOT use -- only 4 pci bus master's | ||
108 | * allowed -- SouthBridge, JP4, JP5, JP6 | ||
109 | */ | ||
110 | |||
111 | #include <linux/init.h> | ||
112 | #include <linux/types.h> | ||
113 | #include <linux/interrupt.h> | ||
114 | #include <linux/irq.h> | ||
115 | #include <asm/io.h> | ||
116 | #include <asm/mipsregs.h> | ||
117 | #include <asm/txx9/generic.h> | ||
118 | #include <asm/txx9/rbtx4927.h> | ||
119 | |||
120 | static int toshiba_rbtx4927_irq_nested(int sw_irq) | ||
121 | { | ||
122 | u8 level3; | ||
123 | |||
124 | level3 = readb(rbtx4927_imstat_addr) & 0x1f; | ||
125 | if (unlikely(!level3)) | ||
126 | return -1; | ||
127 | return RBTX4927_IRQ_IOC + __fls8(level3); | ||
128 | } | ||
129 | |||
130 | static void toshiba_rbtx4927_irq_ioc_enable(struct irq_data *d) | ||
131 | { | ||
132 | unsigned char v; | ||
133 | |||
134 | v = readb(rbtx4927_imask_addr); | ||
135 | v |= (1 << (d->irq - RBTX4927_IRQ_IOC)); | ||
136 | writeb(v, rbtx4927_imask_addr); | ||
137 | } | ||
138 | |||
139 | static void toshiba_rbtx4927_irq_ioc_disable(struct irq_data *d) | ||
140 | { | ||
141 | unsigned char v; | ||
142 | |||
143 | v = readb(rbtx4927_imask_addr); | ||
144 | v &= ~(1 << (d->irq - RBTX4927_IRQ_IOC)); | ||
145 | writeb(v, rbtx4927_imask_addr); | ||
146 | mmiowb(); | ||
147 | } | ||
148 | |||
149 | #define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC" | ||
150 | static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { | ||
151 | .name = TOSHIBA_RBTX4927_IOC_NAME, | ||
152 | .irq_mask = toshiba_rbtx4927_irq_ioc_disable, | ||
153 | .irq_unmask = toshiba_rbtx4927_irq_ioc_enable, | ||
154 | }; | ||
155 | |||
156 | static void __init toshiba_rbtx4927_irq_ioc_init(void) | ||
157 | { | ||
158 | int i; | ||
159 | |||
160 | /* mask all IOC interrupts */ | ||
161 | writeb(0, rbtx4927_imask_addr); | ||
162 | /* clear SoftInt interrupts */ | ||
163 | writeb(0, rbtx4927_softint_addr); | ||
164 | |||
165 | for (i = RBTX4927_IRQ_IOC; | ||
166 | i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++) | ||
167 | irq_set_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type, | ||
168 | handle_level_irq); | ||
169 | irq_set_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq); | ||
170 | } | ||
171 | |||
172 | static int rbtx4927_irq_dispatch(int pending) | ||
173 | { | ||
174 | int irq; | ||
175 | |||
176 | if (pending & STATUSF_IP7) /* cpu timer */ | ||
177 | irq = MIPS_CPU_IRQ_BASE + 7; | ||
178 | else if (pending & STATUSF_IP2) { /* tx4927 pic */ | ||
179 | irq = txx9_irq(); | ||
180 | if (irq == RBTX4927_IRQ_IOCINT) | ||
181 | irq = toshiba_rbtx4927_irq_nested(irq); | ||
182 | } else if (pending & STATUSF_IP0) /* user line 0 */ | ||
183 | irq = MIPS_CPU_IRQ_BASE + 0; | ||
184 | else if (pending & STATUSF_IP1) /* user line 1 */ | ||
185 | irq = MIPS_CPU_IRQ_BASE + 1; | ||
186 | else | ||
187 | irq = -1; | ||
188 | return irq; | ||
189 | } | ||
190 | |||
191 | void __init rbtx4927_irq_setup(void) | ||
192 | { | ||
193 | txx9_irq_dispatch = rbtx4927_irq_dispatch; | ||
194 | tx4927_irq_init(); | ||
195 | toshiba_rbtx4927_irq_ioc_init(); | ||
196 | /* Onboard 10M Ether: High Active */ | ||
197 | irq_set_irq_type(RBTX4927_RTL_8019_IRQ, IRQF_TRIGGER_HIGH); | ||
198 | } | ||
diff --git a/arch/mips/txx9/rbtx4927/prom.c b/arch/mips/txx9/rbtx4927/prom.c new file mode 100644 index 000000000..9b4acff82 --- /dev/null +++ b/arch/mips/txx9/rbtx4927/prom.c | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * rbtx4927 specific prom routines | ||
3 | * | ||
4 | * Author: MontaVista Software, Inc. | ||
5 | * source@mvista.com | ||
6 | * | ||
7 | * Copyright 2001-2002 MontaVista Software Inc. | ||
8 | * | ||
9 | * Copyright (C) 2004 MontaVista Software Inc. | ||
10 | * Author: Manish Lachwani, mlachwani@mvista.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
22 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
23 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
25 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
26 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License along | ||
29 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
30 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
31 | */ | ||
32 | |||
33 | #include <linux/init.h> | ||
34 | #include <linux/memblock.h> | ||
35 | #include <asm/txx9/generic.h> | ||
36 | #include <asm/txx9/rbtx4927.h> | ||
37 | |||
38 | void __init rbtx4927_prom_init(void) | ||
39 | { | ||
40 | memblock_add(0, tx4927_get_mem_size()); | ||
41 | txx9_sio_putchar_init(TX4927_SIO_REG(0) & 0xfffffffffULL); | ||
42 | } | ||
diff --git a/arch/mips/txx9/rbtx4927/setup.c b/arch/mips/txx9/rbtx4927/setup.c new file mode 100644 index 000000000..31955c1d5 --- /dev/null +++ b/arch/mips/txx9/rbtx4927/setup.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /* | ||
2 | * Toshiba rbtx4927 specific setup | ||
3 | * | ||
4 | * Author: MontaVista Software, Inc. | ||
5 | * source@mvista.com | ||
6 | * | ||
7 | * Copyright 2001-2002 MontaVista Software Inc. | ||
8 | * | ||
9 | * Copyright (C) 1996, 97, 2001, 04 Ralf Baechle (ralf@linux-mips.org) | ||
10 | * Copyright (C) 2000 RidgeRun, Inc. | ||
11 | * Author: RidgeRun, Inc. | ||
12 | * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com | ||
13 | * | ||
14 | * Copyright 2001 MontaVista Software Inc. | ||
15 | * Author: jsun@mvista.com or jsun@junsun.net | ||
16 | * | ||
17 | * Copyright 2002 MontaVista Software Inc. | ||
18 | * Author: Michael Pruznick, michael_pruznick@mvista.com | ||
19 | * | ||
20 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
21 | * | ||
22 | * Copyright (C) 2004 MontaVista Software Inc. | ||
23 | * Author: Manish Lachwani, mlachwani@mvista.com | ||
24 | * | ||
25 | * This program is free software; you can redistribute it and/or modify it | ||
26 | * under the terms of the GNU General Public License as published by the | ||
27 | * Free Software Foundation; either version 2 of the License, or (at your | ||
28 | * option) any later version. | ||
29 | * | ||
30 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
31 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
32 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
33 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
34 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
35 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
36 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
37 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
38 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
39 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
40 | * | ||
41 | * You should have received a copy of the GNU General Public License along | ||
42 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
43 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
44 | */ | ||
45 | #include <linux/init.h> | ||
46 | #include <linux/kernel.h> | ||
47 | #include <linux/types.h> | ||
48 | #include <linux/ioport.h> | ||
49 | #include <linux/platform_device.h> | ||
50 | #include <linux/delay.h> | ||
51 | #include <linux/gpio.h> | ||
52 | #include <linux/leds.h> | ||
53 | #include <asm/io.h> | ||
54 | #include <asm/reboot.h> | ||
55 | #include <asm/txx9pio.h> | ||
56 | #include <asm/txx9/generic.h> | ||
57 | #include <asm/txx9/pci.h> | ||
58 | #include <asm/txx9/rbtx4927.h> | ||
59 | #include <asm/txx9/tx4938.h> /* for TX4937 */ | ||
60 | |||
61 | #ifdef CONFIG_PCI | ||
62 | static void __init tx4927_pci_setup(void) | ||
63 | { | ||
64 | int extarb = !(__raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCIARB); | ||
65 | struct pci_controller *c = &txx9_primary_pcic; | ||
66 | |||
67 | register_pci_controller(c); | ||
68 | |||
69 | if (__raw_readq(&tx4927_ccfgptr->ccfg) & TX4927_CCFG_PCI66) | ||
70 | txx9_pci_option = | ||
71 | (txx9_pci_option & ~TXX9_PCI_OPT_CLK_MASK) | | ||
72 | TXX9_PCI_OPT_CLK_66; /* already configured */ | ||
73 | |||
74 | /* Reset PCI Bus */ | ||
75 | writeb(1, rbtx4927_pcireset_addr); | ||
76 | /* Reset PCIC */ | ||
77 | txx9_set64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST); | ||
78 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | ||
79 | TXX9_PCI_OPT_CLK_66) | ||
80 | tx4927_pciclk66_setup(); | ||
81 | mdelay(10); | ||
82 | /* clear PCIC reset */ | ||
83 | txx9_clear64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST); | ||
84 | writeb(0, rbtx4927_pcireset_addr); | ||
85 | iob(); | ||
86 | |||
87 | tx4927_report_pciclk(); | ||
88 | tx4927_pcic_setup(tx4927_pcicptr, c, extarb); | ||
89 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | ||
90 | TXX9_PCI_OPT_CLK_AUTO && | ||
91 | txx9_pci66_check(c, 0, 0)) { | ||
92 | /* Reset PCI Bus */ | ||
93 | writeb(1, rbtx4927_pcireset_addr); | ||
94 | /* Reset PCIC */ | ||
95 | txx9_set64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST); | ||
96 | tx4927_pciclk66_setup(); | ||
97 | mdelay(10); | ||
98 | /* clear PCIC reset */ | ||
99 | txx9_clear64(&tx4927_ccfgptr->clkctr, TX4927_CLKCTR_PCIRST); | ||
100 | writeb(0, rbtx4927_pcireset_addr); | ||
101 | iob(); | ||
102 | /* Reinitialize PCIC */ | ||
103 | tx4927_report_pciclk(); | ||
104 | tx4927_pcic_setup(tx4927_pcicptr, c, extarb); | ||
105 | } | ||
106 | tx4927_setup_pcierr_irq(); | ||
107 | } | ||
108 | |||
109 | static void __init tx4937_pci_setup(void) | ||
110 | { | ||
111 | int extarb = !(__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCIARB); | ||
112 | struct pci_controller *c = &txx9_primary_pcic; | ||
113 | |||
114 | register_pci_controller(c); | ||
115 | |||
116 | if (__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66) | ||
117 | txx9_pci_option = | ||
118 | (txx9_pci_option & ~TXX9_PCI_OPT_CLK_MASK) | | ||
119 | TXX9_PCI_OPT_CLK_66; /* already configured */ | ||
120 | |||
121 | /* Reset PCI Bus */ | ||
122 | writeb(1, rbtx4927_pcireset_addr); | ||
123 | /* Reset PCIC */ | ||
124 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
125 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | ||
126 | TXX9_PCI_OPT_CLK_66) | ||
127 | tx4938_pciclk66_setup(); | ||
128 | mdelay(10); | ||
129 | /* clear PCIC reset */ | ||
130 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
131 | writeb(0, rbtx4927_pcireset_addr); | ||
132 | iob(); | ||
133 | |||
134 | tx4938_report_pciclk(); | ||
135 | tx4927_pcic_setup(tx4938_pcicptr, c, extarb); | ||
136 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | ||
137 | TXX9_PCI_OPT_CLK_AUTO && | ||
138 | txx9_pci66_check(c, 0, 0)) { | ||
139 | /* Reset PCI Bus */ | ||
140 | writeb(1, rbtx4927_pcireset_addr); | ||
141 | /* Reset PCIC */ | ||
142 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
143 | tx4938_pciclk66_setup(); | ||
144 | mdelay(10); | ||
145 | /* clear PCIC reset */ | ||
146 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
147 | writeb(0, rbtx4927_pcireset_addr); | ||
148 | iob(); | ||
149 | /* Reinitialize PCIC */ | ||
150 | tx4938_report_pciclk(); | ||
151 | tx4927_pcic_setup(tx4938_pcicptr, c, extarb); | ||
152 | } | ||
153 | tx4938_setup_pcierr_irq(); | ||
154 | } | ||
155 | #else | ||
156 | static inline void tx4927_pci_setup(void) {} | ||
157 | static inline void tx4937_pci_setup(void) {} | ||
158 | #endif /* CONFIG_PCI */ | ||
159 | |||
160 | static void __init rbtx4927_gpio_init(void) | ||
161 | { | ||
162 | /* TX4927-SIO DTR on (PIO[15]) */ | ||
163 | gpio_request(15, "sio-dtr"); | ||
164 | gpio_direction_output(15, 1); | ||
165 | |||
166 | tx4927_sio_init(0, 0); | ||
167 | } | ||
168 | |||
169 | static void __init rbtx4927_arch_init(void) | ||
170 | { | ||
171 | txx9_gpio_init(TX4927_PIO_REG & 0xfffffffffULL, 0, TX4927_NUM_PIO); | ||
172 | |||
173 | rbtx4927_gpio_init(); | ||
174 | |||
175 | tx4927_pci_setup(); | ||
176 | } | ||
177 | |||
178 | static void __init rbtx4937_arch_init(void) | ||
179 | { | ||
180 | txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, TX4938_NUM_PIO); | ||
181 | |||
182 | rbtx4927_gpio_init(); | ||
183 | |||
184 | tx4937_pci_setup(); | ||
185 | } | ||
186 | |||
187 | static void toshiba_rbtx4927_restart(char *command) | ||
188 | { | ||
189 | /* enable the s/w reset register */ | ||
190 | writeb(1, rbtx4927_softresetlock_addr); | ||
191 | |||
192 | /* wait for enable to be seen */ | ||
193 | while (!(readb(rbtx4927_softresetlock_addr) & 1)) | ||
194 | ; | ||
195 | |||
196 | /* do a s/w reset */ | ||
197 | writeb(1, rbtx4927_softreset_addr); | ||
198 | |||
199 | /* fallback */ | ||
200 | (*_machine_halt)(); | ||
201 | } | ||
202 | |||
203 | static void __init rbtx4927_clock_init(void); | ||
204 | static void __init rbtx4937_clock_init(void); | ||
205 | |||
206 | static void __init rbtx4927_mem_setup(void) | ||
207 | { | ||
208 | if (TX4927_REV_PCODE() == 0x4927) { | ||
209 | rbtx4927_clock_init(); | ||
210 | tx4927_setup(); | ||
211 | } else { | ||
212 | rbtx4937_clock_init(); | ||
213 | tx4938_setup(); | ||
214 | } | ||
215 | |||
216 | _machine_restart = toshiba_rbtx4927_restart; | ||
217 | |||
218 | #ifdef CONFIG_PCI | ||
219 | txx9_alloc_pci_controller(&txx9_primary_pcic, | ||
220 | RBTX4927_PCIMEM, RBTX4927_PCIMEM_SIZE, | ||
221 | RBTX4927_PCIIO, RBTX4927_PCIIO_SIZE); | ||
222 | txx9_board_pcibios_setup = tx4927_pcibios_setup; | ||
223 | #else | ||
224 | set_io_port_base(KSEG1 + RBTX4927_ISA_IO_OFFSET); | ||
225 | #endif | ||
226 | } | ||
227 | |||
228 | static void __init rbtx4927_clock_init(void) | ||
229 | { | ||
230 | /* | ||
231 | * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz. | ||
232 | * | ||
233 | * For TX4927: | ||
234 | * PCIDIVMODE[12:11]'s initial value is given by S9[4:3] (ON:0, OFF:1). | ||
235 | * CPU 166MHz: PCI 66MHz : PCIDIVMODE: 00 (1/2.5) | ||
236 | * CPU 200MHz: PCI 66MHz : PCIDIVMODE: 01 (1/3) | ||
237 | * CPU 166MHz: PCI 33MHz : PCIDIVMODE: 10 (1/5) | ||
238 | * CPU 200MHz: PCI 33MHz : PCIDIVMODE: 11 (1/6) | ||
239 | * i.e. S9[3]: ON (83MHz), OFF (100MHz) | ||
240 | */ | ||
241 | switch ((unsigned long)__raw_readq(&tx4927_ccfgptr->ccfg) & | ||
242 | TX4927_CCFG_PCIDIVMODE_MASK) { | ||
243 | case TX4927_CCFG_PCIDIVMODE_2_5: | ||
244 | case TX4927_CCFG_PCIDIVMODE_5: | ||
245 | txx9_cpu_clock = 166666666; /* 166MHz */ | ||
246 | break; | ||
247 | default: | ||
248 | txx9_cpu_clock = 200000000; /* 200MHz */ | ||
249 | } | ||
250 | } | ||
251 | |||
252 | static void __init rbtx4937_clock_init(void) | ||
253 | { | ||
254 | /* | ||
255 | * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz. | ||
256 | * | ||
257 | * For TX4937: | ||
258 | * PCIDIVMODE[12:11]'s initial value is given by S1[5:4] (ON:0, OFF:1) | ||
259 | * PCIDIVMODE[10] is 0. | ||
260 | * CPU 266MHz: PCI 33MHz : PCIDIVMODE: 000 (1/8) | ||
261 | * CPU 266MHz: PCI 66MHz : PCIDIVMODE: 001 (1/4) | ||
262 | * CPU 300MHz: PCI 33MHz : PCIDIVMODE: 010 (1/9) | ||
263 | * CPU 300MHz: PCI 66MHz : PCIDIVMODE: 011 (1/4.5) | ||
264 | * CPU 333MHz: PCI 33MHz : PCIDIVMODE: 100 (1/10) | ||
265 | * CPU 333MHz: PCI 66MHz : PCIDIVMODE: 101 (1/5) | ||
266 | */ | ||
267 | switch ((unsigned long)__raw_readq(&tx4938_ccfgptr->ccfg) & | ||
268 | TX4938_CCFG_PCIDIVMODE_MASK) { | ||
269 | case TX4938_CCFG_PCIDIVMODE_8: | ||
270 | case TX4938_CCFG_PCIDIVMODE_4: | ||
271 | txx9_cpu_clock = 266666666; /* 266MHz */ | ||
272 | break; | ||
273 | case TX4938_CCFG_PCIDIVMODE_9: | ||
274 | case TX4938_CCFG_PCIDIVMODE_4_5: | ||
275 | txx9_cpu_clock = 300000000; /* 300MHz */ | ||
276 | break; | ||
277 | default: | ||
278 | txx9_cpu_clock = 333333333; /* 333MHz */ | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static void __init rbtx4927_time_init(void) | ||
283 | { | ||
284 | tx4927_time_init(0); | ||
285 | } | ||
286 | |||
287 | static void __init toshiba_rbtx4927_rtc_init(void) | ||
288 | { | ||
289 | struct resource res = { | ||
290 | .start = RBTX4927_BRAMRTC_BASE - IO_BASE, | ||
291 | .end = RBTX4927_BRAMRTC_BASE - IO_BASE + 0x800 - 1, | ||
292 | .flags = IORESOURCE_MEM, | ||
293 | }; | ||
294 | platform_device_register_simple("rtc-ds1742", -1, &res, 1); | ||
295 | } | ||
296 | |||
297 | static void __init rbtx4927_ne_init(void) | ||
298 | { | ||
299 | struct resource res[] = { | ||
300 | { | ||
301 | .start = RBTX4927_RTL_8019_BASE, | ||
302 | .end = RBTX4927_RTL_8019_BASE + 0x20 - 1, | ||
303 | .flags = IORESOURCE_IO, | ||
304 | }, { | ||
305 | .start = RBTX4927_RTL_8019_IRQ, | ||
306 | .flags = IORESOURCE_IRQ, | ||
307 | } | ||
308 | }; | ||
309 | platform_device_register_simple("ne", -1, res, ARRAY_SIZE(res)); | ||
310 | } | ||
311 | |||
312 | static void __init rbtx4927_mtd_init(void) | ||
313 | { | ||
314 | int i; | ||
315 | |||
316 | for (i = 0; i < 2; i++) | ||
317 | tx4927_mtd_init(i); | ||
318 | } | ||
319 | |||
320 | static void __init rbtx4927_gpioled_init(void) | ||
321 | { | ||
322 | static const struct gpio_led leds[] = { | ||
323 | { .name = "gpioled:green:0", .gpio = 0, .active_low = 1, }, | ||
324 | { .name = "gpioled:green:1", .gpio = 1, .active_low = 1, }, | ||
325 | }; | ||
326 | static struct gpio_led_platform_data pdata = { | ||
327 | .num_leds = ARRAY_SIZE(leds), | ||
328 | .leds = leds, | ||
329 | }; | ||
330 | struct platform_device *pdev = platform_device_alloc("leds-gpio", 0); | ||
331 | |||
332 | if (!pdev) | ||
333 | return; | ||
334 | pdev->dev.platform_data = &pdata; | ||
335 | if (platform_device_add(pdev)) | ||
336 | platform_device_put(pdev); | ||
337 | } | ||
338 | |||
339 | static void __init rbtx4927_device_init(void) | ||
340 | { | ||
341 | toshiba_rbtx4927_rtc_init(); | ||
342 | rbtx4927_ne_init(); | ||
343 | tx4927_wdt_init(); | ||
344 | rbtx4927_mtd_init(); | ||
345 | if (TX4927_REV_PCODE() == 0x4927) { | ||
346 | tx4927_dmac_init(2); | ||
347 | tx4927_aclc_init(0, 1); | ||
348 | } else { | ||
349 | tx4938_dmac_init(0, 2); | ||
350 | tx4938_aclc_init(); | ||
351 | } | ||
352 | platform_device_register_simple("txx9aclc-generic", -1, NULL, 0); | ||
353 | txx9_iocled_init(RBTX4927_LED_ADDR - IO_BASE, -1, 3, 1, "green", NULL); | ||
354 | rbtx4927_gpioled_init(); | ||
355 | } | ||
356 | |||
357 | struct txx9_board_vec rbtx4927_vec __initdata = { | ||
358 | .system = "Toshiba RBTX4927", | ||
359 | .prom_init = rbtx4927_prom_init, | ||
360 | .mem_setup = rbtx4927_mem_setup, | ||
361 | .irq_setup = rbtx4927_irq_setup, | ||
362 | .time_init = rbtx4927_time_init, | ||
363 | .device_init = rbtx4927_device_init, | ||
364 | .arch_init = rbtx4927_arch_init, | ||
365 | #ifdef CONFIG_PCI | ||
366 | .pci_map_irq = rbtx4927_pci_map_irq, | ||
367 | #endif | ||
368 | }; | ||
369 | struct txx9_board_vec rbtx4937_vec __initdata = { | ||
370 | .system = "Toshiba RBTX4937", | ||
371 | .prom_init = rbtx4927_prom_init, | ||
372 | .mem_setup = rbtx4927_mem_setup, | ||
373 | .irq_setup = rbtx4927_irq_setup, | ||
374 | .time_init = rbtx4927_time_init, | ||
375 | .device_init = rbtx4927_device_init, | ||
376 | .arch_init = rbtx4937_arch_init, | ||
377 | #ifdef CONFIG_PCI | ||
378 | .pci_map_irq = rbtx4927_pci_map_irq, | ||
379 | #endif | ||
380 | }; | ||
diff --git a/arch/mips/txx9/rbtx4938/Makefile b/arch/mips/txx9/rbtx4938/Makefile new file mode 100644 index 000000000..08a02aebd --- /dev/null +++ b/arch/mips/txx9/rbtx4938/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | obj-y += prom.o setup.o irq.o | ||
diff --git a/arch/mips/txx9/rbtx4938/irq.c b/arch/mips/txx9/rbtx4938/irq.c new file mode 100644 index 000000000..58cd7a927 --- /dev/null +++ b/arch/mips/txx9/rbtx4938/irq.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * Toshiba RBTX4938 specific interrupt handlers | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * MIPS_CPU_IRQ_BASE+00 Software 0 | ||
15 | * MIPS_CPU_IRQ_BASE+01 Software 1 | ||
16 | * MIPS_CPU_IRQ_BASE+02 Cascade TX4938-CP0 | ||
17 | * MIPS_CPU_IRQ_BASE+03 Multiplexed -- do not use | ||
18 | * MIPS_CPU_IRQ_BASE+04 Multiplexed -- do not use | ||
19 | * MIPS_CPU_IRQ_BASE+05 Multiplexed -- do not use | ||
20 | * MIPS_CPU_IRQ_BASE+06 Multiplexed -- do not use | ||
21 | * MIPS_CPU_IRQ_BASE+07 CPU TIMER | ||
22 | * | ||
23 | * TXX9_IRQ_BASE+00 | ||
24 | * TXX9_IRQ_BASE+01 | ||
25 | * TXX9_IRQ_BASE+02 Cascade RBTX4938-IOC | ||
26 | * TXX9_IRQ_BASE+03 RBTX4938 RTL-8019AS Ethernet | ||
27 | * TXX9_IRQ_BASE+04 | ||
28 | * TXX9_IRQ_BASE+05 TX4938 ETH1 | ||
29 | * TXX9_IRQ_BASE+06 TX4938 ETH0 | ||
30 | * TXX9_IRQ_BASE+07 | ||
31 | * TXX9_IRQ_BASE+08 TX4938 SIO 0 | ||
32 | * TXX9_IRQ_BASE+09 TX4938 SIO 1 | ||
33 | * TXX9_IRQ_BASE+10 TX4938 DMA0 | ||
34 | * TXX9_IRQ_BASE+11 TX4938 DMA1 | ||
35 | * TXX9_IRQ_BASE+12 TX4938 DMA2 | ||
36 | * TXX9_IRQ_BASE+13 TX4938 DMA3 | ||
37 | * TXX9_IRQ_BASE+14 | ||
38 | * TXX9_IRQ_BASE+15 | ||
39 | * TXX9_IRQ_BASE+16 TX4938 PCIC | ||
40 | * TXX9_IRQ_BASE+17 TX4938 TMR0 | ||
41 | * TXX9_IRQ_BASE+18 TX4938 TMR1 | ||
42 | * TXX9_IRQ_BASE+19 TX4938 TMR2 | ||
43 | * TXX9_IRQ_BASE+20 | ||
44 | * TXX9_IRQ_BASE+21 | ||
45 | * TXX9_IRQ_BASE+22 TX4938 PCIERR | ||
46 | * TXX9_IRQ_BASE+23 | ||
47 | * TXX9_IRQ_BASE+24 | ||
48 | * TXX9_IRQ_BASE+25 | ||
49 | * TXX9_IRQ_BASE+26 | ||
50 | * TXX9_IRQ_BASE+27 | ||
51 | * TXX9_IRQ_BASE+28 | ||
52 | * TXX9_IRQ_BASE+29 | ||
53 | * TXX9_IRQ_BASE+30 | ||
54 | * TXX9_IRQ_BASE+31 TX4938 SPI | ||
55 | * | ||
56 | * RBTX4938_IRQ_IOC+00 PCI-D | ||
57 | * RBTX4938_IRQ_IOC+01 PCI-C | ||
58 | * RBTX4938_IRQ_IOC+02 PCI-B | ||
59 | * RBTX4938_IRQ_IOC+03 PCI-A | ||
60 | * RBTX4938_IRQ_IOC+04 RTC | ||
61 | * RBTX4938_IRQ_IOC+05 ATA | ||
62 | * RBTX4938_IRQ_IOC+06 MODEM | ||
63 | * RBTX4938_IRQ_IOC+07 SWINT | ||
64 | */ | ||
65 | #include <linux/init.h> | ||
66 | #include <linux/interrupt.h> | ||
67 | #include <linux/irq.h> | ||
68 | #include <asm/mipsregs.h> | ||
69 | #include <asm/txx9/generic.h> | ||
70 | #include <asm/txx9/rbtx4938.h> | ||
71 | |||
72 | static int toshiba_rbtx4938_irq_nested(int sw_irq) | ||
73 | { | ||
74 | u8 level3; | ||
75 | |||
76 | level3 = readb(rbtx4938_imstat_addr); | ||
77 | if (unlikely(!level3)) | ||
78 | return -1; | ||
79 | /* must use fls so onboard ATA has priority */ | ||
80 | return RBTX4938_IRQ_IOC + __fls8(level3); | ||
81 | } | ||
82 | |||
83 | static void toshiba_rbtx4938_irq_ioc_enable(struct irq_data *d) | ||
84 | { | ||
85 | unsigned char v; | ||
86 | |||
87 | v = readb(rbtx4938_imask_addr); | ||
88 | v |= (1 << (d->irq - RBTX4938_IRQ_IOC)); | ||
89 | writeb(v, rbtx4938_imask_addr); | ||
90 | mmiowb(); | ||
91 | } | ||
92 | |||
93 | static void toshiba_rbtx4938_irq_ioc_disable(struct irq_data *d) | ||
94 | { | ||
95 | unsigned char v; | ||
96 | |||
97 | v = readb(rbtx4938_imask_addr); | ||
98 | v &= ~(1 << (d->irq - RBTX4938_IRQ_IOC)); | ||
99 | writeb(v, rbtx4938_imask_addr); | ||
100 | mmiowb(); | ||
101 | } | ||
102 | |||
103 | #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" | ||
104 | static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { | ||
105 | .name = TOSHIBA_RBTX4938_IOC_NAME, | ||
106 | .irq_mask = toshiba_rbtx4938_irq_ioc_disable, | ||
107 | .irq_unmask = toshiba_rbtx4938_irq_ioc_enable, | ||
108 | }; | ||
109 | |||
110 | static int rbtx4938_irq_dispatch(int pending) | ||
111 | { | ||
112 | int irq; | ||
113 | |||
114 | if (pending & STATUSF_IP7) | ||
115 | irq = MIPS_CPU_IRQ_BASE + 7; | ||
116 | else if (pending & STATUSF_IP2) { | ||
117 | irq = txx9_irq(); | ||
118 | if (irq == RBTX4938_IRQ_IOCINT) | ||
119 | irq = toshiba_rbtx4938_irq_nested(irq); | ||
120 | } else if (pending & STATUSF_IP1) | ||
121 | irq = MIPS_CPU_IRQ_BASE + 0; | ||
122 | else if (pending & STATUSF_IP0) | ||
123 | irq = MIPS_CPU_IRQ_BASE + 1; | ||
124 | else | ||
125 | irq = -1; | ||
126 | return irq; | ||
127 | } | ||
128 | |||
129 | static void __init toshiba_rbtx4938_irq_ioc_init(void) | ||
130 | { | ||
131 | int i; | ||
132 | |||
133 | for (i = RBTX4938_IRQ_IOC; | ||
134 | i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++) | ||
135 | irq_set_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type, | ||
136 | handle_level_irq); | ||
137 | |||
138 | irq_set_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq); | ||
139 | } | ||
140 | |||
141 | void __init rbtx4938_irq_setup(void) | ||
142 | { | ||
143 | txx9_irq_dispatch = rbtx4938_irq_dispatch; | ||
144 | /* Now, interrupt control disabled, */ | ||
145 | /* all IRC interrupts are masked, */ | ||
146 | /* all IRC interrupt mode are Low Active. */ | ||
147 | |||
148 | /* mask all IOC interrupts */ | ||
149 | writeb(0, rbtx4938_imask_addr); | ||
150 | |||
151 | /* clear SoftInt interrupts */ | ||
152 | writeb(0, rbtx4938_softint_addr); | ||
153 | tx4938_irq_init(); | ||
154 | toshiba_rbtx4938_irq_ioc_init(); | ||
155 | /* Onboard 10M Ether: High Active */ | ||
156 | irq_set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH); | ||
157 | } | ||
diff --git a/arch/mips/txx9/rbtx4938/prom.c b/arch/mips/txx9/rbtx4938/prom.c new file mode 100644 index 000000000..0de84716a --- /dev/null +++ b/arch/mips/txx9/rbtx4938/prom.c | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * rbtx4938 specific prom routines | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/memblock.h> | ||
15 | #include <asm/txx9/generic.h> | ||
16 | #include <asm/txx9/rbtx4938.h> | ||
17 | |||
18 | void __init rbtx4938_prom_init(void) | ||
19 | { | ||
20 | memblock_add(0, tx4938_get_mem_size()); | ||
21 | txx9_sio_putchar_init(TX4938_SIO_REG(0) & 0xfffffffffULL); | ||
22 | } | ||
diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c new file mode 100644 index 000000000..e68eb2e7c --- /dev/null +++ b/arch/mips/txx9/rbtx4938/setup.c | |||
@@ -0,0 +1,372 @@ | |||
1 | /* | ||
2 | * Setup pointers to hardware-dependent routines. | ||
3 | * Copyright (C) 2000-2001 Toshiba Corporation | ||
4 | * | ||
5 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
6 | * terms of the GNU General Public License version 2. This program is | ||
7 | * licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/ioport.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/gpio/driver.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/mtd/physmap.h> | ||
20 | |||
21 | #include <asm/reboot.h> | ||
22 | #include <asm/io.h> | ||
23 | #include <asm/txx9/generic.h> | ||
24 | #include <asm/txx9/pci.h> | ||
25 | #include <asm/txx9/rbtx4938.h> | ||
26 | #include <linux/spi/spi.h> | ||
27 | #include <asm/txx9/spi.h> | ||
28 | #include <asm/txx9pio.h> | ||
29 | |||
30 | static void rbtx4938_machine_restart(char *command) | ||
31 | { | ||
32 | local_irq_disable(); | ||
33 | writeb(1, rbtx4938_softresetlock_addr); | ||
34 | writeb(1, rbtx4938_sfvol_addr); | ||
35 | writeb(1, rbtx4938_softreset_addr); | ||
36 | /* fallback */ | ||
37 | (*_machine_halt)(); | ||
38 | } | ||
39 | |||
40 | static void __init rbtx4938_pci_setup(void) | ||
41 | { | ||
42 | #ifdef CONFIG_PCI | ||
43 | int extarb = !(__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCIARB); | ||
44 | struct pci_controller *c = &txx9_primary_pcic; | ||
45 | |||
46 | register_pci_controller(c); | ||
47 | |||
48 | if (__raw_readq(&tx4938_ccfgptr->ccfg) & TX4938_CCFG_PCI66) | ||
49 | txx9_pci_option = | ||
50 | (txx9_pci_option & ~TXX9_PCI_OPT_CLK_MASK) | | ||
51 | TXX9_PCI_OPT_CLK_66; /* already configured */ | ||
52 | |||
53 | /* Reset PCI Bus */ | ||
54 | writeb(0, rbtx4938_pcireset_addr); | ||
55 | /* Reset PCIC */ | ||
56 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
57 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | ||
58 | TXX9_PCI_OPT_CLK_66) | ||
59 | tx4938_pciclk66_setup(); | ||
60 | mdelay(10); | ||
61 | /* clear PCIC reset */ | ||
62 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
63 | writeb(1, rbtx4938_pcireset_addr); | ||
64 | iob(); | ||
65 | |||
66 | tx4938_report_pciclk(); | ||
67 | tx4927_pcic_setup(tx4938_pcicptr, c, extarb); | ||
68 | if ((txx9_pci_option & TXX9_PCI_OPT_CLK_MASK) == | ||
69 | TXX9_PCI_OPT_CLK_AUTO && | ||
70 | txx9_pci66_check(c, 0, 0)) { | ||
71 | /* Reset PCI Bus */ | ||
72 | writeb(0, rbtx4938_pcireset_addr); | ||
73 | /* Reset PCIC */ | ||
74 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
75 | tx4938_pciclk66_setup(); | ||
76 | mdelay(10); | ||
77 | /* clear PCIC reset */ | ||
78 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIRST); | ||
79 | writeb(1, rbtx4938_pcireset_addr); | ||
80 | iob(); | ||
81 | /* Reinitialize PCIC */ | ||
82 | tx4938_report_pciclk(); | ||
83 | tx4927_pcic_setup(tx4938_pcicptr, c, extarb); | ||
84 | } | ||
85 | |||
86 | if (__raw_readq(&tx4938_ccfgptr->pcfg) & | ||
87 | (TX4938_PCFG_ETH0_SEL|TX4938_PCFG_ETH1_SEL)) { | ||
88 | /* Reset PCIC1 */ | ||
89 | txx9_set64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST); | ||
90 | /* PCI1DMD==0 => PCI1CLK==GBUSCLK/2 => PCI66 */ | ||
91 | if (!(__raw_readq(&tx4938_ccfgptr->ccfg) | ||
92 | & TX4938_CCFG_PCI1DMD)) | ||
93 | tx4938_ccfg_set(TX4938_CCFG_PCI1_66); | ||
94 | mdelay(10); | ||
95 | /* clear PCIC1 reset */ | ||
96 | txx9_clear64(&tx4938_ccfgptr->clkctr, TX4938_CLKCTR_PCIC1RST); | ||
97 | tx4938_report_pci1clk(); | ||
98 | |||
99 | /* mem:64K(max), io:64K(max) (enough for ETH0,ETH1) */ | ||
100 | c = txx9_alloc_pci_controller(NULL, 0, 0x10000, 0, 0x10000); | ||
101 | register_pci_controller(c); | ||
102 | tx4927_pcic_setup(tx4938_pcic1ptr, c, 0); | ||
103 | } | ||
104 | tx4938_setup_pcierr_irq(); | ||
105 | #endif /* CONFIG_PCI */ | ||
106 | } | ||
107 | |||
108 | /* SPI support */ | ||
109 | |||
110 | /* chip select for SPI devices */ | ||
111 | #define SEEPROM1_CS 7 /* PIO7 */ | ||
112 | #define SEEPROM2_CS 0 /* IOC */ | ||
113 | #define SEEPROM3_CS 1 /* IOC */ | ||
114 | #define SRTC_CS 2 /* IOC */ | ||
115 | #define SPI_BUSNO 0 | ||
116 | |||
117 | static int __init rbtx4938_ethaddr_init(void) | ||
118 | { | ||
119 | #ifdef CONFIG_PCI | ||
120 | unsigned char dat[17]; | ||
121 | unsigned char sum; | ||
122 | int i; | ||
123 | |||
124 | /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ | ||
125 | if (spi_eeprom_read(SPI_BUSNO, SEEPROM1_CS, 0, dat, sizeof(dat))) { | ||
126 | pr_err("seeprom: read error.\n"); | ||
127 | return -ENODEV; | ||
128 | } else { | ||
129 | if (strcmp(dat, "MAC") != 0) | ||
130 | pr_warn("seeprom: bad signature.\n"); | ||
131 | for (i = 0, sum = 0; i < sizeof(dat); i++) | ||
132 | sum += dat[i]; | ||
133 | if (sum) | ||
134 | pr_warn("seeprom: bad checksum.\n"); | ||
135 | } | ||
136 | tx4938_ethaddr_init(&dat[4], &dat[4 + 6]); | ||
137 | #endif /* CONFIG_PCI */ | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static void __init rbtx4938_spi_setup(void) | ||
142 | { | ||
143 | /* set SPI_SEL */ | ||
144 | txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_SPI_SEL); | ||
145 | } | ||
146 | |||
147 | static struct resource rbtx4938_fpga_resource; | ||
148 | |||
149 | static void __init rbtx4938_time_init(void) | ||
150 | { | ||
151 | tx4938_time_init(0); | ||
152 | } | ||
153 | |||
154 | static void __init rbtx4938_mem_setup(void) | ||
155 | { | ||
156 | unsigned long long pcfg; | ||
157 | |||
158 | if (txx9_master_clock == 0) | ||
159 | txx9_master_clock = 25000000; /* 25MHz */ | ||
160 | |||
161 | tx4938_setup(); | ||
162 | |||
163 | #ifdef CONFIG_PCI | ||
164 | txx9_alloc_pci_controller(&txx9_primary_pcic, 0, 0, 0, 0); | ||
165 | txx9_board_pcibios_setup = tx4927_pcibios_setup; | ||
166 | #else | ||
167 | set_io_port_base(RBTX4938_ETHER_BASE); | ||
168 | #endif | ||
169 | |||
170 | tx4938_sio_init(7372800, 0); | ||
171 | |||
172 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61 | ||
173 | pr_info("PIOSEL: disabling both ATA and NAND selection\n"); | ||
174 | txx9_clear64(&tx4938_ccfgptr->pcfg, | ||
175 | TX4938_PCFG_NDF_SEL | TX4938_PCFG_ATA_SEL); | ||
176 | #endif | ||
177 | |||
178 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND | ||
179 | pr_info("PIOSEL: enabling NAND selection\n"); | ||
180 | txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); | ||
181 | txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); | ||
182 | #endif | ||
183 | |||
184 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA | ||
185 | pr_info("PIOSEL: enabling ATA selection\n"); | ||
186 | txx9_set64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_ATA_SEL); | ||
187 | txx9_clear64(&tx4938_ccfgptr->pcfg, TX4938_PCFG_NDF_SEL); | ||
188 | #endif | ||
189 | |||
190 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_KEEP | ||
191 | pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); | ||
192 | pr_info("PIOSEL: NAND %s, ATA %s\n", | ||
193 | (pcfg & TX4938_PCFG_NDF_SEL) ? "enabled" : "disabled", | ||
194 | (pcfg & TX4938_PCFG_ATA_SEL) ? "enabled" : "disabled"); | ||
195 | #endif | ||
196 | |||
197 | rbtx4938_spi_setup(); | ||
198 | pcfg = ____raw_readq(&tx4938_ccfgptr->pcfg); /* updated */ | ||
199 | /* fixup piosel */ | ||
200 | if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) == | ||
201 | TX4938_PCFG_ATA_SEL) | ||
202 | writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x04, | ||
203 | rbtx4938_piosel_addr); | ||
204 | else if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) == | ||
205 | TX4938_PCFG_NDF_SEL) | ||
206 | writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x08, | ||
207 | rbtx4938_piosel_addr); | ||
208 | else | ||
209 | writeb(readb(rbtx4938_piosel_addr) & ~(0x08 | 0x04), | ||
210 | rbtx4938_piosel_addr); | ||
211 | |||
212 | rbtx4938_fpga_resource.name = "FPGA Registers"; | ||
213 | rbtx4938_fpga_resource.start = CPHYSADDR(RBTX4938_FPGA_REG_ADDR); | ||
214 | rbtx4938_fpga_resource.end = CPHYSADDR(RBTX4938_FPGA_REG_ADDR) + 0xffff; | ||
215 | rbtx4938_fpga_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
216 | if (request_resource(&txx9_ce_res[2], &rbtx4938_fpga_resource)) | ||
217 | pr_err("request resource for fpga failed\n"); | ||
218 | |||
219 | _machine_restart = rbtx4938_machine_restart; | ||
220 | |||
221 | writeb(0xff, rbtx4938_led_addr); | ||
222 | pr_info("RBTX4938 --- FPGA(Rev %02x) DIPSW:%02x,%02x\n", | ||
223 | readb(rbtx4938_fpga_rev_addr), | ||
224 | readb(rbtx4938_dipsw_addr), readb(rbtx4938_bdipsw_addr)); | ||
225 | } | ||
226 | |||
227 | static void __init rbtx4938_ne_init(void) | ||
228 | { | ||
229 | struct resource res[] = { | ||
230 | { | ||
231 | .start = RBTX4938_RTL_8019_BASE, | ||
232 | .end = RBTX4938_RTL_8019_BASE + 0x20 - 1, | ||
233 | .flags = IORESOURCE_IO, | ||
234 | }, { | ||
235 | .start = RBTX4938_RTL_8019_IRQ, | ||
236 | .flags = IORESOURCE_IRQ, | ||
237 | } | ||
238 | }; | ||
239 | platform_device_register_simple("ne", -1, res, ARRAY_SIZE(res)); | ||
240 | } | ||
241 | |||
242 | static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock); | ||
243 | |||
244 | static void rbtx4938_spi_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
245 | int value) | ||
246 | { | ||
247 | u8 val; | ||
248 | unsigned long flags; | ||
249 | spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags); | ||
250 | val = readb(rbtx4938_spics_addr); | ||
251 | if (value) | ||
252 | val |= 1 << offset; | ||
253 | else | ||
254 | val &= ~(1 << offset); | ||
255 | writeb(val, rbtx4938_spics_addr); | ||
256 | mmiowb(); | ||
257 | spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags); | ||
258 | } | ||
259 | |||
260 | static int rbtx4938_spi_gpio_dir_out(struct gpio_chip *chip, | ||
261 | unsigned int offset, int value) | ||
262 | { | ||
263 | rbtx4938_spi_gpio_set(chip, offset, value); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static struct gpio_chip rbtx4938_spi_gpio_chip = { | ||
268 | .set = rbtx4938_spi_gpio_set, | ||
269 | .direction_output = rbtx4938_spi_gpio_dir_out, | ||
270 | .label = "RBTX4938-SPICS", | ||
271 | .base = 16, | ||
272 | .ngpio = 3, | ||
273 | }; | ||
274 | |||
275 | static int __init rbtx4938_spi_init(void) | ||
276 | { | ||
277 | struct spi_board_info srtc_info = { | ||
278 | .modalias = "rtc-rs5c348", | ||
279 | .max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */ | ||
280 | .bus_num = 0, | ||
281 | .chip_select = 16 + SRTC_CS, | ||
282 | /* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS */ | ||
283 | .mode = SPI_MODE_1 | SPI_CS_HIGH, | ||
284 | }; | ||
285 | spi_register_board_info(&srtc_info, 1); | ||
286 | spi_eeprom_register(SPI_BUSNO, SEEPROM1_CS, 128); | ||
287 | spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM2_CS, 128); | ||
288 | spi_eeprom_register(SPI_BUSNO, 16 + SEEPROM3_CS, 128); | ||
289 | gpio_request(16 + SRTC_CS, "rtc-rs5c348"); | ||
290 | gpio_direction_output(16 + SRTC_CS, 0); | ||
291 | gpio_request(SEEPROM1_CS, "seeprom1"); | ||
292 | gpio_direction_output(SEEPROM1_CS, 1); | ||
293 | gpio_request(16 + SEEPROM2_CS, "seeprom2"); | ||
294 | gpio_direction_output(16 + SEEPROM2_CS, 1); | ||
295 | gpio_request(16 + SEEPROM3_CS, "seeprom3"); | ||
296 | gpio_direction_output(16 + SEEPROM3_CS, 1); | ||
297 | tx4938_spi_init(SPI_BUSNO); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static void __init rbtx4938_mtd_init(void) | ||
302 | { | ||
303 | struct physmap_flash_data pdata = { | ||
304 | .width = 4, | ||
305 | }; | ||
306 | |||
307 | switch (readb(rbtx4938_bdipsw_addr) & 7) { | ||
308 | case 0: | ||
309 | /* Boot */ | ||
310 | txx9_physmap_flash_init(0, 0x1fc00000, 0x400000, &pdata); | ||
311 | /* System */ | ||
312 | txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); | ||
313 | break; | ||
314 | case 1: | ||
315 | /* System */ | ||
316 | txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); | ||
317 | /* Boot */ | ||
318 | txx9_physmap_flash_init(1, 0x1ec00000, 0x400000, &pdata); | ||
319 | break; | ||
320 | case 2: | ||
321 | /* Ext */ | ||
322 | txx9_physmap_flash_init(0, 0x1f000000, 0x1000000, &pdata); | ||
323 | /* System */ | ||
324 | txx9_physmap_flash_init(1, 0x1e000000, 0x1000000, &pdata); | ||
325 | /* Boot */ | ||
326 | txx9_physmap_flash_init(2, 0x1dc00000, 0x400000, &pdata); | ||
327 | break; | ||
328 | case 3: | ||
329 | /* Boot */ | ||
330 | txx9_physmap_flash_init(1, 0x1bc00000, 0x400000, &pdata); | ||
331 | /* System */ | ||
332 | txx9_physmap_flash_init(2, 0x1a000000, 0x1000000, &pdata); | ||
333 | break; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | static void __init rbtx4938_arch_init(void) | ||
338 | { | ||
339 | txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, TX4938_NUM_PIO); | ||
340 | gpiochip_add_data(&rbtx4938_spi_gpio_chip, NULL); | ||
341 | rbtx4938_pci_setup(); | ||
342 | rbtx4938_spi_init(); | ||
343 | } | ||
344 | |||
345 | static void __init rbtx4938_device_init(void) | ||
346 | { | ||
347 | rbtx4938_ethaddr_init(); | ||
348 | rbtx4938_ne_init(); | ||
349 | tx4938_wdt_init(); | ||
350 | rbtx4938_mtd_init(); | ||
351 | /* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */ | ||
352 | tx4938_ndfmc_init(10, 35); | ||
353 | tx4938_ata_init(RBTX4938_IRQ_IOC_ATA, 0, 1); | ||
354 | tx4938_dmac_init(0, 2); | ||
355 | tx4938_aclc_init(); | ||
356 | platform_device_register_simple("txx9aclc-generic", -1, NULL, 0); | ||
357 | tx4938_sramc_init(); | ||
358 | txx9_iocled_init(RBTX4938_LED_ADDR - IO_BASE, -1, 8, 1, "green", NULL); | ||
359 | } | ||
360 | |||
361 | struct txx9_board_vec rbtx4938_vec __initdata = { | ||
362 | .system = "Toshiba RBTX4938", | ||
363 | .prom_init = rbtx4938_prom_init, | ||
364 | .mem_setup = rbtx4938_mem_setup, | ||
365 | .irq_setup = rbtx4938_irq_setup, | ||
366 | .time_init = rbtx4938_time_init, | ||
367 | .device_init = rbtx4938_device_init, | ||
368 | .arch_init = rbtx4938_arch_init, | ||
369 | #ifdef CONFIG_PCI | ||
370 | .pci_map_irq = rbtx4938_pci_map_irq, | ||
371 | #endif | ||
372 | }; | ||
diff --git a/arch/mips/txx9/rbtx4939/Makefile b/arch/mips/txx9/rbtx4939/Makefile new file mode 100644 index 000000000..840496e7a --- /dev/null +++ b/arch/mips/txx9/rbtx4939/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0-only | ||
2 | obj-y += irq.o setup.o prom.o | ||
diff --git a/arch/mips/txx9/rbtx4939/irq.c b/arch/mips/txx9/rbtx4939/irq.c new file mode 100644 index 000000000..69a80616f --- /dev/null +++ b/arch/mips/txx9/rbtx4939/irq.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * Toshiba RBTX4939 interrupt routines | ||
3 | * Based on linux/arch/mips/txx9/rbtx4938/irq.c, | ||
4 | * and RBTX49xx patch from CELF patch archive. | ||
5 | * | ||
6 | * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation | ||
7 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <asm/mipsregs.h> | ||
16 | #include <asm/txx9/rbtx4939.h> | ||
17 | |||
18 | /* | ||
19 | * RBTX4939 IOC controller definition | ||
20 | */ | ||
21 | |||
22 | static void rbtx4939_ioc_irq_unmask(struct irq_data *d) | ||
23 | { | ||
24 | int ioc_nr = d->irq - RBTX4939_IRQ_IOC; | ||
25 | |||
26 | writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr); | ||
27 | } | ||
28 | |||
29 | static void rbtx4939_ioc_irq_mask(struct irq_data *d) | ||
30 | { | ||
31 | int ioc_nr = d->irq - RBTX4939_IRQ_IOC; | ||
32 | |||
33 | writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr); | ||
34 | mmiowb(); | ||
35 | } | ||
36 | |||
37 | static struct irq_chip rbtx4939_ioc_irq_chip = { | ||
38 | .name = "IOC", | ||
39 | .irq_mask = rbtx4939_ioc_irq_mask, | ||
40 | .irq_unmask = rbtx4939_ioc_irq_unmask, | ||
41 | }; | ||
42 | |||
43 | |||
44 | static inline int rbtx4939_ioc_irqroute(void) | ||
45 | { | ||
46 | unsigned char istat = readb(rbtx4939_ifac2_addr); | ||
47 | |||
48 | if (unlikely(istat == 0)) | ||
49 | return -1; | ||
50 | return RBTX4939_IRQ_IOC + __fls8(istat); | ||
51 | } | ||
52 | |||
53 | static int rbtx4939_irq_dispatch(int pending) | ||
54 | { | ||
55 | int irq; | ||
56 | |||
57 | if (pending & CAUSEF_IP7) | ||
58 | return MIPS_CPU_IRQ_BASE + 7; | ||
59 | irq = tx4939_irq(); | ||
60 | if (likely(irq >= 0)) { | ||
61 | /* redirect IOC interrupts */ | ||
62 | switch (irq) { | ||
63 | case RBTX4939_IRQ_IOCINT: | ||
64 | irq = rbtx4939_ioc_irqroute(); | ||
65 | break; | ||
66 | } | ||
67 | } else if (pending & CAUSEF_IP0) | ||
68 | irq = MIPS_CPU_IRQ_BASE + 0; | ||
69 | else if (pending & CAUSEF_IP1) | ||
70 | irq = MIPS_CPU_IRQ_BASE + 1; | ||
71 | else | ||
72 | irq = -1; | ||
73 | return irq; | ||
74 | } | ||
75 | |||
76 | void __init rbtx4939_irq_setup(void) | ||
77 | { | ||
78 | int i; | ||
79 | |||
80 | /* mask all IOC interrupts */ | ||
81 | writeb(0, rbtx4939_ien_addr); | ||
82 | |||
83 | /* clear SoftInt interrupts */ | ||
84 | writeb(0, rbtx4939_softint_addr); | ||
85 | |||
86 | txx9_irq_dispatch = rbtx4939_irq_dispatch; | ||
87 | |||
88 | tx4939_irq_init(); | ||
89 | for (i = RBTX4939_IRQ_IOC; | ||
90 | i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++) | ||
91 | irq_set_chip_and_handler(i, &rbtx4939_ioc_irq_chip, | ||
92 | handle_level_irq); | ||
93 | |||
94 | irq_set_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq); | ||
95 | } | ||
diff --git a/arch/mips/txx9/rbtx4939/prom.c b/arch/mips/txx9/rbtx4939/prom.c new file mode 100644 index 000000000..ba25ba1bd --- /dev/null +++ b/arch/mips/txx9/rbtx4939/prom.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * rbtx4939 specific prom routines | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | */ | ||
8 | |||
9 | #include <linux/init.h> | ||
10 | #include <linux/memblock.h> | ||
11 | #include <asm/txx9/generic.h> | ||
12 | #include <asm/txx9/rbtx4939.h> | ||
13 | |||
14 | void __init rbtx4939_prom_init(void) | ||
15 | { | ||
16 | unsigned long start, size; | ||
17 | u64 win; | ||
18 | int i; | ||
19 | |||
20 | for (i = 0; i < 4; i++) { | ||
21 | if (!((__u32)____raw_readq(&tx4939_ddrcptr->winen) & (1 << i))) | ||
22 | continue; | ||
23 | win = ____raw_readq(&tx4939_ddrcptr->win[i]); | ||
24 | start = (unsigned long)(win >> 48); | ||
25 | size = (((unsigned long)(win >> 32) & 0xffff) + 1) - start; | ||
26 | memblock_add(start << 20, size << 20); | ||
27 | } | ||
28 | txx9_sio_putchar_init(TX4939_SIO_REG(0) & 0xfffffffffULL); | ||
29 | } | ||
diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c new file mode 100644 index 000000000..ef29a9c2f --- /dev/null +++ b/arch/mips/txx9/rbtx4939/setup.c | |||
@@ -0,0 +1,554 @@ | |||
1 | /* | ||
2 | * Toshiba RBTX4939 setup routines. | ||
3 | * Based on linux/arch/mips/txx9/rbtx4938/setup.c, | ||
4 | * and RBTX49xx patch from CELF patch archive. | ||
5 | * | ||
6 | * Copyright (C) 2000-2001,2005-2007 Toshiba Corporation | ||
7 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/export.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/leds.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/smc91x.h> | ||
21 | #include <linux/mtd/mtd.h> | ||
22 | #include <linux/mtd/partitions.h> | ||
23 | #include <linux/mtd/map.h> | ||
24 | #include <asm/reboot.h> | ||
25 | #include <asm/txx9/generic.h> | ||
26 | #include <asm/txx9/pci.h> | ||
27 | #include <asm/txx9/rbtx4939.h> | ||
28 | |||
29 | static void rbtx4939_machine_restart(char *command) | ||
30 | { | ||
31 | local_irq_disable(); | ||
32 | writeb(1, rbtx4939_reseten_addr); | ||
33 | writeb(1, rbtx4939_softreset_addr); | ||
34 | while (1) | ||
35 | ; | ||
36 | } | ||
37 | |||
38 | static void __init rbtx4939_time_init(void) | ||
39 | { | ||
40 | tx4939_time_init(0); | ||
41 | } | ||
42 | |||
43 | #if defined(__BIG_ENDIAN) && IS_ENABLED(CONFIG_SMC91X) | ||
44 | #define HAVE_RBTX4939_IOSWAB | ||
45 | #define IS_CE1_ADDR(addr) \ | ||
46 | ((((unsigned long)(addr) - IO_BASE) & 0xfff00000) == TXX9_CE(1)) | ||
47 | static u16 rbtx4939_ioswabw(volatile u16 *a, u16 x) | ||
48 | { | ||
49 | return IS_CE1_ADDR(a) ? x : le16_to_cpu(x); | ||
50 | } | ||
51 | static u16 rbtx4939_mem_ioswabw(volatile u16 *a, u16 x) | ||
52 | { | ||
53 | return !IS_CE1_ADDR(a) ? x : le16_to_cpu(x); | ||
54 | } | ||
55 | #endif /* __BIG_ENDIAN && CONFIG_SMC91X */ | ||
56 | |||
57 | static void __init rbtx4939_pci_setup(void) | ||
58 | { | ||
59 | #ifdef CONFIG_PCI | ||
60 | int extarb = !(__raw_readq(&tx4939_ccfgptr->ccfg) & TX4939_CCFG_PCIARB); | ||
61 | struct pci_controller *c = &txx9_primary_pcic; | ||
62 | |||
63 | register_pci_controller(c); | ||
64 | |||
65 | tx4939_report_pciclk(); | ||
66 | tx4927_pcic_setup(tx4939_pcicptr, c, extarb); | ||
67 | if (!(__raw_readq(&tx4939_ccfgptr->pcfg) & TX4939_PCFG_ATA1MODE) && | ||
68 | (__raw_readq(&tx4939_ccfgptr->pcfg) & | ||
69 | (TX4939_PCFG_ET0MODE | TX4939_PCFG_ET1MODE))) { | ||
70 | tx4939_report_pci1clk(); | ||
71 | |||
72 | /* mem:64K(max), io:64K(max) (enough for ETH0,ETH1) */ | ||
73 | c = txx9_alloc_pci_controller(NULL, 0, 0x10000, 0, 0x10000); | ||
74 | register_pci_controller(c); | ||
75 | tx4927_pcic_setup(tx4939_pcic1ptr, c, 0); | ||
76 | } | ||
77 | |||
78 | tx4939_setup_pcierr_irq(); | ||
79 | #endif /* CONFIG_PCI */ | ||
80 | } | ||
81 | |||
82 | static unsigned long long default_ebccr[] __initdata = { | ||
83 | 0x01c0000000007608ULL, /* 64M ROM */ | ||
84 | 0x017f000000007049ULL, /* 1M IOC */ | ||
85 | 0x0180000000408608ULL, /* ISA */ | ||
86 | 0, | ||
87 | }; | ||
88 | |||
89 | static void __init rbtx4939_ebusc_setup(void) | ||
90 | { | ||
91 | int i; | ||
92 | unsigned int sp; | ||
93 | |||
94 | /* use user-configured speed */ | ||
95 | sp = TX4939_EBUSC_CR(0) & 0x30; | ||
96 | default_ebccr[0] |= sp; | ||
97 | default_ebccr[1] |= sp; | ||
98 | default_ebccr[2] |= sp; | ||
99 | /* initialise by myself */ | ||
100 | for (i = 0; i < ARRAY_SIZE(default_ebccr); i++) { | ||
101 | if (default_ebccr[i]) | ||
102 | ____raw_writeq(default_ebccr[i], | ||
103 | &tx4939_ebuscptr->cr[i]); | ||
104 | else | ||
105 | ____raw_writeq(____raw_readq(&tx4939_ebuscptr->cr[i]) | ||
106 | & ~8, | ||
107 | &tx4939_ebuscptr->cr[i]); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static void __init rbtx4939_update_ioc_pen(void) | ||
112 | { | ||
113 | __u64 pcfg = ____raw_readq(&tx4939_ccfgptr->pcfg); | ||
114 | __u64 ccfg = ____raw_readq(&tx4939_ccfgptr->ccfg); | ||
115 | __u8 pe1 = readb(rbtx4939_pe1_addr); | ||
116 | __u8 pe2 = readb(rbtx4939_pe2_addr); | ||
117 | __u8 pe3 = readb(rbtx4939_pe3_addr); | ||
118 | if (pcfg & TX4939_PCFG_ATA0MODE) | ||
119 | pe1 |= RBTX4939_PE1_ATA(0); | ||
120 | else | ||
121 | pe1 &= ~RBTX4939_PE1_ATA(0); | ||
122 | if (pcfg & TX4939_PCFG_ATA1MODE) { | ||
123 | pe1 |= RBTX4939_PE1_ATA(1); | ||
124 | pe1 &= ~(RBTX4939_PE1_RMII(0) | RBTX4939_PE1_RMII(1)); | ||
125 | } else { | ||
126 | pe1 &= ~RBTX4939_PE1_ATA(1); | ||
127 | if (pcfg & TX4939_PCFG_ET0MODE) | ||
128 | pe1 |= RBTX4939_PE1_RMII(0); | ||
129 | else | ||
130 | pe1 &= ~RBTX4939_PE1_RMII(0); | ||
131 | if (pcfg & TX4939_PCFG_ET1MODE) | ||
132 | pe1 |= RBTX4939_PE1_RMII(1); | ||
133 | else | ||
134 | pe1 &= ~RBTX4939_PE1_RMII(1); | ||
135 | } | ||
136 | if (ccfg & TX4939_CCFG_PTSEL) | ||
137 | pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P | | ||
138 | RBTX4939_PE3_VP_S); | ||
139 | else { | ||
140 | __u64 vmode = pcfg & | ||
141 | (TX4939_PCFG_VSSMODE | TX4939_PCFG_VPSMODE); | ||
142 | if (vmode == 0) | ||
143 | pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_P | | ||
144 | RBTX4939_PE3_VP_S); | ||
145 | else if (vmode == TX4939_PCFG_VPSMODE) { | ||
146 | pe3 |= RBTX4939_PE3_VP_P; | ||
147 | pe3 &= ~(RBTX4939_PE3_VP | RBTX4939_PE3_VP_S); | ||
148 | } else if (vmode == TX4939_PCFG_VSSMODE) { | ||
149 | pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_S; | ||
150 | pe3 &= ~RBTX4939_PE3_VP_P; | ||
151 | } else { | ||
152 | pe3 |= RBTX4939_PE3_VP | RBTX4939_PE3_VP_P; | ||
153 | pe3 &= ~RBTX4939_PE3_VP_S; | ||
154 | } | ||
155 | } | ||
156 | if (pcfg & TX4939_PCFG_SPIMODE) { | ||
157 | if (pcfg & TX4939_PCFG_SIO2MODE_GPIO) | ||
158 | pe2 &= ~(RBTX4939_PE2_SIO2 | RBTX4939_PE2_SIO0); | ||
159 | else { | ||
160 | if (pcfg & TX4939_PCFG_SIO2MODE_SIO2) { | ||
161 | pe2 |= RBTX4939_PE2_SIO2; | ||
162 | pe2 &= ~RBTX4939_PE2_SIO0; | ||
163 | } else { | ||
164 | pe2 |= RBTX4939_PE2_SIO0; | ||
165 | pe2 &= ~RBTX4939_PE2_SIO2; | ||
166 | } | ||
167 | } | ||
168 | if (pcfg & TX4939_PCFG_SIO3MODE) | ||
169 | pe2 |= RBTX4939_PE2_SIO3; | ||
170 | else | ||
171 | pe2 &= ~RBTX4939_PE2_SIO3; | ||
172 | pe2 &= ~RBTX4939_PE2_SPI; | ||
173 | } else { | ||
174 | pe2 |= RBTX4939_PE2_SPI; | ||
175 | pe2 &= ~(RBTX4939_PE2_SIO3 | RBTX4939_PE2_SIO2 | | ||
176 | RBTX4939_PE2_SIO0); | ||
177 | } | ||
178 | if ((pcfg & TX4939_PCFG_I2SMODE_MASK) == TX4939_PCFG_I2SMODE_GPIO) | ||
179 | pe2 |= RBTX4939_PE2_GPIO; | ||
180 | else | ||
181 | pe2 &= ~RBTX4939_PE2_GPIO; | ||
182 | writeb(pe1, rbtx4939_pe1_addr); | ||
183 | writeb(pe2, rbtx4939_pe2_addr); | ||
184 | writeb(pe3, rbtx4939_pe3_addr); | ||
185 | } | ||
186 | |||
187 | #define RBTX4939_MAX_7SEGLEDS 8 | ||
188 | |||
189 | #if IS_BUILTIN(CONFIG_LEDS_CLASS) | ||
190 | static u8 led_val[RBTX4939_MAX_7SEGLEDS]; | ||
191 | struct rbtx4939_led_data { | ||
192 | struct led_classdev cdev; | ||
193 | char name[32]; | ||
194 | unsigned int num; | ||
195 | }; | ||
196 | |||
197 | /* Use "dot" in 7seg LEDs */ | ||
198 | static void rbtx4939_led_brightness_set(struct led_classdev *led_cdev, | ||
199 | enum led_brightness value) | ||
200 | { | ||
201 | struct rbtx4939_led_data *led_dat = | ||
202 | container_of(led_cdev, struct rbtx4939_led_data, cdev); | ||
203 | unsigned int num = led_dat->num; | ||
204 | unsigned long flags; | ||
205 | |||
206 | local_irq_save(flags); | ||
207 | led_val[num] = (led_val[num] & 0x7f) | (value ? 0x80 : 0); | ||
208 | writeb(led_val[num], rbtx4939_7seg_addr(num / 4, num % 4)); | ||
209 | local_irq_restore(flags); | ||
210 | } | ||
211 | |||
212 | static int __init rbtx4939_led_probe(struct platform_device *pdev) | ||
213 | { | ||
214 | struct rbtx4939_led_data *leds_data; | ||
215 | int i; | ||
216 | static char *default_triggers[] __initdata = { | ||
217 | "heartbeat", | ||
218 | "disk-activity", | ||
219 | "nand-disk", | ||
220 | }; | ||
221 | |||
222 | leds_data = kcalloc(RBTX4939_MAX_7SEGLEDS, sizeof(*leds_data), | ||
223 | GFP_KERNEL); | ||
224 | if (!leds_data) | ||
225 | return -ENOMEM; | ||
226 | for (i = 0; i < RBTX4939_MAX_7SEGLEDS; i++) { | ||
227 | int rc; | ||
228 | struct rbtx4939_led_data *led_dat = &leds_data[i]; | ||
229 | |||
230 | led_dat->num = i; | ||
231 | led_dat->cdev.brightness_set = rbtx4939_led_brightness_set; | ||
232 | sprintf(led_dat->name, "rbtx4939:amber:%u", i); | ||
233 | led_dat->cdev.name = led_dat->name; | ||
234 | if (i < ARRAY_SIZE(default_triggers)) | ||
235 | led_dat->cdev.default_trigger = default_triggers[i]; | ||
236 | rc = led_classdev_register(&pdev->dev, &led_dat->cdev); | ||
237 | if (rc < 0) | ||
238 | return rc; | ||
239 | led_dat->cdev.brightness_set(&led_dat->cdev, 0); | ||
240 | } | ||
241 | return 0; | ||
242 | |||
243 | } | ||
244 | |||
245 | static struct platform_driver rbtx4939_led_driver = { | ||
246 | .driver = { | ||
247 | .name = "rbtx4939-led", | ||
248 | }, | ||
249 | }; | ||
250 | |||
251 | static void __init rbtx4939_led_setup(void) | ||
252 | { | ||
253 | platform_device_register_simple("rbtx4939-led", -1, NULL, 0); | ||
254 | platform_driver_probe(&rbtx4939_led_driver, rbtx4939_led_probe); | ||
255 | } | ||
256 | #else | ||
257 | static inline void rbtx4939_led_setup(void) | ||
258 | { | ||
259 | } | ||
260 | #endif | ||
261 | |||
262 | static void __rbtx4939_7segled_putc(unsigned int pos, unsigned char val) | ||
263 | { | ||
264 | #if IS_BUILTIN(CONFIG_LEDS_CLASS) | ||
265 | unsigned long flags; | ||
266 | local_irq_save(flags); | ||
267 | /* bit7: reserved for LED class */ | ||
268 | led_val[pos] = (led_val[pos] & 0x80) | (val & 0x7f); | ||
269 | val = led_val[pos]; | ||
270 | local_irq_restore(flags); | ||
271 | #endif | ||
272 | writeb(val, rbtx4939_7seg_addr(pos / 4, pos % 4)); | ||
273 | } | ||
274 | |||
275 | static void rbtx4939_7segled_putc(unsigned int pos, unsigned char val) | ||
276 | { | ||
277 | /* convert from map_to_seg7() notation */ | ||
278 | val = (val & 0x88) | | ||
279 | ((val & 0x40) >> 6) | | ||
280 | ((val & 0x20) >> 4) | | ||
281 | ((val & 0x10) >> 2) | | ||
282 | ((val & 0x04) << 2) | | ||
283 | ((val & 0x02) << 4) | | ||
284 | ((val & 0x01) << 6); | ||
285 | __rbtx4939_7segled_putc(pos, val); | ||
286 | } | ||
287 | |||
288 | #if IS_ENABLED(CONFIG_MTD_RBTX4939) | ||
289 | /* special mapping for boot rom */ | ||
290 | static unsigned long rbtx4939_flash_fixup_ofs(unsigned long ofs) | ||
291 | { | ||
292 | u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f; | ||
293 | unsigned char shift; | ||
294 | |||
295 | if (bdipsw & 8) { | ||
296 | /* BOOT Mode: USER ROM1 / USER ROM2 */ | ||
297 | shift = bdipsw & 3; | ||
298 | /* rotate A[23:22] */ | ||
299 | return (ofs & ~0xc00000) | ((((ofs >> 22) + shift) & 3) << 22); | ||
300 | } | ||
301 | #ifdef __BIG_ENDIAN | ||
302 | if (bdipsw == 0) | ||
303 | /* BOOT Mode: Monitor ROM */ | ||
304 | ofs ^= 0x400000; /* swap A[22] */ | ||
305 | #endif | ||
306 | return ofs; | ||
307 | } | ||
308 | |||
309 | static map_word rbtx4939_flash_read16(struct map_info *map, unsigned long ofs) | ||
310 | { | ||
311 | map_word r; | ||
312 | |||
313 | ofs = rbtx4939_flash_fixup_ofs(ofs); | ||
314 | r.x[0] = __raw_readw(map->virt + ofs); | ||
315 | return r; | ||
316 | } | ||
317 | |||
318 | static void rbtx4939_flash_write16(struct map_info *map, const map_word datum, | ||
319 | unsigned long ofs) | ||
320 | { | ||
321 | ofs = rbtx4939_flash_fixup_ofs(ofs); | ||
322 | __raw_writew(datum.x[0], map->virt + ofs); | ||
323 | mb(); /* see inline_map_write() in mtd/map.h */ | ||
324 | } | ||
325 | |||
326 | static void rbtx4939_flash_copy_from(struct map_info *map, void *to, | ||
327 | unsigned long from, ssize_t len) | ||
328 | { | ||
329 | u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f; | ||
330 | unsigned char shift; | ||
331 | ssize_t curlen; | ||
332 | |||
333 | from += (unsigned long)map->virt; | ||
334 | if (bdipsw & 8) { | ||
335 | /* BOOT Mode: USER ROM1 / USER ROM2 */ | ||
336 | shift = bdipsw & 3; | ||
337 | while (len) { | ||
338 | curlen = min_t(unsigned long, len, | ||
339 | 0x400000 - (from & (0x400000 - 1))); | ||
340 | memcpy(to, | ||
341 | (void *)((from & ~0xc00000) | | ||
342 | ((((from >> 22) + shift) & 3) << 22)), | ||
343 | curlen); | ||
344 | len -= curlen; | ||
345 | from += curlen; | ||
346 | to += curlen; | ||
347 | } | ||
348 | return; | ||
349 | } | ||
350 | #ifdef __BIG_ENDIAN | ||
351 | if (bdipsw == 0) { | ||
352 | /* BOOT Mode: Monitor ROM */ | ||
353 | while (len) { | ||
354 | curlen = min_t(unsigned long, len, | ||
355 | 0x400000 - (from & (0x400000 - 1))); | ||
356 | memcpy(to, (void *)(from ^ 0x400000), curlen); | ||
357 | len -= curlen; | ||
358 | from += curlen; | ||
359 | to += curlen; | ||
360 | } | ||
361 | return; | ||
362 | } | ||
363 | #endif | ||
364 | memcpy(to, (void *)from, len); | ||
365 | } | ||
366 | |||
367 | static void rbtx4939_flash_map_init(struct map_info *map) | ||
368 | { | ||
369 | map->read = rbtx4939_flash_read16; | ||
370 | map->write = rbtx4939_flash_write16; | ||
371 | map->copy_from = rbtx4939_flash_copy_from; | ||
372 | } | ||
373 | |||
374 | static void __init rbtx4939_mtd_init(void) | ||
375 | { | ||
376 | static struct { | ||
377 | struct platform_device dev; | ||
378 | struct resource res; | ||
379 | struct rbtx4939_flash_data data; | ||
380 | } pdevs[4]; | ||
381 | int i; | ||
382 | static char names[4][8]; | ||
383 | static struct mtd_partition parts[4]; | ||
384 | struct rbtx4939_flash_data *boot_pdata = &pdevs[0].data; | ||
385 | u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f; | ||
386 | |||
387 | if (bdipsw & 8) { | ||
388 | /* BOOT Mode: USER ROM1 / USER ROM2 */ | ||
389 | boot_pdata->nr_parts = 4; | ||
390 | for (i = 0; i < boot_pdata->nr_parts; i++) { | ||
391 | sprintf(names[i], "img%d", 4 - i); | ||
392 | parts[i].name = names[i]; | ||
393 | parts[i].size = 0x400000; | ||
394 | parts[i].offset = MTDPART_OFS_NXTBLK; | ||
395 | } | ||
396 | } else if (bdipsw == 0) { | ||
397 | /* BOOT Mode: Monitor ROM */ | ||
398 | boot_pdata->nr_parts = 2; | ||
399 | strcpy(names[0], "big"); | ||
400 | strcpy(names[1], "little"); | ||
401 | for (i = 0; i < boot_pdata->nr_parts; i++) { | ||
402 | parts[i].name = names[i]; | ||
403 | parts[i].size = 0x400000; | ||
404 | parts[i].offset = MTDPART_OFS_NXTBLK; | ||
405 | } | ||
406 | } else { | ||
407 | /* BOOT Mode: ROM Emulator */ | ||
408 | boot_pdata->nr_parts = 2; | ||
409 | parts[0].name = "boot"; | ||
410 | parts[0].offset = 0xc00000; | ||
411 | parts[0].size = 0x400000; | ||
412 | parts[1].name = "user"; | ||
413 | parts[1].offset = 0; | ||
414 | parts[1].size = 0xc00000; | ||
415 | } | ||
416 | boot_pdata->parts = parts; | ||
417 | boot_pdata->map_init = rbtx4939_flash_map_init; | ||
418 | |||
419 | for (i = 0; i < ARRAY_SIZE(pdevs); i++) { | ||
420 | struct resource *r = &pdevs[i].res; | ||
421 | struct platform_device *dev = &pdevs[i].dev; | ||
422 | |||
423 | r->start = 0x1f000000 - i * 0x1000000; | ||
424 | r->end = r->start + 0x1000000 - 1; | ||
425 | r->flags = IORESOURCE_MEM; | ||
426 | pdevs[i].data.width = 2; | ||
427 | dev->num_resources = 1; | ||
428 | dev->resource = r; | ||
429 | dev->id = i; | ||
430 | dev->name = "rbtx4939-flash"; | ||
431 | dev->dev.platform_data = &pdevs[i].data; | ||
432 | platform_device_register(dev); | ||
433 | } | ||
434 | } | ||
435 | #else | ||
436 | static void __init rbtx4939_mtd_init(void) | ||
437 | { | ||
438 | } | ||
439 | #endif | ||
440 | |||
441 | static void __init rbtx4939_arch_init(void) | ||
442 | { | ||
443 | rbtx4939_pci_setup(); | ||
444 | } | ||
445 | |||
446 | static void __init rbtx4939_device_init(void) | ||
447 | { | ||
448 | unsigned long smc_addr = RBTX4939_ETHER_ADDR - IO_BASE; | ||
449 | struct resource smc_res[] = { | ||
450 | { | ||
451 | .start = smc_addr, | ||
452 | .end = smc_addr + 0x10 - 1, | ||
453 | .flags = IORESOURCE_MEM, | ||
454 | }, { | ||
455 | .start = RBTX4939_IRQ_ETHER, | ||
456 | /* override default irq flag defined in smc91x.h */ | ||
457 | .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW, | ||
458 | }, | ||
459 | }; | ||
460 | struct smc91x_platdata smc_pdata = { | ||
461 | .flags = SMC91X_USE_16BIT, | ||
462 | }; | ||
463 | struct platform_device *pdev; | ||
464 | #if IS_ENABLED(CONFIG_TC35815) | ||
465 | int i, j; | ||
466 | unsigned char ethaddr[2][6]; | ||
467 | u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f; | ||
468 | |||
469 | for (i = 0; i < 2; i++) { | ||
470 | unsigned long area = CKSEG1 + 0x1fff0000 + (i * 0x10); | ||
471 | if (bdipsw == 0) | ||
472 | memcpy(ethaddr[i], (void *)area, 6); | ||
473 | else { | ||
474 | u16 buf[3]; | ||
475 | if (bdipsw & 8) | ||
476 | area -= 0x03000000; | ||
477 | else | ||
478 | area -= 0x01000000; | ||
479 | for (j = 0; j < 3; j++) | ||
480 | buf[j] = le16_to_cpup((u16 *)(area + j * 2)); | ||
481 | memcpy(ethaddr[i], buf, 6); | ||
482 | } | ||
483 | } | ||
484 | tx4939_ethaddr_init(ethaddr[0], ethaddr[1]); | ||
485 | #endif | ||
486 | pdev = platform_device_alloc("smc91x", -1); | ||
487 | if (!pdev || | ||
488 | platform_device_add_resources(pdev, smc_res, ARRAY_SIZE(smc_res)) || | ||
489 | platform_device_add_data(pdev, &smc_pdata, sizeof(smc_pdata)) || | ||
490 | platform_device_add(pdev)) | ||
491 | platform_device_put(pdev); | ||
492 | rbtx4939_mtd_init(); | ||
493 | /* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */ | ||
494 | tx4939_ndfmc_init(10, 35, | ||
495 | (1 << 1) | (1 << 2), | ||
496 | (1 << 2)); /* ch1:8bit, ch2:16bit */ | ||
497 | rbtx4939_led_setup(); | ||
498 | tx4939_wdt_init(); | ||
499 | tx4939_ata_init(); | ||
500 | tx4939_rtc_init(); | ||
501 | tx4939_dmac_init(0, 2); | ||
502 | tx4939_aclc_init(); | ||
503 | platform_device_register_simple("txx9aclc-generic", -1, NULL, 0); | ||
504 | tx4939_sramc_init(); | ||
505 | tx4939_rng_init(); | ||
506 | } | ||
507 | |||
508 | static void __init rbtx4939_setup(void) | ||
509 | { | ||
510 | int i; | ||
511 | |||
512 | rbtx4939_ebusc_setup(); | ||
513 | /* always enable ATA0 */ | ||
514 | txx9_set64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_ATA0MODE); | ||
515 | if (txx9_master_clock == 0) | ||
516 | txx9_master_clock = 20000000; | ||
517 | tx4939_setup(); | ||
518 | rbtx4939_update_ioc_pen(); | ||
519 | #ifdef HAVE_RBTX4939_IOSWAB | ||
520 | ioswabw = rbtx4939_ioswabw; | ||
521 | __mem_ioswabw = rbtx4939_mem_ioswabw; | ||
522 | #endif | ||
523 | |||
524 | _machine_restart = rbtx4939_machine_restart; | ||
525 | |||
526 | txx9_7segled_init(RBTX4939_MAX_7SEGLEDS, rbtx4939_7segled_putc); | ||
527 | for (i = 0; i < RBTX4939_MAX_7SEGLEDS; i++) | ||
528 | txx9_7segled_putc(i, '-'); | ||
529 | pr_info("RBTX4939 (Rev %02x) --- FPGA(Rev %02x) DIPSW:%02x,%02x\n", | ||
530 | readb(rbtx4939_board_rev_addr), readb(rbtx4939_ioc_rev_addr), | ||
531 | readb(rbtx4939_udipsw_addr), readb(rbtx4939_bdipsw_addr)); | ||
532 | |||
533 | #ifdef CONFIG_PCI | ||
534 | txx9_alloc_pci_controller(&txx9_primary_pcic, 0, 0, 0, 0); | ||
535 | txx9_board_pcibios_setup = tx4927_pcibios_setup; | ||
536 | #else | ||
537 | set_io_port_base(RBTX4939_ETHER_BASE); | ||
538 | #endif | ||
539 | |||
540 | tx4939_sio_init(TX4939_SCLK0(txx9_master_clock), 0); | ||
541 | } | ||
542 | |||
543 | struct txx9_board_vec rbtx4939_vec __initdata = { | ||
544 | .system = "Toshiba RBTX4939", | ||
545 | .prom_init = rbtx4939_prom_init, | ||
546 | .mem_setup = rbtx4939_setup, | ||
547 | .irq_setup = rbtx4939_irq_setup, | ||
548 | .time_init = rbtx4939_time_init, | ||
549 | .device_init = rbtx4939_device_init, | ||
550 | .arch_init = rbtx4939_arch_init, | ||
551 | #ifdef CONFIG_PCI | ||
552 | .pci_map_irq = tx4939_pci_map_irq, | ||
553 | #endif | ||
554 | }; | ||