diff options
author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2008-07-10 11:31:36 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2008-07-15 13:44:35 -0400 |
commit | 22b1d707ffc99faebd86257ad19d5bb9fc624734 (patch) | |
tree | 9bd0bcd3878611d74db29e17f3c6e951f4656e61 /arch/mips/txx9/rbtx4938 | |
parent | 14476007c90005c8992b786c15a59cca31f53268 (diff) |
[MIPS] TXx9: Reorganize code
Move arch/mips/{jmr3927,tx4927,tx4938} into arch/mips/txx9/ tree.
This will help more code sharing and maintainance.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/txx9/rbtx4938')
-rw-r--r-- | arch/mips/txx9/rbtx4938/Makefile | 3 | ||||
-rw-r--r-- | arch/mips/txx9/rbtx4938/irq.c | 159 | ||||
-rw-r--r-- | arch/mips/txx9/rbtx4938/prom.c | 72 | ||||
-rw-r--r-- | arch/mips/txx9/rbtx4938/setup.c | 1122 | ||||
-rw-r--r-- | arch/mips/txx9/rbtx4938/spi_eeprom.c | 99 |
5 files changed, 1455 insertions, 0 deletions
diff --git a/arch/mips/txx9/rbtx4938/Makefile b/arch/mips/txx9/rbtx4938/Makefile new file mode 100644 index 000000000000..9dcc52ae5b9d --- /dev/null +++ b/arch/mips/txx9/rbtx4938/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-y += prom.o setup.o irq.o spi_eeprom.o | ||
2 | |||
3 | EXTRA_CFLAGS += -Werror | ||
diff --git a/arch/mips/txx9/rbtx4938/irq.c b/arch/mips/txx9/rbtx4938/irq.c new file mode 100644 index 000000000000..f4984820251a --- /dev/null +++ b/arch/mips/txx9/rbtx4938/irq.c | |||
@@ -0,0 +1,159 @@ | |||
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 | IRQ Device | ||
15 | |||
16 | 16 TX4938-CP0/00 Software 0 | ||
17 | 17 TX4938-CP0/01 Software 1 | ||
18 | 18 TX4938-CP0/02 Cascade TX4938-CP0 | ||
19 | 19 TX4938-CP0/03 Multiplexed -- do not use | ||
20 | 20 TX4938-CP0/04 Multiplexed -- do not use | ||
21 | 21 TX4938-CP0/05 Multiplexed -- do not use | ||
22 | 22 TX4938-CP0/06 Multiplexed -- do not use | ||
23 | 23 TX4938-CP0/07 CPU TIMER | ||
24 | |||
25 | 24 TX4938-PIC/00 | ||
26 | 25 TX4938-PIC/01 | ||
27 | 26 TX4938-PIC/02 Cascade RBTX4938-IOC | ||
28 | 27 TX4938-PIC/03 RBTX4938 RTL-8019AS Ethernet | ||
29 | 28 TX4938-PIC/04 | ||
30 | 29 TX4938-PIC/05 TX4938 ETH1 | ||
31 | 30 TX4938-PIC/06 TX4938 ETH0 | ||
32 | 31 TX4938-PIC/07 | ||
33 | 32 TX4938-PIC/08 TX4938 SIO 0 | ||
34 | 33 TX4938-PIC/09 TX4938 SIO 1 | ||
35 | 34 TX4938-PIC/10 TX4938 DMA0 | ||
36 | 35 TX4938-PIC/11 TX4938 DMA1 | ||
37 | 36 TX4938-PIC/12 TX4938 DMA2 | ||
38 | 37 TX4938-PIC/13 TX4938 DMA3 | ||
39 | 38 TX4938-PIC/14 | ||
40 | 39 TX4938-PIC/15 | ||
41 | 40 TX4938-PIC/16 TX4938 PCIC | ||
42 | 41 TX4938-PIC/17 TX4938 TMR0 | ||
43 | 42 TX4938-PIC/18 TX4938 TMR1 | ||
44 | 43 TX4938-PIC/19 TX4938 TMR2 | ||
45 | 44 TX4938-PIC/20 | ||
46 | 45 TX4938-PIC/21 | ||
47 | 46 TX4938-PIC/22 TX4938 PCIERR | ||
48 | 47 TX4938-PIC/23 | ||
49 | 48 TX4938-PIC/24 | ||
50 | 49 TX4938-PIC/25 | ||
51 | 50 TX4938-PIC/26 | ||
52 | 51 TX4938-PIC/27 | ||
53 | 52 TX4938-PIC/28 | ||
54 | 53 TX4938-PIC/29 | ||
55 | 54 TX4938-PIC/30 | ||
56 | 55 TX4938-PIC/31 TX4938 SPI | ||
57 | |||
58 | 56 RBTX4938-IOC/00 PCI-D | ||
59 | 57 RBTX4938-IOC/01 PCI-C | ||
60 | 58 RBTX4938-IOC/02 PCI-B | ||
61 | 59 RBTX4938-IOC/03 PCI-A | ||
62 | 60 RBTX4938-IOC/04 RTC | ||
63 | 61 RBTX4938-IOC/05 ATA | ||
64 | 62 RBTX4938-IOC/06 MODEM | ||
65 | 63 RBTX4938-IOC/07 SWINT | ||
66 | */ | ||
67 | #include <linux/init.h> | ||
68 | #include <linux/interrupt.h> | ||
69 | #include <asm/txx9/rbtx4938.h> | ||
70 | |||
71 | static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq); | ||
72 | static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq); | ||
73 | |||
74 | #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" | ||
75 | static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { | ||
76 | .name = TOSHIBA_RBTX4938_IOC_NAME, | ||
77 | .ack = toshiba_rbtx4938_irq_ioc_disable, | ||
78 | .mask = toshiba_rbtx4938_irq_ioc_disable, | ||
79 | .mask_ack = toshiba_rbtx4938_irq_ioc_disable, | ||
80 | .unmask = toshiba_rbtx4938_irq_ioc_enable, | ||
81 | }; | ||
82 | |||
83 | int | ||
84 | toshiba_rbtx4938_irq_nested(int sw_irq) | ||
85 | { | ||
86 | u8 level3; | ||
87 | |||
88 | level3 = readb(rbtx4938_imstat_addr); | ||
89 | if (level3) | ||
90 | /* must use fls so onboard ATA has priority */ | ||
91 | sw_irq = TOSHIBA_RBTX4938_IRQ_IOC_BEG + fls(level3) - 1; | ||
92 | |||
93 | return sw_irq; | ||
94 | } | ||
95 | |||
96 | static struct irqaction toshiba_rbtx4938_irq_ioc_action = { | ||
97 | .handler = no_action, | ||
98 | .flags = 0, | ||
99 | .mask = CPU_MASK_NONE, | ||
100 | .name = TOSHIBA_RBTX4938_IOC_NAME, | ||
101 | }; | ||
102 | |||
103 | /**********************************************************************************/ | ||
104 | /* Functions for ioc */ | ||
105 | /**********************************************************************************/ | ||
106 | static void __init | ||
107 | toshiba_rbtx4938_irq_ioc_init(void) | ||
108 | { | ||
109 | int i; | ||
110 | |||
111 | for (i = TOSHIBA_RBTX4938_IRQ_IOC_BEG; | ||
112 | i <= TOSHIBA_RBTX4938_IRQ_IOC_END; i++) | ||
113 | set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type, | ||
114 | handle_level_irq); | ||
115 | |||
116 | setup_irq(RBTX4938_IRQ_IOCINT, | ||
117 | &toshiba_rbtx4938_irq_ioc_action); | ||
118 | } | ||
119 | |||
120 | static void | ||
121 | toshiba_rbtx4938_irq_ioc_enable(unsigned int irq) | ||
122 | { | ||
123 | unsigned char v; | ||
124 | |||
125 | v = readb(rbtx4938_imask_addr); | ||
126 | v |= (1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG)); | ||
127 | writeb(v, rbtx4938_imask_addr); | ||
128 | mmiowb(); | ||
129 | } | ||
130 | |||
131 | static void | ||
132 | toshiba_rbtx4938_irq_ioc_disable(unsigned int irq) | ||
133 | { | ||
134 | unsigned char v; | ||
135 | |||
136 | v = readb(rbtx4938_imask_addr); | ||
137 | v &= ~(1 << (irq - TOSHIBA_RBTX4938_IRQ_IOC_BEG)); | ||
138 | writeb(v, rbtx4938_imask_addr); | ||
139 | mmiowb(); | ||
140 | } | ||
141 | |||
142 | void __init arch_init_irq(void) | ||
143 | { | ||
144 | extern void tx4938_irq_init(void); | ||
145 | |||
146 | /* Now, interrupt control disabled, */ | ||
147 | /* all IRC interrupts are masked, */ | ||
148 | /* all IRC interrupt mode are Low Active. */ | ||
149 | |||
150 | /* mask all IOC interrupts */ | ||
151 | writeb(0, rbtx4938_imask_addr); | ||
152 | |||
153 | /* clear SoftInt interrupts */ | ||
154 | writeb(0, rbtx4938_softint_addr); | ||
155 | tx4938_irq_init(); | ||
156 | toshiba_rbtx4938_irq_ioc_init(); | ||
157 | /* Onboard 10M Ether: High Active */ | ||
158 | set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH); | ||
159 | } | ||
diff --git a/arch/mips/txx9/rbtx4938/prom.c b/arch/mips/txx9/rbtx4938/prom.c new file mode 100644 index 000000000000..134fcc2dc7d2 --- /dev/null +++ b/arch/mips/txx9/rbtx4938/prom.c | |||
@@ -0,0 +1,72 @@ | |||
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/mm.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/bootmem.h> | ||
17 | |||
18 | #include <asm/addrspace.h> | ||
19 | #include <asm/bootinfo.h> | ||
20 | #include <asm/txx9/tx4938.h> | ||
21 | |||
22 | void __init prom_init_cmdline(void) | ||
23 | { | ||
24 | int argc = (int) fw_arg0; | ||
25 | char **argv = (char **) fw_arg1; | ||
26 | int i; | ||
27 | |||
28 | /* ignore all built-in args if any f/w args given */ | ||
29 | if (argc > 1) { | ||
30 | *arcs_cmdline = '\0'; | ||
31 | } | ||
32 | |||
33 | for (i = 1; i < argc; i++) { | ||
34 | if (i != 1) { | ||
35 | strcat(arcs_cmdline, " "); | ||
36 | } | ||
37 | strcat(arcs_cmdline, argv[i]); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | void __init prom_init(void) | ||
42 | { | ||
43 | extern int tx4938_get_mem_size(void); | ||
44 | int msize; | ||
45 | #ifndef CONFIG_TX4938_NAND_BOOT | ||
46 | prom_init_cmdline(); | ||
47 | #endif | ||
48 | |||
49 | msize = tx4938_get_mem_size(); | ||
50 | add_memory_region(0, msize << 20, BOOT_MEM_RAM); | ||
51 | |||
52 | return; | ||
53 | } | ||
54 | |||
55 | void __init prom_free_prom_memory(void) | ||
56 | { | ||
57 | } | ||
58 | |||
59 | void __init prom_fixup_mem_map(unsigned long start, unsigned long end) | ||
60 | { | ||
61 | return; | ||
62 | } | ||
63 | |||
64 | const char *get_system_type(void) | ||
65 | { | ||
66 | return "Toshiba RBTX4938"; | ||
67 | } | ||
68 | |||
69 | char * __init prom_getcmdline(void) | ||
70 | { | ||
71 | return &(arcs_cmdline[0]); | ||
72 | } | ||
diff --git a/arch/mips/txx9/rbtx4938/setup.c b/arch/mips/txx9/rbtx4938/setup.c new file mode 100644 index 000000000000..bbd572c9675b --- /dev/null +++ b/arch/mips/txx9/rbtx4938/setup.c | |||
@@ -0,0 +1,1122 @@ | |||
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/interrupt.h> | ||
17 | #include <linux/console.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/pm.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/gpio.h> | ||
23 | |||
24 | #include <asm/reboot.h> | ||
25 | #include <asm/time.h> | ||
26 | #include <asm/txx9tmr.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/bootinfo.h> | ||
29 | #include <asm/txx9/rbtx4938.h> | ||
30 | #ifdef CONFIG_SERIAL_TXX9 | ||
31 | #include <linux/serial_core.h> | ||
32 | #endif | ||
33 | #include <linux/spi/spi.h> | ||
34 | #include <asm/txx9/spi.h> | ||
35 | #include <asm/txx9pio.h> | ||
36 | |||
37 | extern char * __init prom_getcmdline(void); | ||
38 | static inline void tx4938_report_pcic_status1(struct tx4938_pcic_reg *pcicptr); | ||
39 | |||
40 | /* These functions are used for rebooting or halting the machine*/ | ||
41 | extern void rbtx4938_machine_restart(char *command); | ||
42 | extern void rbtx4938_machine_halt(void); | ||
43 | extern void rbtx4938_machine_power_off(void); | ||
44 | |||
45 | /* clocks */ | ||
46 | unsigned int txx9_master_clock; | ||
47 | unsigned int txx9_cpu_clock; | ||
48 | unsigned int txx9_gbus_clock; | ||
49 | |||
50 | unsigned long rbtx4938_ce_base[8]; | ||
51 | unsigned long rbtx4938_ce_size[8]; | ||
52 | int txboard_pci66_mode; | ||
53 | static int tx4938_pcic_trdyto; /* default: disabled */ | ||
54 | static int tx4938_pcic_retryto; /* default: disabled */ | ||
55 | static int tx4938_ccfg_toeon = 1; | ||
56 | |||
57 | struct tx4938_pcic_reg *pcicptrs[4] = { | ||
58 | tx4938_pcicptr /* default setting for TX4938 */ | ||
59 | }; | ||
60 | |||
61 | static struct { | ||
62 | unsigned long base; | ||
63 | unsigned long size; | ||
64 | } phys_regions[16] __initdata; | ||
65 | static int num_phys_regions __initdata; | ||
66 | |||
67 | #define PHYS_REGION_MINSIZE 0x10000 | ||
68 | |||
69 | void rbtx4938_machine_halt(void) | ||
70 | { | ||
71 | printk(KERN_NOTICE "System Halted\n"); | ||
72 | local_irq_disable(); | ||
73 | |||
74 | while (1) | ||
75 | __asm__(".set\tmips3\n\t" | ||
76 | "wait\n\t" | ||
77 | ".set\tmips0"); | ||
78 | } | ||
79 | |||
80 | void rbtx4938_machine_power_off(void) | ||
81 | { | ||
82 | rbtx4938_machine_halt(); | ||
83 | /* no return */ | ||
84 | } | ||
85 | |||
86 | void rbtx4938_machine_restart(char *command) | ||
87 | { | ||
88 | local_irq_disable(); | ||
89 | |||
90 | printk("Rebooting..."); | ||
91 | writeb(1, rbtx4938_softresetlock_addr); | ||
92 | writeb(1, rbtx4938_sfvol_addr); | ||
93 | writeb(1, rbtx4938_softreset_addr); | ||
94 | while(1) | ||
95 | ; | ||
96 | } | ||
97 | |||
98 | void __init | ||
99 | txboard_add_phys_region(unsigned long base, unsigned long size) | ||
100 | { | ||
101 | if (num_phys_regions >= ARRAY_SIZE(phys_regions)) { | ||
102 | printk("phys_region overflow\n"); | ||
103 | return; | ||
104 | } | ||
105 | phys_regions[num_phys_regions].base = base; | ||
106 | phys_regions[num_phys_regions].size = size; | ||
107 | num_phys_regions++; | ||
108 | } | ||
109 | unsigned long __init | ||
110 | txboard_find_free_phys_region(unsigned long begin, unsigned long end, | ||
111 | unsigned long size) | ||
112 | { | ||
113 | unsigned long base; | ||
114 | int i; | ||
115 | |||
116 | for (base = begin / size * size; base < end; base += size) { | ||
117 | for (i = 0; i < num_phys_regions; i++) { | ||
118 | if (phys_regions[i].size && | ||
119 | base <= phys_regions[i].base + (phys_regions[i].size - 1) && | ||
120 | base + (size - 1) >= phys_regions[i].base) | ||
121 | break; | ||
122 | } | ||
123 | if (i == num_phys_regions) | ||
124 | return base; | ||
125 | } | ||
126 | return 0; | ||
127 | } | ||
128 | unsigned long __init | ||
129 | txboard_find_free_phys_region_shrink(unsigned long begin, unsigned long end, | ||
130 | unsigned long *size) | ||
131 | { | ||
132 | unsigned long sz, base; | ||
133 | for (sz = *size; sz >= PHYS_REGION_MINSIZE; sz /= 2) { | ||
134 | base = txboard_find_free_phys_region(begin, end, sz); | ||
135 | if (base) { | ||
136 | *size = sz; | ||
137 | return base; | ||
138 | } | ||
139 | } | ||
140 | return 0; | ||
141 | } | ||
142 | unsigned long __init | ||
143 | txboard_request_phys_region_range(unsigned long begin, unsigned long end, | ||
144 | unsigned long size) | ||
145 | { | ||
146 | unsigned long base; | ||
147 | base = txboard_find_free_phys_region(begin, end, size); | ||
148 | if (base) | ||
149 | txboard_add_phys_region(base, size); | ||
150 | return base; | ||
151 | } | ||
152 | unsigned long __init | ||
153 | txboard_request_phys_region(unsigned long size) | ||
154 | { | ||
155 | unsigned long base; | ||
156 | unsigned long begin = 0, end = 0x20000000; /* search low 512MB */ | ||
157 | base = txboard_find_free_phys_region(begin, end, size); | ||
158 | if (base) | ||
159 | txboard_add_phys_region(base, size); | ||
160 | return base; | ||
161 | } | ||
162 | unsigned long __init | ||
163 | txboard_request_phys_region_shrink(unsigned long *size) | ||
164 | { | ||
165 | unsigned long base; | ||
166 | unsigned long begin = 0, end = 0x20000000; /* search low 512MB */ | ||
167 | base = txboard_find_free_phys_region_shrink(begin, end, size); | ||
168 | if (base) | ||
169 | txboard_add_phys_region(base, *size); | ||
170 | return base; | ||
171 | } | ||
172 | |||
173 | #ifdef CONFIG_PCI | ||
174 | void __init | ||
175 | tx4938_pcic_setup(struct tx4938_pcic_reg *pcicptr, | ||
176 | struct pci_controller *channel, | ||
177 | unsigned long pci_io_base, | ||
178 | int extarb) | ||
179 | { | ||
180 | int i; | ||
181 | |||
182 | /* Disable All Initiator Space */ | ||
183 | pcicptr->pciccfg &= ~(TX4938_PCIC_PCICCFG_G2PMEN(0)| | ||
184 | TX4938_PCIC_PCICCFG_G2PMEN(1)| | ||
185 | TX4938_PCIC_PCICCFG_G2PMEN(2)| | ||
186 | TX4938_PCIC_PCICCFG_G2PIOEN); | ||
187 | |||
188 | /* GB->PCI mappings */ | ||
189 | pcicptr->g2piomask = (channel->io_resource->end - channel->io_resource->start) >> 4; | ||
190 | pcicptr->g2piogbase = pci_io_base | | ||
191 | #ifdef __BIG_ENDIAN | ||
192 | TX4938_PCIC_G2PIOGBASE_ECHG | ||
193 | #else | ||
194 | TX4938_PCIC_G2PIOGBASE_BSDIS | ||
195 | #endif | ||
196 | ; | ||
197 | pcicptr->g2piopbase = 0; | ||
198 | for (i = 0; i < 3; i++) { | ||
199 | pcicptr->g2pmmask[i] = 0; | ||
200 | pcicptr->g2pmgbase[i] = 0; | ||
201 | pcicptr->g2pmpbase[i] = 0; | ||
202 | } | ||
203 | if (channel->mem_resource->end) { | ||
204 | pcicptr->g2pmmask[0] = (channel->mem_resource->end - channel->mem_resource->start) >> 4; | ||
205 | pcicptr->g2pmgbase[0] = channel->mem_resource->start | | ||
206 | #ifdef __BIG_ENDIAN | ||
207 | TX4938_PCIC_G2PMnGBASE_ECHG | ||
208 | #else | ||
209 | TX4938_PCIC_G2PMnGBASE_BSDIS | ||
210 | #endif | ||
211 | ; | ||
212 | pcicptr->g2pmpbase[0] = channel->mem_resource->start; | ||
213 | } | ||
214 | /* PCI->GB mappings (I/O 256B) */ | ||
215 | pcicptr->p2giopbase = 0; /* 256B */ | ||
216 | pcicptr->p2giogbase = 0; | ||
217 | /* PCI->GB mappings (MEM 512MB (64MB on R1.x)) */ | ||
218 | pcicptr->p2gm0plbase = 0; | ||
219 | pcicptr->p2gm0pubase = 0; | ||
220 | pcicptr->p2gmgbase[0] = 0 | | ||
221 | TX4938_PCIC_P2GMnGBASE_TMEMEN | | ||
222 | #ifdef __BIG_ENDIAN | ||
223 | TX4938_PCIC_P2GMnGBASE_TECHG | ||
224 | #else | ||
225 | TX4938_PCIC_P2GMnGBASE_TBSDIS | ||
226 | #endif | ||
227 | ; | ||
228 | /* PCI->GB mappings (MEM 16MB) */ | ||
229 | pcicptr->p2gm1plbase = 0xffffffff; | ||
230 | pcicptr->p2gm1pubase = 0xffffffff; | ||
231 | pcicptr->p2gmgbase[1] = 0; | ||
232 | /* PCI->GB mappings (MEM 1MB) */ | ||
233 | pcicptr->p2gm2pbase = 0xffffffff; /* 1MB */ | ||
234 | pcicptr->p2gmgbase[2] = 0; | ||
235 | |||
236 | pcicptr->pciccfg &= TX4938_PCIC_PCICCFG_GBWC_MASK; | ||
237 | /* Enable Initiator Memory Space */ | ||
238 | if (channel->mem_resource->end) | ||
239 | pcicptr->pciccfg |= TX4938_PCIC_PCICCFG_G2PMEN(0); | ||
240 | /* Enable Initiator I/O Space */ | ||
241 | if (channel->io_resource->end) | ||
242 | pcicptr->pciccfg |= TX4938_PCIC_PCICCFG_G2PIOEN; | ||
243 | /* Enable Initiator Config */ | ||
244 | pcicptr->pciccfg |= | ||
245 | TX4938_PCIC_PCICCFG_ICAEN | | ||
246 | TX4938_PCIC_PCICCFG_TCAR; | ||
247 | |||
248 | /* Do not use MEMMUL, MEMINF: YMFPCI card causes M_ABORT. */ | ||
249 | pcicptr->pcicfg1 = 0; | ||
250 | |||
251 | pcicptr->g2ptocnt &= ~0xffff; | ||
252 | |||
253 | if (tx4938_pcic_trdyto >= 0) { | ||
254 | pcicptr->g2ptocnt &= ~0xff; | ||
255 | pcicptr->g2ptocnt |= (tx4938_pcic_trdyto & 0xff); | ||
256 | } | ||
257 | |||
258 | if (tx4938_pcic_retryto >= 0) { | ||
259 | pcicptr->g2ptocnt &= ~0xff00; | ||
260 | pcicptr->g2ptocnt |= ((tx4938_pcic_retryto<<8) & 0xff00); | ||
261 | } | ||
262 | |||
263 | /* Clear All Local Bus Status */ | ||
264 | pcicptr->pcicstatus = TX4938_PCIC_PCICSTATUS_ALL; | ||
265 | /* Enable All Local Bus Interrupts */ | ||
266 | pcicptr->pcicmask = TX4938_PCIC_PCICSTATUS_ALL; | ||
267 | /* Clear All Initiator Status */ | ||
268 | pcicptr->g2pstatus = TX4938_PCIC_G2PSTATUS_ALL; | ||
269 | /* Enable All Initiator Interrupts */ | ||
270 | pcicptr->g2pmask = TX4938_PCIC_G2PSTATUS_ALL; | ||
271 | /* Clear All PCI Status Error */ | ||
272 | pcicptr->pcistatus = | ||
273 | (pcicptr->pcistatus & 0x0000ffff) | | ||
274 | (TX4938_PCIC_PCISTATUS_ALL << 16); | ||
275 | /* Enable All PCI Status Error Interrupts */ | ||
276 | pcicptr->pcimask = TX4938_PCIC_PCISTATUS_ALL; | ||
277 | |||
278 | if (!extarb) { | ||
279 | /* Reset Bus Arbiter */ | ||
280 | pcicptr->pbacfg = TX4938_PCIC_PBACFG_RPBA; | ||
281 | pcicptr->pbabm = 0; | ||
282 | /* Enable Bus Arbiter */ | ||
283 | pcicptr->pbacfg = TX4938_PCIC_PBACFG_PBAEN; | ||
284 | } | ||
285 | |||
286 | /* PCIC Int => IRC IRQ16 */ | ||
287 | pcicptr->pcicfg2 = | ||
288 | (pcicptr->pcicfg2 & 0xffffff00) | TX4938_IR_PCIC; | ||
289 | |||
290 | pcicptr->pcistatus = PCI_COMMAND_MASTER | | ||
291 | PCI_COMMAND_MEMORY | | ||
292 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; | ||
293 | } | ||
294 | |||
295 | int __init | ||
296 | tx4938_report_pciclk(void) | ||
297 | { | ||
298 | unsigned long pcode = TX4938_REV_PCODE(); | ||
299 | int pciclk = 0; | ||
300 | printk("TX%lx PCIC --%s PCICLK:", | ||
301 | pcode, | ||
302 | (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI66) ? " PCI66" : ""); | ||
303 | if (tx4938_ccfgptr->pcfg & TX4938_PCFG_PCICLKEN_ALL) { | ||
304 | |||
305 | switch ((unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIDIVMODE_MASK) { | ||
306 | case TX4938_CCFG_PCIDIVMODE_4: | ||
307 | pciclk = txx9_cpu_clock / 4; break; | ||
308 | case TX4938_CCFG_PCIDIVMODE_4_5: | ||
309 | pciclk = txx9_cpu_clock * 2 / 9; break; | ||
310 | case TX4938_CCFG_PCIDIVMODE_5: | ||
311 | pciclk = txx9_cpu_clock / 5; break; | ||
312 | case TX4938_CCFG_PCIDIVMODE_5_5: | ||
313 | pciclk = txx9_cpu_clock * 2 / 11; break; | ||
314 | case TX4938_CCFG_PCIDIVMODE_8: | ||
315 | pciclk = txx9_cpu_clock / 8; break; | ||
316 | case TX4938_CCFG_PCIDIVMODE_9: | ||
317 | pciclk = txx9_cpu_clock / 9; break; | ||
318 | case TX4938_CCFG_PCIDIVMODE_10: | ||
319 | pciclk = txx9_cpu_clock / 10; break; | ||
320 | case TX4938_CCFG_PCIDIVMODE_11: | ||
321 | pciclk = txx9_cpu_clock / 11; break; | ||
322 | } | ||
323 | printk("Internal(%dMHz)", pciclk / 1000000); | ||
324 | } else { | ||
325 | printk("External"); | ||
326 | pciclk = -1; | ||
327 | } | ||
328 | printk("\n"); | ||
329 | return pciclk; | ||
330 | } | ||
331 | |||
332 | void __init set_tx4938_pcicptr(int ch, struct tx4938_pcic_reg *pcicptr) | ||
333 | { | ||
334 | pcicptrs[ch] = pcicptr; | ||
335 | } | ||
336 | |||
337 | struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch) | ||
338 | { | ||
339 | return pcicptrs[ch]; | ||
340 | } | ||
341 | |||
342 | static struct pci_dev *fake_pci_dev(struct pci_controller *hose, | ||
343 | int top_bus, int busnr, int devfn) | ||
344 | { | ||
345 | static struct pci_dev dev; | ||
346 | static struct pci_bus bus; | ||
347 | |||
348 | dev.sysdata = bus.sysdata = hose; | ||
349 | dev.devfn = devfn; | ||
350 | bus.number = busnr; | ||
351 | bus.ops = hose->pci_ops; | ||
352 | bus.parent = NULL; | ||
353 | dev.bus = &bus; | ||
354 | |||
355 | return &dev; | ||
356 | } | ||
357 | |||
358 | #define EARLY_PCI_OP(rw, size, type) \ | ||
359 | static int early_##rw##_config_##size(struct pci_controller *hose, \ | ||
360 | int top_bus, int bus, int devfn, int offset, type value) \ | ||
361 | { \ | ||
362 | return pci_##rw##_config_##size( \ | ||
363 | fake_pci_dev(hose, top_bus, bus, devfn), \ | ||
364 | offset, value); \ | ||
365 | } | ||
366 | |||
367 | EARLY_PCI_OP(read, word, u16 *) | ||
368 | |||
369 | int txboard_pci66_check(struct pci_controller *hose, int top_bus, int current_bus) | ||
370 | { | ||
371 | u32 pci_devfn; | ||
372 | unsigned short vid; | ||
373 | int devfn_start = 0; | ||
374 | int devfn_stop = 0xff; | ||
375 | int cap66 = -1; | ||
376 | u16 stat; | ||
377 | |||
378 | printk("PCI: Checking 66MHz capabilities...\n"); | ||
379 | |||
380 | for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) { | ||
381 | if (early_read_config_word(hose, top_bus, current_bus, | ||
382 | pci_devfn, PCI_VENDOR_ID, | ||
383 | &vid) != PCIBIOS_SUCCESSFUL) | ||
384 | continue; | ||
385 | |||
386 | if (vid == 0xffff) continue; | ||
387 | |||
388 | /* check 66MHz capability */ | ||
389 | if (cap66 < 0) | ||
390 | cap66 = 1; | ||
391 | if (cap66) { | ||
392 | early_read_config_word(hose, top_bus, current_bus, pci_devfn, | ||
393 | PCI_STATUS, &stat); | ||
394 | if (!(stat & PCI_STATUS_66MHZ)) { | ||
395 | printk(KERN_DEBUG "PCI: %02x:%02x not 66MHz capable.\n", | ||
396 | current_bus, pci_devfn); | ||
397 | cap66 = 0; | ||
398 | break; | ||
399 | } | ||
400 | } | ||
401 | } | ||
402 | return cap66 > 0; | ||
403 | } | ||
404 | |||
405 | int __init | ||
406 | tx4938_pciclk66_setup(void) | ||
407 | { | ||
408 | int pciclk; | ||
409 | |||
410 | /* Assert M66EN */ | ||
411 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_PCI66; | ||
412 | /* Double PCICLK (if possible) */ | ||
413 | if (tx4938_ccfgptr->pcfg & TX4938_PCFG_PCICLKEN_ALL) { | ||
414 | unsigned int pcidivmode = | ||
415 | tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIDIVMODE_MASK; | ||
416 | switch (pcidivmode) { | ||
417 | case TX4938_CCFG_PCIDIVMODE_8: | ||
418 | case TX4938_CCFG_PCIDIVMODE_4: | ||
419 | pcidivmode = TX4938_CCFG_PCIDIVMODE_4; | ||
420 | pciclk = txx9_cpu_clock / 4; | ||
421 | break; | ||
422 | case TX4938_CCFG_PCIDIVMODE_9: | ||
423 | case TX4938_CCFG_PCIDIVMODE_4_5: | ||
424 | pcidivmode = TX4938_CCFG_PCIDIVMODE_4_5; | ||
425 | pciclk = txx9_cpu_clock * 2 / 9; | ||
426 | break; | ||
427 | case TX4938_CCFG_PCIDIVMODE_10: | ||
428 | case TX4938_CCFG_PCIDIVMODE_5: | ||
429 | pcidivmode = TX4938_CCFG_PCIDIVMODE_5; | ||
430 | pciclk = txx9_cpu_clock / 5; | ||
431 | break; | ||
432 | case TX4938_CCFG_PCIDIVMODE_11: | ||
433 | case TX4938_CCFG_PCIDIVMODE_5_5: | ||
434 | default: | ||
435 | pcidivmode = TX4938_CCFG_PCIDIVMODE_5_5; | ||
436 | pciclk = txx9_cpu_clock * 2 / 11; | ||
437 | break; | ||
438 | } | ||
439 | tx4938_ccfgptr->ccfg = | ||
440 | (tx4938_ccfgptr->ccfg & ~TX4938_CCFG_PCIDIVMODE_MASK) | ||
441 | | pcidivmode; | ||
442 | printk(KERN_DEBUG "PCICLK: ccfg:%08lx\n", | ||
443 | (unsigned long)tx4938_ccfgptr->ccfg); | ||
444 | } else { | ||
445 | pciclk = -1; | ||
446 | } | ||
447 | return pciclk; | ||
448 | } | ||
449 | |||
450 | extern struct pci_controller tx4938_pci_controller[]; | ||
451 | static int __init tx4938_pcibios_init(void) | ||
452 | { | ||
453 | unsigned long mem_base[2]; | ||
454 | unsigned long mem_size[2] = {TX4938_PCIMEM_SIZE_0, TX4938_PCIMEM_SIZE_1}; /* MAX 128M,64K */ | ||
455 | unsigned long io_base[2]; | ||
456 | unsigned long io_size[2] = {TX4938_PCIIO_SIZE_0, TX4938_PCIIO_SIZE_1}; /* MAX 16M,64K */ | ||
457 | /* TX4938 PCIC1: 64K MEM/IO is enough for ETH0,ETH1 */ | ||
458 | int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB); | ||
459 | |||
460 | PCIBIOS_MIN_IO = 0x00001000UL; | ||
461 | |||
462 | mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]); | ||
463 | io_base[0] = txboard_request_phys_region_shrink(&io_size[0]); | ||
464 | |||
465 | printk("TX4938 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n", | ||
466 | (unsigned short)(tx4938_pcicptr->pciid >> 16), | ||
467 | (unsigned short)(tx4938_pcicptr->pciid & 0xffff), | ||
468 | (unsigned short)(tx4938_pcicptr->pciccrev & 0xff), | ||
469 | extarb ? "External" : "Internal"); | ||
470 | |||
471 | /* setup PCI area */ | ||
472 | tx4938_pci_controller[0].io_resource->start = io_base[0]; | ||
473 | tx4938_pci_controller[0].io_resource->end = (io_base[0] + io_size[0]) - 1; | ||
474 | tx4938_pci_controller[0].mem_resource->start = mem_base[0]; | ||
475 | tx4938_pci_controller[0].mem_resource->end = mem_base[0] + mem_size[0] - 1; | ||
476 | |||
477 | set_tx4938_pcicptr(0, tx4938_pcicptr); | ||
478 | |||
479 | register_pci_controller(&tx4938_pci_controller[0]); | ||
480 | |||
481 | if (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI66) { | ||
482 | printk("TX4938_CCFG_PCI66 already configured\n"); | ||
483 | txboard_pci66_mode = -1; /* already configured */ | ||
484 | } | ||
485 | |||
486 | /* Reset PCI Bus */ | ||
487 | writeb(0, rbtx4938_pcireset_addr); | ||
488 | /* Reset PCIC */ | ||
489 | tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST; | ||
490 | if (txboard_pci66_mode > 0) | ||
491 | tx4938_pciclk66_setup(); | ||
492 | mdelay(10); | ||
493 | /* clear PCIC reset */ | ||
494 | tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST; | ||
495 | writeb(1, rbtx4938_pcireset_addr); | ||
496 | mmiowb(); | ||
497 | tx4938_report_pcic_status1(tx4938_pcicptr); | ||
498 | |||
499 | tx4938_report_pciclk(); | ||
500 | tx4938_pcic_setup(tx4938_pcicptr, &tx4938_pci_controller[0], io_base[0], extarb); | ||
501 | if (txboard_pci66_mode == 0 && | ||
502 | txboard_pci66_check(&tx4938_pci_controller[0], 0, 0)) { | ||
503 | /* Reset PCI Bus */ | ||
504 | writeb(0, rbtx4938_pcireset_addr); | ||
505 | /* Reset PCIC */ | ||
506 | tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIRST; | ||
507 | tx4938_pciclk66_setup(); | ||
508 | mdelay(10); | ||
509 | /* clear PCIC reset */ | ||
510 | tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIRST; | ||
511 | writeb(1, rbtx4938_pcireset_addr); | ||
512 | mmiowb(); | ||
513 | /* Reinitialize PCIC */ | ||
514 | tx4938_report_pciclk(); | ||
515 | tx4938_pcic_setup(tx4938_pcicptr, &tx4938_pci_controller[0], io_base[0], extarb); | ||
516 | } | ||
517 | |||
518 | mem_base[1] = txboard_request_phys_region_shrink(&mem_size[1]); | ||
519 | io_base[1] = txboard_request_phys_region_shrink(&io_size[1]); | ||
520 | /* Reset PCIC1 */ | ||
521 | tx4938_ccfgptr->clkctr |= TX4938_CLKCTR_PCIC1RST; | ||
522 | /* PCI1DMD==0 => PCI1CLK==GBUSCLK/2 => PCI66 */ | ||
523 | if (!(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI1DMD)) | ||
524 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_PCI1_66; | ||
525 | else | ||
526 | tx4938_ccfgptr->ccfg &= ~TX4938_CCFG_PCI1_66; | ||
527 | mdelay(10); | ||
528 | /* clear PCIC1 reset */ | ||
529 | tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIC1RST; | ||
530 | tx4938_report_pcic_status1(tx4938_pcic1ptr); | ||
531 | |||
532 | printk("TX4938 PCIC1 -- DID:%04x VID:%04x RID:%02x", | ||
533 | (unsigned short)(tx4938_pcic1ptr->pciid >> 16), | ||
534 | (unsigned short)(tx4938_pcic1ptr->pciid & 0xffff), | ||
535 | (unsigned short)(tx4938_pcic1ptr->pciccrev & 0xff)); | ||
536 | printk("%s PCICLK:%dMHz\n", | ||
537 | (tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI1_66) ? " PCI66" : "", | ||
538 | txx9_gbus_clock / | ||
539 | ((tx4938_ccfgptr->ccfg & TX4938_CCFG_PCI1DMD) ? 4 : 2) / | ||
540 | 1000000); | ||
541 | |||
542 | /* assumption: CPHYSADDR(mips_io_port_base) == io_base[0] */ | ||
543 | tx4938_pci_controller[1].io_resource->start = | ||
544 | io_base[1] - io_base[0]; | ||
545 | tx4938_pci_controller[1].io_resource->end = | ||
546 | io_base[1] - io_base[0] + io_size[1] - 1; | ||
547 | tx4938_pci_controller[1].mem_resource->start = mem_base[1]; | ||
548 | tx4938_pci_controller[1].mem_resource->end = | ||
549 | mem_base[1] + mem_size[1] - 1; | ||
550 | set_tx4938_pcicptr(1, tx4938_pcic1ptr); | ||
551 | |||
552 | register_pci_controller(&tx4938_pci_controller[1]); | ||
553 | |||
554 | tx4938_pcic_setup(tx4938_pcic1ptr, &tx4938_pci_controller[1], io_base[1], extarb); | ||
555 | |||
556 | /* map ioport 0 to PCI I/O space address 0 */ | ||
557 | set_io_port_base(KSEG1 + io_base[0]); | ||
558 | |||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | arch_initcall(tx4938_pcibios_init); | ||
563 | |||
564 | #endif /* CONFIG_PCI */ | ||
565 | |||
566 | /* SPI support */ | ||
567 | |||
568 | /* chip select for SPI devices */ | ||
569 | #define SEEPROM1_CS 7 /* PIO7 */ | ||
570 | #define SEEPROM2_CS 0 /* IOC */ | ||
571 | #define SEEPROM3_CS 1 /* IOC */ | ||
572 | #define SRTC_CS 2 /* IOC */ | ||
573 | |||
574 | #ifdef CONFIG_PCI | ||
575 | static int __init rbtx4938_ethaddr_init(void) | ||
576 | { | ||
577 | unsigned char dat[17]; | ||
578 | unsigned char sum; | ||
579 | int i; | ||
580 | |||
581 | /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */ | ||
582 | if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) { | ||
583 | printk(KERN_ERR "seeprom: read error.\n"); | ||
584 | return -ENODEV; | ||
585 | } else { | ||
586 | if (strcmp(dat, "MAC") != 0) | ||
587 | printk(KERN_WARNING "seeprom: bad signature.\n"); | ||
588 | for (i = 0, sum = 0; i < sizeof(dat); i++) | ||
589 | sum += dat[i]; | ||
590 | if (sum) | ||
591 | printk(KERN_WARNING "seeprom: bad checksum.\n"); | ||
592 | } | ||
593 | for (i = 0; i < 2; i++) { | ||
594 | unsigned int id = | ||
595 | TXX9_IRQ_BASE + (i ? TX4938_IR_ETH1 : TX4938_IR_ETH0); | ||
596 | struct platform_device *pdev; | ||
597 | if (!(tx4938_ccfgptr->pcfg & | ||
598 | (i ? TX4938_PCFG_ETH1_SEL : TX4938_PCFG_ETH0_SEL))) | ||
599 | continue; | ||
600 | pdev = platform_device_alloc("tc35815-mac", id); | ||
601 | if (!pdev || | ||
602 | platform_device_add_data(pdev, &dat[4 + 6 * i], 6) || | ||
603 | platform_device_add(pdev)) | ||
604 | platform_device_put(pdev); | ||
605 | } | ||
606 | return 0; | ||
607 | } | ||
608 | device_initcall(rbtx4938_ethaddr_init); | ||
609 | #endif /* CONFIG_PCI */ | ||
610 | |||
611 | static void __init rbtx4938_spi_setup(void) | ||
612 | { | ||
613 | /* set SPI_SEL */ | ||
614 | tx4938_ccfgptr->pcfg |= TX4938_PCFG_SPI_SEL; | ||
615 | } | ||
616 | |||
617 | static struct resource rbtx4938_fpga_resource; | ||
618 | |||
619 | static char pcode_str[8]; | ||
620 | static struct resource tx4938_reg_resource = { | ||
621 | .start = TX4938_REG_BASE, | ||
622 | .end = TX4938_REG_BASE + TX4938_REG_SIZE, | ||
623 | .name = pcode_str, | ||
624 | .flags = IORESOURCE_MEM | ||
625 | }; | ||
626 | |||
627 | void __init tx4938_board_setup(void) | ||
628 | { | ||
629 | int i; | ||
630 | unsigned long divmode; | ||
631 | int cpuclk = 0; | ||
632 | unsigned long pcode = TX4938_REV_PCODE(); | ||
633 | |||
634 | ioport_resource.start = 0x1000; | ||
635 | ioport_resource.end = 0xffffffff; | ||
636 | iomem_resource.start = 0x1000; | ||
637 | iomem_resource.end = 0xffffffff; /* expand to 4GB */ | ||
638 | |||
639 | sprintf(pcode_str, "TX%lx", pcode); | ||
640 | /* SDRAMC,EBUSC are configured by PROM */ | ||
641 | for (i = 0; i < 8; i++) { | ||
642 | if (!(tx4938_ebuscptr->cr[i] & 0x8)) | ||
643 | continue; /* disabled */ | ||
644 | rbtx4938_ce_base[i] = (unsigned long)TX4938_EBUSC_BA(i); | ||
645 | txboard_add_phys_region(rbtx4938_ce_base[i], TX4938_EBUSC_SIZE(i)); | ||
646 | } | ||
647 | |||
648 | /* clocks */ | ||
649 | if (txx9_master_clock) { | ||
650 | /* calculate gbus_clock and cpu_clock_freq from master_clock */ | ||
651 | divmode = (unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_DIVMODE_MASK; | ||
652 | switch (divmode) { | ||
653 | case TX4938_CCFG_DIVMODE_8: | ||
654 | case TX4938_CCFG_DIVMODE_10: | ||
655 | case TX4938_CCFG_DIVMODE_12: | ||
656 | case TX4938_CCFG_DIVMODE_16: | ||
657 | case TX4938_CCFG_DIVMODE_18: | ||
658 | txx9_gbus_clock = txx9_master_clock * 4; break; | ||
659 | default: | ||
660 | txx9_gbus_clock = txx9_master_clock; | ||
661 | } | ||
662 | switch (divmode) { | ||
663 | case TX4938_CCFG_DIVMODE_2: | ||
664 | case TX4938_CCFG_DIVMODE_8: | ||
665 | cpuclk = txx9_gbus_clock * 2; break; | ||
666 | case TX4938_CCFG_DIVMODE_2_5: | ||
667 | case TX4938_CCFG_DIVMODE_10: | ||
668 | cpuclk = txx9_gbus_clock * 5 / 2; break; | ||
669 | case TX4938_CCFG_DIVMODE_3: | ||
670 | case TX4938_CCFG_DIVMODE_12: | ||
671 | cpuclk = txx9_gbus_clock * 3; break; | ||
672 | case TX4938_CCFG_DIVMODE_4: | ||
673 | case TX4938_CCFG_DIVMODE_16: | ||
674 | cpuclk = txx9_gbus_clock * 4; break; | ||
675 | case TX4938_CCFG_DIVMODE_4_5: | ||
676 | case TX4938_CCFG_DIVMODE_18: | ||
677 | cpuclk = txx9_gbus_clock * 9 / 2; break; | ||
678 | } | ||
679 | txx9_cpu_clock = cpuclk; | ||
680 | } else { | ||
681 | if (txx9_cpu_clock == 0) { | ||
682 | txx9_cpu_clock = 300000000; /* 300MHz */ | ||
683 | } | ||
684 | /* calculate gbus_clock and master_clock from cpu_clock_freq */ | ||
685 | cpuclk = txx9_cpu_clock; | ||
686 | divmode = (unsigned long)tx4938_ccfgptr->ccfg & TX4938_CCFG_DIVMODE_MASK; | ||
687 | switch (divmode) { | ||
688 | case TX4938_CCFG_DIVMODE_2: | ||
689 | case TX4938_CCFG_DIVMODE_8: | ||
690 | txx9_gbus_clock = cpuclk / 2; break; | ||
691 | case TX4938_CCFG_DIVMODE_2_5: | ||
692 | case TX4938_CCFG_DIVMODE_10: | ||
693 | txx9_gbus_clock = cpuclk * 2 / 5; break; | ||
694 | case TX4938_CCFG_DIVMODE_3: | ||
695 | case TX4938_CCFG_DIVMODE_12: | ||
696 | txx9_gbus_clock = cpuclk / 3; break; | ||
697 | case TX4938_CCFG_DIVMODE_4: | ||
698 | case TX4938_CCFG_DIVMODE_16: | ||
699 | txx9_gbus_clock = cpuclk / 4; break; | ||
700 | case TX4938_CCFG_DIVMODE_4_5: | ||
701 | case TX4938_CCFG_DIVMODE_18: | ||
702 | txx9_gbus_clock = cpuclk * 2 / 9; break; | ||
703 | } | ||
704 | switch (divmode) { | ||
705 | case TX4938_CCFG_DIVMODE_8: | ||
706 | case TX4938_CCFG_DIVMODE_10: | ||
707 | case TX4938_CCFG_DIVMODE_12: | ||
708 | case TX4938_CCFG_DIVMODE_16: | ||
709 | case TX4938_CCFG_DIVMODE_18: | ||
710 | txx9_master_clock = txx9_gbus_clock / 4; break; | ||
711 | default: | ||
712 | txx9_master_clock = txx9_gbus_clock; | ||
713 | } | ||
714 | } | ||
715 | /* change default value to udelay/mdelay take reasonable time */ | ||
716 | loops_per_jiffy = txx9_cpu_clock / HZ / 2; | ||
717 | |||
718 | /* CCFG */ | ||
719 | /* clear WatchDogReset,BusErrorOnWrite flag (W1C) */ | ||
720 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_WDRST | TX4938_CCFG_BEOW; | ||
721 | /* do reset on watchdog */ | ||
722 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_WR; | ||
723 | /* clear PCIC1 reset */ | ||
724 | if (tx4938_ccfgptr->clkctr & TX4938_CLKCTR_PCIC1RST) | ||
725 | tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIC1RST; | ||
726 | |||
727 | /* enable Timeout BusError */ | ||
728 | if (tx4938_ccfg_toeon) | ||
729 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_TOE; | ||
730 | |||
731 | /* DMA selection */ | ||
732 | tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_DMASEL_ALL; | ||
733 | |||
734 | /* Use external clock for external arbiter */ | ||
735 | if (!(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB)) | ||
736 | tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_PCICLKEN_ALL; | ||
737 | |||
738 | printk("%s -- %dMHz(M%dMHz) CRIR:%08lx CCFG:%Lx PCFG:%Lx\n", | ||
739 | pcode_str, | ||
740 | cpuclk / 1000000, txx9_master_clock / 1000000, | ||
741 | (unsigned long)tx4938_ccfgptr->crir, | ||
742 | tx4938_ccfgptr->ccfg, | ||
743 | tx4938_ccfgptr->pcfg); | ||
744 | |||
745 | printk("%s SDRAMC --", pcode_str); | ||
746 | for (i = 0; i < 4; i++) { | ||
747 | unsigned long long cr = tx4938_sdramcptr->cr[i]; | ||
748 | unsigned long ram_base, ram_size; | ||
749 | if (!((unsigned long)cr & 0x00000400)) | ||
750 | continue; /* disabled */ | ||
751 | ram_base = (unsigned long)(cr >> 49) << 21; | ||
752 | ram_size = ((unsigned long)(cr >> 33) + 1) << 21; | ||
753 | if (ram_base >= 0x20000000) | ||
754 | continue; /* high memory (ignore) */ | ||
755 | printk(" CR%d:%016Lx", i, cr); | ||
756 | txboard_add_phys_region(ram_base, ram_size); | ||
757 | } | ||
758 | printk(" TR:%09Lx\n", tx4938_sdramcptr->tr); | ||
759 | |||
760 | /* SRAM */ | ||
761 | if (pcode == 0x4938 && tx4938_sramcptr->cr & 1) { | ||
762 | unsigned int size = 0x800; | ||
763 | unsigned long base = | ||
764 | (tx4938_sramcptr->cr >> (39-11)) & ~(size - 1); | ||
765 | txboard_add_phys_region(base, size); | ||
766 | } | ||
767 | |||
768 | /* TMR */ | ||
769 | for (i = 0; i < TX4938_NR_TMR; i++) | ||
770 | txx9_tmr_init(TX4938_TMR_REG(i) & 0xfffffffffULL); | ||
771 | |||
772 | /* enable DMA */ | ||
773 | for (i = 0; i < 2; i++) | ||
774 | ____raw_writeq(TX4938_DMA_MCR_MSTEN, | ||
775 | (void __iomem *)(TX4938_DMA_REG(i) + 0x50)); | ||
776 | |||
777 | /* PIO */ | ||
778 | __raw_writel(0, &tx4938_pioptr->maskcpu); | ||
779 | __raw_writel(0, &tx4938_pioptr->maskext); | ||
780 | |||
781 | /* TX4938 internal registers */ | ||
782 | if (request_resource(&iomem_resource, &tx4938_reg_resource)) | ||
783 | printk("request resource for internal registers failed\n"); | ||
784 | } | ||
785 | |||
786 | #ifdef CONFIG_PCI | ||
787 | static inline void tx4938_report_pcic_status1(struct tx4938_pcic_reg *pcicptr) | ||
788 | { | ||
789 | unsigned short pcistatus = (unsigned short)(pcicptr->pcistatus >> 16); | ||
790 | unsigned long g2pstatus = pcicptr->g2pstatus; | ||
791 | unsigned long pcicstatus = pcicptr->pcicstatus; | ||
792 | static struct { | ||
793 | unsigned long flag; | ||
794 | const char *str; | ||
795 | } pcistat_tbl[] = { | ||
796 | { PCI_STATUS_DETECTED_PARITY, "DetectedParityError" }, | ||
797 | { PCI_STATUS_SIG_SYSTEM_ERROR, "SignaledSystemError" }, | ||
798 | { PCI_STATUS_REC_MASTER_ABORT, "ReceivedMasterAbort" }, | ||
799 | { PCI_STATUS_REC_TARGET_ABORT, "ReceivedTargetAbort" }, | ||
800 | { PCI_STATUS_SIG_TARGET_ABORT, "SignaledTargetAbort" }, | ||
801 | { PCI_STATUS_PARITY, "MasterParityError" }, | ||
802 | }, g2pstat_tbl[] = { | ||
803 | { TX4938_PCIC_G2PSTATUS_TTOE, "TIOE" }, | ||
804 | { TX4938_PCIC_G2PSTATUS_RTOE, "RTOE" }, | ||
805 | }, pcicstat_tbl[] = { | ||
806 | { TX4938_PCIC_PCICSTATUS_PME, "PME" }, | ||
807 | { TX4938_PCIC_PCICSTATUS_TLB, "TLB" }, | ||
808 | { TX4938_PCIC_PCICSTATUS_NIB, "NIB" }, | ||
809 | { TX4938_PCIC_PCICSTATUS_ZIB, "ZIB" }, | ||
810 | { TX4938_PCIC_PCICSTATUS_PERR, "PERR" }, | ||
811 | { TX4938_PCIC_PCICSTATUS_SERR, "SERR" }, | ||
812 | { TX4938_PCIC_PCICSTATUS_GBE, "GBE" }, | ||
813 | { TX4938_PCIC_PCICSTATUS_IWB, "IWB" }, | ||
814 | }; | ||
815 | int i; | ||
816 | |||
817 | printk("pcistat:%04x(", pcistatus); | ||
818 | for (i = 0; i < ARRAY_SIZE(pcistat_tbl); i++) | ||
819 | if (pcistatus & pcistat_tbl[i].flag) | ||
820 | printk("%s ", pcistat_tbl[i].str); | ||
821 | printk("), g2pstatus:%08lx(", g2pstatus); | ||
822 | for (i = 0; i < ARRAY_SIZE(g2pstat_tbl); i++) | ||
823 | if (g2pstatus & g2pstat_tbl[i].flag) | ||
824 | printk("%s ", g2pstat_tbl[i].str); | ||
825 | printk("), pcicstatus:%08lx(", pcicstatus); | ||
826 | for (i = 0; i < ARRAY_SIZE(pcicstat_tbl); i++) | ||
827 | if (pcicstatus & pcicstat_tbl[i].flag) | ||
828 | printk("%s ", pcicstat_tbl[i].str); | ||
829 | printk(")\n"); | ||
830 | } | ||
831 | |||
832 | void tx4938_report_pcic_status(void) | ||
833 | { | ||
834 | int i; | ||
835 | struct tx4938_pcic_reg *pcicptr; | ||
836 | for (i = 0; (pcicptr = get_tx4938_pcicptr(i)) != NULL; i++) | ||
837 | tx4938_report_pcic_status1(pcicptr); | ||
838 | } | ||
839 | |||
840 | #endif /* CONFIG_PCI */ | ||
841 | |||
842 | void __init plat_time_init(void) | ||
843 | { | ||
844 | mips_hpt_frequency = txx9_cpu_clock / 2; | ||
845 | if (tx4938_ccfgptr->ccfg & TX4938_CCFG_TINTDIS) | ||
846 | txx9_clockevent_init(TX4938_TMR_REG(0) & 0xfffffffffULL, | ||
847 | TXX9_IRQ_BASE + TX4938_IR_TMR(0), | ||
848 | txx9_gbus_clock / 2); | ||
849 | } | ||
850 | |||
851 | void __init plat_mem_setup(void) | ||
852 | { | ||
853 | unsigned long long pcfg; | ||
854 | char *argptr; | ||
855 | |||
856 | iomem_resource.end = 0xffffffff; /* 4GB */ | ||
857 | |||
858 | if (txx9_master_clock == 0) | ||
859 | txx9_master_clock = 25000000; /* 25MHz */ | ||
860 | tx4938_board_setup(); | ||
861 | #ifndef CONFIG_PCI | ||
862 | set_io_port_base(RBTX4938_ETHER_BASE); | ||
863 | #endif | ||
864 | |||
865 | #ifdef CONFIG_SERIAL_TXX9 | ||
866 | { | ||
867 | extern int early_serial_txx9_setup(struct uart_port *port); | ||
868 | int i; | ||
869 | struct uart_port req; | ||
870 | for(i = 0; i < 2; i++) { | ||
871 | memset(&req, 0, sizeof(req)); | ||
872 | req.line = i; | ||
873 | req.iotype = UPIO_MEM; | ||
874 | req.membase = (char *)(0xff1ff300 + i * 0x100); | ||
875 | req.mapbase = 0xff1ff300 + i * 0x100; | ||
876 | req.irq = RBTX4938_IRQ_IRC_SIO(i); | ||
877 | req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/; | ||
878 | req.uartclk = 50000000; | ||
879 | early_serial_txx9_setup(&req); | ||
880 | } | ||
881 | } | ||
882 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE | ||
883 | argptr = prom_getcmdline(); | ||
884 | if (strstr(argptr, "console=") == NULL) { | ||
885 | strcat(argptr, " console=ttyS0,38400"); | ||
886 | } | ||
887 | #endif | ||
888 | #endif | ||
889 | |||
890 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_PIO58_61 | ||
891 | printk("PIOSEL: disabling both ata and nand selection\n"); | ||
892 | local_irq_disable(); | ||
893 | tx4938_ccfgptr->pcfg &= ~(TX4938_PCFG_NDF_SEL | TX4938_PCFG_ATA_SEL); | ||
894 | #endif | ||
895 | |||
896 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_NAND | ||
897 | printk("PIOSEL: enabling nand selection\n"); | ||
898 | tx4938_ccfgptr->pcfg |= TX4938_PCFG_NDF_SEL; | ||
899 | tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_ATA_SEL; | ||
900 | #endif | ||
901 | |||
902 | #ifdef CONFIG_TOSHIBA_RBTX4938_MPLEX_ATA | ||
903 | printk("PIOSEL: enabling ata selection\n"); | ||
904 | tx4938_ccfgptr->pcfg |= TX4938_PCFG_ATA_SEL; | ||
905 | tx4938_ccfgptr->pcfg &= ~TX4938_PCFG_NDF_SEL; | ||
906 | #endif | ||
907 | |||
908 | #ifdef CONFIG_IP_PNP | ||
909 | argptr = prom_getcmdline(); | ||
910 | if (strstr(argptr, "ip=") == NULL) { | ||
911 | strcat(argptr, " ip=any"); | ||
912 | } | ||
913 | #endif | ||
914 | |||
915 | |||
916 | #ifdef CONFIG_FB | ||
917 | { | ||
918 | conswitchp = &dummy_con; | ||
919 | } | ||
920 | #endif | ||
921 | |||
922 | rbtx4938_spi_setup(); | ||
923 | pcfg = tx4938_ccfgptr->pcfg; /* updated */ | ||
924 | /* fixup piosel */ | ||
925 | if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) == | ||
926 | TX4938_PCFG_ATA_SEL) | ||
927 | writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x04, | ||
928 | rbtx4938_piosel_addr); | ||
929 | else if ((pcfg & (TX4938_PCFG_ATA_SEL | TX4938_PCFG_NDF_SEL)) == | ||
930 | TX4938_PCFG_NDF_SEL) | ||
931 | writeb((readb(rbtx4938_piosel_addr) & 0x03) | 0x08, | ||
932 | rbtx4938_piosel_addr); | ||
933 | else | ||
934 | writeb(readb(rbtx4938_piosel_addr) & ~(0x08 | 0x04), | ||
935 | rbtx4938_piosel_addr); | ||
936 | |||
937 | rbtx4938_fpga_resource.name = "FPGA Registers"; | ||
938 | rbtx4938_fpga_resource.start = CPHYSADDR(RBTX4938_FPGA_REG_ADDR); | ||
939 | rbtx4938_fpga_resource.end = CPHYSADDR(RBTX4938_FPGA_REG_ADDR) + 0xffff; | ||
940 | rbtx4938_fpga_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY; | ||
941 | if (request_resource(&iomem_resource, &rbtx4938_fpga_resource)) | ||
942 | printk("request resource for fpga failed\n"); | ||
943 | |||
944 | _machine_restart = rbtx4938_machine_restart; | ||
945 | _machine_halt = rbtx4938_machine_halt; | ||
946 | pm_power_off = rbtx4938_machine_power_off; | ||
947 | |||
948 | writeb(0xff, rbtx4938_led_addr); | ||
949 | printk(KERN_INFO "RBTX4938 --- FPGA(Rev %02x) DIPSW:%02x,%02x\n", | ||
950 | readb(rbtx4938_fpga_rev_addr), | ||
951 | readb(rbtx4938_dipsw_addr), readb(rbtx4938_bdipsw_addr)); | ||
952 | } | ||
953 | |||
954 | static int __init rbtx4938_ne_init(void) | ||
955 | { | ||
956 | struct resource res[] = { | ||
957 | { | ||
958 | .start = RBTX4938_RTL_8019_BASE, | ||
959 | .end = RBTX4938_RTL_8019_BASE + 0x20 - 1, | ||
960 | .flags = IORESOURCE_IO, | ||
961 | }, { | ||
962 | .start = RBTX4938_RTL_8019_IRQ, | ||
963 | .flags = IORESOURCE_IRQ, | ||
964 | } | ||
965 | }; | ||
966 | struct platform_device *dev = | ||
967 | platform_device_register_simple("ne", -1, | ||
968 | res, ARRAY_SIZE(res)); | ||
969 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | ||
970 | } | ||
971 | device_initcall(rbtx4938_ne_init); | ||
972 | |||
973 | /* GPIO support */ | ||
974 | |||
975 | int gpio_to_irq(unsigned gpio) | ||
976 | { | ||
977 | return -EINVAL; | ||
978 | } | ||
979 | |||
980 | int irq_to_gpio(unsigned irq) | ||
981 | { | ||
982 | return -EINVAL; | ||
983 | } | ||
984 | |||
985 | static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock); | ||
986 | |||
987 | static void rbtx4938_spi_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
988 | int value) | ||
989 | { | ||
990 | u8 val; | ||
991 | unsigned long flags; | ||
992 | spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags); | ||
993 | val = readb(rbtx4938_spics_addr); | ||
994 | if (value) | ||
995 | val |= 1 << offset; | ||
996 | else | ||
997 | val &= ~(1 << offset); | ||
998 | writeb(val, rbtx4938_spics_addr); | ||
999 | mmiowb(); | ||
1000 | spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags); | ||
1001 | } | ||
1002 | |||
1003 | static int rbtx4938_spi_gpio_dir_out(struct gpio_chip *chip, | ||
1004 | unsigned int offset, int value) | ||
1005 | { | ||
1006 | rbtx4938_spi_gpio_set(chip, offset, value); | ||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | static struct gpio_chip rbtx4938_spi_gpio_chip = { | ||
1011 | .set = rbtx4938_spi_gpio_set, | ||
1012 | .direction_output = rbtx4938_spi_gpio_dir_out, | ||
1013 | .label = "RBTX4938-SPICS", | ||
1014 | .base = 16, | ||
1015 | .ngpio = 3, | ||
1016 | }; | ||
1017 | |||
1018 | /* SPI support */ | ||
1019 | |||
1020 | static void __init txx9_spi_init(unsigned long base, int irq) | ||
1021 | { | ||
1022 | struct resource res[] = { | ||
1023 | { | ||
1024 | .start = base, | ||
1025 | .end = base + 0x20 - 1, | ||
1026 | .flags = IORESOURCE_MEM, | ||
1027 | }, { | ||
1028 | .start = irq, | ||
1029 | .flags = IORESOURCE_IRQ, | ||
1030 | }, | ||
1031 | }; | ||
1032 | platform_device_register_simple("spi_txx9", 0, | ||
1033 | res, ARRAY_SIZE(res)); | ||
1034 | } | ||
1035 | |||
1036 | static int __init rbtx4938_spi_init(void) | ||
1037 | { | ||
1038 | struct spi_board_info srtc_info = { | ||
1039 | .modalias = "rtc-rs5c348", | ||
1040 | .max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */ | ||
1041 | .bus_num = 0, | ||
1042 | .chip_select = 16 + SRTC_CS, | ||
1043 | /* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS */ | ||
1044 | .mode = SPI_MODE_1 | SPI_CS_HIGH, | ||
1045 | }; | ||
1046 | spi_register_board_info(&srtc_info, 1); | ||
1047 | spi_eeprom_register(SEEPROM1_CS); | ||
1048 | spi_eeprom_register(16 + SEEPROM2_CS); | ||
1049 | spi_eeprom_register(16 + SEEPROM3_CS); | ||
1050 | gpio_request(16 + SRTC_CS, "rtc-rs5c348"); | ||
1051 | gpio_direction_output(16 + SRTC_CS, 0); | ||
1052 | gpio_request(SEEPROM1_CS, "seeprom1"); | ||
1053 | gpio_direction_output(SEEPROM1_CS, 1); | ||
1054 | gpio_request(16 + SEEPROM2_CS, "seeprom2"); | ||
1055 | gpio_direction_output(16 + SEEPROM2_CS, 1); | ||
1056 | gpio_request(16 + SEEPROM3_CS, "seeprom3"); | ||
1057 | gpio_direction_output(16 + SEEPROM3_CS, 1); | ||
1058 | txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI); | ||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static int __init rbtx4938_arch_init(void) | ||
1063 | { | ||
1064 | txx9_gpio_init(TX4938_PIO_REG & 0xfffffffffULL, 0, 16); | ||
1065 | gpiochip_add(&rbtx4938_spi_gpio_chip); | ||
1066 | return rbtx4938_spi_init(); | ||
1067 | } | ||
1068 | arch_initcall(rbtx4938_arch_init); | ||
1069 | |||
1070 | /* Watchdog support */ | ||
1071 | |||
1072 | static int __init txx9_wdt_init(unsigned long base) | ||
1073 | { | ||
1074 | struct resource res = { | ||
1075 | .start = base, | ||
1076 | .end = base + 0x100 - 1, | ||
1077 | .flags = IORESOURCE_MEM, | ||
1078 | }; | ||
1079 | struct platform_device *dev = | ||
1080 | platform_device_register_simple("txx9wdt", -1, &res, 1); | ||
1081 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | ||
1082 | } | ||
1083 | |||
1084 | static int __init rbtx4938_wdt_init(void) | ||
1085 | { | ||
1086 | return txx9_wdt_init(TX4938_TMR_REG(2) & 0xfffffffffULL); | ||
1087 | } | ||
1088 | device_initcall(rbtx4938_wdt_init); | ||
1089 | |||
1090 | /* Minimum CLK support */ | ||
1091 | |||
1092 | struct clk *clk_get(struct device *dev, const char *id) | ||
1093 | { | ||
1094 | if (!strcmp(id, "spi-baseclk")) | ||
1095 | return (struct clk *)(txx9_gbus_clock / 2 / 4); | ||
1096 | if (!strcmp(id, "imbus_clk")) | ||
1097 | return (struct clk *)(txx9_gbus_clock / 2); | ||
1098 | return ERR_PTR(-ENOENT); | ||
1099 | } | ||
1100 | EXPORT_SYMBOL(clk_get); | ||
1101 | |||
1102 | int clk_enable(struct clk *clk) | ||
1103 | { | ||
1104 | return 0; | ||
1105 | } | ||
1106 | EXPORT_SYMBOL(clk_enable); | ||
1107 | |||
1108 | void clk_disable(struct clk *clk) | ||
1109 | { | ||
1110 | } | ||
1111 | EXPORT_SYMBOL(clk_disable); | ||
1112 | |||
1113 | unsigned long clk_get_rate(struct clk *clk) | ||
1114 | { | ||
1115 | return (unsigned long)clk; | ||
1116 | } | ||
1117 | EXPORT_SYMBOL(clk_get_rate); | ||
1118 | |||
1119 | void clk_put(struct clk *clk) | ||
1120 | { | ||
1121 | } | ||
1122 | EXPORT_SYMBOL(clk_put); | ||
diff --git a/arch/mips/txx9/rbtx4938/spi_eeprom.c b/arch/mips/txx9/rbtx4938/spi_eeprom.c new file mode 100644 index 000000000000..a7ea8b041c1d --- /dev/null +++ b/arch/mips/txx9/rbtx4938/spi_eeprom.c | |||
@@ -0,0 +1,99 @@ | |||
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/device.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/spi/eeprom.h> | ||
16 | #include <asm/txx9/spi.h> | ||
17 | |||
18 | #define AT250X0_PAGE_SIZE 8 | ||
19 | |||
20 | /* register board information for at25 driver */ | ||
21 | int __init spi_eeprom_register(int chipid) | ||
22 | { | ||
23 | static struct spi_eeprom eeprom = { | ||
24 | .name = "at250x0", | ||
25 | .byte_len = 128, | ||
26 | .page_size = AT250X0_PAGE_SIZE, | ||
27 | .flags = EE_ADDR1, | ||
28 | }; | ||
29 | struct spi_board_info info = { | ||
30 | .modalias = "at25", | ||
31 | .max_speed_hz = 1500000, /* 1.5Mbps */ | ||
32 | .bus_num = 0, | ||
33 | .chip_select = chipid, | ||
34 | .platform_data = &eeprom, | ||
35 | /* Mode 0: High-Active, Sample-Then-Shift */ | ||
36 | }; | ||
37 | |||
38 | return spi_register_board_info(&info, 1); | ||
39 | } | ||
40 | |||
41 | /* simple temporary spi driver to provide early access to seeprom. */ | ||
42 | |||
43 | static struct read_param { | ||
44 | int chipid; | ||
45 | int address; | ||
46 | unsigned char *buf; | ||
47 | int len; | ||
48 | } *read_param; | ||
49 | |||
50 | static int __init early_seeprom_probe(struct spi_device *spi) | ||
51 | { | ||
52 | int stat = 0; | ||
53 | u8 cmd[2]; | ||
54 | int len = read_param->len; | ||
55 | char *buf = read_param->buf; | ||
56 | int address = read_param->address; | ||
57 | |||
58 | dev_info(&spi->dev, "spiclk %u KHz.\n", | ||
59 | (spi->max_speed_hz + 500) / 1000); | ||
60 | if (read_param->chipid != spi->chip_select) | ||
61 | return -ENODEV; | ||
62 | while (len > 0) { | ||
63 | /* spi_write_then_read can only work with small chunk */ | ||
64 | int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE; | ||
65 | cmd[0] = 0x03; /* AT25_READ */ | ||
66 | cmd[1] = address; | ||
67 | stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c); | ||
68 | buf += c; | ||
69 | len -= c; | ||
70 | address += c; | ||
71 | } | ||
72 | return stat; | ||
73 | } | ||
74 | |||
75 | static struct spi_driver early_seeprom_driver __initdata = { | ||
76 | .driver = { | ||
77 | .name = "at25", | ||
78 | .owner = THIS_MODULE, | ||
79 | }, | ||
80 | .probe = early_seeprom_probe, | ||
81 | }; | ||
82 | |||
83 | int __init spi_eeprom_read(int chipid, int address, | ||
84 | unsigned char *buf, int len) | ||
85 | { | ||
86 | int ret; | ||
87 | struct read_param param = { | ||
88 | .chipid = chipid, | ||
89 | .address = address, | ||
90 | .buf = buf, | ||
91 | .len = len | ||
92 | }; | ||
93 | |||
94 | read_param = ¶m; | ||
95 | ret = spi_register_driver(&early_seeprom_driver); | ||
96 | if (!ret) | ||
97 | spi_unregister_driver(&early_seeprom_driver); | ||
98 | return ret; | ||
99 | } | ||