2 * arch/ppc/platforms/cpci690.c
4 * Board setup routines for the Force CPCI690 board.
6 * Author: Mark A. Greer <mgreer@mvista.com>
8 * 2003 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This programr
10 * is licensed "as is" without any warranty of any kind, whether express
13 #include <linux/config.h>
14 #include <linux/delay.h>
15 #include <linux/pci.h>
16 #include <linux/ide.h>
17 #include <linux/irq.h>
19 #include <linux/seq_file.h>
20 #include <linux/console.h>
21 #include <linux/initrd.h>
22 #include <linux/root_dev.h>
23 #include <linux/mv643xx.h>
24 #include <asm/bootinfo.h>
25 #include <asm/machdep.h>
28 #include <asm/mv64x60.h>
29 #include <platforms/cpci690.h>
31 #define BOARD_VENDOR "Force"
32 #define BOARD_MACHINE "CPCI690"
34 /* Set IDE controllers into Native mode? */
35 #define SET_PCI_IDE_NATIVE
37 static struct mv64x60_handle bh
;
38 static u32 cpci690_br_base
;
40 static const unsigned int cpu_7xx
[16] = { /* 7xx & 74xx (but not 745x) */
41 18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
47 cpci690_map_irq(struct pci_dev
*dev
, unsigned char idsel
, unsigned char pin
)
49 struct pci_controller
*hose
= pci_bus_to_hose(dev
->bus
->number
);
51 if (hose
->index
== 0) {
52 static char pci_irq_table
[][4] =
54 * PCI IDSEL/INTPIN->INTLINE
58 { 90, 91, 88, 89}, /* IDSEL 30/20 - Sentinel */
61 const long min_idsel
= 20, max_idsel
= 20, irqs_per_slot
= 4;
62 return PCI_IRQ_TABLE_LOOKUP
;
64 static char pci_irq_table
[][4] =
66 * PCI IDSEL/INTPIN->INTLINE
70 { 93, 94, 95, 92}, /* IDSEL 28/18 - PMC slot 2 */
71 { 0, 0, 0, 0}, /* IDSEL 29/19 - Not used */
72 { 94, 95, 92, 93}, /* IDSEL 30/20 - PMC slot 1 */
75 const long min_idsel
= 18, max_idsel
= 20, irqs_per_slot
= 4;
76 return PCI_IRQ_TABLE_LOOKUP
;
81 cpci690_get_cpu_speed(void)
85 hid1
= mfspr(SPRN_HID1
) >> 28;
86 return CPCI690_BUS_FREQ
* cpu_7xx
[hid1
]/2;
90 #define MB (1024UL * KB)
91 #define GB (1024UL * MB)
94 cpci690_find_end_of_memory(void)
97 static u32 board_size
;
98 static u8 first_time
= 1;
101 /* Using cpci690_set_bat() mapping ==> virt addr == phys addr */
102 switch (in_8((u8
*) (cpci690_br_base
+
103 CPCI690_BR_MEM_CTLR
)) & 0x07) {
117 board_size
= 1*GB
+ 512*MB
;
123 board_size
= 0xffffffff; /* use mem ctlr size */
126 mem_ctlr_size
= mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE
,
127 MV64x60_TYPE_GT64260A
);
129 /* Check that mem ctlr & board reg agree. If not, pick MIN. */
130 if (board_size
!= mem_ctlr_size
) {
131 printk(KERN_WARNING
"Board register & memory controller"
132 "mem size disagree (board reg: 0x%lx, "
133 "mem ctlr: 0x%lx)\n",
134 (ulong
)board_size
, (ulong
)mem_ctlr_size
);
135 board_size
= min(board_size
, mem_ctlr_size
);
145 cpci690_setup_bridge(void)
147 struct mv64x60_setup_info si
;
150 memset(&si
, 0, sizeof(si
));
152 si
.phys_reg_base
= CONFIG_MV64X60_NEW_BASE
;
154 si
.pci_0
.enable_bus
= 1;
155 si
.pci_0
.pci_io
.cpu_base
= CPCI690_PCI0_IO_START_PROC_ADDR
;
156 si
.pci_0
.pci_io
.pci_base_hi
= 0;
157 si
.pci_0
.pci_io
.pci_base_lo
= CPCI690_PCI0_IO_START_PCI_ADDR
;
158 si
.pci_0
.pci_io
.size
= CPCI690_PCI0_IO_SIZE
;
159 si
.pci_0
.pci_io
.swap
= MV64x60_CPU2PCI_SWAP_NONE
;
160 si
.pci_0
.pci_mem
[0].cpu_base
= CPCI690_PCI0_MEM_START_PROC_ADDR
;
161 si
.pci_0
.pci_mem
[0].pci_base_hi
= CPCI690_PCI0_MEM_START_PCI_HI_ADDR
;
162 si
.pci_0
.pci_mem
[0].pci_base_lo
= CPCI690_PCI0_MEM_START_PCI_LO_ADDR
;
163 si
.pci_0
.pci_mem
[0].size
= CPCI690_PCI0_MEM_SIZE
;
164 si
.pci_0
.pci_mem
[0].swap
= MV64x60_CPU2PCI_SWAP_NONE
;
165 si
.pci_0
.pci_cmd_bits
= 0;
166 si
.pci_0
.latency_timer
= 0x80;
168 si
.pci_1
.enable_bus
= 1;
169 si
.pci_1
.pci_io
.cpu_base
= CPCI690_PCI1_IO_START_PROC_ADDR
;
170 si
.pci_1
.pci_io
.pci_base_hi
= 0;
171 si
.pci_1
.pci_io
.pci_base_lo
= CPCI690_PCI1_IO_START_PCI_ADDR
;
172 si
.pci_1
.pci_io
.size
= CPCI690_PCI1_IO_SIZE
;
173 si
.pci_1
.pci_io
.swap
= MV64x60_CPU2PCI_SWAP_NONE
;
174 si
.pci_1
.pci_mem
[0].cpu_base
= CPCI690_PCI1_MEM_START_PROC_ADDR
;
175 si
.pci_1
.pci_mem
[0].pci_base_hi
= CPCI690_PCI1_MEM_START_PCI_HI_ADDR
;
176 si
.pci_1
.pci_mem
[0].pci_base_lo
= CPCI690_PCI1_MEM_START_PCI_LO_ADDR
;
177 si
.pci_1
.pci_mem
[0].size
= CPCI690_PCI1_MEM_SIZE
;
178 si
.pci_1
.pci_mem
[0].swap
= MV64x60_CPU2PCI_SWAP_NONE
;
179 si
.pci_1
.pci_cmd_bits
= 0;
180 si
.pci_1
.latency_timer
= 0x80;
182 for (i
=0; i
<MV64x60_CPU2MEM_WINDOWS
; i
++) {
183 si
.cpu_prot_options
[i
] = 0;
184 si
.cpu_snoop_options
[i
] = GT64260_CPU_SNOOP_WB
;
185 si
.pci_0
.acc_cntl_options
[i
] =
186 GT64260_PCI_ACC_CNTL_DREADEN
|
187 GT64260_PCI_ACC_CNTL_RDPREFETCH
|
188 GT64260_PCI_ACC_CNTL_RDLINEPREFETCH
|
189 GT64260_PCI_ACC_CNTL_RDMULPREFETCH
|
190 GT64260_PCI_ACC_CNTL_SWAP_NONE
|
191 GT64260_PCI_ACC_CNTL_MBURST_32_BTYES
;
192 si
.pci_0
.snoop_options
[i
] = GT64260_PCI_SNOOP_WB
;
193 si
.pci_1
.acc_cntl_options
[i
] =
194 GT64260_PCI_ACC_CNTL_DREADEN
|
195 GT64260_PCI_ACC_CNTL_RDPREFETCH
|
196 GT64260_PCI_ACC_CNTL_RDLINEPREFETCH
|
197 GT64260_PCI_ACC_CNTL_RDMULPREFETCH
|
198 GT64260_PCI_ACC_CNTL_SWAP_NONE
|
199 GT64260_PCI_ACC_CNTL_MBURST_32_BTYES
;
200 si
.pci_1
.snoop_options
[i
] = GT64260_PCI_SNOOP_WB
;
203 /* Lookup PCI host bridges */
204 if (mv64x60_init(&bh
, &si
))
205 printk(KERN_ERR
"Bridge initialization failed.\n");
207 pci_dram_offset
= 0; /* System mem at same addr on PCI & cpu bus */
208 ppc_md
.pci_swizzle
= common_swizzle
;
209 ppc_md
.pci_map_irq
= cpci690_map_irq
;
210 ppc_md
.pci_exclude_device
= mv64x60_pci_exclude_device
;
212 mv64x60_set_bus(&bh
, 0, 0);
213 bh
.hose_a
->first_busno
= 0;
214 bh
.hose_a
->last_busno
= 0xff;
215 bh
.hose_a
->last_busno
= pciauto_bus_scan(bh
.hose_a
, 0);
217 bh
.hose_b
->first_busno
= bh
.hose_a
->last_busno
+ 1;
218 mv64x60_set_bus(&bh
, 1, bh
.hose_b
->first_busno
);
219 bh
.hose_b
->last_busno
= 0xff;
220 bh
.hose_b
->last_busno
= pciauto_bus_scan(bh
.hose_b
,
221 bh
.hose_b
->first_busno
);
225 cpci690_setup_peripherals(void)
227 /* Set up windows to CPLD, RTC/TODC, IPMI. */
228 mv64x60_set_32bit_window(&bh
, MV64x60_CPU2DEV_0_WIN
, CPCI690_BR_BASE
,
230 bh
.ci
->enable_window_32bit(&bh
, MV64x60_CPU2DEV_0_WIN
);
231 cpci690_br_base
= (u32
)ioremap(CPCI690_BR_BASE
, CPCI690_BR_SIZE
);
233 mv64x60_set_32bit_window(&bh
, MV64x60_CPU2DEV_1_WIN
, CPCI690_TODC_BASE
,
234 CPCI690_TODC_SIZE
, 0);
235 bh
.ci
->enable_window_32bit(&bh
, MV64x60_CPU2DEV_1_WIN
);
236 TODC_INIT(TODC_TYPE_MK48T35
, 0, 0,
237 ioremap(CPCI690_TODC_BASE
, CPCI690_TODC_SIZE
), 8);
239 mv64x60_set_32bit_window(&bh
, MV64x60_CPU2DEV_2_WIN
, CPCI690_IPMI_BASE
,
240 CPCI690_IPMI_SIZE
, 0);
241 bh
.ci
->enable_window_32bit(&bh
, MV64x60_CPU2DEV_2_WIN
);
243 mv64x60_set_bits(&bh
, MV64x60_PCI0_ARBITER_CNTL
, (1<<31));
244 mv64x60_set_bits(&bh
, MV64x60_PCI1_ARBITER_CNTL
, (1<<31));
246 mv64x60_set_bits(&bh
, MV64x60_CPU_MASTER_CNTL
, (1<<9)); /* Only 1 cpu */
249 * Turn off timer/counters. Not turning off watchdog timer because
250 * can't read its reg on the 64260A so don't know if we'll be enabling
253 mv64x60_clr_bits(&bh
, MV64x60_TIMR_CNTR_0_3_CNTL
,
254 ((1<<0) | (1<<8) | (1<<16) | (1<<24)));
255 mv64x60_clr_bits(&bh
, GT64260_TIMR_CNTR_4_7_CNTL
,
256 ((1<<0) | (1<<8) | (1<<16) | (1<<24)));
259 * Set MPSC Multiplex RMII
260 * NOTE: ethernet driver modifies bit 0 and 1
262 mv64x60_write(&bh
, GT64260_MPP_SERIAL_PORTS_MULTIPLEX
, 0x00001102);
264 #define GPP_EXTERNAL_INTERRUPTS \
265 ((1<<24) | (1<<25) | (1<<26) | (1<<27) | \
266 (1<<28) | (1<<29) | (1<<30) | (1<<31))
267 /* PCI interrupts are inputs */
268 mv64x60_clr_bits(&bh
, MV64x60_GPP_IO_CNTL
, GPP_EXTERNAL_INTERRUPTS
);
269 /* PCI interrupts are active low */
270 mv64x60_set_bits(&bh
, MV64x60_GPP_LEVEL_CNTL
, GPP_EXTERNAL_INTERRUPTS
);
272 /* Clear any pending interrupts for these inputs and enable them. */
273 mv64x60_write(&bh
, MV64x60_GPP_INTR_CAUSE
, ~GPP_EXTERNAL_INTERRUPTS
);
274 mv64x60_set_bits(&bh
, MV64x60_GPP_INTR_MASK
, GPP_EXTERNAL_INTERRUPTS
);
276 /* Route MPP interrupt inputs to GPP */
277 mv64x60_write(&bh
, MV64x60_MPP_CNTL_2
, 0x00000000);
278 mv64x60_write(&bh
, MV64x60_MPP_CNTL_3
, 0x00000000);
282 cpci690_setup_arch(void)
285 ppc_md
.progress("cpci690_setup_arch: enter", 0);
286 #ifdef CONFIG_BLK_DEV_INITRD
288 ROOT_DEV
= Root_RAM0
;
291 #ifdef CONFIG_ROOT_NFS
294 ROOT_DEV
= Root_SDA2
;
298 ppc_md
.progress("cpci690_setup_arch: Enabling L2 cache", 0);
300 /* Enable L2 and L3 caches (if 745x) */
301 _set_L2CR(_get_L2CR() | L2CR_L2E
);
302 _set_L3CR(_get_L3CR() | L3CR_L3E
);
305 ppc_md
.progress("cpci690_setup_arch: Initializing bridge", 0);
307 cpci690_setup_bridge(); /* set up PCI bridge(s) */
308 cpci690_setup_peripherals(); /* set up chip selects/GPP/MPP etc */
311 ppc_md
.progress("cpci690_setup_arch: bridge init complete", 0);
313 printk(KERN_INFO
"%s %s port (C) 2003 MontaVista Software, Inc. "
314 "(source@mvista.com)\n", BOARD_VENDOR
, BOARD_MACHINE
);
317 ppc_md
.progress("cpci690_setup_arch: exit", 0);
320 /* Platform device data fixup routines. */
321 #if defined(CONFIG_SERIAL_MPSC)
323 cpci690_fixup_mpsc_pdata(struct platform_device
*pdev
)
325 struct mpsc_pdata
*pdata
;
327 pdata
= (struct mpsc_pdata
*)pdev
->dev
.platform_data
;
329 pdata
->max_idle
= 40;
330 pdata
->default_baud
= CPCI690_MPSC_BAUD
;
331 pdata
->brg_clk_src
= CPCI690_MPSC_CLK_SRC
;
332 pdata
->brg_clk_freq
= CPCI690_BUS_FREQ
;
336 cpci690_platform_notify(struct device
*dev
)
340 void ((*rtn
)(struct platform_device
*pdev
));
342 { MPSC_CTLR_NAME
".0", cpci690_fixup_mpsc_pdata
},
343 { MPSC_CTLR_NAME
".1", cpci690_fixup_mpsc_pdata
},
345 struct platform_device
*pdev
;
348 if (dev
&& dev
->bus_id
)
349 for (i
=0; i
<ARRAY_SIZE(dev_map
); i
++)
350 if (!strncmp(dev
->bus_id
, dev_map
[i
].bus_id
,
353 pdev
= container_of(dev
,
354 struct platform_device
, dev
);
355 dev_map
[i
].rtn(pdev
);
363 cpci690_reset_board(void)
368 out_8((u8
*)(cpci690_br_base
+ CPCI690_BR_SW_RESET
), 0x11);
371 panic("restart failed\n");
375 cpci690_restart(char *cmd
)
377 cpci690_reset_board();
388 cpci690_power_off(void)
395 cpci690_show_cpuinfo(struct seq_file
*m
)
397 seq_printf(m
, "vendor\t\t: " BOARD_VENDOR
"\n");
398 seq_printf(m
, "machine\t\t: " BOARD_MACHINE
"\n");
399 seq_printf(m
, "cpu MHz\t\t: %d\n", cpci690_get_cpu_speed()/1000/1000);
400 seq_printf(m
, "bus MHz\t\t: %d\n", CPCI690_BUS_FREQ
/1000/1000);
406 cpci690_calibrate_decr(void)
410 freq
= CPCI690_BUS_FREQ
/ 4;
412 printk(KERN_INFO
"time_init: decrementer frequency = %lu.%.6lu MHz\n",
413 freq
/1000000, freq
%1000000);
415 tb_ticks_per_jiffy
= freq
/ HZ
;
416 tb_to_us
= mulhwu_scale_factor(freq
, 1000000);
419 static __inline__
void
420 cpci690_set_bat(u32 addr
, u32 size
)
424 size
= ((size
>> 17) - 1) << 2;
427 mtspr(SPRN_DBAT1U
, addr
| size
| 0x2); /* Vs == 1; Vp == 0 */
428 mtspr(SPRN_DBAT1L
, addr
| 0x2a); /* WIMG bits == 0101; PP == r/w access */
432 #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
436 io_block_mapping(CONFIG_MV64X60_NEW_BASE
, CONFIG_MV64X60_NEW_BASE
,
442 platform_init(unsigned long r3
, unsigned long r4
, unsigned long r5
,
443 unsigned long r6
, unsigned long r7
)
445 #ifdef CONFIG_BLK_DEV_INITRD
446 initrd_start
=initrd_end
=0;
447 initrd_below_start_ok
=0;
448 #endif /* CONFIG_BLK_DEV_INITRD */
450 parse_bootinfo(find_bootinfo());
452 loops_per_jiffy
= cpci690_get_cpu_speed() / HZ
;
456 ppc_md
.setup_arch
= cpci690_setup_arch
;
457 ppc_md
.show_cpuinfo
= cpci690_show_cpuinfo
;
458 ppc_md
.init_IRQ
= gt64260_init_irq
;
459 ppc_md
.get_irq
= gt64260_get_irq
;
460 ppc_md
.restart
= cpci690_restart
;
461 ppc_md
.power_off
= cpci690_power_off
;
462 ppc_md
.halt
= cpci690_halt
;
463 ppc_md
.find_end_of_memory
= cpci690_find_end_of_memory
;
464 ppc_md
.time_init
= todc_time_init
;
465 ppc_md
.set_rtc_time
= todc_set_rtc_time
;
466 ppc_md
.get_rtc_time
= todc_get_rtc_time
;
467 ppc_md
.nvram_read_val
= todc_direct_read_val
;
468 ppc_md
.nvram_write_val
= todc_direct_write_val
;
469 ppc_md
.calibrate_decr
= cpci690_calibrate_decr
;
472 * Need to map in board regs (used by cpci690_find_end_of_memory())
473 * and the bridge's regs (used by progress);
475 cpci690_set_bat(CPCI690_BR_BASE
, 32 * MB
);
476 cpci690_br_base
= CPCI690_BR_BASE
;
478 #ifdef CONFIG_SERIAL_TEXT_DEBUG
479 ppc_md
.setup_io_mappings
= cpci690_map_io
;
480 ppc_md
.progress
= mv64x60_mpsc_progress
;
481 mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE
);
482 #endif /* CONFIG_SERIAL_TEXT_DEBUG */
484 ppc_md
.setup_io_mappings
= cpci690_map_io
;
485 ppc_md
.early_serial_map
= cpci690_early_serial_map
;
486 #endif /* CONFIG_KGDB */
488 #if defined(CONFIG_SERIAL_MPSC)
489 platform_notify
= cpci690_platform_notify
;