summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/config.mk52
-rw-r--r--arch/powerpc/cpu/74xx_7xx/Makefile51
-rw-r--r--arch/powerpc/cpu/74xx_7xx/cache.S404
-rw-r--r--arch/powerpc/cpu/74xx_7xx/config.mk26
-rw-r--r--arch/powerpc/cpu/74xx_7xx/cpu.c316
-rw-r--r--arch/powerpc/cpu/74xx_7xx/cpu_init.c63
-rw-r--r--arch/powerpc/cpu/74xx_7xx/interrupts.c104
-rw-r--r--arch/powerpc/cpu/74xx_7xx/io.S128
-rw-r--r--arch/powerpc/cpu/74xx_7xx/kgdb.S77
-rw-r--r--arch/powerpc/cpu/74xx_7xx/speed.c181
-rw-r--r--arch/powerpc/cpu/74xx_7xx/start.S856
-rw-r--r--arch/powerpc/cpu/74xx_7xx/traps.c234
-rw-r--r--arch/powerpc/cpu/74xx_7xx/u-boot.lds94
-rw-r--r--arch/powerpc/cpu/mpc512x/Makefile63
-rw-r--r--arch/powerpc/cpu/mpc512x/asm-offsets.h15
-rw-r--r--arch/powerpc/cpu/mpc512x/cache.c33
-rw-r--r--arch/powerpc/cpu/mpc512x/config.mk26
-rw-r--r--arch/powerpc/cpu/mpc512x/cpu.c216
-rw-r--r--arch/powerpc/cpu/mpc512x/cpu_init.c212
-rw-r--r--arch/powerpc/cpu/mpc512x/diu.c60
-rw-r--r--arch/powerpc/cpu/mpc512x/fixed_sdram.c172
-rw-r--r--arch/powerpc/cpu/mpc512x/i2c.c402
-rw-r--r--arch/powerpc/cpu/mpc512x/ide.c128
-rw-r--r--arch/powerpc/cpu/mpc512x/interrupts.c61
-rw-r--r--arch/powerpc/cpu/mpc512x/iopin.c103
-rw-r--r--arch/powerpc/cpu/mpc512x/pci.c225
-rw-r--r--arch/powerpc/cpu/mpc512x/serial.c459
-rw-r--r--arch/powerpc/cpu/mpc512x/speed.c153
-rw-r--r--arch/powerpc/cpu/mpc512x/start.S708
-rw-r--r--arch/powerpc/cpu/mpc512x/traps.c204
-rw-r--r--arch/powerpc/cpu/mpc512x/u-boot.lds90
-rw-r--r--arch/powerpc/cpu/mpc5xx/Makefile59
-rw-r--r--arch/powerpc/cpu/mpc5xx/config.mk26
-rw-r--r--arch/powerpc/cpu/mpc5xx/cpu.c171
-rw-r--r--arch/powerpc/cpu/mpc5xx/cpu_init.c123
-rw-r--r--arch/powerpc/cpu/mpc5xx/interrupts.c207
-rw-r--r--arch/powerpc/cpu/mpc5xx/serial.c183
-rw-r--r--arch/powerpc/cpu/mpc5xx/speed.c67
-rw-r--r--arch/powerpc/cpu/mpc5xx/spi.c412
-rw-r--r--arch/powerpc/cpu/mpc5xx/start.S561
-rw-r--r--arch/powerpc/cpu/mpc5xx/traps.c227
-rw-r--r--arch/powerpc/cpu/mpc5xx/u-boot.lds103
-rw-r--r--arch/powerpc/cpu/mpc5xxx/Makefile64
-rw-r--r--arch/powerpc/cpu/mpc5xxx/config.mk27
-rw-r--r--arch/powerpc/cpu/mpc5xxx/cpu.c184
-rw-r--r--arch/powerpc/cpu/mpc5xxx/cpu_init.c247
-rw-r--r--arch/powerpc/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S359
-rw-r--r--arch/powerpc/cpu/mpc5xxx/i2c.c472
-rw-r--r--arch/powerpc/cpu/mpc5xxx/ide.c99
-rw-r--r--arch/powerpc/cpu/mpc5xxx/interrupts.c346
-rw-r--r--arch/powerpc/cpu/mpc5xxx/io.S128
-rw-r--r--arch/powerpc/cpu/mpc5xxx/loadtask.c76
-rw-r--r--arch/powerpc/cpu/mpc5xxx/pci_mpc5200.c187
-rw-r--r--arch/powerpc/cpu/mpc5xxx/serial.c292
-rw-r--r--arch/powerpc/cpu/mpc5xxx/speed.c100
-rw-r--r--arch/powerpc/cpu/mpc5xxx/spl_boot.c87
-rw-r--r--arch/powerpc/cpu/mpc5xxx/start.S783
-rw-r--r--arch/powerpc/cpu/mpc5xxx/traps.c236
-rw-r--r--arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds96
-rw-r--r--arch/powerpc/cpu/mpc5xxx/u-boot-spl.lds57
-rw-r--r--arch/powerpc/cpu/mpc5xxx/u-boot.lds92
-rw-r--r--arch/powerpc/cpu/mpc5xxx/usb.c58
-rw-r--r--arch/powerpc/cpu/mpc5xxx/usb_ohci.c1644
-rw-r--r--arch/powerpc/cpu/mpc5xxx/usb_ohci.h418
-rw-r--r--arch/powerpc/cpu/mpc824x/.gitignore1
-rw-r--r--arch/powerpc/cpu/mpc824x/Makefile55
-rw-r--r--arch/powerpc/cpu/mpc824x/config.mk26
-rw-r--r--arch/powerpc/cpu/mpc824x/cpu.c280
-rw-r--r--arch/powerpc/cpu/mpc824x/cpu_init.c417
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/epic.h1
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/epic/README102
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/epic/epic.h163
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c517
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S196
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S57
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/errors.h212
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c270
-rw-r--r--arch/powerpc/cpu/mpc824x/drivers/i2c_export.h103
-rw-r--r--arch/powerpc/cpu/mpc824x/interrupts.c93
-rw-r--r--arch/powerpc/cpu/mpc824x/pci.c78
-rw-r--r--arch/powerpc/cpu/mpc824x/speed.c118
-rw-r--r--arch/powerpc/cpu/mpc824x/start.S745
-rw-r--r--arch/powerpc/cpu/mpc824x/traps.c210
-rw-r--r--arch/powerpc/cpu/mpc824x/u-boot.lds92
-rw-r--r--arch/powerpc/cpu/mpc8260/Makefile53
-rw-r--r--arch/powerpc/cpu/mpc8260/bedbug_603e.c236
-rw-r--r--arch/powerpc/cpu/mpc8260/commproc.c178
-rw-r--r--arch/powerpc/cpu/mpc8260/config.mk27
-rw-r--r--arch/powerpc/cpu/mpc8260/cpu.c337
-rw-r--r--arch/powerpc/cpu/mpc8260/cpu_init.c292
-rw-r--r--arch/powerpc/cpu/mpc8260/ether_fcc.c1188
-rw-r--r--arch/powerpc/cpu/mpc8260/ether_scc.c383
-rw-r--r--arch/powerpc/cpu/mpc8260/i2c.c770
-rw-r--r--arch/powerpc/cpu/mpc8260/interrupts.c279
-rw-r--r--arch/powerpc/cpu/mpc8260/kgdb.S72
-rw-r--r--arch/powerpc/cpu/mpc8260/pci.c466
-rw-r--r--arch/powerpc/cpu/mpc8260/serial_scc.c508
-rw-r--r--arch/powerpc/cpu/mpc8260/serial_smc.c477
-rw-r--r--arch/powerpc/cpu/mpc8260/speed.c244
-rw-r--r--arch/powerpc/cpu/mpc8260/speed.h54
-rw-r--r--arch/powerpc/cpu/mpc8260/spi.c431
-rw-r--r--arch/powerpc/cpu/mpc8260/start.S1008
-rw-r--r--arch/powerpc/cpu/mpc8260/traps.c264
-rw-r--r--arch/powerpc/cpu/mpc8260/u-boot.lds91
-rw-r--r--arch/powerpc/cpu/mpc83xx/Makefile96
-rw-r--r--arch/powerpc/cpu/mpc83xx/cache.c33
-rw-r--r--arch/powerpc/cpu/mpc83xx/config.mk26
-rw-r--r--arch/powerpc/cpu/mpc83xx/cpu.c242
-rw-r--r--arch/powerpc/cpu/mpc83xx/cpu_init.c524
-rw-r--r--arch/powerpc/cpu/mpc83xx/ecc.c395
-rw-r--r--arch/powerpc/cpu/mpc83xx/fdt.c146
-rw-r--r--arch/powerpc/cpu/mpc83xx/interrupts.c97
-rw-r--r--arch/powerpc/cpu/mpc83xx/law.c61
-rw-r--r--arch/powerpc/cpu/mpc83xx/pci.c241
-rw-r--r--arch/powerpc/cpu/mpc83xx/pcie.c346
-rw-r--r--arch/powerpc/cpu/mpc83xx/qe_io.c82
-rw-r--r--arch/powerpc/cpu/mpc83xx/serdes.c154
-rw-r--r--arch/powerpc/cpu/mpc83xx/spd_sdram.c943
-rw-r--r--arch/powerpc/cpu/mpc83xx/speed.c609
-rw-r--r--arch/powerpc/cpu/mpc83xx/spl_minimal.c112
-rw-r--r--arch/powerpc/cpu/mpc83xx/start.S1211
-rw-r--r--arch/powerpc/cpu/mpc83xx/traps.c257
-rw-r--r--arch/powerpc/cpu/mpc83xx/u-boot-spl.lds55
-rw-r--r--arch/powerpc/cpu/mpc83xx/u-boot.lds91
-rw-r--r--arch/powerpc/cpu/mpc85xx/Makefile182
-rw-r--r--arch/powerpc/cpu/mpc85xx/b4860_ids.c147
-rw-r--r--arch/powerpc/cpu/mpc85xx/b4860_serdes.c222
-rw-r--r--arch/powerpc/cpu/mpc85xx/bsc9132_serdes.c96
-rw-r--r--arch/powerpc/cpu/mpc85xx/cache.c33
-rw-r--r--arch/powerpc/cpu/mpc85xx/cmd_errata.c271
-rw-r--r--arch/powerpc/cpu/mpc85xx/commproc.c186
-rw-r--r--arch/powerpc/cpu/mpc85xx/config.mk33
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu.c618
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu_init.c744
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu_init_early.c190
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen1.c89
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen2.c95
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen3.c430
-rw-r--r--arch/powerpc/cpu/mpc85xx/ether_fcc.c468
-rw-r--r--arch/powerpc/cpu/mpc85xx/fdt.c835
-rw-r--r--arch/powerpc/cpu/mpc85xx/fixed_ivor.S79
-rw-r--r--arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.c203
-rw-r--r--arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.h26
-rw-r--r--arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c876
-rw-r--r--arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.h41
-rw-r--r--arch/powerpc/cpu/mpc85xx/interrupts.c126
-rw-r--r--arch/powerpc/cpu/mpc85xx/liodn.c358
-rw-r--r--arch/powerpc/cpu/mpc85xx/mp.c488
-rw-r--r--arch/powerpc/cpu/mpc85xx/mp.h21
-rw-r--r--arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c249
-rw-r--r--arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c95
-rw-r--r--arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c65
-rw-r--r--arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c65
-rw-r--r--arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c74
-rw-r--r--arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c81
-rw-r--r--arch/powerpc/cpu/mpc85xx/p1010_serdes.c75
-rw-r--r--arch/powerpc/cpu/mpc85xx/p1021_serdes.c111
-rw-r--r--arch/powerpc/cpu/mpc85xx/p1022_serdes.c114
-rw-r--r--arch/powerpc/cpu/mpc85xx/p1023_serdes.c53
-rw-r--r--arch/powerpc/cpu/mpc85xx/p2020_serdes.c73
-rw-r--r--arch/powerpc/cpu/mpc85xx/p2041_ids.c129
-rw-r--r--arch/powerpc/cpu/mpc85xx/p2041_serdes.c106
-rw-r--r--arch/powerpc/cpu/mpc85xx/p3041_ids.c128
-rw-r--r--arch/powerpc/cpu/mpc85xx/p3041_serdes.c151
-rw-r--r--arch/powerpc/cpu/mpc85xx/p4080_ids.c128
-rw-r--r--arch/powerpc/cpu/mpc85xx/p4080_serdes.c98
-rw-r--r--arch/powerpc/cpu/mpc85xx/p5020_ids.c141
-rw-r--r--arch/powerpc/cpu/mpc85xx/p5020_serdes.c151
-rw-r--r--arch/powerpc/cpu/mpc85xx/p5040_ids.c127
-rw-r--r--arch/powerpc/cpu/mpc85xx/p5040_serdes.c117
-rw-r--r--arch/powerpc/cpu/mpc85xx/pci.c230
-rw-r--r--arch/powerpc/cpu/mpc85xx/portals.c324
-rw-r--r--arch/powerpc/cpu/mpc85xx/qe_io.c85
-rw-r--r--arch/powerpc/cpu/mpc85xx/release.S493
-rw-r--r--arch/powerpc/cpu/mpc85xx/resetvec.S2
-rw-r--r--arch/powerpc/cpu/mpc85xx/serial_scc.c278
-rw-r--r--arch/powerpc/cpu/mpc85xx/speed.c475
-rw-r--r--arch/powerpc/cpu/mpc85xx/spl_minimal.c59
-rw-r--r--arch/powerpc/cpu/mpc85xx/start.S1979
-rw-r--r--arch/powerpc/cpu/mpc85xx/t1040_ids.c135
-rw-r--r--arch/powerpc/cpu/mpc85xx/t1040_serdes.c93
-rw-r--r--arch/powerpc/cpu/mpc85xx/t4240_ids.c203
-rw-r--r--arch/powerpc/cpu/mpc85xx/t4240_serdes.c369
-rw-r--r--arch/powerpc/cpu/mpc85xx/tlb.c344
-rw-r--r--arch/powerpc/cpu/mpc85xx/traps.c313
-rw-r--r--arch/powerpc/cpu/mpc85xx/u-boot-nand.lds108
-rw-r--r--arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds85
-rw-r--r--arch/powerpc/cpu/mpc85xx/u-boot-spl.lds103
-rw-r--r--arch/powerpc/cpu/mpc85xx/u-boot.lds140
-rw-r--r--arch/powerpc/cpu/mpc86xx/Makefile65
-rw-r--r--arch/powerpc/cpu/mpc86xx/cache.S378
-rw-r--r--arch/powerpc/cpu/mpc86xx/config.mk27
-rw-r--r--arch/powerpc/cpu/mpc86xx/cpu.c218
-rw-r--r--arch/powerpc/cpu/mpc86xx/cpu_init.c118
-rw-r--r--arch/powerpc/cpu/mpc86xx/ddr-8641.c85
-rw-r--r--arch/powerpc/cpu/mpc86xx/fdt.c66
-rw-r--r--arch/powerpc/cpu/mpc86xx/interrupts.c131
-rw-r--r--arch/powerpc/cpu/mpc86xx/mp.c145
-rw-r--r--arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c85
-rw-r--r--arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c94
-rw-r--r--arch/powerpc/cpu/mpc86xx/release.S167
-rw-r--r--arch/powerpc/cpu/mpc86xx/speed.c160
-rw-r--r--arch/powerpc/cpu/mpc86xx/start.S1008
-rw-r--r--arch/powerpc/cpu/mpc86xx/traps.c224
-rw-r--r--arch/powerpc/cpu/mpc86xx/u-boot.lds95
-rw-r--r--arch/powerpc/cpu/mpc8xx/Makefile65
-rw-r--r--arch/powerpc/cpu/mpc8xx/bedbug_860.c314
-rw-r--r--arch/powerpc/cpu/mpc8xx/commproc.c85
-rw-r--r--arch/powerpc/cpu/mpc8xx/config.mk26
-rw-r--r--arch/powerpc/cpu/mpc8xx/cpu.c659
-rw-r--r--arch/powerpc/cpu/mpc8xx/cpu_init.c283
-rw-r--r--arch/powerpc/cpu/mpc8xx/fdt.c46
-rw-r--r--arch/powerpc/cpu/mpc8xx/fec.c1029
-rw-r--r--arch/powerpc/cpu/mpc8xx/fec.h28
-rw-r--r--arch/powerpc/cpu/mpc8xx/i2c.c704
-rw-r--r--arch/powerpc/cpu/mpc8xx/interrupts.c294
-rw-r--r--arch/powerpc/cpu/mpc8xx/kgdb.S74
-rw-r--r--arch/powerpc/cpu/mpc8xx/plprcr_write.S135
-rw-r--r--arch/powerpc/cpu/mpc8xx/scc.c558
-rw-r--r--arch/powerpc/cpu/mpc8xx/serial.c766
-rw-r--r--arch/powerpc/cpu/mpc8xx/speed.c416
-rw-r--r--arch/powerpc/cpu/mpc8xx/spi.c556
-rw-r--r--arch/powerpc/cpu/mpc8xx/start.S669
-rw-r--r--arch/powerpc/cpu/mpc8xx/traps.c232
-rw-r--r--arch/powerpc/cpu/mpc8xx/upatch.c194
-rw-r--r--arch/powerpc/cpu/mpc8xx/video.c1331
-rw-r--r--arch/powerpc/cpu/mpc8xx/wlkbd.c36
-rw-r--r--arch/powerpc/cpu/mpc8xxx/Makefile49
-rw-r--r--arch/powerpc/cpu/mpc8xxx/cpu.c281
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/Makefile45
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h56
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c1645
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ddr.h105
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c343
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c342
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c336
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/interactive.c1868
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c517
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/main.c667
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/options.c1148
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/util.c264
-rw-r--r--arch/powerpc/cpu/mpc8xxx/fdt.c464
-rw-r--r--arch/powerpc/cpu/mpc8xxx/fsl_ifc.c153
-rw-r--r--arch/powerpc/cpu/mpc8xxx/fsl_lbc.c153
-rw-r--r--arch/powerpc/cpu/mpc8xxx/law.c334
-rw-r--r--arch/powerpc/cpu/mpc8xxx/srio.c459
-rw-r--r--arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c464
-rw-r--r--arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c1244
-rw-r--r--arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c3167
-rw-r--r--arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c1256
-rw-r--r--arch/powerpc/cpu/ppc4xx/4xx_pci.c885
-rw-r--r--arch/powerpc/cpu/ppc4xx/4xx_pcie.c1292
-rw-r--r--arch/powerpc/cpu/ppc4xx/4xx_uart.c307
-rw-r--r--arch/powerpc/cpu/ppc4xx/Makefile91
-rw-r--r--arch/powerpc/cpu/ppc4xx/bedbug_405.c308
-rw-r--r--arch/powerpc/cpu/ppc4xx/cache.S235
-rw-r--r--arch/powerpc/cpu/ppc4xx/cmd_chip_config.c148
-rw-r--r--arch/powerpc/cpu/ppc4xx/cmd_ecctest.c279
-rw-r--r--arch/powerpc/cpu/ppc4xx/config.mk34
-rw-r--r--arch/powerpc/cpu/ppc4xx/cpu.c751
-rw-r--r--arch/powerpc/cpu/ppc4xx/cpu_init.c559
-rw-r--r--arch/powerpc/cpu/ppc4xx/dcr.S198
-rw-r--r--arch/powerpc/cpu/ppc4xx/denali_data_eye.c389
-rw-r--r--arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c1249
-rw-r--r--arch/powerpc/cpu/ppc4xx/ecc.c204
-rw-r--r--arch/powerpc/cpu/ppc4xx/ecc.h75
-rw-r--r--arch/powerpc/cpu/ppc4xx/fdt.c176
-rw-r--r--arch/powerpc/cpu/ppc4xx/gpio.c260
-rw-r--r--arch/powerpc/cpu/ppc4xx/interrupts.c209
-rw-r--r--arch/powerpc/cpu/ppc4xx/kgdb.S78
-rw-r--r--arch/powerpc/cpu/ppc4xx/miiphy.c365
-rw-r--r--arch/powerpc/cpu/ppc4xx/reginfo.c370
-rw-r--r--arch/powerpc/cpu/ppc4xx/resetvec.S12
-rw-r--r--arch/powerpc/cpu/ppc4xx/sdram.c468
-rw-r--r--arch/powerpc/cpu/ppc4xx/sdram.h76
-rw-r--r--arch/powerpc/cpu/ppc4xx/speed.c1225
-rw-r--r--arch/powerpc/cpu/ppc4xx/spl_boot.c72
-rw-r--r--arch/powerpc/cpu/ppc4xx/start.S2096
-rw-r--r--arch/powerpc/cpu/ppc4xx/tlb.c352
-rw-r--r--arch/powerpc/cpu/ppc4xx/traps.c408
-rw-r--r--arch/powerpc/cpu/ppc4xx/u-boot-spl.lds74
-rw-r--r--arch/powerpc/cpu/ppc4xx/u-boot.lds149
-rw-r--r--arch/powerpc/cpu/ppc4xx/uic.c180
-rw-r--r--arch/powerpc/cpu/ppc4xx/usb.c61
-rw-r--r--arch/powerpc/cpu/ppc4xx/usb_ohci.c1639
-rw-r--r--arch/powerpc/cpu/ppc4xx/usb_ohci.h410
-rw-r--r--arch/powerpc/cpu/ppc4xx/xilinx_irq.c100
-rw-r--r--arch/powerpc/include/asm/4xx_pci.h60
-rw-r--r--arch/powerpc/include/asm/4xx_pcie.h409
-rw-r--r--arch/powerpc/include/asm/5xx_immap.h439
-rw-r--r--arch/powerpc/include/asm/8xx_immap.h516
-rw-r--r--arch/powerpc/include/asm/apm821xx.h72
-rw-r--r--arch/powerpc/include/asm/arch-mpc83xx/gpio.h38
-rw-r--r--arch/powerpc/include/asm/atomic.h95
-rw-r--r--arch/powerpc/include/asm/bitops.h387
-rw-r--r--arch/powerpc/include/asm/byteorder.h84
-rw-r--r--arch/powerpc/include/asm/cache.h107
-rw-r--r--arch/powerpc/include/asm/config.h114
-rw-r--r--arch/powerpc/include/asm/config_mpc85xx.h643
-rw-r--r--arch/powerpc/include/asm/config_mpc86xx.h38
-rw-r--r--arch/powerpc/include/asm/cpm_8260.h796
-rw-r--r--arch/powerpc/include/asm/cpm_85xx.h830
-rw-r--r--arch/powerpc/include/asm/e300.h91
-rw-r--r--arch/powerpc/include/asm/errno.h1
-rw-r--r--arch/powerpc/include/asm/fsl_ddr_dimm_params.h99
-rw-r--r--arch/powerpc/include/asm/fsl_ddr_sdram.h354
-rw-r--r--arch/powerpc/include/asm/fsl_dma.h141
-rw-r--r--arch/powerpc/include/asm/fsl_dtsec.h244
-rw-r--r--arch/powerpc/include/asm/fsl_enet.h30
-rw-r--r--arch/powerpc/include/asm/fsl_fman.h479
-rw-r--r--arch/powerpc/include/asm/fsl_i2c.h86
-rw-r--r--arch/powerpc/include/asm/fsl_ifc.h999
-rw-r--r--arch/powerpc/include/asm/fsl_law.h143
-rw-r--r--arch/powerpc/include/asm/fsl_lbc.h539
-rw-r--r--arch/powerpc/include/asm/fsl_liodn.h207
-rw-r--r--arch/powerpc/include/asm/fsl_memac.h275
-rw-r--r--arch/powerpc/include/asm/fsl_mpc83xx_serdes.h36
-rw-r--r--arch/powerpc/include/asm/fsl_pci.h272
-rw-r--r--arch/powerpc/include/asm/fsl_portals.h68
-rw-r--r--arch/powerpc/include/asm/fsl_secure_boot.h33
-rw-r--r--arch/powerpc/include/asm/fsl_serdes.h114
-rw-r--r--arch/powerpc/include/asm/fsl_srio.h62
-rw-r--r--arch/powerpc/include/asm/fsl_tgec.h215
-rw-r--r--arch/powerpc/include/asm/global_data.h143
-rw-r--r--arch/powerpc/include/asm/gpio.h2
-rw-r--r--arch/powerpc/include/asm/immap_512x.h1277
-rw-r--r--arch/powerpc/include/asm/immap_8260.h604
-rw-r--r--arch/powerpc/include/asm/immap_83xx.h1060
-rw-r--r--arch/powerpc/include/asm/immap_85xx.h3212
-rw-r--r--arch/powerpc/include/asm/immap_86xx.h1289
-rw-r--r--arch/powerpc/include/asm/immap_qe.h585
-rw-r--r--arch/powerpc/include/asm/interrupt.h36
-rw-r--r--arch/powerpc/include/asm/io.h320
-rw-r--r--arch/powerpc/include/asm/iopin_8260.h168
-rw-r--r--arch/powerpc/include/asm/iopin_85xx.h146
-rw-r--r--arch/powerpc/include/asm/iopin_8xx.h395
-rw-r--r--arch/powerpc/include/asm/m8260_pci.h166
-rw-r--r--arch/powerpc/include/asm/mc146818rtc.h27
-rw-r--r--arch/powerpc/include/asm/mmu.h791
-rw-r--r--arch/powerpc/include/asm/mp.h37
-rw-r--r--arch/powerpc/include/asm/mpc512x.h58
-rw-r--r--arch/powerpc/include/asm/mpc8349_pci.h168
-rw-r--r--arch/powerpc/include/asm/mpc85xx_gpio.h126
-rw-r--r--arch/powerpc/include/asm/mpc8xxx_spi.h49
-rw-r--r--arch/powerpc/include/asm/pci_io.h43
-rw-r--r--arch/powerpc/include/asm/pnp.h643
-rw-r--r--arch/powerpc/include/asm/posix_types.h109
-rw-r--r--arch/powerpc/include/asm/ppc405.h76
-rw-r--r--arch/powerpc/include/asm/ppc405cr.h105
-rw-r--r--arch/powerpc/include/asm/ppc405ep.h252
-rw-r--r--arch/powerpc/include/asm/ppc405ex.h95
-rw-r--r--arch/powerpc/include/asm/ppc405ez.h102
-rw-r--r--arch/powerpc/include/asm/ppc405gp.h108
-rw-r--r--arch/powerpc/include/asm/ppc440.h190
-rw-r--r--arch/powerpc/include/asm/ppc440ep_gr.h244
-rw-r--r--arch/powerpc/include/asm/ppc440epx_grx.h466
-rw-r--r--arch/powerpc/include/asm/ppc440gp.h72
-rw-r--r--arch/powerpc/include/asm/ppc440gx.h102
-rw-r--r--arch/powerpc/include/asm/ppc440sp.h98
-rw-r--r--arch/powerpc/include/asm/ppc440spe.h114
-rw-r--r--arch/powerpc/include/asm/ppc460ex_gt.h222
-rw-r--r--arch/powerpc/include/asm/ppc460sx.h44
-rw-r--r--arch/powerpc/include/asm/ppc4xx-ebc.h200
-rw-r--r--arch/powerpc/include/asm/ppc4xx-emac.h555
-rw-r--r--arch/powerpc/include/asm/ppc4xx-gpio.h119
-rw-r--r--arch/powerpc/include/asm/ppc4xx-i2c.h127
-rw-r--r--arch/powerpc/include/asm/ppc4xx-isram.h83
-rw-r--r--arch/powerpc/include/asm/ppc4xx-mal.h168
-rw-r--r--arch/powerpc/include/asm/ppc4xx-sdram.h1418
-rw-r--r--arch/powerpc/include/asm/ppc4xx-uic.h305
-rw-r--r--arch/powerpc/include/asm/ppc4xx.h324
-rw-r--r--arch/powerpc/include/asm/ppc4xx_config.h42
-rw-r--r--arch/powerpc/include/asm/processor.h1381
-rw-r--r--arch/powerpc/include/asm/ptrace.h107
-rw-r--r--arch/powerpc/include/asm/residual.h331
-rw-r--r--arch/powerpc/include/asm/sections.h27
-rw-r--r--arch/powerpc/include/asm/sigcontext.h15
-rw-r--r--arch/powerpc/include/asm/signal.h154
-rw-r--r--arch/powerpc/include/asm/spl.h31
-rw-r--r--arch/powerpc/include/asm/status_led.h77
-rw-r--r--arch/powerpc/include/asm/string.h29
-rw-r--r--arch/powerpc/include/asm/types.h58
-rw-r--r--arch/powerpc/include/asm/u-boot.h149
-rw-r--r--arch/powerpc/include/asm/unaligned.h16
-rw-r--r--arch/powerpc/include/asm/xilinx_irq.h36
-rw-r--r--arch/powerpc/lib/Makefile120
-rw-r--r--arch/powerpc/lib/_ashldi3.S45
-rw-r--r--arch/powerpc/lib/_ashrdi3.S47
-rw-r--r--arch/powerpc/lib/_lshrdi3.S45
-rw-r--r--arch/powerpc/lib/bat_rw.c261
-rw-r--r--arch/powerpc/lib/board.c1041
-rw-r--r--arch/powerpc/lib/bootm.c295
-rw-r--r--arch/powerpc/lib/cache.c53
-rw-r--r--arch/powerpc/lib/extable.c80
-rw-r--r--arch/powerpc/lib/ide.c201
-rw-r--r--arch/powerpc/lib/ide.h31
-rw-r--r--arch/powerpc/lib/interrupts.c143
-rw-r--r--arch/powerpc/lib/kgdb.c326
-rw-r--r--arch/powerpc/lib/memcpy_mpc5200.c71
-rw-r--r--arch/powerpc/lib/ppccache.S72
-rw-r--r--arch/powerpc/lib/ppcstring.S216
-rw-r--r--arch/powerpc/lib/reloc.S49
-rw-r--r--arch/powerpc/lib/spl.c42
-rw-r--r--arch/powerpc/lib/ticks.S73
-rw-r--r--arch/powerpc/lib/time.c100
405 files changed, 120561 insertions, 0 deletions
diff --git a/arch/powerpc/config.mk b/arch/powerpc/config.mk
new file mode 100644
index 0000000..e32d2bf
--- /dev/null
+++ b/arch/powerpc/config.mk
@@ -0,0 +1,52 @@
+#
+# (C) Copyright 2000-2010
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+CROSS_COMPILE ?= ppc_8xx-
+
+CONFIG_STANDALONE_LOAD_ADDR ?= 0x40000
+LDFLAGS_FINAL += --gc-sections
+PLATFORM_RELFLAGS += -fpic -mrelocatable -ffunction-sections -fdata-sections
+PLATFORM_CPPFLAGS += -DCONFIG_PPC -D__powerpc__
+PLATFORM_LDFLAGS += -n
+
+# Support generic board on PPC
+__HAVE_ARCH_GENERIC_BOARD := y
+
+#
+# When cross-compiling on NetBSD, we have to define __PPC__ or else we
+# will pick up a va_list declaration that is incompatible with the
+# actual argument lists emitted by the compiler.
+#
+# [Tested on NetBSD/i386 1.5 + cross-powerpc-netbsd-1.3]
+
+ifeq ($(CROSS_COMPILE),powerpc-netbsd-)
+PLATFORM_CPPFLAGS+= -D__PPC__
+endif
+ifeq ($(CROSS_COMPILE),powerpc-openbsd-)
+PLATFORM_CPPFLAGS+= -D__PPC__
+endif
+
+# Only test once
+ifneq ($(CONFIG_SPL_BUILD),y)
+ALL-y += checkgcc4
+endif
diff --git a/arch/powerpc/cpu/74xx_7xx/Makefile b/arch/powerpc/cpu/74xx_7xx/Makefile
new file mode 100644
index 0000000..8c2800b
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/Makefile
@@ -0,0 +1,51 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2001
+# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+START = start.o
+SOBJS = cache.o kgdb.o io.o
+COBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/74xx_7xx/cache.S b/arch/powerpc/cpu/74xx_7xx/cache.S
new file mode 100644
index 0000000..66c7298
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/cache.S
@@ -0,0 +1,404 @@
+#include <config.h>
+#include <74xx_7xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CACHE_LINE_SIZE
+# define CACHE_LINE_SIZE L1_CACHE_BYTES
+#endif
+
+#if CACHE_LINE_SIZE == 128
+#define LG_CACHE_LINE_SIZE 7
+#elif CACHE_LINE_SIZE == 32
+#define LG_CACHE_LINE_SIZE 5
+#elif CACHE_LINE_SIZE == 16
+#define LG_CACHE_LINE_SIZE 4
+#elif CACHE_LINE_SIZE == 8
+#define LG_CACHE_LINE_SIZE 3
+#else
+# error "Invalid cache line size!"
+#endif
+
+/*
+ * Invalidate L1 instruction cache.
+ */
+_GLOBAL(invalidate_l1_instruction_cache)
+ mfspr r3,PVR
+ rlwinm r3,r3,16,16,31
+ cmpi 0,r3,1
+ beqlr /* for 601, do nothing */
+ /* 603/604 processor - use invalidate-all bit in HID0 */
+ mfspr r3,HID0
+ ori r3,r3,HID0_ICFI
+ mtspr HID0,r3
+ isync
+ blr
+
+/*
+ * Invalidate L1 data cache.
+ */
+_GLOBAL(invalidate_l1_data_cache)
+ mfspr r3,HID0
+ ori r3,r3,HID0_DCFI
+ mtspr HID0,r3
+ isync
+ blr
+
+/*
+ * Flush data cache.
+ */
+_GLOBAL(flush_dcache)
+ lis r3,0
+ lis r5,CACHE_LINE_SIZE
+flush:
+ cmp 0,1,r3,r5
+ bge done
+ lwz r5,0(r3)
+ lis r5,CACHE_LINE_SIZE
+ addi r3,r3,0x4
+ b flush
+done:
+ blr
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ * This is a no-op on the 601.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+ mfspr r5,PVR
+ rlwinm r5,r5,16,16,31
+ cmpi 0,r5,1
+ beqlr /* for 601, do nothing */
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ *
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(clean_dcache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5 /* align r3 down to cache line */
+ subf r4,r3,r4 /* r4 = offset of stop from start of cache line */
+ add r4,r4,r5 /* r4 += cache_line_size-1 */
+ srwi. r4,r4,LG_CACHE_LINE_SIZE /* r4 = number of cache lines to flush */
+ beqlr /* if r4 == 0 return */
+ mtctr r4 /* ctr = r4 */
+
+ sync
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+ sync
+1: dcbf 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbf's to get to ram */
+ blr
+
+/*
+ * Like above, but invalidate the D-cache. This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ *
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_dcache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+ sync
+1: dcbi 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbi's to get to ram */
+ blr
+
+/*
+ * Flush a particular page from the data cache to RAM.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ * void __flush_page_to_ram(void *page)
+ */
+_GLOBAL(__flush_page_to_ram)
+ mfspr r5,PVR
+ rlwinm r5,r5,16,16,31
+ cmpi 0,r5,1
+ beqlr /* for 601, do nothing */
+ rlwinm r3,r3,0,0,19 /* Get page base address */
+ li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+0: dcbst 0,r3 /* Write line to ram */
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 0b
+ sync
+ mtctr r4
+1: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ isync
+ blr
+
+/*
+ * Flush a particular page from the instruction cache.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ * void __flush_icache_page(void *page)
+ */
+_GLOBAL(__flush_icache_page)
+ mfspr r5,PVR
+ rlwinm r5,r5,16,16,31
+ cmpi 0,r5,1
+ beqlr /* for 601, do nothing */
+ li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+1: icbi 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ isync
+ blr
+
+/*
+ * Clear a page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced). This only works on cacheable memory.
+ */
+_GLOBAL(clear_page)
+ li r0,4096/CACHE_LINE_SIZE
+ mtctr r0
+1: dcbz 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ blr
+
+/*
+ * Enable L1 Instruction cache
+ */
+_GLOBAL(icache_enable)
+ mfspr r3, HID0
+ li r5, HID0_ICFI|HID0_ILOCK
+ andc r3, r3, r5
+ ori r3, r3, HID0_ICE
+ ori r5, r3, HID0_ICFI
+ mtspr HID0, r5
+ mtspr HID0, r3
+ isync
+ blr
+
+/*
+ * Disable L1 Instruction cache
+ */
+_GLOBAL(icache_disable)
+ mflr r4
+ bl invalidate_l1_instruction_cache /* uses r3 */
+ sync
+ mtlr r4
+ mfspr r3, HID0
+ li r5, 0
+ ori r5, r5, HID0_ICE
+ andc r3, r3, r5
+ mtspr HID0, r3
+ isync
+ blr
+
+/*
+ * Is instruction cache enabled?
+ */
+_GLOBAL(icache_status)
+ mfspr r3, HID0
+ andi. r3, r3, HID0_ICE
+ blr
+
+
+_GLOBAL(l1dcache_enable)
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ ori r3, r3, HID0_DCE
+ ori r5, r3, HID0_DCFI
+ mtspr HID0, r5 /* enable + invalidate */
+ mtspr HID0, r3 /* enable */
+ sync
+ blr
+
+/*
+ * Enable data cache(s) - L1 and optionally L2
+ * Calls l2cache_enable. LR saved in r5
+ */
+_GLOBAL(dcache_enable)
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ ori r3, r3, HID0_DCE
+ ori r5, r3, HID0_DCFI
+ mtspr HID0, r5 /* enable + invalidate */
+ mtspr HID0, r3 /* enable */
+ sync
+#ifdef CONFIG_SYS_L2
+ mflr r5
+ bl l2cache_enable /* uses r3 and r4 */
+ sync
+ mtlr r5
+#endif
+ blr
+
+
+/*
+ * Disable data cache(s) - L1 and optionally L2
+ * Calls flush_dcache and l2cache_disable_no_flush.
+ * LR saved in r4
+ */
+_GLOBAL(dcache_disable)
+ mflr r4 /* save link register */
+ bl flush_dcache /* uses r3 and r5 */
+ sync
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ li r5, HID0_DCE|HID0_DCFI
+ andc r3, r3, r5 /* no enable, no invalidate */
+ mtspr HID0, r3
+ sync
+#ifdef CONFIG_SYS_L2
+ bl l2cache_disable_no_flush /* uses r3 */
+#endif
+ mtlr r4 /* restore link register */
+ blr
+
+/*
+ * Is data cache enabled?
+ */
+_GLOBAL(dcache_status)
+ mfspr r3, HID0
+ andi. r3, r3, HID0_DCE
+ blr
+
+/*
+ * Invalidate L2 cache using L2I and polling L2IP or L2I
+ */
+_GLOBAL(l2cache_invalidate)
+ sync
+ mfspr r3, l2cr
+ oris r3, r3, L2CR_L2I@h
+ sync
+ mtspr l2cr, r3
+ sync
+ mfspr r3, PVR
+ sync
+ rlwinm r3, r3, 16,16,31
+ cmpli 0,r3,0x8000 /* 7451, 7441 */
+ beq 0,inv_7450
+ cmpli 0,r3,0x8001 /* 7455, 7445 */
+ beq 0,inv_7450
+ cmpli 0,r3,0x8002 /* 7457, 7447 */
+ beq 0,inv_7450
+ cmpli 0,r3,0x8003 /* 7447A */
+ beq 0,inv_7450
+ cmpli 0,r3,0x8004 /* 7448 */
+ beq 0,inv_7450
+invl2:
+ mfspr r3, l2cr
+ andi. r3, r3, L2CR_L2IP
+ bne invl2
+ /* turn off the global invalidate bit */
+ mfspr r3, l2cr
+ rlwinm r3, r3, 0, 11, 9
+ sync
+ mtspr l2cr, r3
+ sync
+ blr
+inv_7450:
+ mfspr r3, l2cr
+ andis. r3, r3, L2CR_L2I@h
+ bne inv_7450
+ blr
+
+/*
+ * Enable L2 cache
+ * Calls l2cache_invalidate. LR is saved in r4
+ */
+_GLOBAL(l2cache_enable)
+ mflr r4 /* save link register */
+ bl l2cache_invalidate /* uses r3 */
+ sync
+ lis r3, L2_ENABLE@h
+ ori r3, r3, L2_ENABLE@l
+ mtspr l2cr, r3
+ isync
+ mtlr r4 /* restore link register */
+ blr
+
+/*
+ * Disable L2 cache
+ * Calls flush_dcache. LR is saved in r4
+ */
+_GLOBAL(l2cache_disable)
+ mflr r4 /* save link register */
+ bl flush_dcache /* uses r3 and r5 */
+ sync
+ mtlr r4 /* restore link register */
+l2cache_disable_no_flush: /* provide way to disable L2 w/o flushing */
+ lis r3, L2_INIT@h
+ ori r3, r3, L2_INIT@l
+ mtspr l2cr, r3
+ isync
+ blr
diff --git a/arch/powerpc/cpu/74xx_7xx/config.mk b/arch/powerpc/cpu/74xx_7xx/config.mk
new file mode 100644
index 0000000..fb0c715
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2001
+# Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_74xx_7xx -ffixed-r2 -mstring
diff --git a/arch/powerpc/cpu/74xx_7xx/cpu.c b/arch/powerpc/cpu/74xx_7xx/cpu.c
new file mode 100644
index 0000000..17694a1
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/cpu.c
@@ -0,0 +1,316 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ *
+ * more modifications by
+ * Josh Huber <huber@mclx.com>
+ * added support for the 74xx series of cpus
+ * added support for the 7xx series of cpus
+ * made the code a little less hard-coded, and more auto-detectish
+ */
+
+#include <common.h>
+#include <command.h>
+#include <74xx_7xx.h>
+#include <asm/cache.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+cpu_t
+get_cpu_type(void)
+{
+ uint pvr = get_pvr();
+ cpu_t type;
+
+ type = CPU_UNKNOWN;
+
+ switch (PVR_VER(pvr)) {
+ case 0x000c:
+ type = CPU_7400;
+ break;
+ case 0x0008:
+ type = CPU_750;
+
+ if (((pvr >> 8) & 0xff) == 0x01) {
+ type = CPU_750CX; /* old CX (80100 and 8010x?)*/
+ } else if (((pvr >> 8) & 0xff) == 0x22) {
+ type = CPU_750CX; /* CX (82201,82202) and CXe (82214) */
+ } else if (((pvr >> 8) & 0xff) == 0x33) {
+ type = CPU_750CX; /* CXe (83311) */
+ } else if (((pvr >> 12) & 0xF) == 0x3) {
+ type = CPU_755;
+ }
+ break;
+
+ case 0x7000:
+ type = CPU_750FX;
+ break;
+
+ case 0x7002:
+ type = CPU_750GX;
+ break;
+
+ case 0x800C:
+ type = CPU_7410;
+ break;
+
+ case 0x8000:
+ type = CPU_7450;
+ break;
+
+ case 0x8001:
+ type = CPU_7455;
+ break;
+
+ case 0x8002:
+ type = CPU_7457;
+ break;
+
+ case 0x8003:
+ type = CPU_7447A;
+ break;
+
+ case 0x8004:
+ type = CPU_7448;
+ break;
+
+ default:
+ break;
+ }
+
+ return type;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if !defined(CONFIG_BAB7xx)
+int checkcpu (void)
+{
+ uint type = get_cpu_type();
+ uint pvr = get_pvr();
+ ulong clock = gd->cpu_clk;
+ char buf[32];
+ char *str;
+
+ puts ("CPU: ");
+
+ switch (type) {
+ case CPU_750CX:
+ printf ("750CX%s v%d.%d", (pvr&0xf0)?"e":"",
+ (pvr>>8) & 0xf,
+ pvr & 0xf);
+ goto PR_CLK;
+
+ case CPU_750:
+ str = "750";
+ break;
+
+ case CPU_750FX:
+ str = "750FX";
+ break;
+
+ case CPU_750GX:
+ str = "750GX";
+ break;
+
+ case CPU_755:
+ str = "755";
+ break;
+
+ case CPU_7400:
+ str = "MPC7400";
+ break;
+
+ case CPU_7410:
+ str = "MPC7410";
+ break;
+
+ case CPU_7447A:
+ str = "MPC7447A";
+ break;
+
+ case CPU_7448:
+ str = "MPC7448";
+ break;
+
+ case CPU_7450:
+ str = "MPC7450";
+ break;
+
+ case CPU_7455:
+ str = "MPC7455";
+ break;
+
+ case CPU_7457:
+ str = "MPC7457";
+ break;
+
+ default:
+ printf("Unknown CPU -- PVR: 0x%08x\n", pvr);
+ return -1;
+ }
+
+ printf ("%s v%d.%d", str, (pvr >> 8) & 0xFF, pvr & 0xFF);
+PR_CLK:
+ printf (" @ %s MHz\n", strmhz(buf, clock));
+
+ return (0);
+}
+#endif
+/* these two functions are unimplemented currently [josh] */
+
+/* -------------------------------------------------------------------- */
+/* L1 i-cache */
+
+int
+checkicache(void)
+{
+ return 0; /* XXX */
+}
+
+/* -------------------------------------------------------------------- */
+/* L1 d-cache */
+
+int
+checkdcache(void)
+{
+ return 0; /* XXX */
+}
+
+/* -------------------------------------------------------------------- */
+
+static inline void
+soft_restart(unsigned long addr)
+{
+ /* SRR0 has system reset vector, SRR1 has default MSR value */
+ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
+
+ __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr));
+ __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4");
+ __asm__ __volatile__ ("mtspr 27, 4");
+ __asm__ __volatile__ ("rfi");
+
+ while(1); /* not reached */
+}
+
+
+#if !defined(CONFIG_BAB7xx) && \
+ !defined(CONFIG_ELPPC) && \
+ !defined(CONFIG_PPMC7XX)
+/* no generic way to do board reset. simply call soft_reset. */
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong addr;
+ /* flush and disable I/D cache */
+ __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3");
+ __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5");
+ __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4");
+ __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5");
+ __asm__ __volatile__ ("sync");
+ __asm__ __volatile__ ("mtspr 1008, 4");
+ __asm__ __volatile__ ("isync");
+ __asm__ __volatile__ ("sync");
+ __asm__ __volatile__ ("mtspr 1008, 5");
+ __asm__ __volatile__ ("isync");
+ __asm__ __volatile__ ("sync");
+
+#ifdef CONFIG_SYS_RESET_ADDRESS
+ addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+ /*
+ * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
+ * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid
+ * address. Better pick an address known to be invalid on your
+ * system and assign it to CONFIG_SYS_RESET_ADDRESS.
+ */
+ addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+ soft_restart(addr);
+
+ /* not reached */
+ while(1)
+ ;
+
+ return 1;
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * For the 7400 the TB clock runs at 1/4 the cpu bus speed.
+ */
+#ifndef CONFIG_SYS_BUS_CLK
+#define CONFIG_SYS_BUS_CLK gd->bus_clk
+#endif
+
+unsigned long get_tbclk(void)
+{
+ return CONFIG_SYS_BUS_CLK / 4;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_WATCHDOG)
+#if !defined(CONFIG_BAB7xx)
+void
+watchdog_reset(void)
+{
+
+}
+#endif /* !CONFIG_BAB7xx */
+#endif /* CONFIG_WATCHDOG */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_OF_LIBFDT
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", bd->bi_busfreq / 4, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "clock-frequency", bd->bi_intfreq, 1);
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+ fdt_fixup_ethernet(blob);
+}
+#endif
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/74xx_7xx/cpu_init.c b/arch/powerpc/cpu/74xx_7xx/cpu_init.c
new file mode 100644
index 0000000..1dd1b2c
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/cpu_init.c
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu_init.c - low level cpu init
+ *
+ * there's really nothing going on here yet. future work area?
+ */
+
+#include <common.h>
+#include <74xx_7xx.h>
+
+/*
+ * Breath some life into the CPU...
+ *
+ * there's basically nothing to do here since the memory controller
+ * isn't on the CPU in this case.
+ */
+void
+cpu_init_f (void)
+{
+ switch (get_cpu_type()) {
+ case CPU_7450:
+ case CPU_7455:
+ case CPU_7457:
+ case CPU_7447A:
+ case CPU_7448:
+ /* enable the timebase bit in HID0 */
+ set_hid0(get_hid0() | 0x4000000);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+/*
+ * initialize higher level parts of CPU like timers
+ */
+int cpu_init_r (void)
+{
+ return (0);
+}
diff --git a/arch/powerpc/cpu/74xx_7xx/interrupts.c b/arch/powerpc/cpu/74xx_7xx/interrupts.c
new file mode 100644
index 0000000..7fc8a34
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/interrupts.c
@@ -0,0 +1,104 @@
+/*
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * interrupts.c - just enough support for the decrementer/timer
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <mpc8xx_irq.h>
+#include <asm/processor.h>
+#include <commproc.h>
+#include <command.h>
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ debug("interrupt_init: GT main cause reg: %08x:%08x\n",
+ GTREGREAD(LOW_INTERRUPT_CAUSE_REGISTER),
+ GTREGREAD(HIGH_INTERRUPT_CAUSE_REGISTER));
+ debug("interrupt_init: ethernet cause regs: %08x %08x %08x\n",
+ GTREGREAD(ETHERNET0_INTERRUPT_CAUSE_REGISTER),
+ GTREGREAD(ETHERNET1_INTERRUPT_CAUSE_REGISTER),
+ GTREGREAD(ETHERNET2_INTERRUPT_CAUSE_REGISTER));
+ debug("interrupt_init: ethernet mask regs: %08x %08x %08x\n",
+ GTREGREAD(ETHERNET0_INTERRUPT_MASK_REGISTER),
+ GTREGREAD(ETHERNET1_INTERRUPT_MASK_REGISTER),
+ GTREGREAD(ETHERNET2_INTERRUPT_MASK_REGISTER));
+ debug("interrupt_init: setting decrementer_count\n");
+
+ *decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+ return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void
+external_interrupt(struct pt_regs *regs)
+{
+ puts("external_interrupt (oops!)\n");
+}
+
+volatile ulong timestamp = 0;
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void
+timer_interrupt_cpu (struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free a interrupt handler.
+ */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+
+}
+
+void
+irq_free_handler(int vec)
+{
+
+}
+
+/****************************************************************************/
+
+void
+do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char * const argv[])
+{
+ puts("IRQ related functions are unimplemented currently.\n");
+}
diff --git a/arch/powerpc/cpu/74xx_7xx/io.S b/arch/powerpc/cpu/74xx_7xx/io.S
new file mode 100644
index 0000000..af2e6d1
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/io.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ * Copyright (C) 2002 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16 */
+/* Description: Input 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16r */
+/* Description: Input 16 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0(3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32r */
+/* Description: Input 32 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,0,r3
+ sync
+ blr
diff --git a/arch/powerpc/cpu/74xx_7xx/kgdb.S b/arch/powerpc/cpu/74xx_7xx/kgdb.S
new file mode 100644
index 0000000..ad487cd
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/kgdb.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2000 Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <74xx_7xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+
+ /*
+ * cache flushing routines for kgdb
+ */
+
+ .globl kgdb_flush_cache_all
+kgdb_flush_cache_all:
+ lis r3,0
+ addis r4,r0,0x0040
+kgdb_flush_loop:
+ lwz r5,0(r3)
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ cmp 0,0,r3,r4
+ bne kgdb_flush_loop
+ SYNC
+ mfspr r3,1008
+ ori r3,r3,0x8800
+ mtspr 1008,r3
+ sync
+ blr
+
+ .globl kgdb_flush_cache_range
+kgdb_flush_cache_range:
+ li r5,CONFIG_SYS_CACHELINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,CONFIG_SYS_CACHELINE_SHIFT
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 2b
+ SYNC
+ blr
+
+#endif
diff --git a/arch/powerpc/cpu/74xx_7xx/speed.c b/arch/powerpc/cpu/74xx_7xx/speed.c
new file mode 100644
index 0000000..6450c3c
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/speed.c
@@ -0,0 +1,181 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <74xx_7xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern unsigned long get_board_bus_clk (void);
+
+static const int hid1_multipliers_x_10[] = {
+ 25, /* 0000 - 2.5x */
+ 75, /* 0001 - 7.5x */
+ 70, /* 0010 - 7x */
+ 10, /* 0011 - bypass */
+ 20, /* 0100 - 2x */
+ 65, /* 0101 - 6.5x */
+ 100, /* 0110 - 10x */
+ 45, /* 0111 - 4.5x */
+ 30, /* 1000 - 3x */
+ 55, /* 1001 - 5.5x */
+ 40, /* 1010 - 4x */
+ 50, /* 1011 - 5x */
+ 80, /* 1100 - 8x */
+ 60, /* 1101 - 6x */
+ 35, /* 1110 - 3.5x */
+ 0 /* 1111 - off */
+};
+
+/* PLL_CFG[0:4] table for cpu 7448/7447A/7455/7457 */
+static const int hid1_74xx_multipliers_x_10[] = {
+ 115, /* 00000 - 11.5x */
+ 170, /* 00001 - 17x */
+ 75, /* 00010 - 7.5x */
+ 150, /* 00011 - 15x */
+ 70, /* 00100 - 7x */
+ 180, /* 00101 - 18x */
+ 10, /* 00110 - bypass */
+ 200, /* 00111 - 20x */
+ 20, /* 01000 - 2x */
+ 210, /* 01001 - 21x */
+ 65, /* 01010 - 6.5x */
+ 130, /* 01011 - 13x */
+ 85, /* 01100 - 8.5x */
+ 240, /* 01101 - 24x */
+ 95, /* 01110 - 9.5x */
+ 90, /* 01111 - 9x */
+ 30, /* 10000 - 3x */
+ 105, /* 10001 - 10.5x */
+ 55, /* 10010 - 5.5x */
+ 110, /* 10011 - 11x */
+ 40, /* 10100 - 4x */
+ 100, /* 10101 - 10x */
+ 50, /* 10110 - 5x */
+ 120, /* 10111 - 12x */
+ 80, /* 11000 - 8x */
+ 140, /* 11001 - 14x */
+ 60, /* 11010 - 6x */
+ 160, /* 11011 - 16x */
+ 135, /* 11100 - 13.5x */
+ 280, /* 11101 - 28x */
+ 0, /* 11110 - off */
+ 125 /* 11111 - 12.5x */
+};
+
+static const int hid1_fx_multipliers_x_10[] = {
+ 00, /* 0000 - off */
+ 00, /* 0001 - off */
+ 10, /* 0010 - bypass */
+ 10, /* 0011 - bypass */
+ 20, /* 0100 - 2x */
+ 25, /* 0101 - 2.5x */
+ 30, /* 0110 - 3x */
+ 35, /* 0111 - 3.5x */
+ 40, /* 1000 - 4x */
+ 45, /* 1001 - 4.5x */
+ 50, /* 1010 - 5x */
+ 55, /* 1011 - 5.5x */
+ 60, /* 1100 - 6x */
+ 65, /* 1101 - 6.5x */
+ 70, /* 1110 - 7x */
+ 75, /* 1111 - 7.5 */
+ 80, /* 10000 - 8x */
+ 85, /* 10001 - 8.5x */
+ 90, /* 10010 - 9x */
+ 95, /* 10011 - 9.5x */
+ 100, /* 10100 - 10x */
+ 110, /* 10101 - 11x */
+ 120, /* 10110 - 12x */
+};
+
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Measure CPU clock speed (core clock GCLK1, GCLK2)
+ *
+ * (Approx. GCLK frequency in Hz)
+ */
+
+int get_clocks (void)
+{
+ ulong clock = 0;
+
+#ifdef CONFIG_SYS_BUS_CLK
+ gd->bus_clk = CONFIG_SYS_BUS_CLK; /* bus clock is a fixed frequency */
+#else
+ gd->bus_clk = get_board_bus_clk (); /* bus clock is configurable */
+#endif
+
+ /* calculate the clock frequency based upon the CPU type */
+ switch (get_cpu_type()) {
+ case CPU_7447A:
+ case CPU_7448:
+ case CPU_7455:
+ case CPU_7457:
+ /*
+ * Make sure division is done before multiplication to prevent 32-bit
+ * arithmetic overflows which will cause a negative number
+ */
+ clock = (gd->bus_clk / 10) *
+ hid1_74xx_multipliers_x_10[(get_hid1 () >> 12) & 0x1F];
+ break;
+
+ case CPU_750GX:
+ case CPU_750FX:
+ clock = (gd->bus_clk / 10) *
+ hid1_fx_multipliers_x_10[get_hid1 () >> 27];
+ break;
+
+ case CPU_7450:
+ case CPU_740:
+ case CPU_740P:
+ case CPU_745:
+ case CPU_750CX:
+ case CPU_750:
+ case CPU_750P:
+ case CPU_755:
+ case CPU_7400:
+ case CPU_7410:
+ /*
+ * Make sure division is done before multiplication to prevent 32-bit
+ * arithmetic overflows which will cause a negative number
+ */
+ clock = (gd->bus_clk / 10) *
+ hid1_multipliers_x_10[get_hid1 () >> 28];
+ break;
+
+ case CPU_UNKNOWN:
+ printf ("get_gclk_freq(): unknown CPU type\n");
+ clock = 0;
+ return (1);
+ }
+
+ gd->cpu_clk = clock;
+
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/74xx_7xx/start.S b/arch/powerpc/cpu/74xx_7xx/start.S
new file mode 100644
index 0000000..cd8dea8
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/start.S
@@ -0,0 +1,856 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2001 Josh Huber <huber@mclx.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0xfff00100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating.
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ */
+#include <asm-offsets.h>
+#include <config.h>
+#include <74xx_7xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+#if !defined(CONFIG_DB64360) && \
+ !defined(CONFIG_DB64460) && \
+ !defined(CONFIG_CPCI750) && \
+ !defined(CONFIG_P3Mx)
+#include <galileo/gt64260R.h>
+#endif
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* Machine Check and Recoverable Interr. */
+#define MSR_KERNEL ( MSR_ME | MSR_RI )
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+ .text
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ b boot_cold
+
+ /* the boot code is located below the exception table */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* No FPU on MPC8xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ /*
+ * On the MPC8xx, this is a software emulation interrupt. It
+ * occurs for all unimplemented and illegal instructions.
+ */
+ STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x2000
+
+boot_cold:
+ /* disable everything */
+ li r0, 0
+ mtspr HID0, r0
+ sync
+ mtmsr 0
+ bl invalidate_bats
+ sync
+
+#ifdef CONFIG_SYS_L2
+ /* init the L2 cache */
+ addis r3, r0, L2_INIT@h
+ ori r3, r3, L2_INIT@l
+ sync
+ mtspr l2cr, r3
+#endif
+#if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
+ .long 0x7e00066c
+ /*
+ * dssall instruction, gas doesn't have it yet
+ * ...for altivec, data stream stop all this probably
+ * isn't needed unless we warm (software) reboot U-Boot
+ */
+#endif
+
+#ifdef CONFIG_SYS_L2
+ /* invalidate the L2 cache */
+ bl l2cache_invalidate
+ sync
+#endif
+#ifdef CONFIG_SYS_BOARD_ASM_INIT
+ /* do early init */
+ bl board_asm_init
+#endif
+
+ /*
+ * Calculate absolute address in FLASH and jump there
+ *------------------------------------------------------*/
+ lis r3, CONFIG_SYS_MONITOR_BASE@h
+ ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
+ addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r3
+ blr
+
+in_flash:
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*------------------------------------------------------*/
+
+ /* perform low-level init */
+ /* sdram init, galileo init, etc */
+ /* r3: NHR bit from HID0 */
+
+ /* setup the bats */
+ bl setup_bats
+ sync
+
+ /*
+ * Cache must be enabled here for stack-in-cache trick.
+ * This means we need to enable the BATS.
+ * This means:
+ * 1) for the EVB, original gt regs need to be mapped
+ * 2) need to have an IBAT for the 0xf region,
+ * we are running there!
+ * Cache should be turned on after BATs, since by default
+ * everything is write-through.
+ * The init-mem BAT can be reused after reloc. The old
+ * gt-regs BAT can be reused after board_init_f calls
+ * board_early_init_f (EVB only).
+ */
+#if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC) && !defined(CONFIG_P3Mx)
+ /* enable address translation */
+ bl enable_addr_trans
+ sync
+
+ /* enable and invalidate the data cache */
+ bl l1dcache_enable
+ sync
+#endif
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+ bl lock_ram_in_cache
+ sync
+#endif
+
+ /* set up the stack pointer in our newly created
+ * cache-ram (r1) */
+ lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+ ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ GET_GOT /* initialize GOT access */
+
+ /* run low-level CPU init code (from Flash) */
+ bl cpu_init_f
+ sync
+
+ /* run 1st part of board init code (from Flash) */
+ bl board_init_f
+ sync
+
+ /* NOTREACHED - board_init_f() does not return */
+
+ .globl invalidate_bats
+invalidate_bats:
+ /* invalidate BATs */
+ mtspr IBAT0U, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT3U, r0
+#ifdef CONFIG_HIGH_BATS
+ mtspr IBAT4U, r0
+ mtspr IBAT5U, r0
+ mtspr IBAT6U, r0
+ mtspr IBAT7U, r0
+#endif
+ isync
+ mtspr DBAT0U, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT3U, r0
+#ifdef CONFIG_HIGH_BATS
+ mtspr DBAT4U, r0
+ mtspr DBAT5U, r0
+ mtspr DBAT6U, r0
+ mtspr DBAT7U, r0
+#endif
+ isync
+ sync
+ blr
+
+ /* setup_bats - set them up to some initial state */
+ .globl setup_bats
+setup_bats:
+ addis r0, r0, 0x0000
+
+ /* IBAT 0 */
+ addis r4, r0, CONFIG_SYS_IBAT0L@h
+ ori r4, r4, CONFIG_SYS_IBAT0L@l
+ addis r3, r0, CONFIG_SYS_IBAT0U@h
+ ori r3, r3, CONFIG_SYS_IBAT0U@l
+ mtspr IBAT0L, r4
+ mtspr IBAT0U, r3
+ isync
+
+ /* DBAT 0 */
+ addis r4, r0, CONFIG_SYS_DBAT0L@h
+ ori r4, r4, CONFIG_SYS_DBAT0L@l
+ addis r3, r0, CONFIG_SYS_DBAT0U@h
+ ori r3, r3, CONFIG_SYS_DBAT0U@l
+ mtspr DBAT0L, r4
+ mtspr DBAT0U, r3
+ isync
+
+ /* IBAT 1 */
+ addis r4, r0, CONFIG_SYS_IBAT1L@h
+ ori r4, r4, CONFIG_SYS_IBAT1L@l
+ addis r3, r0, CONFIG_SYS_IBAT1U@h
+ ori r3, r3, CONFIG_SYS_IBAT1U@l
+ mtspr IBAT1L, r4
+ mtspr IBAT1U, r3
+ isync
+
+ /* DBAT 1 */
+ addis r4, r0, CONFIG_SYS_DBAT1L@h
+ ori r4, r4, CONFIG_SYS_DBAT1L@l
+ addis r3, r0, CONFIG_SYS_DBAT1U@h
+ ori r3, r3, CONFIG_SYS_DBAT1U@l
+ mtspr DBAT1L, r4
+ mtspr DBAT1U, r3
+ isync
+
+ /* IBAT 2 */
+ addis r4, r0, CONFIG_SYS_IBAT2L@h
+ ori r4, r4, CONFIG_SYS_IBAT2L@l
+ addis r3, r0, CONFIG_SYS_IBAT2U@h
+ ori r3, r3, CONFIG_SYS_IBAT2U@l
+ mtspr IBAT2L, r4
+ mtspr IBAT2U, r3
+ isync
+
+ /* DBAT 2 */
+ addis r4, r0, CONFIG_SYS_DBAT2L@h
+ ori r4, r4, CONFIG_SYS_DBAT2L@l
+ addis r3, r0, CONFIG_SYS_DBAT2U@h
+ ori r3, r3, CONFIG_SYS_DBAT2U@l
+ mtspr DBAT2L, r4
+ mtspr DBAT2U, r3
+ isync
+
+ /* IBAT 3 */
+ addis r4, r0, CONFIG_SYS_IBAT3L@h
+ ori r4, r4, CONFIG_SYS_IBAT3L@l
+ addis r3, r0, CONFIG_SYS_IBAT3U@h
+ ori r3, r3, CONFIG_SYS_IBAT3U@l
+ mtspr IBAT3L, r4
+ mtspr IBAT3U, r3
+ isync
+
+ /* DBAT 3 */
+ addis r4, r0, CONFIG_SYS_DBAT3L@h
+ ori r4, r4, CONFIG_SYS_DBAT3L@l
+ addis r3, r0, CONFIG_SYS_DBAT3U@h
+ ori r3, r3, CONFIG_SYS_DBAT3U@l
+ mtspr DBAT3L, r4
+ mtspr DBAT3U, r3
+ isync
+
+#ifdef CONFIG_HIGH_BATS
+ /* IBAT 4 */
+ addis r4, r0, CONFIG_SYS_IBAT4L@h
+ ori r4, r4, CONFIG_SYS_IBAT4L@l
+ addis r3, r0, CONFIG_SYS_IBAT4U@h
+ ori r3, r3, CONFIG_SYS_IBAT4U@l
+ mtspr IBAT4L, r4
+ mtspr IBAT4U, r3
+ isync
+
+ /* DBAT 4 */
+ addis r4, r0, CONFIG_SYS_DBAT4L@h
+ ori r4, r4, CONFIG_SYS_DBAT4L@l
+ addis r3, r0, CONFIG_SYS_DBAT4U@h
+ ori r3, r3, CONFIG_SYS_DBAT4U@l
+ mtspr DBAT4L, r4
+ mtspr DBAT4U, r3
+ isync
+
+ /* IBAT 5 */
+ addis r4, r0, CONFIG_SYS_IBAT5L@h
+ ori r4, r4, CONFIG_SYS_IBAT5L@l
+ addis r3, r0, CONFIG_SYS_IBAT5U@h
+ ori r3, r3, CONFIG_SYS_IBAT5U@l
+ mtspr IBAT5L, r4
+ mtspr IBAT5U, r3
+ isync
+
+ /* DBAT 5 */
+ addis r4, r0, CONFIG_SYS_DBAT5L@h
+ ori r4, r4, CONFIG_SYS_DBAT5L@l
+ addis r3, r0, CONFIG_SYS_DBAT5U@h
+ ori r3, r3, CONFIG_SYS_DBAT5U@l
+ mtspr DBAT5L, r4
+ mtspr DBAT5U, r3
+ isync
+
+ /* IBAT 6 */
+ addis r4, r0, CONFIG_SYS_IBAT6L@h
+ ori r4, r4, CONFIG_SYS_IBAT6L@l
+ addis r3, r0, CONFIG_SYS_IBAT6U@h
+ ori r3, r3, CONFIG_SYS_IBAT6U@l
+ mtspr IBAT6L, r4
+ mtspr IBAT6U, r3
+ isync
+
+ /* DBAT 6 */
+ addis r4, r0, CONFIG_SYS_DBAT6L@h
+ ori r4, r4, CONFIG_SYS_DBAT6L@l
+ addis r3, r0, CONFIG_SYS_DBAT6U@h
+ ori r3, r3, CONFIG_SYS_DBAT6U@l
+ mtspr DBAT6L, r4
+ mtspr DBAT6U, r3
+ isync
+
+ /* IBAT 7 */
+ addis r4, r0, CONFIG_SYS_IBAT7L@h
+ ori r4, r4, CONFIG_SYS_IBAT7L@l
+ addis r3, r0, CONFIG_SYS_IBAT7U@h
+ ori r3, r3, CONFIG_SYS_IBAT7U@l
+ mtspr IBAT7L, r4
+ mtspr IBAT7U, r3
+ isync
+
+ /* DBAT 7 */
+ addis r4, r0, CONFIG_SYS_DBAT7L@h
+ ori r4, r4, CONFIG_SYS_DBAT7L@l
+ addis r3, r0, CONFIG_SYS_DBAT7U@h
+ ori r3, r3, CONFIG_SYS_DBAT7U@l
+ mtspr DBAT7L, r4
+ mtspr DBAT7U, r3
+ isync
+#endif
+
+ /* bats are done, now invalidate the TLBs */
+
+ addis r3, 0, 0x0000
+ addis r5, 0, 0x4 /* upper bound of 0x00040000 for 7400/750 */
+
+ isync
+
+tlblp:
+ tlbie r3
+ sync
+ addi r3, r3, 0x1000
+ cmp 0, 0, r3, r5
+ blt tlblp
+
+ blr
+
+ .globl enable_addr_trans
+enable_addr_trans:
+ /* enable address translation */
+ mfmsr r5
+ ori r5, r5, (MSR_IR | MSR_DR)
+ mtmsr r5
+ isync
+ blr
+
+ .globl disable_addr_trans
+disable_addr_trans:
+ /* disable address translation */
+ mflr r4
+ mfmsr r3
+ andi. r0, r3, (MSR_IR | MSR_DR)
+ beqlr
+ andc r3, r3, r0
+ mtspr SRR0, r4
+ mtspr SRR1, r3
+ rfi
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+ .globl dc_read
+dc_read:
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+/*-----------------------------------------------------------------------*/
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+#ifdef CONFIG_ECC
+ bl board_relocate_rom
+ sync
+ mr r3, r10 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+#else
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+#endif
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+#ifdef CONFIG_ECC
+ bl board_init_ecc
+#endif
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+/* clear_bss: */
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+ mr r3, r10 /* Destination Address */
+#if defined(CONFIG_DB64360) || \
+ defined(CONFIG_DB64460) || \
+ defined(CONFIG_CPCI750) || \
+ defined(CONFIG_PPMC7XX) || \
+ defined(CONFIG_P3Mx)
+ mr r4, r9 /* Use RAM copy of the global data */
+#endif
+ bl after_reloc
+
+ /* not reached - end relocate_code */
+/*-----------------------------------------------------------------------*/
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ /* enable execptions from RAM vectors */
+ mfmsr r7
+ li r8,MSR_IP
+ andc r7,r7,r8
+ mtmsr r7
+
+ mtlr r4 /* restore link register */
+ blr
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+lock_ram_in_cache:
+ /* Allocate Initial RAM in data cache.
+ */
+ lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+ li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
+ (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+ mtctr r4
+1:
+ dcbz r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+
+ /* Lock the data cache */
+ mfspr r0, HID0
+ ori r0, r0, 0x1000
+ sync
+ mtspr HID0, r0
+ sync
+ blr
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+ li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
+ (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+ mtctr r4
+1: icbi r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+ sync /* Wait for all icbi to complete on bus */
+ isync
+
+ /* Unlock the data cache and invalidate it */
+ mfspr r0, HID0
+ li r3,0x1000
+ andc r0,r0,r3
+ li r3,0x0400
+ or r0,r0,r3
+ sync
+ mtspr HID0, r0
+ sync
+ blr
+#endif
diff --git a/arch/powerpc/cpu/74xx_7xx/traps.c b/arch/powerpc/cpu/74xx_7xx/traps.c
new file mode 100644
index 0000000..a33e283
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/traps.c
@@ -0,0 +1,234 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS:"
+ " %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP:"
+ " %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x000F0000) {
+ case (0x80000000>>12):
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13):
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14):
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000>>15):
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
+ int i, j;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+
+ p = (unsigned char *) ((unsigned long)p & 0xFFFFFFE0);
+ p -= 32;
+ for (i = 0; i < 256; i+=16) {
+ printf("%08x: ", (unsigned int)p+i);
+ for (j = 0; j < 16; j++) {
+ printf("%02x ", p[i+j]);
+ }
+ printf("\n");
+ }
+
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/74xx_7xx/u-boot.lds b/arch/powerpc/cpu/74xx_7xx/u-boot.lds
new file mode 100644
index 0000000..40b89ab
--- /dev/null
+++ b/arch/powerpc/cpu/74xx_7xx/u-boot.lds
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright 2010 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+ .text :
+ {
+ arch/powerpc/cpu/74xx_7xx/start.o (.text*)
+
+ *(.text*)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc512x/Makefile b/arch/powerpc/cpu/mpc512x/Makefile
new file mode 100644
index 0000000..4f4c9ec
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/Makefile
@@ -0,0 +1,63 @@
+#
+# (C) Copyright 2007-2009 DENX Software Engineering
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+$(shell mkdir -p $(OBJTREE)/board/freescale/common)
+
+LIB = $(obj)lib$(CPU).o
+
+START = start.o
+COBJS-y := cpu.o
+COBJS-y += traps.o
+COBJS-y += cpu_init.o
+COBJS-y += fixed_sdram.o
+COBJS-y += i2c.o
+COBJS-y += interrupts.o
+COBJS-y += iopin.o
+COBJS-y += serial.o
+COBJS-y += speed.o
+COBJS-$(CONFIG_FSL_DIU_FB) += diu.o
+COBJS-$(CONFIG_CMD_IDE) += ide.o
+COBJS-$(CONFIG_PCI) += pci.o
+
+# Stub implementations of cache management functions for USB
+COBJS-$(CONFIG_USB_EHCI) += cache.o
+
+COBJS := $(COBJS-y)
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc512x/asm-offsets.h b/arch/powerpc/cpu/mpc512x/asm-offsets.h
new file mode 100644
index 0000000..957d4be
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/asm-offsets.h
@@ -0,0 +1,15 @@
+/*
+ * needed for arch/powerpc/cpu/mpc512x/start.S
+ *
+ * These should be auto-generated
+ */
+#define LPCS0AW 0x0024
+#define SRAMBAR 0x00C4
+#define SWCRR 0x0904
+#define LPC_OFFSET 0x10000
+#define CS0_CONFIG 0x00000
+#define CS_CTRL 0x00020
+#define CS_CTRL_ME 0x01000000 /* CS Master Enable bit */
+
+#define EXC_OFF_SYS_RESET 0x0100
+#define _START_OFFSET EXC_OFF_SYS_RESET
diff --git a/arch/powerpc/cpu/mpc512x/cache.c b/arch/powerpc/cpu/mpc512x/cache.c
new file mode 100644
index 0000000..2a08b65
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/cache.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ *
+ * This file contains stub implementation of
+ * invalidate_dcache_range()
+ * flush_dcache_range()
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
diff --git a/arch/powerpc/cpu/mpc512x/config.mk b/arch/powerpc/cpu/mpc512x/config.mk
new file mode 100644
index 0000000..8fceded
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2007-2010 DENX Software Engineering
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC512X -DCONFIG_E300 \
+ -ffixed-r2 -msoft-float -mcpu=603e
diff --git a/arch/powerpc/cpu/mpc512x/cpu.c b/arch/powerpc/cpu/mpc512x/cpu.c
new file mode 100644
index 0000000..bb03c6d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/cpu.c
@@ -0,0 +1,216 @@
+/*
+ * (C) Copyright 2007-2010 DENX Software Engineering
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC512x family.
+ *
+ * Derived from the MPC83xx code.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ ulong clock = gd->cpu_clk;
+ u32 pvr = get_pvr ();
+ u32 spridr = in_be32(&immr->sysconf.spridr);
+ char buf1[32], buf2[32];
+
+ puts ("CPU: ");
+
+ switch (spridr & 0xffff0000) {
+ case SPR_5121E:
+ puts ("MPC5121e ");
+ break;
+ default:
+ printf ("Unknown part ID %08x ", spridr & 0xffff0000);
+ }
+ printf ("rev. %d.%d, Core ", SVR_MJREV (spridr), SVR_MNREV (spridr));
+
+ switch (pvr & 0xffff0000) {
+ case PVR_E300C4:
+ puts ("e300c4 ");
+ break;
+ default:
+ puts ("unknown ");
+ }
+ printf ("at %s MHz, CSB at %s MHz (RSR=0x%04lx)\n",
+ strmhz(buf1, clock),
+ strmhz(buf2, gd->arch.csb_clk),
+ gd->arch.reset_status & 0xffff);
+ return 0;
+}
+
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong msr;
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~( MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /*
+ * Enable Reset Control Reg - "RSTE" is the magic word that let us go
+ */
+ out_be32(&immap->reset.rpr, 0x52535445);
+
+ /* Verify Reset Control Reg is enabled */
+ while (!(in_be32(&immap->reset.rcer) & RCER_CRE))
+ ;
+
+ printf ("Resetting the board.\n");
+ udelay(200);
+
+ /* Perform reset */
+ out_be32(&immap->reset.rcr, RCR_SWHR);
+
+ /* Unreached... */
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+unsigned long get_tbclk (void)
+{
+ ulong tbclk;
+
+ tbclk = (gd->bus_clk + 3L) / 4L;
+
+ return tbclk;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+ int re_enable = disable_interrupts ();
+
+ /* Reset watchdog */
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ out_be32(&immr->wdt.swsrr, 0x556c);
+ out_be32(&immr->wdt.swsrr, 0xaa39);
+
+ if (re_enable)
+ enable_interrupts ();
+}
+#endif
+
+#ifdef CONFIG_OF_LIBFDT
+
+#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
+/*
+ * fdt setup for old device trees
+ * fix up
+ * cpu clocks
+ * soc clocks
+ * ethernet addresses
+ */
+static void old_ft_cpu_setup(void *blob, bd_t *bd)
+{
+ /*
+ * avoid fixing up by path because that
+ * produces scary error messages
+ */
+ uchar enetaddr[6];
+
+ /*
+ * old device trees have ethernet nodes with
+ * device_type = "network"
+ */
+ eth_getenv_enetaddr("ethaddr", enetaddr);
+ do_fixup_by_prop(blob, "device_type", "network", 8,
+ "local-mac-address", enetaddr, 6, 0);
+ do_fixup_by_prop(blob, "device_type", "network", 8,
+ "address", enetaddr, 6, 0);
+ /*
+ * old device trees have soc nodes with
+ * device_type = "soc"
+ */
+ do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+ "bus-frequency", bd->bi_ipsfreq, 0);
+}
+#endif
+
+static void ft_clock_setup(void *blob, bd_t *bd)
+{
+ char *cpu_path = "/cpus/" OF_CPU;
+
+ /*
+ * fixup cpu clocks using path
+ */
+ do_fixup_by_path_u32(blob, cpu_path,
+ "timebase-frequency", OF_TBCLK, 1);
+ do_fixup_by_path_u32(blob, cpu_path,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_path_u32(blob, cpu_path,
+ "clock-frequency", bd->bi_intfreq, 1);
+ /*
+ * fixup soc clocks using compatible
+ */
+ do_fixup_by_compat_u32(blob, OF_SOC_COMPAT,
+ "bus-frequency", bd->bi_ipsfreq, 1);
+}
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+#ifdef CONFIG_OF_SUPPORT_OLD_DEVICE_TREES
+ old_ft_cpu_setup(blob, bd);
+#endif
+ ft_clock_setup(blob, bd);
+#ifdef CONFIG_HAS_ETH0
+ fdt_fixup_ethernet(blob);
+#endif
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
+#endif
+
+#ifdef CONFIG_MPC512x_FEC
+/* Default initializations for FEC controllers. To override,
+ * create a board-specific function called:
+ * int board_eth_init(bd_t *bis)
+ */
+
+int cpu_eth_init(bd_t *bis)
+{
+ return mpc512x_fec_initialize(bis);
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc512x/cpu_init.c b/arch/powerpc/cpu/mpc512x/cpu_init.c
new file mode 100644
index 0000000..0e20ded
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/cpu_init.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007-2009 DENX Software Engineering
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Derived from the MPC83xx code.
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/mpc512x.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Set up the memory map, initialize registers,
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+ u32 ips_div;
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ memset ((void *) gd, 0, sizeof (gd_t));
+
+ /* Local Window and chip select configuration */
+#if defined(CONFIG_SYS_CS0_START) && defined(CONFIG_SYS_CS0_SIZE)
+ out_be32(&im->sysconf.lpcs0aw,
+ CSAW_START(CONFIG_SYS_CS0_START) |
+ CSAW_STOP(CONFIG_SYS_CS0_START, CONFIG_SYS_CS0_SIZE));
+ sync_law(&im->sysconf.lpcs0aw);
+#endif
+#if defined(CONFIG_SYS_CS0_CFG)
+ out_be32(&im->lpc.cs_cfg[0], CONFIG_SYS_CS0_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS1_START) && defined(CONFIG_SYS_CS1_SIZE)
+ out_be32(&im->sysconf.lpcs1aw,
+ CSAW_START(CONFIG_SYS_CS1_START) |
+ CSAW_STOP(CONFIG_SYS_CS1_START, CONFIG_SYS_CS1_SIZE));
+ sync_law(&im->sysconf.lpcs1aw);
+#endif
+#if defined(CONFIG_SYS_CS1_CFG)
+ out_be32(&im->lpc.cs_cfg[1], CONFIG_SYS_CS1_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS2_START) && (defined CONFIG_SYS_CS2_SIZE)
+ out_be32(&im->sysconf.lpcs2aw,
+ CSAW_START(CONFIG_SYS_CS2_START) |
+ CSAW_STOP(CONFIG_SYS_CS2_START, CONFIG_SYS_CS2_SIZE));
+ sync_law(&im->sysconf.lpcs2aw);
+#endif
+#if defined(CONFIG_SYS_CS2_CFG)
+ out_be32(&im->lpc.cs_cfg[2], CONFIG_SYS_CS2_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS3_START) && defined(CONFIG_SYS_CS3_SIZE)
+ out_be32(&im->sysconf.lpcs3aw,
+ CSAW_START(CONFIG_SYS_CS3_START) |
+ CSAW_STOP(CONFIG_SYS_CS3_START, CONFIG_SYS_CS3_SIZE));
+ sync_law(&im->sysconf.lpcs3aw);
+#endif
+#if defined(CONFIG_SYS_CS3_CFG)
+ out_be32(&im->lpc.cs_cfg[3], CONFIG_SYS_CS3_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS4_START) && defined(CONFIG_SYS_CS4_SIZE)
+ out_be32(&im->sysconf.lpcs4aw,
+ CSAW_START(CONFIG_SYS_CS4_START) |
+ CSAW_STOP(CONFIG_SYS_CS4_START, CONFIG_SYS_CS4_SIZE));
+ sync_law(&im->sysconf.lpcs4aw);
+#endif
+#if defined(CONFIG_SYS_CS4_CFG)
+ out_be32(&im->lpc.cs_cfg[4], CONFIG_SYS_CS4_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS5_START) && defined(CONFIG_SYS_CS5_SIZE)
+ out_be32(&im->sysconf.lpcs5aw,
+ CSAW_START(CONFIG_SYS_CS5_START) |
+ CSAW_STOP(CONFIG_SYS_CS5_START, CONFIG_SYS_CS5_SIZE));
+ sync_law(&im->sysconf.lpcs5aw);
+#endif
+#if defined(CONFIG_SYS_CS5_CFG)
+ out_be32(&im->lpc.cs_cfg[5], CONFIG_SYS_CS5_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS6_START) && defined(CONFIG_SYS_CS6_SIZE)
+ out_be32(&im->sysconf.lpcs6aw,
+ CSAW_START(CONFIG_SYS_CS6_START) |
+ CSAW_STOP(CONFIG_SYS_CS6_START, CONFIG_SYS_CS6_SIZE));
+ sync_law(&im->sysconf.lpcs6aw);
+#endif
+#if defined(CONFIG_SYS_CS6_CFG)
+ out_be32(&im->lpc.cs_cfg[6], CONFIG_SYS_CS6_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS7_START) && defined(CONFIG_SYS_CS7_SIZE)
+ out_be32(&im->sysconf.lpcs7aw,
+ CSAW_START(CONFIG_SYS_CS7_START) |
+ CSAW_STOP(CONFIG_SYS_CS7_START, CONFIG_SYS_CS7_SIZE));
+ sync_law(&im->sysconf.lpcs7aw);
+#endif
+#if defined(CONFIG_SYS_CS7_CFG)
+ out_be32(&im->lpc.cs_cfg[7], CONFIG_SYS_CS7_CFG);
+#endif
+
+#if defined CONFIG_SYS_CS_ALETIMING
+ if (SVR_MJREV(in_be32(&im->sysconf.spridr)) >= 2)
+ out_be32(&im->lpc.altr, CONFIG_SYS_CS_ALETIMING);
+#endif
+#if defined CONFIG_SYS_CS_BURST
+ out_be32(&im->lpc.cs_bcr, CONFIG_SYS_CS_BURST);
+#endif
+#if defined CONFIG_SYS_CS_DEADCYCLE
+ out_be32(&im->lpc.cs_dccr, CONFIG_SYS_CS_DEADCYCLE);
+#endif
+#if defined CONFIG_SYS_CS_HOLDCYCLE
+ out_be32(&im->lpc.cs_hccr, CONFIG_SYS_CS_HOLDCYCLE);
+#endif
+
+ /* system performance tweaking */
+
+#ifdef CONFIG_SYS_ACR_PIPE_DEP
+ /* Arbiter pipeline depth */
+ out_be32(&im->arbiter.acr,
+ (im->arbiter.acr & ~ACR_PIPE_DEP) |
+ (CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT)
+ );
+#endif
+
+#ifdef CONFIG_SYS_ACR_RPTCNT
+ /* Arbiter repeat count */
+ out_be32(im->arbiter.acr,
+ (im->arbiter.acr & ~(ACR_RPTCNT)) |
+ (CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT)
+ );
+#endif
+
+ /* RSR - Reset Status Register - clear all status */
+ gd->arch.reset_status = im->reset.rsr;
+ out_be32(&im->reset.rsr, ~RSR_RES);
+
+ /*
+ * RMR - Reset Mode Register - enable checkstop reset
+ */
+ out_be32(&im->reset.rmr, RMR_CSRE & (1 << RMR_CSRE_SHIFT));
+
+ /* Set IPS-CSB divider: IPS = 1/2 CSB */
+ ips_div = in_be32(&im->clk.scfr[0]);
+ ips_div &= ~(SCFR1_IPS_DIV_MASK);
+ ips_div |= SCFR1_IPS_DIV << SCFR1_IPS_DIV_SHIFT;
+ out_be32(&im->clk.scfr[0], ips_div);
+
+#ifdef SCFR1_LPC_DIV
+ clrsetbits_be32(&im->clk.scfr[0], SCFR1_LPC_DIV_MASK,
+ SCFR1_LPC_DIV << SCFR1_LPC_DIV_SHIFT);
+#endif
+
+#ifdef SCFR1_NFC_DIV
+ clrsetbits_be32(&im->clk.scfr[0], SCFR1_NFC_DIV_MASK,
+ SCFR1_NFC_DIV << SCFR1_NFC_DIV_SHIFT);
+#endif
+
+#ifdef SCFR1_DIU_DIV
+ clrsetbits_be32(&im->clk.scfr[0], SCFR1_DIU_DIV_MASK,
+ SCFR1_DIU_DIV << SCFR1_DIU_DIV_SHIFT);
+#endif
+
+ /*
+ * Enable Time Base/Decrementer
+ *
+ * NOTICE: TB needs to be enabled as early as possible in order to
+ * have udelay() working; if not enabled, usually leads to a hang, like
+ * during FLASH chip identification etc.
+ */
+ setbits_be32(&im->sysconf.spcr, SPCR_TBEN);
+
+ /*
+ * Enable clocks
+ */
+ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN);
+ out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN);
+#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE)
+ setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN);
+#endif
+}
+
+int cpu_init_r (void)
+{
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc512x/diu.c b/arch/powerpc/cpu/mpc512x/diu.c
new file mode 100644
index 0000000..b7db249
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/diu.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ * York Sun <yorksun@freescale.com>
+ *
+ * FSL DIU Framebuffer driver
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+
+#include <fsl_diu_fb.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void diu_set_pixel_clock(unsigned int pixclock)
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile clk512x_t *clk = &immap->clk;
+ volatile unsigned int *clkdvdr = &clk->scfr[0];
+ unsigned long speed_ccb, temp, pixval;
+
+ speed_ccb = get_bus_freq(0) * 4;
+ temp = 1000000000/pixclock;
+ temp *= 1000;
+ pixval = speed_ccb / temp;
+ debug("DIU pixval = %lu\n", pixval);
+
+ /* Modify PXCLK in GUTS CLKDVDR */
+ debug("DIU: Current value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr));
+ temp = in_be32(clkdvdr) & 0xFFFFFF00;
+ out_be32(clkdvdr, temp | (pixval & 0xFF));
+ debug("DIU: Modified value of CLKDVDR = 0x%08x\n", in_be32(clkdvdr));
+}
+
+int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
+{
+ unsigned int pixel_format = 0x88883316;
+
+ debug("mpc5121_diu_init\n");
+ return fsl_diu_init(xres, yres, pixel_format, 0);
+}
diff --git a/arch/powerpc/cpu/mpc512x/fixed_sdram.c b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
new file mode 100644
index 0000000..6635fb0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
@@ -0,0 +1,172 @@
+/*
+ * (C) Copyright 2007-2009 DENX Software Engineering
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/mpc512x.h>
+
+/*
+ * MDDRC Config Runtime Settings
+ */
+ddr512x_config_t default_mddrc_config = {
+ .ddr_sys_config = CONFIG_SYS_MDDRC_SYS_CFG,
+ .ddr_time_config0 = CONFIG_SYS_MDDRC_TIME_CFG0,
+ .ddr_time_config1 = CONFIG_SYS_MDDRC_TIME_CFG1,
+ .ddr_time_config2 = CONFIG_SYS_MDDRC_TIME_CFG2,
+};
+
+u32 default_init_seq[] = {
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_PCHG_ALL,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_RFSH,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_RFSH,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_MICRON_INIT_DEV_OP,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_EM2,
+ CONFIG_SYS_DDRCMD_NOP,
+ CONFIG_SYS_DDRCMD_PCHG_ALL,
+ CONFIG_SYS_DDRCMD_EM2,
+ CONFIG_SYS_DDRCMD_EM3,
+ CONFIG_SYS_DDRCMD_EN_DLL,
+ CONFIG_SYS_MICRON_INIT_DEV_OP,
+ CONFIG_SYS_DDRCMD_PCHG_ALL,
+ CONFIG_SYS_DDRCMD_RFSH,
+ CONFIG_SYS_MICRON_INIT_DEV_OP,
+ CONFIG_SYS_DDRCMD_OCD_DEFAULT,
+ CONFIG_SYS_DDRCMD_PCHG_ALL,
+ CONFIG_SYS_DDRCMD_NOP
+};
+
+/*
+ * fixed sdram init:
+ * The board doesn't use memory modules that have serial presence
+ * detect or similar mechanism for discovery of the DRAM settings
+ */
+long int fixed_sdram(ddr512x_config_t *mddrc_config,
+ u32 *dram_init_seq, int seq_sz)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ u32 msize = CONFIG_SYS_MAX_RAM_SIZE;
+ u32 msize_log2 = __ilog2(msize);
+ u32 i;
+
+ /* take default settings and init sequence if necessary */
+ if (mddrc_config == NULL)
+ mddrc_config = &default_mddrc_config;
+ if (dram_init_seq == NULL) {
+ dram_init_seq = default_init_seq;
+ seq_sz = sizeof(default_init_seq)/sizeof(u32);
+ }
+
+ /* Initialize IO Control */
+ out_be32(&im->io_ctrl.io_control_mem, CONFIG_SYS_IOCTRL_MUX_DDR);
+
+ /* Initialize DDR Local Window */
+ out_be32(&im->sysconf.ddrlaw.bar, CONFIG_SYS_DDR_BASE & 0xFFFFF000);
+ out_be32(&im->sysconf.ddrlaw.ar, msize_log2 - 1);
+ sync_law(&im->sysconf.ddrlaw.ar);
+
+ /* DDR Enable */
+ /*
+ * the "enable" combination: DRAM controller out of reset,
+ * clock enabled, command mode -- BUT leave CKE low for now
+ */
+ i = MDDRC_SYS_CFG_EN & ~MDDRC_SYS_CFG_CKE_MASK;
+ out_be32(&im->mddrc.ddr_sys_config, i);
+ /* maintain 200 microseconds of stable power and clock */
+ udelay(200);
+ /* apply a NOP, it shouldn't harm */
+ out_be32(&im->mddrc.ddr_command, CONFIG_SYS_DDRCMD_NOP);
+ /* now assert CKE (high) */
+ i |= MDDRC_SYS_CFG_CKE_MASK;
+ out_be32(&im->mddrc.ddr_sys_config, i);
+
+ /* Initialize DDR Priority Manager */
+ out_be32(&im->mddrc.prioman_config1, CONFIG_SYS_MDDRCGRP_PM_CFG1);
+ out_be32(&im->mddrc.prioman_config2, CONFIG_SYS_MDDRCGRP_PM_CFG2);
+ out_be32(&im->mddrc.hiprio_config, CONFIG_SYS_MDDRCGRP_HIPRIO_CFG);
+ out_be32(&im->mddrc.lut_table0_main_upper, CONFIG_SYS_MDDRCGRP_LUT0_MU);
+ out_be32(&im->mddrc.lut_table0_main_lower, CONFIG_SYS_MDDRCGRP_LUT0_ML);
+ out_be32(&im->mddrc.lut_table1_main_upper, CONFIG_SYS_MDDRCGRP_LUT1_MU);
+ out_be32(&im->mddrc.lut_table1_main_lower, CONFIG_SYS_MDDRCGRP_LUT1_ML);
+ out_be32(&im->mddrc.lut_table2_main_upper, CONFIG_SYS_MDDRCGRP_LUT2_MU);
+ out_be32(&im->mddrc.lut_table2_main_lower, CONFIG_SYS_MDDRCGRP_LUT2_ML);
+ out_be32(&im->mddrc.lut_table3_main_upper, CONFIG_SYS_MDDRCGRP_LUT3_MU);
+ out_be32(&im->mddrc.lut_table3_main_lower, CONFIG_SYS_MDDRCGRP_LUT3_ML);
+ out_be32(&im->mddrc.lut_table4_main_upper, CONFIG_SYS_MDDRCGRP_LUT4_MU);
+ out_be32(&im->mddrc.lut_table4_main_lower, CONFIG_SYS_MDDRCGRP_LUT4_ML);
+ out_be32(&im->mddrc.lut_table0_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT0_AU);
+ out_be32(&im->mddrc.lut_table0_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT0_AL);
+ out_be32(&im->mddrc.lut_table1_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT1_AU);
+ out_be32(&im->mddrc.lut_table1_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT1_AL);
+ out_be32(&im->mddrc.lut_table2_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT2_AU);
+ out_be32(&im->mddrc.lut_table2_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT2_AL);
+ out_be32(&im->mddrc.lut_table3_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT3_AU);
+ out_be32(&im->mddrc.lut_table3_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT3_AL);
+ out_be32(&im->mddrc.lut_table4_alternate_upper, CONFIG_SYS_MDDRCGRP_LUT4_AU);
+ out_be32(&im->mddrc.lut_table4_alternate_lower, CONFIG_SYS_MDDRCGRP_LUT4_AL);
+
+ /*
+ * Initialize MDDRC
+ * put MDDRC in CMD mode and
+ * set the max time between refreshes to 0 during init process
+ */
+ out_be32(&im->mddrc.ddr_sys_config,
+ mddrc_config->ddr_sys_config | MDDRC_SYS_CFG_CMD_MASK);
+ out_be32(&im->mddrc.ddr_time_config0,
+ mddrc_config->ddr_time_config0 & MDDRC_REFRESH_ZERO_MASK);
+ out_be32(&im->mddrc.ddr_time_config1,
+ mddrc_config->ddr_time_config1);
+ out_be32(&im->mddrc.ddr_time_config2,
+ mddrc_config->ddr_time_config2);
+
+ /* Initialize DDR with either default or supplied init sequence */
+ for (i = 0; i < seq_sz; i++)
+ out_be32(&im->mddrc.ddr_command, dram_init_seq[i]);
+
+ /* Start MDDRC */
+ out_be32(&im->mddrc.ddr_time_config0, mddrc_config->ddr_time_config0);
+ out_be32(&im->mddrc.ddr_sys_config, mddrc_config->ddr_sys_config);
+
+ /* Allow for the DLL to startup before accessing data */
+ udelay(10);
+
+ msize = get_ram_size(CONFIG_SYS_DDR_BASE, CONFIG_SYS_MAX_RAM_SIZE);
+ /* Fix DDR Local Window for new size */
+ out_be32(&im->sysconf.ddrlaw.ar, __ilog2(msize) - 1);
+ sync_law(&im->sysconf.ddrlaw.ar);
+
+ return msize;
+}
diff --git a/arch/powerpc/cpu/mpc512x/i2c.c b/arch/powerpc/cpu/mpc512x/i2c.c
new file mode 100644
index 0000000..59040f8
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/i2c.c
@@ -0,0 +1,402 @@
+/*
+ * (C) Copyright 2003 - 2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC5xxx code.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_HARD_I2C
+
+#include <i2c.h>
+
+/* by default set I2C bus 0 active */
+static unsigned int bus_num __attribute__ ((section (".data"))) = 0;
+
+#define I2C_TIMEOUT 100
+#define I2C_RETRIES 3
+
+struct mpc512x_i2c_tap {
+ int scl2tap;
+ int tap2tap;
+};
+
+static int mpc_reg_in(volatile u32 *reg);
+static void mpc_reg_out(volatile u32 *reg, int val, int mask);
+static int wait_for_bb(void);
+static int wait_for_pin(int *status);
+static int do_address(uchar chip, char rdwr_flag);
+static int send_bytes(uchar chip, char *buf, int len);
+static int receive_bytes(uchar chip, char *buf, int len);
+static int mpc_get_fdr(int);
+
+static int mpc_reg_in (volatile u32 *reg)
+{
+ int ret = in_be32(reg) >> 24;
+
+ return ret;
+}
+
+static void mpc_reg_out (volatile u32 *reg, int val, int mask)
+{
+ if (!mask) {
+ out_be32(reg, val << 24);
+ } else {
+ clrsetbits_be32(reg, mask << 24, (val & mask) << 24);
+ }
+}
+
+static int wait_for_bb (void)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ int timeout = I2C_TIMEOUT;
+ int status;
+
+ status = mpc_reg_in (&regs->msr);
+
+ while (timeout-- && (status & I2C_BB)) {
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+ (void)mpc_reg_in(&regs->mdr);
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ mpc_reg_out (&regs->mcr, 0, 0);
+ mpc_reg_out (&regs->mcr, I2C_EN, 0);
+
+ udelay (1000);
+ status = mpc_reg_in (&regs->msr);
+ }
+
+ return (status & I2C_BB);
+}
+
+static int wait_for_pin (int *status)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ int timeout = I2C_TIMEOUT;
+
+ *status = mpc_reg_in (&regs->msr);
+
+ while (timeout-- && !(*status & I2C_IF)) {
+ udelay (1000);
+ *status = mpc_reg_in (&regs->msr);
+ }
+
+ if (!(*status & I2C_IF)) {
+ return -1;
+ }
+
+ mpc_reg_out (&regs->msr, 0, I2C_IF);
+
+ return 0;
+}
+
+static int do_address (uchar chip, char rdwr_flag)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ int status;
+
+ chip <<= 1;
+
+ if (rdwr_flag) {
+ chip |= 1;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_TX, I2C_TX);
+ mpc_reg_out (&regs->mdr, chip, 0);
+
+ if (wait_for_pin (&status)) {
+ return -2;
+ }
+
+ if (status & I2C_RXAK) {
+ return -3;
+ }
+
+ return 0;
+}
+
+static int send_bytes (uchar chip, char *buf, int len)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ int wrcount;
+ int status;
+
+ for (wrcount = 0; wrcount < len; ++wrcount) {
+
+ mpc_reg_out (&regs->mdr, buf[wrcount], 0);
+
+ if (wait_for_pin (&status)) {
+ break;
+ }
+
+ if (status & I2C_RXAK) {
+ break;
+ }
+
+ }
+
+ return !(wrcount == len);
+}
+
+static int receive_bytes (uchar chip, char *buf, int len)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ int dummy = 1;
+ int rdcount = 0;
+ int status;
+ int i;
+
+ mpc_reg_out (&regs->mcr, 0, I2C_TX);
+
+ for (i = 0; i < len; ++i) {
+ buf[rdcount] = mpc_reg_in (&regs->mdr);
+
+ if (dummy) {
+ dummy = 0;
+ } else {
+ rdcount++;
+ }
+
+ if (wait_for_pin (&status)) {
+ return -4;
+ }
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_TXAK, I2C_TXAK);
+ buf[rdcount++] = mpc_reg_in (&regs->mdr);
+
+ if (wait_for_pin (&status)) {
+ return -5;
+ }
+
+ mpc_reg_out (&regs->mcr, 0, I2C_TXAK);
+
+ return 0;
+}
+
+/**************** I2C API ****************/
+
+void i2c_init (int speed, int saddr)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ int i;
+
+ for (i = 0; i < I2C_BUS_CNT; i++){
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[i];
+
+ mpc_reg_out (&regs->mcr, 0, 0);
+
+ /* Set clock */
+ mpc_reg_out (&regs->mfdr, mpc_get_fdr (speed), 0);
+ mpc_reg_out (&regs->madr, saddr << 1, 0);
+
+ /* Enable module */
+ mpc_reg_out (&regs->mcr, I2C_EN, I2C_INIT_MASK);
+ mpc_reg_out (&regs->msr, 0, I2C_IF);
+ }
+
+ /* Disable interrupts */
+ out_be32(&im->i2c.icr, 0);
+
+ /* Turn off filters */
+ out_be32(&im->i2c.mifr, 0);
+}
+
+static int mpc_get_fdr (int speed)
+{
+ static int fdr = -1;
+
+ if (fdr == -1) {
+ ulong best_speed = 0;
+ ulong divider;
+ ulong ips, scl;
+ ulong bestmatch = 0xffffffffUL;
+ int best_i = 0, best_j = 0, i, j;
+ int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
+ struct mpc512x_i2c_tap scltap[] = {
+ {4, 1},
+ {4, 2},
+ {6, 4},
+ {6, 8},
+ {14, 16},
+ {30, 32},
+ {62, 64},
+ {126, 128}
+ };
+
+ ips = gd->arch.ips_clk;
+ for (i = 7; i >= 0; i--) {
+ for (j = 7; j >= 0; j--) {
+ scl = 2 * (scltap[j].scl2tap +
+ (SCL_Tap[i] - 1) * scltap[j].tap2tap
+ + 2);
+ if (ips <= speed*scl) {
+ if ((speed*scl - ips) < bestmatch) {
+ bestmatch = speed*scl - ips;
+ best_i = i;
+ best_j = j;
+ best_speed = ips/scl;
+ }
+ }
+ }
+ }
+ divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+ if (gd->flags & GD_FLG_RELOC) {
+ fdr = divider;
+ } else {
+ debug("%ld kHz, \n", best_speed / 1000);
+ return divider;
+ }
+ }
+
+ return fdr;
+}
+
+int i2c_probe (uchar chip)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ int i;
+
+ for (i = 0; i < I2C_RETRIES; i++) {
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+
+ if (! do_address (chip, 0)) {
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ udelay (500);
+ break;
+ }
+
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ udelay (500);
+ }
+
+ return (i == I2C_RETRIES);
+}
+
+int i2c_read (uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ char xaddr[4];
+ int ret = -1;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+ if (wait_for_bb ()) {
+ printf ("i2c_read: bus is busy\n");
+ goto Done;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+ if (do_address (chip, 0)) {
+ printf ("i2c_read: failed to address chip\n");
+ goto Done;
+ }
+
+ if (send_bytes (chip, &xaddr[4-alen], alen)) {
+ printf ("i2c_read: send_bytes failed\n");
+ goto Done;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_RSTA, I2C_RSTA);
+ if (do_address (chip, 1)) {
+ printf ("i2c_read: failed to address chip\n");
+ goto Done;
+ }
+
+ if (receive_bytes (chip, (char *)buf, len)) {
+ printf ("i2c_read: receive_bytes failed\n");
+ goto Done;
+ }
+
+ ret = 0;
+Done:
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ return ret;
+}
+
+int i2c_write (uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c512x_dev_t *regs = &im->i2c.dev[bus_num];
+ char xaddr[4];
+ int ret = -1;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+ if (wait_for_bb ()) {
+ printf ("i2c_write: bus is busy\n");
+ goto Done;
+ }
+
+ mpc_reg_out (&regs->mcr, I2C_STA, I2C_STA);
+ if (do_address (chip, 0)) {
+ printf ("i2c_write: failed to address chip\n");
+ goto Done;
+ }
+
+ if (send_bytes (chip, &xaddr[4-alen], alen)) {
+ printf ("i2c_write: send_bytes failed\n");
+ goto Done;
+ }
+
+ if (send_bytes (chip, (char *)buf, len)) {
+ printf ("i2c_write: send_bytes failed\n");
+ goto Done;
+ }
+
+ ret = 0;
+Done:
+ mpc_reg_out (&regs->mcr, 0, I2C_STA);
+ return ret;
+}
+
+int i2c_set_bus_num (unsigned int bus)
+{
+ if (bus >= I2C_BUS_CNT) {
+ return -1;
+ }
+ bus_num = bus;
+
+ return 0;
+}
+
+unsigned int i2c_get_bus_num (void)
+{
+ return bus_num;
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc512x/ide.c b/arch/powerpc/cpu/mpc512x/ide.c
new file mode 100644
index 0000000..7a49673
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/ide.c
@@ -0,0 +1,128 @@
+/*
+ * (C) Copyright 2007-2009 DENX Software Engineering
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_IDE_RESET)
+
+void ide_set_reset (int idereset)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ debug ("ide_set_reset(%d)\n", idereset);
+
+ if (idereset) {
+ out_be32(&im->pata.pata_ata_control, 0);
+ } else {
+ out_be32(&im->pata.pata_ata_control, FSL_ATA_CTRL_ATA_RST_B);
+ }
+ udelay(100);
+}
+
+void init_ide_reset (void)
+{
+ debug ("init_ide_reset\n");
+
+ /*
+ * Clear the reset bit to reset the interface
+ * cf. RefMan MPC5121EE: 28.4.1 Resetting the ATA Bus
+ */
+ ide_set_reset(1);
+
+ /* Assert the reset bit to enable the interface */
+ ide_set_reset(0);
+
+}
+
+#define CALC_TIMING(t) (t + period - 1) / period
+
+int ide_preinit (void)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ long t;
+ const struct {
+ short t0;
+ short t1;
+ short t2_8;
+ short t2_16;
+ short t2i;
+ short t4;
+ short t9;
+ short tA;
+ } pio_specs = {
+ .t0 = 600,
+ .t1 = 70,
+ .t2_8 = 290,
+ .t2_16 = 165,
+ .t2i = 0,
+ .t4 = 30,
+ .t9 = 20,
+ .tA = 50,
+ };
+ union {
+ u32 config;
+ struct {
+ u8 field1;
+ u8 field2;
+ u8 field3;
+ u8 field4;
+ }bytes;
+ } cfg;
+
+ debug ("IDE preinit using PATA peripheral at IMMR-ADDR %08x\n",
+ (u32)&im->pata);
+
+ /* Set the reset bit to 1 to enable the interface */
+ ide_set_reset(0);
+
+ /* Init timings : we use PIO mode 0 timings */
+ t = 1000000000 / gd->arch.ips_clk; /* period in ns */
+ cfg.bytes.field1 = 3;
+ cfg.bytes.field2 = 3;
+ cfg.bytes.field3 = (pio_specs.t1 + t) / t;
+ cfg.bytes.field4 = (pio_specs.t2_8 + t) / t;
+
+ out_be32(&im->pata.pata_time1, cfg.config);
+
+ cfg.bytes.field1 = (pio_specs.t2_8 + t) / t;
+ cfg.bytes.field2 = (pio_specs.tA + t) / t + 2;
+ cfg.bytes.field3 = 1;
+ cfg.bytes.field4 = (pio_specs.t4 + t) / t;
+
+ out_be32(&im->pata.pata_time2, cfg.config);
+
+ cfg.config = in_be32(&im->pata.pata_time3);
+ cfg.bytes.field1 = (pio_specs.t9 + t) / t;
+
+ out_be32(&im->pata.pata_time3, cfg.config);
+
+ debug ("PATA preinit complete.\n");
+
+ return 0;
+}
+
+#endif /* defined(CONFIG_IDE_RESET) */
diff --git a/arch/powerpc/cpu/mpc512x/interrupts.c b/arch/powerpc/cpu/mpc512x/interrupts.c
new file mode 100644
index 0000000..ef7c773
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/interrupts.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Derived from the MPC83xx code.
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ ulong count;
+};
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ *decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
+
+ return 0;
+}
+
+/*
+ * Install and free an interrupt handler.
+ */
+void
+irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
+{
+}
+
+void irq_free_handler (int irq)
+{
+}
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
diff --git a/arch/powerpc/cpu/mpc512x/iopin.c b/arch/powerpc/cpu/mpc512x/iopin.c
new file mode 100644
index 0000000..1a39101
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/iopin.c
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2008
+ * Martha J Marx, Silicon Turnkey Express, mmarx@silicontkx.com
+ * mpc512x I/O pin/pad initialization for the ADS5121 board
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+void iopin_initialize(iopin_t *ioregs_init, int len)
+{
+ short i, j, p;
+ u32 *reg;
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+
+ reg = (u32 *)&(im->io_ctrl);
+
+ if (sizeof(ioregs_init) == 0)
+ return;
+
+ for (i = 0; i < len; i++) {
+ for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long);
+ p < ioregs_init[i].nr_pins; p++, j++) {
+ if (ioregs_init[i].bit_or)
+ setbits_be32(reg + j, ioregs_init[i].val);
+ else
+ out_be32 (reg + j, ioregs_init[i].val);
+ }
+ }
+ return;
+}
+
+void iopin_initialize_bits(iopin_t *ioregs_init, int len)
+{
+ short i, j, p;
+ u32 *reg, mask;
+ immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+
+ reg = (u32 *)&(im->io_ctrl);
+
+ /* iterate over table entries */
+ for (i = 0; i < len; i++) {
+ /* iterate over pins within a table entry */
+ for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long);
+ p < ioregs_init[i].nr_pins; p++, j++) {
+ if (ioregs_init[i].bit_or & IO_PIN_OVER_EACH) {
+ /* replace all settings at once */
+ out_be32(reg + j, ioregs_init[i].val);
+ } else {
+ /*
+ * only replace individual parts, but
+ * REPLACE them instead of just ORing
+ * them in and "inheriting" previously
+ * set bits which we don't want
+ */
+ mask = 0;
+ if (ioregs_init[i].bit_or & IO_PIN_OVER_FMUX)
+ mask |= IO_PIN_FMUX(3);
+
+ if (ioregs_init[i].bit_or & IO_PIN_OVER_HOLD)
+ mask |= IO_PIN_HOLD(3);
+
+ if (ioregs_init[i].bit_or & IO_PIN_OVER_PULL)
+ mask |= IO_PIN_PUD(1) | IO_PIN_PUE(1);
+
+ if (ioregs_init[i].bit_or & IO_PIN_OVER_STRIG)
+ mask |= IO_PIN_ST(1);
+
+ if (ioregs_init[i].bit_or & IO_PIN_OVER_DRVSTR)
+ mask |= IO_PIN_DS(3);
+ /*
+ * DON'T do the "mask, then insert"
+ * in place on the register, it may
+ * break access to external hardware
+ * (like boot ROMs) when configuring
+ * LPB related pins, while the code to
+ * configure the pin is read from this
+ * very address region
+ */
+ clrsetbits_be32(reg + j, mask,
+ ioregs_init[i].val & mask);
+ }
+ }
+ }
+}
diff --git a/arch/powerpc/cpu/mpc512x/pci.c b/arch/powerpc/cpu/mpc512x/pci.c
new file mode 100644
index 0000000..16f034d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/pci.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2009-2010 DENX Software Engineering <wd@denx.de>
+ * Copyright (C) Freescale Semiconductor, Inc. 2006, 2007.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/global_data.h>
+#include <pci.h>
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* System RAM mapped to PCI space */
+#define CONFIG_PCI_SYS_MEM_BUS CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_SYS_MEM_PHYS CONFIG_SYS_SDRAM_BASE
+
+static struct pci_controller pci_hose;
+
+
+/**************************************************************************
+ * pci_init_board()
+ *
+ */
+void
+pci_init_board(void)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile law512x_t *pci_law;
+ volatile pot512x_t *pci_pot;
+ volatile pcictrl512x_t *pci_ctrl;
+ u16 reg16;
+ u32 reg32;
+ u32 dev;
+ int i;
+ struct pci_controller *hose;
+
+ /* Set PCI divider for 33MHz */
+ reg32 = in_be32(&im->clk.scfr[0]);
+ reg32 &= ~(SCFR1_PCI_DIV_MASK);
+ reg32 |= SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT;
+ out_be32(&im->clk.scfr[0], reg32);
+
+ clrsetbits_be32(&im->clk.scfr[0],
+ SCFR1_PCI_DIV_MASK,
+ SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT
+ );
+
+ pci_law = im->sysconf.pcilaw;
+ pci_pot = im->ios.pot;
+ pci_ctrl = &im->pci_ctrl;
+
+ hose = &pci_hose;
+
+ /*
+ * Release PCI RST Output signal
+ */
+ out_be32(&pci_ctrl->gcr, 0);
+ udelay(2000);
+ out_be32(&pci_ctrl->gcr, 1);
+
+ /* We need to wait at least a 1sec based on PCI specs */
+ for (i = 0; i < 1000; i++)
+ udelay(1000);
+
+ /*
+ * Configure PCI Local Access Windows
+ */
+ out_be32(&pci_law[0].bar, CONFIG_SYS_PCI_MEM_PHYS & LAWBAR_BAR);
+ out_be32(&pci_law[0].ar, LAWAR_EN | LAWAR_SIZE_512M);
+
+ out_be32(&pci_law[1].bar, CONFIG_SYS_PCI_IO_PHYS & LAWBAR_BAR);
+ out_be32(&pci_law[1].ar, LAWAR_EN | LAWAR_SIZE_16M);
+
+ /*
+ * Configure PCI Outbound Translation Windows
+ */
+
+ /* PCI mem space - prefetch */
+ out_be32(&pci_pot[0].potar,
+ (CONFIG_SYS_PCI_MEM_BASE >> 12) & POTAR_TA_MASK);
+ out_be32(&pci_pot[0].pobar,
+ (CONFIG_SYS_PCI_MEM_PHYS >> 12) & POBAR_BA_MASK);
+ out_be32(&pci_pot[0].pocmr,
+ POCMR_EN | POCMR_PRE | POCMR_CM_256M);
+
+ /* PCI IO space */
+ out_be32(&pci_pot[1].potar,
+ (CONFIG_SYS_PCI_IO_BASE >> 12) & POTAR_TA_MASK);
+ out_be32(&pci_pot[1].pobar,
+ (CONFIG_SYS_PCI_IO_PHYS >> 12) & POBAR_BA_MASK);
+ out_be32(&pci_pot[1].pocmr,
+ POCMR_EN | POCMR_IO | POCMR_CM_16M);
+
+ /* PCI mmio - non-prefetch mem space */
+ out_be32(&pci_pot[2].potar,
+ (CONFIG_SYS_PCI_MMIO_BASE >> 12) & POTAR_TA_MASK);
+ out_be32(&pci_pot[2].pobar,
+ (CONFIG_SYS_PCI_MMIO_PHYS >> 12) & POBAR_BA_MASK);
+ out_be32(&pci_pot[2].pocmr,
+ POCMR_EN | POCMR_CM_256M);
+
+ /*
+ * Configure PCI Inbound Translation Windows
+ */
+
+ /* we need RAM mapped to PCI space for the devices to
+ * access main memory */
+ out_be32(&pci_ctrl[0].pitar1, 0x0);
+ out_be32(&pci_ctrl[0].pibar1, 0x0);
+ out_be32(&pci_ctrl[0].piebar1, 0x0);
+ out_be32(&pci_ctrl[0].piwar1,
+ PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
+ PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size) - 1));
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* PCI memory prefetch space */
+ pci_set_region(hose->regions + 0,
+ CONFIG_SYS_PCI_MEM_BASE,
+ CONFIG_SYS_PCI_MEM_PHYS,
+ CONFIG_SYS_PCI_MEM_SIZE,
+ PCI_REGION_MEM|PCI_REGION_PREFETCH);
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + 1,
+ CONFIG_SYS_PCI_MMIO_BASE,
+ CONFIG_SYS_PCI_MMIO_PHYS,
+ CONFIG_SYS_PCI_MMIO_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI IO space */
+ pci_set_region(hose->regions + 2,
+ CONFIG_SYS_PCI_IO_BASE,
+ CONFIG_SYS_PCI_IO_PHYS,
+ CONFIG_SYS_PCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ /* System memory space */
+ pci_set_region(hose->regions + 3,
+ CONFIG_PCI_SYS_MEM_BUS,
+ CONFIG_PCI_SYS_MEM_PHYS,
+ gd->ram_size,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ hose->region_count = 4;
+
+ pci_setup_indirect(hose,
+ (CONFIG_SYS_IMMR + 0x8300),
+ (CONFIG_SYS_IMMR + 0x8304));
+
+ pci_register_hose(hose);
+
+ /*
+ * Write to Command register
+ */
+ reg16 = 0xff;
+ dev = PCI_BDF(hose->first_busno, 0, 0);
+ pci_hose_read_config_word(hose, dev, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+ pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+ pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+ /*
+ * Hose scan.
+ */
+ hose->last_busno = pci_hose_scan(hose);
+}
+
+#if defined(CONFIG_OF_LIBFDT)
+void ft_pci_setup(void *blob, bd_t *bd)
+{
+ int nodeoffset;
+ int tmp[2];
+ const char *path;
+
+ nodeoffset = fdt_path_offset(blob, "/aliases");
+ if (nodeoffset >= 0) {
+ path = fdt_getprop(blob, nodeoffset, "pci", NULL);
+ if (path) {
+ tmp[0] = cpu_to_be32(pci_hose.first_busno);
+ tmp[1] = cpu_to_be32(pci_hose.last_busno);
+ do_fixup_by_path(blob, path, "bus-range",
+ &tmp, sizeof(tmp), 1);
+
+ tmp[0] = cpu_to_be32(gd->pci_clk);
+ do_fixup_by_path(blob, path, "clock-frequency",
+ &tmp, sizeof(tmp[0]), 1);
+ }
+ }
+}
+#endif /* CONFIG_OF_LIBFDT */
diff --git a/arch/powerpc/cpu/mpc512x/serial.c b/arch/powerpc/cpu/mpc512x/serial.c
new file mode 100644
index 0000000..3afbe81
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/serial.c
@@ -0,0 +1,459 @@
+/*
+ * (C) Copyright 2000 - 2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based ont the MPC5200 PSC driver.
+ * Adapted for MPC512x by Jan Wrobel <wrr@semihalf.com>
+ */
+
+/*
+ * Minimal serial functions needed to use one of the PSC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_PSC_CONSOLE)
+
+static void fifo_init (volatile psc512x_t *psc)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ u32 tfsize, rfsize;
+
+ /* reset Rx & Tx fifo slice */
+ out_be32(&psc->rfcmd, PSC_FIFO_RESET_SLICE);
+ out_be32(&psc->tfcmd, PSC_FIFO_RESET_SLICE);
+
+ /* disable Tx & Rx FIFO interrupts */
+ out_be32(&psc->rfintmask, 0);
+ out_be32(&psc->tfintmask, 0);
+
+ switch (((u32)psc & 0xf00) >> 8) {
+ case 0:
+ tfsize = FIFOC_PSC0_TX_SIZE | (FIFOC_PSC0_TX_ADDR << 16);
+ rfsize = FIFOC_PSC0_RX_SIZE | (FIFOC_PSC0_RX_ADDR << 16);
+ break;
+ case 1:
+ tfsize = FIFOC_PSC1_TX_SIZE | (FIFOC_PSC1_TX_ADDR << 16);
+ rfsize = FIFOC_PSC1_RX_SIZE | (FIFOC_PSC1_RX_ADDR << 16);
+ break;
+ case 2:
+ tfsize = FIFOC_PSC2_TX_SIZE | (FIFOC_PSC2_TX_ADDR << 16);
+ rfsize = FIFOC_PSC2_RX_SIZE | (FIFOC_PSC2_RX_ADDR << 16);
+ break;
+ case 3:
+ tfsize = FIFOC_PSC3_TX_SIZE | (FIFOC_PSC3_TX_ADDR << 16);
+ rfsize = FIFOC_PSC3_RX_SIZE | (FIFOC_PSC3_RX_ADDR << 16);
+ break;
+ case 4:
+ tfsize = FIFOC_PSC4_TX_SIZE | (FIFOC_PSC4_TX_ADDR << 16);
+ rfsize = FIFOC_PSC4_RX_SIZE | (FIFOC_PSC4_RX_ADDR << 16);
+ break;
+ case 5:
+ tfsize = FIFOC_PSC5_TX_SIZE | (FIFOC_PSC5_TX_ADDR << 16);
+ rfsize = FIFOC_PSC5_RX_SIZE | (FIFOC_PSC5_RX_ADDR << 16);
+ break;
+ case 6:
+ tfsize = FIFOC_PSC6_TX_SIZE | (FIFOC_PSC6_TX_ADDR << 16);
+ rfsize = FIFOC_PSC6_RX_SIZE | (FIFOC_PSC6_RX_ADDR << 16);
+ break;
+ case 7:
+ tfsize = FIFOC_PSC7_TX_SIZE | (FIFOC_PSC7_TX_ADDR << 16);
+ rfsize = FIFOC_PSC7_RX_SIZE | (FIFOC_PSC7_RX_ADDR << 16);
+ break;
+ case 8:
+ tfsize = FIFOC_PSC8_TX_SIZE | (FIFOC_PSC8_TX_ADDR << 16);
+ rfsize = FIFOC_PSC8_RX_SIZE | (FIFOC_PSC8_RX_ADDR << 16);
+ break;
+ case 9:
+ tfsize = FIFOC_PSC9_TX_SIZE | (FIFOC_PSC9_TX_ADDR << 16);
+ rfsize = FIFOC_PSC9_RX_SIZE | (FIFOC_PSC9_RX_ADDR << 16);
+ break;
+ case 10:
+ tfsize = FIFOC_PSC10_TX_SIZE | (FIFOC_PSC10_TX_ADDR << 16);
+ rfsize = FIFOC_PSC10_RX_SIZE | (FIFOC_PSC10_RX_ADDR << 16);
+ break;
+ case 11:
+ tfsize = FIFOC_PSC11_TX_SIZE | (FIFOC_PSC11_TX_ADDR << 16);
+ rfsize = FIFOC_PSC11_RX_SIZE | (FIFOC_PSC11_RX_ADDR << 16);
+ break;
+ default:
+ return;
+ }
+
+ out_be32(&psc->tfsize, tfsize);
+ out_be32(&psc->rfsize, rfsize);
+
+ /* enable Tx & Rx FIFO slice */
+ out_be32(&psc->rfcmd, PSC_FIFO_ENABLE_SLICE);
+ out_be32(&psc->tfcmd, PSC_FIFO_ENABLE_SLICE);
+
+ out_be32(&im->fifoc.fifoc_cmd, FIFOC_DISABLE_CLOCK_GATE);
+ __asm__ volatile ("sync");
+}
+
+void serial_setbrg_dev(unsigned int idx)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+ unsigned long baseclk, div;
+ unsigned long baudrate;
+ char buf[16];
+ char *br_env;
+
+ baudrate = gd->baudrate;
+ if (idx != CONFIG_PSC_CONSOLE) {
+ /* Allows setting baudrate for other serial devices
+ * on PSCx using environment. If not specified, use
+ * the same baudrate as for console.
+ */
+ sprintf(buf, "psc%d_baudrate", idx);
+ br_env = getenv(buf);
+ if (br_env)
+ baudrate = simple_strtoul(br_env, NULL, 10);
+
+ debug("%s: idx %d, baudrate %ld\n", __func__, idx, baudrate);
+ }
+
+ /* calculate divisor for setting PSC CTUR and CTLR registers */
+ baseclk = (gd->arch.ips_clk + 8) / 16;
+ div = (baseclk + (baudrate / 2)) / baudrate;
+
+ out_8(&psc->ctur, (div >> 8) & 0xff);
+ out_8(&psc->ctlr, div & 0xff); /* set baudrate */
+}
+
+int serial_init_dev(unsigned int idx)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+ u32 reg;
+
+ reg = in_be32(&im->clk.sccr[0]);
+ out_be32(&im->clk.sccr[0], reg | CLOCK_SCCR1_PSC_EN(idx));
+
+ fifo_init (psc);
+
+ /* set MR register to point to MR1 */
+ out_8(&psc->command, PSC_SEL_MODE_REG_1);
+
+ /* disable Tx/Rx */
+ out_8(&psc->command, PSC_TX_DISABLE | PSC_RX_DISABLE);
+
+ /* choose the prescaler by 16 for the Tx/Rx clock generation */
+ out_be16(&psc->psc_clock_select, 0xdd00);
+
+ /* switch to UART mode */
+ out_be32(&psc->sicr, 0);
+
+ /* mode register points to mr1 */
+ /* configure parity, bit length and so on in mode register 1*/
+ out_8(&psc->mode, PSC_MODE_8_BITS | PSC_MODE_PARNONE);
+ /* now, mode register points to mr2 */
+ out_8(&psc->mode, PSC_MODE_1_STOPBIT);
+
+ /* set baudrate */
+ serial_setbrg_dev(idx);
+
+ /* disable all interrupts */
+ out_be16(&psc->psc_imr, 0);
+
+ /* reset and enable Rx/Tx */
+ out_8(&psc->command, PSC_RST_RX);
+ out_8(&psc->command, PSC_RST_TX);
+ out_8(&psc->command, PSC_RX_ENABLE | PSC_TX_ENABLE);
+
+ return 0;
+}
+
+int serial_uninit_dev(unsigned int idx)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+ u32 reg;
+
+ out_8(&psc->command, PSC_RX_DISABLE | PSC_TX_DISABLE);
+ reg = in_be32(&im->clk.sccr[0]);
+ reg &= ~CLOCK_SCCR1_PSC_EN(idx);
+ out_be32(&im->clk.sccr[0], reg);
+
+ return 0;
+}
+
+void serial_putc_dev(unsigned int idx, const char c)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+
+ if (c == '\n')
+ serial_putc_dev(idx, '\r');
+
+ /* Wait for last character to go. */
+ while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
+ ;
+
+ out_8(&psc->tfdata_8, c);
+}
+
+void serial_putc_raw_dev(unsigned int idx, const char c)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+
+ /* Wait for last character to go. */
+ while (!(in_be16(&psc->psc_status) & PSC_SR_TXEMP))
+ ;
+
+ out_8(&psc->tfdata_8, c);
+}
+
+void serial_puts_dev(unsigned int idx, const char *s)
+{
+ while (*s)
+ serial_putc_dev(idx, *s++);
+}
+
+int serial_getc_dev(unsigned int idx)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+
+ /* Wait for a character to arrive. */
+ while (in_be32(&psc->rfstat) & PSC_FIFO_EMPTY)
+ ;
+
+ return in_8(&psc->rfdata_8);
+}
+
+int serial_tstc_dev(unsigned int idx)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+
+ return !(in_be32(&psc->rfstat) & PSC_FIFO_EMPTY);
+}
+
+void serial_setrts_dev(unsigned int idx, int s)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+
+ if (s) {
+ /* Assert RTS (become LOW) */
+ out_8(&psc->op1, 0x1);
+ }
+ else {
+ /* Negate RTS (become HIGH) */
+ out_8(&psc->op0, 0x1);
+ }
+}
+
+int serial_getcts_dev(unsigned int idx)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ volatile psc512x_t *psc = (psc512x_t *) &im->psc[idx];
+
+ return (in_8(&psc->ip) & 0x1) ? 0 : 1;
+}
+#endif /* CONFIG_PSC_CONSOLE */
+
+#define DECLARE_PSC_SERIAL_FUNCTIONS(port) \
+ int serial##port##_init(void) \
+ { \
+ return serial_init_dev(port); \
+ } \
+ int serial##port##_uninit(void) \
+ { \
+ return serial_uninit_dev(port); \
+ } \
+ void serial##port##_setbrg(void) \
+ { \
+ serial_setbrg_dev(port); \
+ } \
+ int serial##port##_getc(void) \
+ { \
+ return serial_getc_dev(port); \
+ } \
+ int serial##port##_tstc(void) \
+ { \
+ return serial_tstc_dev(port); \
+ } \
+ void serial##port##_putc(const char c) \
+ { \
+ serial_putc_dev(port, c); \
+ } \
+ void serial##port##_puts(const char *s) \
+ { \
+ serial_puts_dev(port, s); \
+ }
+
+#define INIT_PSC_SERIAL_STRUCTURE(port, __name) { \
+ .name = __name, \
+ .start = serial##port##_init, \
+ .stop = serial##port##_uninit, \
+ .setbrg = serial##port##_setbrg, \
+ .getc = serial##port##_getc, \
+ .tstc = serial##port##_tstc, \
+ .putc = serial##port##_putc, \
+ .puts = serial##port##_puts, \
+}
+
+#if defined(CONFIG_SYS_PSC1)
+DECLARE_PSC_SERIAL_FUNCTIONS(1);
+struct serial_device serial1_device =
+INIT_PSC_SERIAL_STRUCTURE(1, "psc1");
+#endif
+
+#if defined(CONFIG_SYS_PSC3)
+DECLARE_PSC_SERIAL_FUNCTIONS(3);
+struct serial_device serial3_device =
+INIT_PSC_SERIAL_STRUCTURE(3, "psc3");
+#endif
+
+#if defined(CONFIG_SYS_PSC4)
+DECLARE_PSC_SERIAL_FUNCTIONS(4);
+struct serial_device serial4_device =
+INIT_PSC_SERIAL_STRUCTURE(4, "psc4");
+#endif
+
+#if defined(CONFIG_SYS_PSC6)
+DECLARE_PSC_SERIAL_FUNCTIONS(6);
+struct serial_device serial6_device =
+INIT_PSC_SERIAL_STRUCTURE(6, "psc6");
+#endif
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if (CONFIG_PSC_CONSOLE == 3)
+ return &serial3_device;
+#elif (CONFIG_PSC_CONSOLE == 6)
+ return &serial6_device;
+#else
+#error "invalid CONFIG_PSC_CONSOLE"
+#endif
+}
+
+void mpc512x_serial_initialize(void)
+{
+#if defined(CONFIG_SYS_PSC1)
+ serial_register(&serial1_device);
+#endif
+#if defined(CONFIG_SYS_PSC3)
+ serial_register(&serial3_device);
+#endif
+#if defined(CONFIG_SYS_PSC4)
+ serial_register(&serial4_device);
+#endif
+#if defined(CONFIG_SYS_PSC6)
+ serial_register(&serial6_device);
+#endif
+}
+
+#include <stdio_dev.h>
+/*
+ * Routines for communication with serial devices over PSC
+ */
+/* Bitfield for initialized PSCs */
+static unsigned int initialized;
+
+struct stdio_dev *open_port(int num, int baudrate)
+{
+ struct stdio_dev *port;
+ char env_var[16];
+ char env_val[10];
+ char name[7];
+
+ if (num < 0 || num > 11)
+ return NULL;
+
+ sprintf(name, "psc%d", num);
+ port = stdio_get_by_name(name);
+ if (!port)
+ return NULL;
+
+ if (!test_bit(num, &initialized)) {
+ sprintf(env_var, "psc%d_baudrate", num);
+ sprintf(env_val, "%d", baudrate);
+ setenv(env_var, env_val);
+
+ if (port->start())
+ return NULL;
+
+ set_bit(num, &initialized);
+ }
+
+ return port;
+}
+
+int close_port(int num)
+{
+ struct stdio_dev *port;
+ int ret;
+ char name[7];
+
+ if (num < 0 || num > 11)
+ return -1;
+
+ sprintf(name, "psc%d", num);
+ port = stdio_get_by_name(name);
+ if (!port)
+ return -1;
+
+ ret = port->stop();
+ clear_bit(num, &initialized);
+
+ return ret;
+}
+
+int write_port(struct stdio_dev *port, char *buf)
+{
+ if (!port || !buf)
+ return -1;
+
+ port->puts(buf);
+
+ return 0;
+}
+
+int read_port(struct stdio_dev *port, char *buf, int size)
+{
+ int cnt = 0;
+
+ if (!port || !buf)
+ return -1;
+
+ if (!size)
+ return 0;
+
+ while (port->tstc()) {
+ buf[cnt++] = port->getc();
+ if (cnt > size)
+ break;
+ }
+
+ return cnt;
+}
diff --git a/arch/powerpc/cpu/mpc512x/speed.c b/arch/powerpc/cpu/mpc512x/speed.c
new file mode 100644
index 0000000..6761877
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/speed.c
@@ -0,0 +1,153 @@
+/*
+ * (C) Copyright 2000-2009
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC83xx code.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int spmf_mult[] = {
+ 68, 1, 12, 16,
+ 20, 24, 28, 32,
+ 36, 40, 44, 48,
+ 52, 56, 60, 64
+};
+
+static int cpmf_mult[][2] = {
+ {0, 1}, {0, 1}, /* 0 and 1 are not valid */
+ {1, 1}, {3, 2},
+ {2, 1}, {5, 2},
+ {3, 1}, {7, 2},
+ {0, 1}, {0, 1}, /* and all above 7 are not valid too */
+ {0, 1}, {0, 1},
+ {0, 1}, {0, 1},
+ {0, 1}, {0, 1}
+};
+
+static int sys_dividors[][2] = {
+ {2, 1}, {5, 2}, {3, 1}, {7, 2}, {4, 1},
+ {9, 2}, {5, 1}, {7, 1}, {6, 1}, {8, 1},
+ {9, 1}, {11, 1}, {10, 1}, {12, 1}, {13, 1},
+ {15, 1}, {14, 1}, {16, 1}, {17, 1}, {19, 1},
+ {18, 1}, {20, 1}, {21, 1}, {23, 1}, {22, 1},
+ {24, 1}, {25, 1}, {27, 1}, {26, 1}, {28, 1},
+ {29, 1}, {31, 1}, {30, 1}, {32, 1}, {33, 1}
+};
+
+int get_clocks (void)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ u8 spmf;
+ u8 cpmf;
+ u8 sys_div;
+ u8 ips_div;
+ u8 pci_div;
+ u32 ref_clk = CONFIG_SYS_MPC512X_CLKIN;
+ u32 spll;
+ u32 sys_clk;
+ u32 core_clk;
+ u32 csb_clk;
+ u32 ips_clk;
+ u32 pci_clk;
+ u32 reg;
+
+ reg = in_be32(&im->sysconf.immrbar);
+ if ((reg & IMMRBAR_BASE_ADDR) != (u32) im)
+ return -1;
+
+ reg = in_be32(&im->clk.spmr);
+ spmf = (reg & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
+ spll = ref_clk * spmf_mult[spmf];
+
+ reg = in_be32(&im->clk.scfr[1]);
+ sys_div = (reg & SCFR2_SYS_DIV) >> SCFR2_SYS_DIV_SHIFT;
+ sys_clk = (spll * sys_dividors[sys_div][1]) / sys_dividors[sys_div][0];
+
+ csb_clk = sys_clk / 2;
+
+ reg = in_be32(&im->clk.spmr);
+ cpmf = (reg & SPMR_CPMF) >> SPMR_CPMF_SHIFT;
+ core_clk = (csb_clk * cpmf_mult[cpmf][0]) / cpmf_mult[cpmf][1];
+
+ reg = in_be32(&im->clk.scfr[0]);
+ ips_div = (reg & SCFR1_IPS_DIV_MASK) >> SCFR1_IPS_DIV_SHIFT;
+ if (ips_div != 0) {
+ ips_clk = csb_clk / ips_div;
+ } else {
+ /* in case we cannot get a sane IPS divisor, fail gracefully */
+ ips_clk = 0;
+ }
+
+ reg = in_be32(&im->clk.scfr[0]);
+ pci_div = (reg & SCFR1_PCI_DIV_MASK) >> SCFR1_PCI_DIV_SHIFT;
+ if (pci_div != 0) {
+ pci_clk = csb_clk / pci_div;
+ } else {
+ /* in case we cannot get a sane IPS divisor, fail gracefully */
+ pci_clk = 333333;
+ }
+
+ gd->arch.ips_clk = ips_clk;
+ gd->pci_clk = pci_clk;
+ gd->arch.csb_clk = csb_clk;
+ gd->cpu_clk = core_clk;
+ gd->bus_clk = csb_clk;
+ return 0;
+
+}
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+ return gd->arch.csb_clk;
+}
+
+int do_clocks (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ char buf[32];
+
+ printf("Clock configuration:\n");
+ printf(" CPU: %-4s MHz\n", strmhz(buf, gd->cpu_clk));
+ printf(" Coherent System Bus: %-4s MHz\n",
+ strmhz(buf, gd->arch.csb_clk));
+ printf(" IPS Bus: %-4s MHz\n",
+ strmhz(buf, gd->arch.ips_clk));
+ printf(" PCI: %-4s MHz\n", strmhz(buf, gd->pci_clk));
+ printf(" DDR: %-4s MHz\n",
+ strmhz(buf, 2 * gd->arch.csb_clk));
+ return 0;
+}
+
+U_BOOT_CMD(clocks, 1, 0, do_clocks,
+ "print clock configuration",
+ " clocks"
+);
diff --git a/arch/powerpc/cpu/mpc512x/start.S b/arch/powerpc/cpu/mpc512x/start.S
new file mode 100644
index 0000000..6d1a99a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/start.S
@@ -0,0 +1,708 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000-2009 Wolfgang Denk <wd@denx.de>
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC83xx code.
+ */
+
+/*
+ * U-Boot - Startup Code for MPC512x based Embedded Boards
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING "MPC512X"
+#endif
+#include <version.h>
+
+#define CONFIG_521X 1 /* needed for Linux kernel header files*/
+
+#include <asm/immap_512x.h>
+#include "asm-offsets.h"
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/*
+ * Floating Point enable, Machine Check and Recoverable Interr.
+ */
+#undef MSR_KERNEL
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/* Macros for manipulating CSx_START/STOP */
+#define START_REG(start) ((start) >> 16)
+#define STOP_REG(start, size) (((start) + (size) - 1) >> 16)
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * Magic number and version string
+ */
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+/*
+ * Vector Table
+ */
+ .text
+ . = EXC_OFF_SYS_RESET
+
+ .globl _start
+ /* Start from here after reset/power on */
+_start:
+ b boot_cold
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, UnknownException)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+/* Floating Point Unit unavailable exception */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+/* Decrementer */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+/* Critical interrupt */
+ STD_EXCEPTION(0xa00, Critical, UnknownException)
+
+/* System Call */
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+/* Trace interrupt */
+ STD_EXCEPTION(0xd00, Trace, UnknownException)
+
+/* Performance Monitor interrupt */
+ STD_EXCEPTION(0xf00, PerfMon, UnknownException)
+
+/* Intruction Translation Miss */
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+
+/* Data Load Translation Miss */
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+
+/* Data Store Translation Miss */
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+
+/* Instruction Address Breakpoint */
+ STD_EXCEPTION(0x1300, InstructionAddrBreakpoint, DebugException)
+
+/* System Management interrupt */
+ STD_EXCEPTION(0x1400, SystemMgmtInterrupt, UnknownException)
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+boot_cold:
+ /* Save msr contents */
+ mfmsr r5
+
+ /* Set IMMR area to our preferred location */
+ lis r4, CONFIG_DEFAULT_IMMR@h
+ lis r3, CONFIG_SYS_IMMR@h
+ ori r3, r3, CONFIG_SYS_IMMR@l
+ stw r3, IMMRBAR(r4)
+ mtspr MBAR, r3 /* IMMRBAR is mirrored into the MBAR SPR (311) */
+
+ /* Initialise the machine */
+ bl cpu_early_init
+
+ /*
+ * Set up Local Access Windows:
+ *
+ * 1) Boot/CS0 (boot FLASH)
+ * 2) On-chip SRAM (initial stack purposes)
+ */
+
+ /* Boot CS/CS0 window range */
+ lis r3, CONFIG_SYS_IMMR@h
+ ori r3, r3, CONFIG_SYS_IMMR@l
+
+ lis r4, START_REG(CONFIG_SYS_FLASH_BASE)
+ ori r4, r4, STOP_REG(CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_SIZE)
+ stw r4, LPCS0AW(r3)
+
+ /*
+ * The SRAM window has a fixed size (256K), so only the start address
+ * is necessary
+ */
+ lis r4, START_REG(CONFIG_SYS_SRAM_BASE) & 0xff00
+ stw r4, SRAMBAR(r3)
+
+ /*
+ * According to MPC5121e RM, configuring local access windows should
+ * be followed by a dummy read of the config register that was
+ * modified last and an isync
+ */
+ lwz r4, SRAMBAR(r3)
+ isync
+
+ /*
+ * Set configuration of the Boot/CS0, the SRAM window does not have a
+ * config register so no params can be set for it
+ */
+ lis r3, (CONFIG_SYS_IMMR + LPC_OFFSET)@h
+ ori r3, r3, (CONFIG_SYS_IMMR + LPC_OFFSET)@l
+
+ lis r4, CONFIG_SYS_CS0_CFG@h
+ ori r4, r4, CONFIG_SYS_CS0_CFG@l
+ stw r4, CS0_CONFIG(r3)
+
+ /* Master enable all CS's */
+ lis r4, CS_CTRL_ME@h
+ ori r4, r4, CS_CTRL_ME@l
+ stw r4, CS_CTRL(r3)
+
+ lis r4, (CONFIG_SYS_MONITOR_BASE)@h
+ ori r4, r4, (CONFIG_SYS_MONITOR_BASE)@l
+ addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r5
+ blr
+
+in_flash:
+ lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+ ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable & stack humble */
+ /*------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ lis r3, CONFIG_SYS_IMMR@h
+ /* run low-level CPU init code (in Flash) */
+ bl cpu_init_f
+
+ /* run 1st part of board init code (in Flash) */
+ bl board_init_f
+
+ /* NOTREACHED - board_init_f() does not return */
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/*
+ * This code initialises the machine, it expects original MSR contents to be in r5.
+ */
+cpu_early_init:
+ /* Initialize machine status; enable machine check interrupt */
+ /*-----------------------------------------------------------*/
+
+ li r3, MSR_KERNEL /* Set ME and RI flags */
+ rlwimi r3, r5, 0, 25, 25 /* preserve IP bit */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE, BE bits */
+#endif
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Mirror current MSR state in SRR1 */
+
+ lis r3, CONFIG_SYS_IMMR@h
+
+#if defined(CONFIG_WATCHDOG)
+ /* Initialise the watchdog and reset it */
+ /*--------------------------------------*/
+ lis r4, CONFIG_SYS_WATCHDOG_VALUE
+ ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
+ stw r4, SWCRR(r3)
+
+ /* reset */
+ li r4, 0x556C
+ sth r4, SWSRR@l(r3)
+ li r4, 0x0
+ ori r4, r4, 0xAA39
+ sth r4, SWSRR@l(r3)
+#else
+ /* Disable the watchdog */
+ /*----------------------*/
+ lwz r4, SWCRR(r3)
+ /*
+ * Check to see if it's enabled for disabling: once disabled by s/w
+ * it's not possible to re-enable it
+ */
+ andi. r4, r4, 0x4
+ beq 1f
+ xor r4, r4, r4
+ stw r4, SWCRR(r3)
+1:
+#endif /* CONFIG_WATCHDOG */
+
+ /* Initialize the Hardware Implementation-dependent Registers */
+ /* HID0 also contains cache control */
+ /*------------------------------------------------------*/
+ lis r3, CONFIG_SYS_HID0_INIT@h
+ ori r3, r3, CONFIG_SYS_HID0_INIT@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CONFIG_SYS_HID0_FINAL@h
+ ori r3, r3, CONFIG_SYS_HID0_FINAL@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CONFIG_SYS_HID2@h
+ ori r3, r3, CONFIG_SYS_HID2@l
+ SYNC
+ mtspr HID2, r3
+ sync
+ blr
+
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICE
+ lis r4, 0
+ ori r4, r4, HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ICE|HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock*/
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ ori r3, r3, HID0_DCE
+ ori r5, r3, HID0_DCFI
+ mtspr HID0, r5 /* enable + invalidate */
+ mtspr HID0, r3 /* enable */
+ sync
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_DCE|HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+/*-------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE)
+ * + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+ la r8,-4(r4)
+ la r7,-4(r3)
+
+ /* copy */
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+
+ addi r0,r5,3
+ srwi. r0,r0,2
+ mtctr r0
+ la r8,-4(r4)
+ la r7,-4(r3)
+
+ /* and compare */
+20: lwzu r20,4(r8)
+ lwzu r21,4(r7)
+ xor. r22, r20, r21
+ bne 30f
+ bdnz 20b
+ b 4f
+
+ /* compare failed */
+30: li r3, 0
+ blr
+
+2: slwi r0,r0,2 /* re copy in reverse order ... y do we needed it? */
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_Trace - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mfmsr r3 /* now that the vectors have */
+ lis r7, MSR_IP@h /* relocated into low memory */
+ ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
+ andc r3, r3, r7 /* (if it was on) */
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+
+ mtlr r4 /* restore link register */
+ blr
diff --git a/arch/powerpc/cpu/mpc512x/traps.c b/arch/powerpc/cpu/mpc512x/traps.c
new file mode 100644
index 0000000..15468e5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/traps.c
@@ -0,0 +1,204 @@
+/*
+ * (C) Copyright 2000 - 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Derived from the MPC83xx code.
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware
+ * exceptions
+ */
+
+#include <common.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of addressable memory. This may be less than the actual
+ * amount of memory on the system if we're unable to keep all
+ * the memory mapped in.
+ */
+extern ulong get_effective_memsize(void);
+#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ puts("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ putc('\n');
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *) *sp;
+ }
+ putc('\n');
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr & MSR_EE ? 1 : 0, regs->msr & MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr & MSR_ME ? 1 : 0,
+ regs->msr & MSR_IR ? 1 : 0,
+ regs->msr & MSR_DR ? 1 : 0);
+
+ putc('\n');
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0) {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7) {
+ putc('\n');
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception at pc %lx signal %d", regs->nip, signr);
+}
+
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup = search_exception_table(regs->nip);
+
+ if (fixup) {
+ regs->nip = fixup;
+ return;
+ }
+
+#ifdef CONFIG_CMD_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ puts("Machine check.\nCaused by (from msr): ");
+ printf("regs %p ", regs);
+ switch (regs->msr & 0x00FF0000) {
+ case (0x80000000 >> 10):
+ puts("Instruction cache parity signal\n");
+ break;
+ case (0x80000000 >> 11):
+ puts("Data cache parity signal\n");
+ break;
+ case (0x80000000 >> 12):
+ puts("Machine check signal\n");
+ break;
+ case (0x80000000 >> 13):
+ puts("Transfer error ack signal\n");
+ break;
+ case (0x80000000 >> 14):
+ puts("Data parity signal\n");
+ break;
+ case (0x80000000 >> 15):
+ puts("Address parity signal\n");
+ break;
+ default:
+ puts("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+#ifdef CONFIG_CMD_KGDB
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+#ifdef CONFIG_CMD_BEDBUG
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip);
+ show_regs(regs);
+#ifdef CONFIG_CMD_BEDBUG
+ do_bedbug_breakpoint(regs);
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc512x/u-boot.lds b/arch/powerpc/cpu/mpc512x/u-boot.lds
new file mode 100644
index 0000000..0d86979
--- /dev/null
+++ b/arch/powerpc/cpu/mpc512x/u-boot.lds
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2007-2010 DENX Software Engineering.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ .text :
+ {
+ arch/powerpc/cpu/mpc512x/start.o (.text*)
+ *(.text*)
+ . = ALIGN(16);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ *(.fixup)
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
+ENTRY(_start)
diff --git a/arch/powerpc/cpu/mpc5xx/Makefile b/arch/powerpc/cpu/mpc5xx/Makefile
new file mode 100644
index 0000000..078b524
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/Makefile
@@ -0,0 +1,59 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2003
+# Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# File: arch/powerpc/cpu/mpc5xx/Makefile
+#
+# Discription: Makefile to build mpc5xx cpu configuration.
+# Will include top config.mk which itselfs
+# uses the definitions made in arch/powerpc/cpu/mpc5xx/config.mk
+#
+
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+START = start.o
+COBJS = serial.o cpu.o cpu_init.o interrupts.o traps.o speed.o spi.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc5xx/config.mk b/arch/powerpc/cpu/mpc5xx/config.mk
new file mode 100644
index 0000000..ab55040
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2003
+# Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_5xx -ffixed-r2 -mpowerpc -msoft-float
diff --git a/arch/powerpc/cpu/mpc5xx/cpu.c b/arch/powerpc/cpu/mpc5xx/cpu.c
new file mode 100644
index 0000000..5aa7f84
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/cpu.c
@@ -0,0 +1,171 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File: cpu.c
+ *
+ * Discription: Some cpu specific function for watchdog,
+ * cpu version test, clock setting ...
+ *
+ */
+
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc5xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if (defined(CONFIG_MPC555))
+# define ID_STR "MPC555/556"
+
+/*
+ * Check version of cpu with Processor Version Register (PVR)
+ */
+static int check_cpu_version (long clock, uint pvr, uint immr)
+{
+ char buf[32];
+ /* The highest 16 bits should be 0x0002 for a MPC555/556 */
+ if ((pvr >> 16) == 0x0002) {
+ printf (" " ID_STR " Version %x", (pvr >> 16));
+ printf (" at %s MHz:", strmhz (buf, clock));
+ } else {
+ printf ("Not supported cpu version");
+ return -1;
+ }
+ return 0;
+}
+#endif /* CONFIG_MPC555 */
+
+
+/*
+ * Check version of mpc5xx
+ */
+int checkcpu (void)
+{
+ ulong clock = gd->cpu_clk;
+ uint immr = get_immr (0); /* Return full IMMR contents */
+ uint pvr = get_pvr (); /* Retrieve PVR register */
+
+ puts ("CPU: ");
+
+ return check_cpu_version (clock, pvr, immr);
+}
+
+/*
+ * Called by macro WATCHDOG_RESET
+ */
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+ int re_enable = disable_interrupts ();
+
+ reset_5xx_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+ if (re_enable)
+ enable_interrupts ();
+}
+
+/*
+ * Will clear software reset
+ */
+void reset_5xx_watchdog (volatile immap_t * immr)
+{
+ /* Use the MPC5xx Internal Watchdog */
+ immr->im_siu_conf.sc_swsr = 0x556c; /* Prevent SW time-out */
+ immr->im_siu_conf.sc_swsr = 0xaa39;
+}
+
+#endif /* CONFIG_WATCHDOG */
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+ volatile immap_t *immr = (volatile immap_t *) CONFIG_SYS_IMMR;
+ ulong oscclk, factor;
+
+ if (immr->im_clkrst.car_sccr & SCCR_TBS) {
+ return (gd->cpu_clk / 16);
+ }
+
+ factor = (((CONFIG_SYS_PLPRCR) & PLPRCR_MF_MSK) >> PLPRCR_MF_SHIFT) + 1;
+
+ oscclk = gd->cpu_clk / factor;
+
+ if ((immr->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) {
+ return (oscclk / 4);
+ }
+ return (oscclk / 16);
+}
+
+void dcache_enable (void)
+{
+ return;
+}
+
+void dcache_disable (void)
+{
+ return;
+}
+
+int dcache_status (void)
+{
+ return 0; /* always off */
+}
+
+/*
+ * Reset board
+ */
+int do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+#if defined(CONFIG_PATI)
+ volatile ulong *addr = (ulong *) CONFIG_SYS_RESET_ADDRESS;
+ *addr = 1;
+#else
+ ulong addr;
+
+ /* Interrupts off, enable reset */
+ __asm__ volatile (" mtspr 81, %r0 \n\t"
+ " mfmsr %r3 \n\t"
+ " rlwinm %r31,%r3,0,25,23\n\t"
+ " mtmsr %r31 \n\t");
+ /*
+ * Trying to execute the next instruction at a non-existing address
+ * should cause a machine check, resulting in reset
+ */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+ addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+ /*
+ * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE * - sizeof (ulong) is usually a valid address. Better pick an address
+ * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+ * "(ulong)-1" used to be a good choice for many systems...
+ */
+ addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+ ((void (*) (void)) addr) ();
+#endif /* #if defined(CONFIG_PATI) */
+ return 1;
+}
diff --git a/arch/powerpc/cpu/mpc5xx/cpu_init.c b/arch/powerpc/cpu/mpc5xx/cpu_init.c
new file mode 100644
index 0000000..cb4bf84
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/cpu_init.c
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2003 Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File: cpu_init.c
+ *
+ * Discription: Contains initialisation functions to setup
+ * the cpu properly
+ *
+ */
+
+#include <common.h>
+#include <mpc5xx.h>
+#include <watchdog.h>
+
+/*
+ * Setup essential cpu registers to run
+ */
+void cpu_init_f (volatile immap_t * immr)
+{
+ volatile memctl5xx_t *memctl = &immr->im_memctl;
+ ulong reg;
+
+ /* SYPCR - contains watchdog control. This will enable watchdog */
+ /* if CONFIG_WATCHDOG is set */
+ immr->im_siu_conf.sc_sypcr = CONFIG_SYS_SYPCR;
+
+#if defined(CONFIG_WATCHDOG)
+ reset_5xx_watchdog (immr);
+#endif
+
+ /* SIUMCR - contains debug pin configuration */
+ immr->im_siu_conf.sc_siumcr |= CONFIG_SYS_SIUMCR;
+
+ /* Initialize timebase. Unlock TBSCRK */
+ immr->im_sitk.sitk_tbscrk = KAPWR_KEY;
+ immr->im_sit.sit_tbscr = CONFIG_SYS_TBSCR;
+
+ /* Full IMB bus speed */
+ immr->im_uimb.uimb_umcr = CONFIG_SYS_UMCR;
+
+ /* Time base and decrementer will be enables (TBE) */
+ /* in init_timebase() in time.c called from board_init_f(). */
+
+ /* Initialize the PIT. Unlock PISCRK */
+ immr->im_sitk.sitk_piscrk = KAPWR_KEY;
+ immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+#if !defined(CONFIG_PATI)
+ /* PATI sest PLL in start.S */
+ /* PLL (CPU clock) settings */
+ immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+
+ /* If CONFIG_SYS_PLPRCR (set in the various *_config.h files) tries to
+ * set the MF field, then just copy CONFIG_SYS_PLPRCR over car_plprcr,
+ * otherwise OR in CONFIG_SYS_PLPRCR so we do not change the currentMF
+ * field value.
+ */
+#if ((CONFIG_SYS_PLPRCR & PLPRCR_MF_MSK) != 0)
+ reg = CONFIG_SYS_PLPRCR; /* reset control bits */
+#else
+ reg = immr->im_clkrst.car_plprcr;
+ reg &= PLPRCR_MF_MSK; /* isolate MF field */
+ reg |= CONFIG_SYS_PLPRCR; /* reset control bits */
+#endif
+ immr->im_clkrst.car_plprcr = reg;
+
+#endif /* !defined(CONFIG_PATI) */
+
+ /* System integration timers. CONFIG_SYS_MASK has EBDF configuration */
+ immr->im_clkrstk.cark_sccrk = KAPWR_KEY;
+ reg = immr->im_clkrst.car_sccr;
+ reg &= SCCR_MASK;
+ reg |= CONFIG_SYS_SCCR;
+ immr->im_clkrst.car_sccr = reg;
+
+ /* Memory Controller */
+ memctl->memc_br0 = CONFIG_SYS_BR0_PRELIM;
+ memctl->memc_or0 = CONFIG_SYS_OR0_PRELIM;
+
+#if (defined(CONFIG_SYS_OR1_PRELIM) && defined(CONFIG_SYS_BR1_PRELIM))
+ memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM;
+ memctl->memc_br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR2_PRELIM) && defined(CONFIG_SYS_BR2_PRELIM)
+ memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM;
+ memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR3_PRELIM) && defined(CONFIG_SYS_BR3_PRELIM)
+ memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
+ memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+}
+
+/*
+ * Initialize higher level parts of cpu
+ */
+int cpu_init_r (void)
+{
+ /* Nothing to do at the moment */
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc5xx/interrupts.c b/arch/powerpc/cpu/mpc5xx/interrupts.c
new file mode 100644
index 0000000..66bce30
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/interrupts.c
@@ -0,0 +1,207 @@
+/*
+ * (C) Copyright 2000-2002 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * (C) Copyright 2003 Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File: interrupt.c
+ *
+ * Discription: Contains interrupt routines needed by U-Boot
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc5xx.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_PATI)
+/* PATI uses IRQs for PCI doorbell */
+#undef NR_IRQS
+#define NR_IRQS 16
+#endif
+
+struct interrupt_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ int count;
+};
+
+static struct interrupt_action irq_vecs[NR_IRQS];
+
+/*
+ * Initialise interrupts
+ */
+
+int interrupt_init_cpu (ulong *decrementer_count)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ int vec;
+
+ /* Decrementer used here for status led */
+ *decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
+
+ /* Disable all interrupts */
+ immr->im_siu_conf.sc_simask = 0;
+ for (vec=0; vec<NR_IRQS; vec++) {
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
+ irq_vecs[vec].count = 0;
+ }
+
+ return (0);
+}
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ int irq;
+ ulong simask, newmask;
+ ulong vec, v_bit;
+
+ /*
+ * read the SIVEC register and shift the bits down
+ * to get the irq number
+ */
+ vec = immr->im_siu_conf.sc_sivec;
+ irq = vec >> 26;
+ v_bit = 0x80000000UL >> irq;
+
+ /*
+ * Read Interrupt Mask Register and Mask Interrupts
+ */
+ simask = immr->im_siu_conf.sc_simask;
+ newmask = simask & (~(0xFFFF0000 >> irq));
+ immr->im_siu_conf.sc_simask = newmask;
+
+ if (!(irq & 0x1)) { /* External Interrupt ? */
+ ulong siel;
+
+ /*
+ * Read Interrupt Edge/Level Register
+ */
+ siel = immr->im_siu_conf.sc_siel;
+
+ if (siel & v_bit) { /* edge triggered interrupt ? */
+ /*
+ * Rewrite SIPEND Register to clear interrupt
+ */
+ immr->im_siu_conf.sc_sipend = v_bit;
+ }
+ }
+
+ if (irq_vecs[irq].handler != NULL) {
+ irq_vecs[irq].handler (irq_vecs[irq].arg);
+ } else {
+ printf ("\nBogus External Interrupt IRQ %d Vector %ld\n",
+ irq, vec);
+ /* turn off the bogus interrupt to avoid it from now */
+ simask &= ~v_bit;
+ }
+ /*
+ * Re-Enable old Interrupt Mask
+ */
+ immr->im_siu_conf.sc_simask = simask;
+}
+
+/*
+ * Install and free an interrupt handler
+ */
+void irq_install_handler (int vec, interrupt_handler_t * handler,
+ void *arg)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ /* SIU interrupt */
+ if (irq_vecs[vec].handler != NULL) {
+ printf ("SIU interrupt %d 0x%x\n",
+ vec,
+ (uint) handler);
+ }
+ irq_vecs[vec].handler = handler;
+ irq_vecs[vec].arg = arg;
+ immr->im_siu_conf.sc_simask |= 1 << (31 - vec);
+#if 0
+ printf ("Install SIU interrupt for vector %d ==> %p\n",
+ vec, handler);
+#endif
+}
+
+void irq_free_handler (int vec)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ /* SIU interrupt */
+#if 0
+ printf ("Free CPM interrupt for vector %d\n",
+ vec);
+#endif
+ immr->im_siu_conf.sc_simask &= ~(1 << (31 - vec));
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
+}
+
+/*
+ * Timer interrupt - gets called when bit 0 of DEC changes from
+ * 0. Decrementer is enabled with bit TBE in TBSCR.
+ */
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if 0
+ printf ("*** Timer Interrupt *** ");
+#endif
+ /* Reset Timer Status Bit and Timers Interrupt Status */
+ immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+ __asm__ ("nop");
+ immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS | PLPRCR_TMIST;
+
+ return;
+}
+
+#if defined(CONFIG_CMD_IRQ)
+/*******************************************************************************
+ *
+ * irqinfo - print information about IRQs
+ *
+ */
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int vec;
+
+ printf ("\nInterrupt-Information:\n");
+ printf ("Nr Routine Arg Count\n");
+
+ for (vec=0; vec<NR_IRQS; vec++) {
+ if (irq_vecs[vec].handler != NULL) {
+ printf ("%02d %08lx %08lx %d\n",
+ vec,
+ (ulong)irq_vecs[vec].handler,
+ (ulong)irq_vecs[vec].arg,
+ irq_vecs[vec].count);
+ }
+ }
+ return 0;
+}
+
+
+#endif
diff --git a/arch/powerpc/cpu/mpc5xx/serial.c b/arch/powerpc/cpu/mpc5xx/serial.c
new file mode 100644
index 0000000..732856a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/serial.c
@@ -0,0 +1,183 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File: serial.c
+ *
+ * Discription: Serial interface driver for SCI1 and SCI2.
+ * Since this code will be called from ROM use
+ * only non-static local variables.
+ *
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc5xx.h>
+#include <serial.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Local functions
+ */
+
+static int ready_to_send(void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile short status;
+
+ do {
+#if defined(CONFIG_5xx_CONS_SCI1)
+ status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+ status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+ reset_5xx_watchdog (immr);
+#endif
+ } while ((status & SCI_TDRE) == 0);
+ return 1;
+
+}
+
+/*
+ * Minimal global serial functions needed to use one of the SCI modules.
+ */
+
+static int mpc5xx_serial_init(void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ serial_setbrg();
+
+#if defined(CONFIG_5xx_CONS_SCI1)
+ /* 10-Bit, 1 start bit, 8 data bit, no parity, 1 stop bit */
+ immr->im_qsmcm.qsmcm_scc1r1 = SCI_M_10;
+ immr->im_qsmcm.qsmcm_scc1r1 = SCI_TE | SCI_RE;
+#else
+ immr->im_qsmcm.qsmcm_scc2r1 = SCI_M_10;
+ immr->im_qsmcm.qsmcm_scc2r1 = SCI_TE | SCI_RE;
+#endif
+ return 0;
+}
+
+static void mpc5xx_serial_putc(const char c)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ /* Test for completition */
+ if(ready_to_send()) {
+#if defined(CONFIG_5xx_CONS_SCI1)
+ immr->im_qsmcm.qsmcm_sc1dr = (short)c;
+#else
+ immr->im_qsmcm.qsmcm_sc2dr = (short)c;
+#endif
+ if(c == '\n') {
+ if(ready_to_send());
+#if defined(CONFIG_5xx_CONS_SCI1)
+ immr->im_qsmcm.qsmcm_sc1dr = (short)'\r';
+#else
+ immr->im_qsmcm.qsmcm_sc2dr = (short)'\r';
+#endif
+ }
+ }
+}
+
+static int mpc5xx_serial_getc(void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile short status;
+ unsigned char tmp;
+
+ /* New data ? */
+ do {
+#if defined(CONFIG_5xx_CONS_SCI1)
+ status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+ status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+ reset_5xx_watchdog (immr);
+#endif
+ } while ((status & SCI_RDRF) == 0);
+
+ /* Read data */
+#if defined(CONFIG_5xx_CONS_SCI1)
+ tmp = (unsigned char)(immr->im_qsmcm.qsmcm_sc1dr & SCI_SCXDR_MK);
+#else
+ tmp = (unsigned char)( immr->im_qsmcm.qsmcm_sc2dr & SCI_SCXDR_MK);
+#endif
+ return tmp;
+}
+
+static int mpc5xx_serial_tstc(void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ short status;
+
+ /* New data character ? */
+#if defined(CONFIG_5xx_CONS_SCI1)
+ status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+ status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+ return (status & SCI_RDRF);
+}
+
+static void mpc5xx_serial_setbrg(void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ short scxbr;
+
+ /* Set baudrate */
+ scxbr = (gd->cpu_clk / (32 * gd->baudrate));
+#if defined(CONFIG_5xx_CONS_SCI1)
+ immr->im_qsmcm.qsmcm_scc1r0 = (scxbr & SCI_SCXBR_MK);
+#else
+ immr->im_qsmcm.qsmcm_scc2r0 = (scxbr & SCI_SCXBR_MK);
+#endif
+}
+
+static struct serial_device mpc5xx_serial_drv = {
+ .name = "mpc5xx_serial",
+ .start = mpc5xx_serial_init,
+ .stop = NULL,
+ .setbrg = mpc5xx_serial_setbrg,
+ .putc = mpc5xx_serial_putc,
+ .puts = default_serial_puts,
+ .getc = mpc5xx_serial_getc,
+ .tstc = mpc5xx_serial_tstc,
+};
+
+void mpc5xx_serial_initialize(void)
+{
+ serial_register(&mpc5xx_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &mpc5xx_serial_drv;
+}
diff --git a/arch/powerpc/cpu/mpc5xx/speed.c b/arch/powerpc/cpu/mpc5xx/speed.c
new file mode 100644
index 0000000..ea5c1de
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/speed.c
@@ -0,0 +1,67 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File: speed.c
+ *
+ * Discription: Provides cpu speed calculation
+ *
+ */
+
+#include <common.h>
+#include <mpc5xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Get cpu and bus clock
+ */
+int get_clocks (void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#ifndef CONFIG_5xx_GCLK_FREQ
+ uint divf = (immr->im_clkrst.car_plprcr & PLPRCR_DIVF_MSK);
+ uint mf = ((immr->im_clkrst.car_plprcr & PLPRCR_MF_MSK) >> PLPRCR_MF_SHIFT);
+ ulong vcoout;
+
+ vcoout = (CONFIG_SYS_OSC_CLK / (divf + 1)) * (mf + 1) * 2;
+ if(immr->im_clkrst.car_plprcr & PLPRCR_CSRC_MSK) {
+ gd->cpu_clk = vcoout / (2^(((immr->im_clkrst.car_sccr & SCCR_DFNL_MSK) >> SCCR_DFNL_SHIFT) + 1));
+ } else {
+ gd->cpu_clk = vcoout / (2^(immr->im_clkrst.car_sccr & SCCR_DFNH_MSK));
+ }
+
+#else /* CONFIG_5xx_GCLK_FREQ */
+ gd->bus_clk = CONFIG_5xx_GCLK_FREQ;
+#endif /* CONFIG_5xx_GCLK_FREQ */
+
+ if ((immr->im_clkrst.car_sccr & SCCR_EBDF11) == 0) {
+ /* No Bus Divider active */
+ gd->bus_clk = gd->cpu_clk;
+ } else {
+ /* CLKOUT is GCLK / 2 */
+ gd->bus_clk = gd->cpu_clk / 2;
+ }
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc5xx/spi.c b/arch/powerpc/cpu/mpc5xx/spi.c
new file mode 100644
index 0000000..3ca15ea
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/spi.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2001 Navin Boppuri / Prashant Patel
+ * <nboppuri@trinetcommunication.com>,
+ * <pmpatel@trinetcommunication.com>
+ * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
+ * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC5xx CPM SPI interface.
+ *
+ * Parts of this code are probably not portable and/or specific to
+ * the board which I used for the tests. Please send fixes/complaints
+ * to wd@denx.de
+ *
+ * Ported to MPC5xx
+ * Copyright (c) 2003 Denis Peter, MPL AG Switzerland, d.petr@mpl.ch.
+ */
+
+#include <common.h>
+#include <mpc5xx.h>
+#include <asm/5xx_immap.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+#include <post.h>
+#include <net.h>
+
+#if defined(CONFIG_SPI)
+
+#undef DEBUG
+
+#define SPI_EEPROM_WREN 0x06
+#define SPI_EEPROM_RDSR 0x05
+#define SPI_EEPROM_READ 0x03
+#define SPI_EEPROM_WRITE 0x02
+
+
+#ifdef DEBUG
+
+#define DPRINT(a) printf a;
+/* -----------------------------------------------
+ * Helper functions to peek into tx and rx buffers
+ * ----------------------------------------------- */
+static const char * const hex_digit = "0123456789ABCDEF";
+
+static char quickhex (int i)
+{
+ return hex_digit[i];
+}
+
+static void memdump (void *pv, int num)
+{
+ int i;
+ unsigned char *pc = (unsigned char *) pv;
+
+ for (i = 0; i < num; i++)
+ printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
+ printf ("\t");
+ for (i = 0; i < num; i++)
+ printf ("%c", isprint (pc[i]) ? pc[i] : '.');
+ printf ("\n");
+}
+#else /* !DEBUG */
+
+#define DPRINT(a)
+
+#endif /* DEBUG */
+
+/* -------------------
+ * Function prototypes
+ * ------------------- */
+void spi_init (void);
+
+ssize_t spi_read (uchar *, int, uchar *, int);
+ssize_t spi_write (uchar *, int, uchar *, int);
+ssize_t spi_xfer (size_t);
+
+
+/* **************************************************************************
+ *
+ * Function: spi_init_f
+ *
+ * Description: Init SPI-Controller (ROM part)
+ *
+ * return: ---
+ *
+ * *********************************************************************** */
+
+void spi_init_f (void)
+{
+ int i;
+
+ volatile immap_t *immr;
+ volatile qsmcm5xx_t *qsmcm;
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+
+ qsmcm->qsmcm_qsmcr = 0; /* all accesses enabled */
+ qsmcm->qsmcm_qspi_il = 0; /* lowest IRQ */
+
+ /* --------------------------------------------
+ * GPIO or per. Function
+ * PQSPAR[00] = 0 reserved
+ * PQSPAR[01] = 1 [0x4000] -> PERI: (SPICS3)
+ * PQSPAR[02] = 0 [0x0000] -> GPIO
+ * PQSPAR[03] = 0 [0x0000] -> GPIO
+ * PQSPAR[04] = 1 [0x0800] -> PERI: (SPICS0)
+ * PQSPAR[05] = 0 reseved
+ * PQSPAR[06] = 1 [0x0200] -> PERI: (SPIMOSI)
+ * PQSPAR[07] = 1 [0x0100] -> PERI: (SPIMISO)
+ * -------------------------------------------- */
+ qsmcm->qsmcm_pqspar = 0x3 | (CONFIG_SYS_SPI_CS_USED << 3);
+
+ /* --------------------------------------------
+ * DDRQS[00] = 0 reserved
+ * DDRQS[01] = 1 [0x0040] -> SPICS3 Output
+ * DDRQS[02] = 0 [0x0000] -> GPIO Output
+ * DDRQS[03] = 0 [0x0000] -> GPIO Output
+ * DDRQS[04] = 1 [0x0008] -> SPICS0 Output
+ * DDRQS[05] = 1 [0x0004] -> SPICLK Output
+ * DDRQS[06] = 1 [0x0002] -> SPIMOSI Output
+ * DDRQS[07] = 0 [0x0001] -> SPIMISO Input
+ * -------------------------------------------- */
+ qsmcm->qsmcm_ddrqs = 0x7E;
+ /* --------------------------------------------
+ * Base state for used SPI CS pins, if base = 0 active must be 1
+ * PORTQS[00] = 0 reserved
+ * PORTQS[01] = 0 reserved
+ * PORTQS[02] = 0 reserved
+ * PORTQS[03] = 0 reserved
+ * PORTQS[04] = 0 [0x0000] RxD2
+ * PORTQS[05] = 1 [0x0400] TxD2
+ * PORTQS[06] = 0 [0x0000] RxD1
+ * PORTQS[07] = 1 [0x0100] TxD1
+ * PORTQS[08] = 0 reserved
+ * PORTQS[09] = 0 [0x0000] -> SPICS3 Base Output
+ * PORTQS[10] = 0 [0x0000] -> SPICS2 Base Output
+ * PORTQS[11] = 0 [0x0000] -> SPICS1 Base Output
+ * PORTQS[12] = 0 [0x0000] -> SPICS0 Base Output
+ * PORTQS[13] = 0 [0x0004] -> SPICLK Output
+ * PORTQS[14] = 0 [0x0002] -> SPIMOSI Output
+ * PORTQS[15] = 0 [0x0001] -> SPIMISO Input
+ * -------------------------------------------- */
+ qsmcm->qsmcm_portqs |= (CONFIG_SYS_SPI_CS_BASE << 3);
+ /* --------------------------------------------
+ * Controll Register 0
+ * SPCR0[00] = 1 (0x8000) Master
+ * SPCR0[01] = 0 (0x0000) Wired-Or
+ * SPCR0[2..5] = (0x2000) Bits per transfer (default 8)
+ * SPCR0[06] = 0 (0x0000) Normal polarity
+ * SPCR0[07] = 0 (0x0000) Normal Clock Phase
+ * SPCR0[08..15] = 14 1.4MHz
+ */
+ qsmcm->qsmcm_spcr0=0xA00E;
+ /* --------------------------------------------
+ * Controll Register 1
+ * SPCR1[00] = 0 (0x0000) QSPI enabled
+ * SPCR1[1..7] = (0x7F00) Delay before Transfer
+ * SPCR1[8..15] = (0x0000) Delay After transfer (204.8usec@40MHz)
+ */
+ qsmcm->qsmcm_spcr1=0x7F00;
+ /* --------------------------------------------
+ * Controll Register 2
+ * SPCR2[00] = 0 (0x0000) SPI IRQs Disabeld
+ * SPCR2[01] = 0 (0x0000) No Wrap around
+ * SPCR2[02] = 0 (0x0000) Wrap to 0
+ * SPCR2[3..7] = (0x0000) End Queue pointer = 0
+ * SPCR2[8..10] = 0 (0x0000) reserved
+ * SPCR2[11..15] = 0 (0x0000) NewQueue Address = 0
+ */
+ qsmcm->qsmcm_spcr2=0x0000;
+ /* --------------------------------------------
+ * Controll Register 3
+ * SPCR3[00..04] = 0 (0x0000) reserved
+ * SPCR3[05] = 0 (0x0000) Feedback disabled
+ * SPCR3[06] = 0 (0x0000) IRQ on HALTA & MODF disabled
+ * SPCR3[07] = 0 (0x0000) Not halted
+ */
+ qsmcm->qsmcm_spcr3=0x00;
+ /* --------------------------------------------
+ * SPSR (Controll Register 3) Read only/ reset Flags 08,09,10
+ * SPCR3[08] = 1 (0x80) QSPI finished
+ * SPCR3[09] = 1 (0x40) Mode Fault Flag
+ * SPCR3[10] = 1 (0x20) HALTA
+ * SPCR3[11..15] = 0 (0x0000) Last executed command
+ */
+ qsmcm->qsmcm_spsr=0xE0;
+ /*-------------------------------------------
+ * Setup RAM
+ */
+ for(i=0;i<32;i++) {
+ qsmcm->qsmcm_recram[i]=0x0000;
+ qsmcm->qsmcm_tranram[i]=0x0000;
+ qsmcm->qsmcm_comdram[i]=0x00;
+ }
+ return;
+}
+
+/* **************************************************************************
+ *
+ * Function: spi_init_r
+ * Dummy, all initializations have been done in spi_init_r
+ * *********************************************************************** */
+void spi_init_r (void)
+{
+ return;
+
+}
+
+/****************************************************************************
+ * Function: spi_write
+ **************************************************************************** */
+ssize_t short_spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+ int i,dlen;
+ volatile immap_t *immr;
+ volatile qsmcm5xx_t *qsmcm;
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+ for(i=0;i<32;i++) {
+ qsmcm->qsmcm_recram[i]=0x0000;
+ qsmcm->qsmcm_tranram[i]=0x0000;
+ qsmcm->qsmcm_comdram[i]=0x00;
+ }
+ qsmcm->qsmcm_tranram[0] = SPI_EEPROM_WREN; /* write enable */
+ spi_xfer(1);
+ i=0;
+ qsmcm->qsmcm_tranram[i++] = SPI_EEPROM_WRITE; /* WRITE memory array */
+ qsmcm->qsmcm_tranram[i++] = addr[0];
+ qsmcm->qsmcm_tranram[i++] = addr[1];
+
+ for(dlen=0;dlen<len;dlen++) {
+ qsmcm->qsmcm_tranram[i+dlen] = buffer[dlen]; /* WRITE memory array */
+ }
+ /* transmit it */
+ spi_xfer(i+dlen);
+ /* ignore received data */
+ for (i = 0; i < 1000; i++) {
+ qsmcm->qsmcm_tranram[0] = SPI_EEPROM_RDSR; /* read status */
+ qsmcm->qsmcm_tranram[1] = 0;
+ spi_xfer(2);
+ if (!(qsmcm->qsmcm_recram[1] & 1)) {
+ break;
+ }
+ udelay(1000);
+ }
+ if (i >= 1000) {
+ printf ("*** spi_write: Time out while writing!\n");
+ }
+ return len;
+}
+
+#define TRANSFER_LEN 16
+
+ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+ int index,i,newlen;
+ uchar newaddr[2];
+ int curraddr;
+
+ curraddr=(addr[alen-2]<<8)+addr[alen-1];
+ i=len;
+ index=0;
+ do {
+ newaddr[1]=(curraddr & 0xff);
+ newaddr[0]=((curraddr>>8) & 0xff);
+ if(i>TRANSFER_LEN) {
+ newlen=TRANSFER_LEN;
+ i-=TRANSFER_LEN;
+ }
+ else {
+ newlen=i;
+ i=0;
+ }
+ short_spi_write (newaddr, 2, &buffer[index], newlen);
+ index+=newlen;
+ curraddr+=newlen;
+ }while(i);
+ return (len);
+}
+
+/****************************************************************************
+ * Function: spi_read
+ **************************************************************************** */
+ssize_t short_spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+ int i;
+ volatile immap_t *immr;
+ volatile qsmcm5xx_t *qsmcm;
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+
+ for(i=0;i<32;i++) {
+ qsmcm->qsmcm_recram[i]=0x0000;
+ qsmcm->qsmcm_tranram[i]=0x0000;
+ qsmcm->qsmcm_comdram[i]=0x00;
+ }
+ i=0;
+ qsmcm->qsmcm_tranram[i++] = (SPI_EEPROM_READ); /* READ memory array */
+ qsmcm->qsmcm_tranram[i++] = addr[0] & 0xff;
+ qsmcm->qsmcm_tranram[i++] = addr[1] & 0xff;
+ spi_xfer(3 + len);
+ for(i=0;i<len;i++) {
+ *buffer++=(char)qsmcm->qsmcm_recram[i+3];
+ }
+ return len;
+}
+
+ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+ int index,i,newlen;
+ uchar newaddr[2];
+ int curraddr;
+
+ curraddr=(addr[alen-2]<<8)+addr[alen-1];
+ i=len;
+ index=0;
+ do {
+ newaddr[1]=(curraddr & 0xff);
+ newaddr[0]=((curraddr>>8) & 0xff);
+ if(i>TRANSFER_LEN) {
+ newlen=TRANSFER_LEN;
+ i-=TRANSFER_LEN;
+ }
+ else {
+ newlen=i;
+ i=0;
+ }
+ short_spi_read (newaddr, 2, &buffer[index], newlen);
+ index+=newlen;
+ curraddr+=newlen;
+ }while(i);
+ return (len);
+}
+
+/****************************************************************************
+ * Function: spi_xfer
+ **************************************************************************** */
+ssize_t spi_xfer (size_t count)
+{
+ volatile immap_t *immr;
+ volatile qsmcm5xx_t *qsmcm;
+ int i;
+ int tm;
+ ushort status;
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ qsmcm = (qsmcm5xx_t *)&immr->im_qsmcm;
+ DPRINT (("*** spi_xfer entered count %d***\n",count));
+
+ /* Set CS for device */
+ for(i=0;i<(count-1);i++)
+ qsmcm->qsmcm_comdram[i] = 0x80 | CONFIG_SYS_SPI_CS_ACT; /* CS3 is connected to the SPI EEPROM */
+
+ qsmcm->qsmcm_comdram[i] = CONFIG_SYS_SPI_CS_ACT; /* CS3 is connected to the SPI EEPROM */
+ qsmcm->qsmcm_spcr2=((count-1)&0x1F)<<8;
+
+ DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n", count));
+
+ qsmcm->qsmcm_spsr=0xE0; /* clear all flags */
+
+ /* start spi transfer */
+ DPRINT (("*** spi_xfer: Performing transfer ...\n"));
+ qsmcm->qsmcm_spcr1 |= 0x8000; /* Start transmit */
+
+ /* --------------------------------
+ * Wait for SPI transmit to get out
+ * or time out (1 second = 1000 ms)
+ * -------------------------------- */
+ for (tm=0; tm<1000; ++tm) {
+ status=qsmcm->qsmcm_spcr1;
+ if((status & 0x8000)==0)
+ break;
+ udelay (1000);
+ }
+ if (tm >= 1000) {
+ printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
+ }
+#ifdef DEBUG
+ printf ("\nspi_xfer: txbuf after xfer\n");
+ memdump ((void *) qsmcm->qsmcm_tranram, 32); /* dump of txbuf before transmit */
+ printf ("spi_xfer: rxbuf after xfer\n");
+ memdump ((void *) qsmcm->qsmcm_recram, 32); /* dump of rxbuf after transmit */
+ printf ("\nspi_xfer: commbuf after xfer\n");
+ memdump ((void *) qsmcm->qsmcm_comdram, 32); /* dump of txbuf before transmit */
+ printf ("\n");
+#endif
+
+ return count;
+}
+
+#endif /* CONFIG_SPI */
diff --git a/arch/powerpc/cpu/mpc5xx/start.S b/arch/powerpc/cpu/mpc5xx/start.S
new file mode 100644
index 0000000..1b275c6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/start.S
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000, 2001, 2002 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2003 Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * File: start.S
+ *
+ * Discription: startup code
+ *
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc5xx.h>
+#include <version.h>
+
+#define CONFIG_5xx 1 /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/u-boot.h>
+
+/* We don't have a MMU.
+*/
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+ .text
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ mfspr r3, 638
+ li r4, CONFIG_SYS_ISB /* Set ISB bit */
+ or r3, r3, r4
+ mtspr 638, r3
+
+ /* Initialize machine status; enable machine check interrupt */
+ /*----------------------------------------------------------------------*/
+ li r3, MSR_KERNEL /* Set ME, RI flags */
+ mtmsr r3
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ /* Initialize debug port registers */
+ /*----------------------------------------------------------------------*/
+ xor r0, r0, r0 /* Clear R0 */
+ mtspr LCTRL1, r0 /* Initialize debug port regs */
+ mtspr LCTRL2, r0
+ mtspr COUNTA, r0
+ mtspr COUNTB, r0
+
+#if defined(CONFIG_PATI)
+ /* the external flash access on PATI fails if programming the PLL to 40MHz.
+ * Copy the PLL programming code to the internal RAM and execute it
+ *----------------------------------------------------------------------*/
+ lis r3, CONFIG_SYS_MONITOR_BASE@h
+ ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
+ addi r3, r3, pll_prog_code_start - _start + EXC_OFF_SYS_RESET
+
+ lis r4, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r4, r4, CONFIG_SYS_INIT_RAM_ADDR@l
+ mtlr r4
+ addis r5,0,0x0
+ ori r5,r5,((pll_prog_code_end - pll_prog_code_start) >>2)
+ mtctr r5
+ addi r3, r3, -4
+ addi r4, r4, -4
+0:
+ lwzu r0,4(r3)
+ stwu r0,4(r4)
+ bdnz 0b /* copy loop */
+ blrl
+#endif
+
+ /*
+ * Calculate absolute address in FLASH and jump there
+ *----------------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_MONITOR_BASE@h
+ ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
+ addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r3
+ blr
+
+in_flash:
+
+ /* Initialize some SPRs that are hard to access from C */
+ /*----------------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_IMMR@h /* Pass IMMR as arg1 to C routine */
+ lis r2, CONFIG_SYS_INIT_SP_ADDR@h
+ ori r1, r2, CONFIG_SYS_INIT_SP_ADDR@l /* Set up the stack in internal SRAM */
+ /* Note: R0 is still 0 here */
+ stwu r0, -4(r1) /* Clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /*
+ * Disable serialized ifetch and show cycles
+ * (i.e. set processor to normal mode) for maximum
+ * performance.
+ */
+
+ li r2, 0x0007
+ mtspr ICTRL, r2
+
+ /* Set up debug mode entry */
+
+ lis r2, CONFIG_SYS_DER@h
+ ori r2, r2, CONFIG_SYS_DER@l
+ mtspr DER, r2
+
+ /* Let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*----------------------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
+
+ bl board_init_f /* run 1st part of board init code (from Flash) */
+
+ /* NOTREACHED - board_init_f() does not return */
+
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* FPU on MPC5xx available. We will use it later.
+ */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ /* On the MPC8xx, this is a software emulation interrupt. It occurs
+ * for all unimplemented and illegal instructions.
+ */
+ STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = 0x2000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+
+/*
+ * unsigned int get_immr (unsigned int mask)
+ *
+ * return (mask ? (IMMR & mask) : IMMR);
+ */
+ .globl get_immr
+get_immr:
+ mr r4,r3 /* save mask */
+ mfspr r3, IMMR /* IMMR */
+ cmpwi 0,r4,0 /* mask != 0 ? */
+ beq 4f
+ and r3,r3,r4 /* IMMR & mask */
+4:
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer in SRAM */
+ mr r9, r4 /* Save copy of global data pointer in SRAM */
+ mr r10, r5 /* Save copy of monitor destination Address in SRAM */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* the the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 4f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+4: sync
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mtlr r4 /* restore link register */
+ blr
+
+#if defined(CONFIG_PATI)
+/* Program the PLL */
+pll_prog_code_start:
+ lis r4, (CONFIG_SYS_IMMR + 0x002fc384)@h
+ ori r4, r4, (CONFIG_SYS_IMMR + 0x002fc384)@l
+ lis r3, (0x55ccaa33)@h
+ ori r3, r3, (0x55ccaa33)@l
+ stw r3, 0(r4)
+ lis r4, (CONFIG_SYS_IMMR + 0x002fc284)@h
+ ori r4, r4, (CONFIG_SYS_IMMR + 0x002fc284)@l
+ lis r3, CONFIG_SYS_PLPRCR@h
+ ori r3, r3, CONFIG_SYS_PLPRCR@l
+ stw r3, 0(r4)
+ addis r3,0,0x0
+ ori r3,r3,0xA000
+ mtctr r3
+..spinlp:
+ bdnz ..spinlp /* spin loop */
+ blr
+pll_prog_code_end:
+ nop
+ blr
+#endif
diff --git a/arch/powerpc/cpu/mpc5xx/traps.c b/arch/powerpc/cpu/mpc5xx/traps.c
new file mode 100644
index 0000000..90da73b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/traps.c
@@ -0,0 +1,227 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x0001000
+
+
+/*
+ * Print stack backtrace
+ */
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+/*
+ * Print current registers
+ */
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+/*
+ * General exception handler routine
+ */
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+/*
+ * Machine check exception handler routine
+ */
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x000F0000) {
+ case (0x80000000>>12):
+ printf("Machine check signal\n");
+ break;
+ case (0x80000000>>13):
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14):
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000>>15):
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+/*
+ * Alignment exception handler routine
+ */
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+/*
+ * Program check exception handler routine
+ */
+void ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+/*
+ * Software emulation exception handler routine
+ */
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+/*
+ * Unknown exception handler routine
+ */
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+/*
+ * Debug exception handler routine
+ */
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc5xx/u-boot.lds b/arch/powerpc/cpu/mpc5xx/u-boot.lds
new file mode 100644
index 0000000..8385a29
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xx/u-boot.lds
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2001-2010 Wolfgang Denk, DENX Software Engineering, wd@denx.de
+ * (C) Copyright 2003 Martin Winistoerfer, martinwinistoerfer@gmx.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .text :
+ {
+ arch/powerpc/cpu/mpc5xx/start.o (.text*)
+
+ *(.text*)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+
+ __bss_end = . ;
+ PROVIDE (end = .);
+ . = env_start;
+ .ppcenv :
+ {
+ common/env_embedded.o (.ppcenv)
+ }
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/Makefile b/arch/powerpc/cpu/mpc5xxx/Makefile
new file mode 100644
index 0000000..8de2c13
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/Makefile
@@ -0,0 +1,64 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+SSTART = start.o
+CSTART = traps.o
+SOBJS += io.o
+SOBJS += firmware_sc_task_bestcomm.impl.o
+COBJS-y += i2c.o
+COBJS-y += cpu.o
+COBJS-y += cpu_init.o
+COBJS-y += ide.o
+COBJS-y += interrupts.o
+COBJS-y += loadtask.o
+COBJS-y += pci_mpc5200.o
+COBJS-y += serial.o
+COBJS-y += speed.o
+COBJS-$(CONFIG_CMD_USB) += usb_ohci.o
+COBJS-$(CONFIG_CMD_USB) += usb.o
+
+ifdef CONFIG_SPL_BUILD
+COBJS-y += spl_boot.o
+endif
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS-y))
+START := $(addprefix $(obj),$(SSTART) $(CSTART))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc5xxx/config.mk b/arch/powerpc/cpu/mpc5xxx/config.mk
new file mode 100644
index 0000000..fb87980
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/config.mk
@@ -0,0 +1,27 @@
+#
+# (C) Copyright 2003-2010
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC5xxx -ffixed-r2 \
+ -mstring -mcpu=603e -mmultiple
diff --git a/arch/powerpc/cpu/mpc5xxx/cpu.c b/arch/powerpc/cpu/mpc5xxx/cpu.c
new file mode 100644
index 0000000..dc021e3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/cpu.c
@@ -0,0 +1,184 @@
+/*
+ * (C) Copyright 2000-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC5xxx CPUs
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <net.h>
+#include <mpc5xxx.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+#if defined(CONFIG_OF_IDE_FIXUP)
+#include <ide.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+ ulong clock = gd->cpu_clk;
+ char buf[32];
+ uint svr, pvr;
+
+ puts ("CPU: ");
+
+ svr = get_svr();
+ pvr = get_pvr();
+
+ switch (pvr) {
+ case PVR_5200:
+ printf("MPC5200");
+ break;
+ case PVR_5200B:
+ printf("MPC5200B");
+ break;
+ default:
+ printf("Unknown MPC5xxx");
+ break;
+ }
+
+ printf (" v%d.%d, Core v%d.%d", SVR_MJREV (svr), SVR_MNREV (svr),
+ PVR_MAJ(pvr), PVR_MIN(pvr));
+ printf (" at %s MHz\n", strmhz (buf, clock));
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong msr;
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /* Charge the watchdog timer */
+ *(vu_long *)(MPC5XXX_GPT0_COUNTER) = 0x0001000f;
+ *(vu_long *)(MPC5XXX_GPT0_ENABLE) = 0x9004; /* wden|ce|timer_ms */
+ while(1);
+
+ return 1;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ */
+unsigned long get_tbclk (void)
+{
+ ulong tbclk;
+
+ tbclk = (gd->bus_clk + 3L) / 4L;
+
+ return (tbclk);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP)
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ int div = in_8((void*)CONFIG_SYS_MBAR + 0x204) & 0x0020 ? 8 : 4;
+ char * cpu_path = "/cpus/" OF_CPU;
+#ifdef CONFIG_MPC5xxx_FEC
+ uchar enetaddr[6];
+ char * eth_path = "/" OF_SOC "/ethernet@3000";
+#endif
+
+ do_fixup_by_path_u32(blob, cpu_path, "timebase-frequency", OF_TBCLK, 1);
+ do_fixup_by_path_u32(blob, cpu_path, "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_path_u32(blob, cpu_path, "clock-frequency", bd->bi_intfreq, 1);
+ do_fixup_by_path_u32(blob, "/" OF_SOC, "bus-frequency", bd->bi_ipbfreq, 1);
+ do_fixup_by_path_u32(blob, "/" OF_SOC, "system-frequency",
+ bd->bi_busfreq*div, 1);
+#ifdef CONFIG_MPC5xxx_FEC
+ eth_getenv_enetaddr("ethaddr", enetaddr);
+ do_fixup_by_path(blob, eth_path, "mac-address", enetaddr, 6, 0);
+ do_fixup_by_path(blob, eth_path, "local-mac-address", enetaddr, 6, 0);
+#endif
+#if defined(CONFIG_OF_IDE_FIXUP)
+ if (!ide_device_present(0)) {
+ /* NO CF card detected -> delete ata node in DTS */
+ int nodeoffset = 0;
+ char nodename[] = "/soc5200@f0000000/ata@3a00";
+
+ nodeoffset = fdt_path_offset(blob, nodename);
+ if (nodeoffset >= 0) {
+ fdt_del_node(blob, nodeoffset);
+ } else {
+ printf("%s: cannot find %s node err:%s\n",
+ __func__, nodename, fdt_strerror(nodeoffset));
+ }
+ }
+
+#endif
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
+#endif
+
+#ifdef CONFIG_MPC5xxx_FEC
+/* Default initializations for FEC controllers. To override,
+ * create a board-specific function called:
+ * int board_eth_init(bd_t *bis)
+ */
+
+int cpu_eth_init(bd_t *bis)
+{
+ return mpc5xxx_fec_initialize(bis);
+}
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset(void)
+{
+ int re_enable = disable_interrupts();
+ reset_5xxx_watchdog();
+ if (re_enable) enable_interrupts();
+}
+
+void reset_5xxx_watchdog(void)
+{
+ volatile struct mpc5xxx_gpt *gpt0 =
+ (struct mpc5xxx_gpt *) MPC5XXX_GPT;
+
+ /* Trigger TIMER_0 by writing A5 to OCPW */
+ clrsetbits_be32(&gpt0->emsr, 0xff000000, 0xa5000000);
+}
+#endif /* CONFIG_WATCHDOG */
diff --git a/arch/powerpc/cpu/mpc5xxx/cpu_init.c b/arch/powerpc/cpu/mpc5xxx/cpu_init.c
new file mode 100644
index 0000000..3044b41
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/cpu_init.c
@@ -0,0 +1,247 @@
+/*
+ * (C) Copyright 2000-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+#include <asm/io.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers.
+ */
+void cpu_init_f (void)
+{
+ volatile struct mpc5xxx_mmap_ctl *mm =
+ (struct mpc5xxx_mmap_ctl *) CONFIG_SYS_MBAR;
+ volatile struct mpc5xxx_lpb *lpb =
+ (struct mpc5xxx_lpb *) MPC5XXX_LPB;
+ volatile struct mpc5xxx_gpio *gpio =
+ (struct mpc5xxx_gpio *) MPC5XXX_GPIO;
+ volatile struct mpc5xxx_xlb *xlb =
+ (struct mpc5xxx_xlb *) MPC5XXX_XLBARB;
+#if defined(CONFIG_SYS_IPBCLK_EQUALS_XLBCLK)
+ volatile struct mpc5xxx_cdm *cdm =
+ (struct mpc5xxx_cdm *) MPC5XXX_CDM;
+#endif /* CONFIG_SYS_IPBCLK_EQUALS_XLBCLK */
+#if defined(CONFIG_WATCHDOG)
+ volatile struct mpc5xxx_gpt *gpt0 =
+ (struct mpc5xxx_gpt *) MPC5XXX_GPT;
+#endif /* CONFIG_WATCHDOG */
+ unsigned long addecr = (1 << 25); /* Boot_CS */
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ memset ((void *) gd, 0, sizeof (gd_t));
+
+ /*
+ * Memory Controller: configure chip selects and enable them
+ */
+#if defined(CONFIG_SYS_BOOTCS_START) && defined(CONFIG_SYS_BOOTCS_SIZE)
+ out_be32(&mm->boot_start, START_REG(CONFIG_SYS_BOOTCS_START));
+ out_be32(&mm->boot_stop, STOP_REG(CONFIG_SYS_BOOTCS_START,
+ CONFIG_SYS_BOOTCS_SIZE));
+#endif
+#if defined(CONFIG_SYS_BOOTCS_CFG)
+ out_be32(&lpb->cs0_cfg, CONFIG_SYS_BOOTCS_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS0_START) && defined(CONFIG_SYS_CS0_SIZE)
+ out_be32(&mm->cs0_start, START_REG(CONFIG_SYS_CS0_START));
+ out_be32(&mm->cs0_stop, STOP_REG(CONFIG_SYS_CS0_START,
+ CONFIG_SYS_CS0_SIZE));
+ /* CS0 and BOOT_CS cannot be enabled at once. */
+ /* addecr |= (1 << 16); */
+#endif
+#if defined(CONFIG_SYS_CS0_CFG)
+ out_be32(&lpb->cs0_cfg, CONFIG_SYS_CS0_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS1_START) && defined(CONFIG_SYS_CS1_SIZE)
+ out_be32(&mm->cs1_start, START_REG(CONFIG_SYS_CS1_START));
+ out_be32(&mm->cs1_stop, STOP_REG(CONFIG_SYS_CS1_START,
+ CONFIG_SYS_CS1_SIZE));
+ addecr |= (1 << 17);
+#endif
+#if defined(CONFIG_SYS_CS1_CFG)
+ out_be32(&lpb->cs1_cfg, CONFIG_SYS_CS1_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS2_START) && defined(CONFIG_SYS_CS2_SIZE)
+ out_be32(&mm->cs2_start, START_REG(CONFIG_SYS_CS2_START));
+ out_be32(&mm->cs2_stop, STOP_REG(CONFIG_SYS_CS2_START,
+ CONFIG_SYS_CS2_SIZE));
+ addecr |= (1 << 18);
+#endif
+#if defined(CONFIG_SYS_CS2_CFG)
+ out_be32(&lpb->cs2_cfg, CONFIG_SYS_CS2_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS3_START) && defined(CONFIG_SYS_CS3_SIZE)
+ out_be32(&mm->cs3_start, START_REG(CONFIG_SYS_CS3_START));
+ out_be32(&mm->cs3_stop, STOP_REG(CONFIG_SYS_CS3_START,
+ CONFIG_SYS_CS3_SIZE));
+ addecr |= (1 << 19);
+#endif
+#if defined(CONFIG_SYS_CS3_CFG)
+ out_be32(&lpb->cs3_cfg, CONFIG_SYS_CS3_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS4_START) && defined(CONFIG_SYS_CS4_SIZE)
+ out_be32(&mm->cs4_start, START_REG(CONFIG_SYS_CS4_START));
+ out_be32(&mm->cs4_stop, STOP_REG(CONFIG_SYS_CS4_START,
+ CONFIG_SYS_CS4_SIZE));
+ addecr |= (1 << 20);
+#endif
+#if defined(CONFIG_SYS_CS4_CFG)
+ out_be32(&lpb->cs4_cfg, CONFIG_SYS_CS4_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS5_START) && defined(CONFIG_SYS_CS5_SIZE)
+ out_be32(&mm->cs5_start, START_REG(CONFIG_SYS_CS5_START));
+ out_be32(&mm->cs5_stop, STOP_REG(CONFIG_SYS_CS5_START,
+ CONFIG_SYS_CS5_SIZE));
+ addecr |= (1 << 21);
+#endif
+#if defined(CONFIG_SYS_CS5_CFG)
+ out_be32(&lpb->cs5_cfg, CONFIG_SYS_CS5_CFG);
+#endif
+
+ addecr |= 1;
+#if defined(CONFIG_SYS_CS6_START) && defined(CONFIG_SYS_CS6_SIZE)
+ out_be32(&mm->cs6_start, START_REG(CONFIG_SYS_CS6_START));
+ out_be32(&mm->cs6_stop, STOP_REG(CONFIG_SYS_CS6_START,
+ CONFIG_SYS_CS6_SIZE));
+ addecr |= (1 << 26);
+#endif
+#if defined(CONFIG_SYS_CS6_CFG)
+ out_be32(&lpb->cs6_cfg, CONFIG_SYS_CS6_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS7_START) && defined(CONFIG_SYS_CS7_SIZE)
+ out_be32(&mm->cs7_start, START_REG(CONFIG_SYS_CS7_START));
+ out_be32(&mm->cs7_stop, STOP_REG(CONFIG_SYS_CS7_START,
+ CONFIG_SYS_CS7_SIZE));
+ addecr |= (1 << 27);
+#endif
+#if defined(CONFIG_SYS_CS7_CFG)
+ out_be32(&lpb->cs7_cfg, CONFIG_SYS_CS7_CFG);
+#endif
+
+#if defined(CONFIG_SYS_CS_BURST)
+ out_be32(&lpb->cs_burst, CONFIG_SYS_CS_BURST);
+#endif
+#if defined(CONFIG_SYS_CS_DEADCYCLE)
+ out_be32(&lpb->cs_deadcycle, CONFIG_SYS_CS_DEADCYCLE);
+#endif
+
+ /* Enable chip selects */
+ out_be32(&mm->ipbi_ws_ctrl, addecr);
+ out_be32(&lpb->cs_ctrl, (1 << 24));
+
+ /* Setup pin multiplexing */
+#if defined(CONFIG_SYS_GPS_PORT_CONFIG)
+ out_be32(&gpio->port_config, CONFIG_SYS_GPS_PORT_CONFIG);
+#endif
+
+ /* Setup gpios */
+#if defined(CONFIG_SYS_GPIO_DATADIR)
+ out_be32(&gpio->simple_ddr, CONFIG_SYS_GPIO_DATADIR);
+#endif
+#if defined(CONFIG_SYS_GPIO_OPENDRAIN)
+ out_be32(&gpio->simple_ode, CONFIG_SYS_GPIO_OPENDRAIN);
+#endif
+#if defined(CONFIG_SYS_GPIO_DATAVALUE)
+ out_be32(&gpio->simple_dvo, CONFIG_SYS_GPIO_DATAVALUE);
+#endif
+#if defined(CONFIG_SYS_GPIO_ENABLE)
+ out_be32(&gpio->simple_gpioe, CONFIG_SYS_GPIO_ENABLE);
+#endif
+
+ /* enable timebase */
+ setbits_be32(&xlb->config, (1 << 13));
+
+ /* Enable snooping for RAM */
+ setbits_be32(&xlb->config, (1 << 15));
+ out_be32(&xlb->snoop_window, CONFIG_SYS_SDRAM_BASE | 0x1d);
+
+#if defined(CONFIG_SYS_IPBCLK_EQUALS_XLBCLK)
+ /* Motorola reports IPB should better run at 133 MHz. */
+ setbits_be32(&mm->ipbi_ws_ctrl, 1);
+ /* pci_clk_sel = 0x02, ipb_clk_sel = 0x00; */
+ addecr = in_be32(&cdm->cfg);
+ addecr &= ~0x103;
+# if defined(CONFIG_SYS_PCICLK_EQUALS_IPBCLK_DIV2)
+ /* pci_clk_sel = 0x01 -> IPB_CLK/2 */
+ addecr |= 0x01;
+# else
+ /* pci_clk_sel = 0x02 -> XLB_CLK/4 = IPB_CLK/4 */
+ addecr |= 0x02;
+# endif /* CONFIG_SYS_PCICLK_EQUALS_IPBCLK_DIV2 */
+ out_be32(&cdm->cfg, addecr);
+#endif /* CONFIG_SYS_IPBCLK_EQUALS_XLBCLK */
+ /* Configure the XLB Arbiter */
+ out_be32(&xlb->master_pri_enable, 0xff);
+ out_be32(&xlb->master_priority, 0x11111111);
+
+#if defined(CONFIG_SYS_XLB_PIPELINING)
+ /* Enable piplining */
+ clrbits_be32(&xlb->config, (1 << 31));
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+ /* Charge the watchdog timer - prescaler = 64k, count = 64k*/
+ out_be32(&gpt0->cir, 0x0000ffff);
+ out_be32(&gpt0->emsr, 0x9004); /* wden|ce|timer_ms */
+
+ reset_5xxx_watchdog();
+#endif /* CONFIG_WATCHDOG */
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+ volatile struct mpc5xxx_intr *intr =
+ (struct mpc5xxx_intr *) MPC5XXX_ICTL;
+
+ /* mask all interrupts */
+ out_be32(&intr->per_mask, 0xffffff00);
+ setbits_be32(&intr->main_mask, 0x0001ffff);
+ clrbits_be32(&intr->ctrl, 0x00000f00);
+ /* route critical ints to normal ints */
+ setbits_be32(&intr->ctrl, 0x00000001);
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_MPC5xxx_FEC)
+ /* load FEC microcode */
+ loadtask(0, 2);
+#endif
+
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S b/arch/powerpc/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S
new file mode 100644
index 0000000..00c2312
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2001, Software Center, Motorola China.
+ *
+ * This file contains microcode for the FEC controller of the MPC5200 CPU.
+ */
+
+#include <config.h>
+
+/* sas/sccg, gas target */
+.section smartdmaInitData,"aw",@progbits /* Initialized data for task variables */
+.section smartdmaTaskTable,"aw",@progbits /* Task tables */
+.align 9
+.globl taskTable
+taskTable:
+.globl scEthernetRecv_Entry
+scEthernetRecv_Entry: /* Task 0 */
+.long scEthernetRecv_TDT - taskTable /* Task 0 Descriptor Table */
+.long scEthernetRecv_TDT - taskTable + 0x000000a4
+.long scEthernetRecv_VarTab - taskTable /* Task 0 Variable Table */
+.long scEthernetRecv_FDT - taskTable + 0x03 /* Task 0 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetRecv_CSave - taskTable /* Task 0 context save space */
+.long CONFIG_SYS_MBAR
+.globl scEthernetXmit_Entry
+scEthernetXmit_Entry: /* Task 1 */
+.long scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */
+.long scEthernetXmit_TDT - taskTable + 0x000000d0
+.long scEthernetXmit_VarTab - taskTable /* Task 1 Variable Table */
+.long scEthernetXmit_FDT - taskTable + 0x03 /* Task 1 Function Descriptor Table & Flags */
+.long 0x00000000
+.long 0x00000000
+.long scEthernetXmit_CSave - taskTable /* Task 1 context save space */
+.long CONFIG_SYS_MBAR
+
+
+.globl scEthernetRecv_TDT
+scEthernetRecv_TDT: /* Task 0 Descriptor Table */
+.long 0xc4c50000 /* 0000: LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
+.long 0x84c5e000 /* 0004: LCD: idx1 = var9 + var11; ; idx1 += inc0 */
+.long 0x10001f08 /* 0008: DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000380 /* 000C: DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f88 /* 0010: DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x010cf04c /* 0020: DRD2B1: var4 = EU3(); EU3(var1,var12) */
+.long 0x82180349 /* 0024: LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
+.long 0x81c68004 /* 0028: LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x70000000 /* 002C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018cf04e /* 0030: DRD2B1: var6 = EU3(); EU3(var1,var14) */
+.long 0x70000000 /* 0034: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x020cf04f /* 0038: DRD2B1: var8 = EU3(); EU3(var1,var15) */
+.long 0x00000b88 /* 003C: DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d184 /* 0040: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0xc6990452 /* 0044: LCDEXT: idx2 = var13; idx2 < var17; idx2 += inc2 */
+.long 0x81486010 /* 0048: LCD: idx3 = var2 + var16; ; idx3 += inc2 */
+.long 0x006acf88 /* 004C: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 0050: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x86810492 /* 0054: LCD: idx2 = var13, idx3 = var2; idx2 < var18; idx2 += inc2, idx3 += inc2 */
+.long 0x006acf88 /* 0058: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
+.long 0x8000d184 /* 005C: LCDEXT: idx1 = 0xf0003184; ; */
+.long 0x868184d2 /* 0060: LCD: idx2 = var13, idx3 = var3; idx2 < var19; idx2 += inc2, idx3 += inc2 */
+.long 0x000acf88 /* 0064: DRD1A: *idx3 = *idx1; FN=0 init=0 WS=1 RS=1 */
+.long 0xc318839b /* 0068: LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc3 */
+.long 0x80190000 /* 006C: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008468 /* 0070: DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4038358 /* 0074: LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc3, idx2 += inc0 */
+.long 0x81c50000 /* 0078: LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
+.long 0x1000cb18 /* 007C: DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 0080: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188364 /* 0084: LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc4 */
+.long 0x83990000 /* 0088: LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
+.long 0x10000c00 /* 008C: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x0000c800 /* 0090: DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 0094: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 0098: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 009C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080cf04c /* 00A0: DRD2B1: idx0 = EU3(); EU3(var1,var12) */
+.long 0x000001f8 /* 00A4(:0): NOP */
+
+
+.globl scEthernetXmit_TDT
+scEthernetXmit_TDT: /* Task 1 Descriptor Table */
+.long 0x80024800 /* 0000: LCDEXT: idx0 = 0xf0008800; ; */
+.long 0x85c60004 /* 0004: LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
+.long 0x10002308 /* 0008: DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x10000f88 /* 000C: DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000380 /* 0010: DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
+.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
+.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x024cf04d /* 0020: DRD2B1: var9 = EU3(); EU3(var1,var13) */
+.long 0x84980309 /* 0024: LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
+.long 0xc0004003 /* 0028: LCDEXT: idx1 = 0x00000003; ; */
+.long 0x81c60004 /* 002C: LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
+.long 0x70000000 /* 0030: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x010cf04e /* 0034: DRD2B1: var4 = EU3(); EU3(var1,var14) */
+.long 0x70000000 /* 0038: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x014cf04f /* 003C: DRD2B1: var5 = EU3(); EU3(var1,var15) */
+.long 0x70000000 /* 0040: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x028cf050 /* 0044: DRD2B1: var10 = EU3(); EU3(var1,var16) */
+.long 0x70000000 /* 0048: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
+.long 0x018cf051 /* 004C: DRD2B1: var6 = EU3(); EU3(var1,var17) */
+.long 0x10000b90 /* 0050: DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 0054: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x01ccf0a1 /* 0058: DRD2B1: var7 = EU3(); EU3(var2,idx1) */
+.long 0xc2988312 /* 005C: LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
+.long 0x83490000 /* 0060: LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
+.long 0x00001b10 /* 0064: DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
+.long 0x8000d1a4 /* 0068: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0x8301031c /* 006C: LCD: idx2 = var6, idx3 = var2; idx2 > var12; idx2 += inc3, idx3 += inc4 */
+.long 0x008ac798 /* 0070: DRD1A: *idx1 = *idx3; FN=0 init=4 WS=1 RS=1 */
+.long 0x8000d1a4 /* 0074: LCDEXT: idx1 = 0xf00031a4; ; */
+.long 0xc1430000 /* 0078: LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
+.long 0x82998312 /* 007C: LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
+.long 0x088ac790 /* 0080: DRD1A: *idx1 = *idx2; FN=0 TFD init=4 WS=1 RS=1 */
+.long 0x81988000 /* 0084: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x60000001 /* 0088: DRD2A: EU0=0 EU1=0 EU2=0 EU3=1 EXT init=0 WS=0 RS=0 */
+.long 0x0c4cfc4d /* 008C: DRD2B1: *idx1 = EU3(); EU3(*idx1,var13) */
+.long 0xc21883ad /* 0090: LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
+.long 0x80190000 /* 0094: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
+.long 0x04008460 /* 0098: DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
+.long 0xc4052305 /* 009C: LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
+.long 0x81c98000 /* 00A0: LCD: idx3 = var3 + var19; idx3 once var0; idx3 += inc0 */
+.long 0x1000c718 /* 00A4: DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00000f18 /* 00A8: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
+.long 0xc4188000 /* 00AC: LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
+.long 0x85190312 /* 00B0: LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
+.long 0x10000c00 /* 00B4: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x1000c400 /* 00B8: DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x00008860 /* 00BC: DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
+.long 0x81988000 /* 00C0: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
+.long 0x10000788 /* 00C4: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
+.long 0x60000000 /* 00C8: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
+.long 0x080cf04d /* 00CC: DRD2B1: idx0 = EU3(); EU3(var1,var13) */
+.long 0x000001f8 /* 00D0(:0): NOP */
+
+.align 8
+
+.globl scEthernetRecv_VarTab
+scEthernetRecv_VarTab: /* Task 0 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long (CONFIG_SYS_MBAR + 0x8800) /* var[9] */
+.long 0x00000008 /* var[10] */
+.long 0x0000000c /* var[11] */
+.long 0x80000000 /* var[12] */
+.long 0x00000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x20000000 /* var[15] */
+.long 0x000005e4 /* var[16] */
+.long 0x0000000e /* var[17] */
+.long 0x000005e0 /* var[18] */
+.long 0x00000004 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x20000001 /* inc[2] */
+.long 0x80000000 /* inc[3] */
+.long 0x40000000 /* inc[4] */
+.long 0x00000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetXmit_VarTab
+scEthernetXmit_VarTab: /* Task 1 Variable Table */
+.long 0x00000000 /* var[0] */
+.long 0x00000000 /* var[1] */
+.long 0x00000000 /* var[2] */
+.long 0x00000000 /* var[3] */
+.long 0x00000000 /* var[4] */
+.long 0x00000000 /* var[5] */
+.long 0x00000000 /* var[6] */
+.long 0x00000000 /* var[7] */
+.long 0x00000000 /* var[8] */
+.long 0x00000000 /* var[9] */
+.long 0x00000000 /* var[10] */
+.long (CONFIG_SYS_MBAR + 0x8800) /* var[11] */
+.long 0x00000000 /* var[12] */
+.long 0x80000000 /* var[13] */
+.long 0x10000000 /* var[14] */
+.long 0x08000000 /* var[15] */
+.long 0x20000000 /* var[16] */
+.long 0x0000ffff /* var[17] */
+.long 0xffffffff /* var[18] */
+.long 0x00000008 /* var[19] */
+.long 0x00000000 /* var[20] */
+.long 0x00000000 /* var[21] */
+.long 0x00000000 /* var[22] */
+.long 0x00000000 /* var[23] */
+.long 0x00000000 /* inc[0] */
+.long 0x60000000 /* inc[1] */
+.long 0x40000000 /* inc[2] */
+.long 0x4000ffff /* inc[3] */
+.long 0xe0000001 /* inc[4] */
+.long 0x80000000 /* inc[5] */
+.long 0x00000000 /* inc[6] */
+.long 0x00000000 /* inc[7] */
+
+.align 8
+
+.globl scEthernetRecv_FDT
+scEthernetRecv_FDT: /* Task 0 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x21800000 /* and(), EU# 3 */
+.long 0x21400000 /* andn(), EU# 3 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+.align 8
+
+.globl scEthernetXmit_FDT
+scEthernetXmit_FDT: /* Task 1 Function Descriptor Table */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x21800000 /* and(), EU# 3 */
+.long 0x21400000 /* andn(), EU# 3 */
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+.long 0x00000000
+
+
+.globl scEthernetRecv_CSave
+scEthernetRecv_CSave: /* Task 0 context save space */
+.space 128, 0x0
+
+
+.globl scEthernetXmit_CSave
+scEthernetXmit_CSave: /* Task 1 context save space */
+.space 128, 0x0
diff --git a/arch/powerpc/cpu/mpc5xxx/i2c.c b/arch/powerpc/cpu/mpc5xxx/i2c.c
new file mode 100644
index 0000000..8d5f47b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/i2c.c
@@ -0,0 +1,472 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_HARD_I2C
+
+#include <mpc5xxx.h>
+#include <i2c.h>
+
+#if !defined(CONFIG_I2C_MULTI_BUS)
+#if (CONFIG_SYS_I2C_MODULE == 2)
+#define I2C_BASE MPC5XXX_I2C2
+#elif (CONFIG_SYS_I2C_MODULE == 1)
+#define I2C_BASE MPC5XXX_I2C1
+#else
+#error CONFIG_SYS_I2C_MODULE is not properly configured
+#endif
+#else
+static unsigned int i2c_bus_num __attribute__ ((section (".data"))) =
+ CONFIG_SYS_SPD_BUS_NUM;
+static unsigned int i2c_bus_speed[2] = {CONFIG_SYS_I2C_SPEED,
+ CONFIG_SYS_I2C_SPEED};
+
+static const unsigned long i2c_dev[2] = {
+ MPC5XXX_I2C1,
+ MPC5XXX_I2C2,
+};
+
+#define I2C_BASE ((struct mpc5xxx_i2c *)i2c_dev[i2c_bus_num])
+#endif
+
+#define I2C_TIMEOUT 6667
+#define I2C_RETRIES 3
+
+struct mpc5xxx_i2c_tap {
+ int scl2tap;
+ int tap2tap;
+};
+
+static int mpc_reg_in (volatile u32 *reg);
+static void mpc_reg_out (volatile u32 *reg, int val, int mask);
+static int wait_for_bb (void);
+static int wait_for_pin (int *status);
+static int do_address (uchar chip, char rdwr_flag);
+static int send_bytes (uchar chip, char *buf, int len);
+static int receive_bytes (uchar chip, char *buf, int len);
+static int mpc_get_fdr (int);
+
+static int mpc_reg_in(volatile u32 *reg)
+{
+ int ret = *reg >> 24;
+ __asm__ __volatile__ ("eieio");
+ return ret;
+}
+
+static void mpc_reg_out(volatile u32 *reg, int val, int mask)
+{
+ int tmp;
+
+ if (!mask) {
+ *reg = val << 24;
+ } else {
+ tmp = mpc_reg_in(reg);
+ *reg = ((tmp & ~mask) | (val & mask)) << 24;
+ }
+ __asm__ __volatile__ ("eieio");
+
+ return;
+}
+
+static int wait_for_bb(void)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int timeout = I2C_TIMEOUT;
+ int status;
+
+ status = mpc_reg_in(&regs->msr);
+
+ while (timeout-- && (status & I2C_BB)) {
+ mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+ (void)mpc_reg_in(&regs->mdr);
+ mpc_reg_out(&regs->mcr, 0, I2C_STA);
+ mpc_reg_out(&regs->mcr, 0, 0);
+ mpc_reg_out(&regs->mcr, I2C_EN, 0);
+ udelay(15);
+ status = mpc_reg_in(&regs->msr);
+ }
+
+ return (status & I2C_BB);
+}
+
+static int wait_for_pin(int *status)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int timeout = I2C_TIMEOUT;
+
+ *status = mpc_reg_in(&regs->msr);
+
+ while (timeout-- && !(*status & I2C_IF)) {
+ udelay(15);
+ *status = mpc_reg_in(&regs->msr);
+ }
+
+ if (!(*status & I2C_IF)) {
+ return -1;
+ }
+
+ mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+ return 0;
+}
+
+static int do_address(uchar chip, char rdwr_flag)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int status;
+
+ chip <<= 1;
+
+ if (rdwr_flag) {
+ chip |= 1;
+ }
+
+ mpc_reg_out(&regs->mcr, I2C_TX, I2C_TX);
+ mpc_reg_out(&regs->mdr, chip, 0);
+
+ if (wait_for_pin(&status)) {
+ return -2;
+ }
+
+ if (status & I2C_RXAK) {
+ return -3;
+ }
+
+ return 0;
+}
+
+static int send_bytes(uchar chip, char *buf, int len)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int wrcount;
+ int status;
+
+ for (wrcount = 0; wrcount < len; ++wrcount) {
+
+ mpc_reg_out(&regs->mdr, buf[wrcount], 0);
+
+ if (wait_for_pin(&status)) {
+ break;
+ }
+
+ if (status & I2C_RXAK) {
+ break;
+ }
+
+ }
+
+ return !(wrcount == len);
+}
+
+static int receive_bytes(uchar chip, char *buf, int len)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int dummy = 1;
+ int rdcount = 0;
+ int status;
+ int i;
+
+ mpc_reg_out(&regs->mcr, 0, I2C_TX);
+
+ for (i = 0; i < len; ++i) {
+ buf[rdcount] = mpc_reg_in(&regs->mdr);
+
+ if (dummy) {
+ dummy = 0;
+ } else {
+ rdcount++;
+ }
+
+
+ if (wait_for_pin(&status)) {
+ return -4;
+ }
+ }
+
+ mpc_reg_out(&regs->mcr, I2C_TXAK, I2C_TXAK);
+ buf[rdcount++] = mpc_reg_in(&regs->mdr);
+
+ if (wait_for_pin(&status)) {
+ return -5;
+ }
+
+ mpc_reg_out(&regs->mcr, 0, I2C_TXAK);
+
+ return 0;
+}
+
+#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX)
+
+#define FDR510(x) (u8) (((x & 0x20) >> 3) | (x & 0x3))
+#define FDR432(x) (u8) ((x & 0x1C) >> 2)
+/*
+ * Reset any i2c devices that may have been interrupted during a system reset.
+ * Normally this would be accomplished by clocking the line until SCL and SDA
+ * are released and then sending a start condtiion (From an Atmel datasheet).
+ * There is no direct access to the i2c pins so instead create start commands
+ * through the i2c interface. Send a start command then delay for the SDA Hold
+ * time, repeat this by disabling/enabling the bus a total of 9 times.
+ */
+static void send_reset(void)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int i;
+ u32 delay;
+ u8 fdr;
+ int SDA_Tap[] = { 3, 3, 4, 4, 1, 1, 2, 2};
+ struct mpc5xxx_i2c_tap scltap[] = {
+ {4, 1},
+ {4, 2},
+ {6, 4},
+ {6, 8},
+ {14, 16},
+ {30, 32},
+ {62, 64},
+ {126, 128}
+ };
+
+ fdr = (u8)mpc_reg_in(&regs->mfdr);
+
+ delay = scltap[FDR432(fdr)].scl2tap + ((SDA_Tap[FDR510(fdr)] - 1) * \
+ scltap[FDR432(fdr)].tap2tap) + 3;
+
+ for (i = 0; i < 9; i++) {
+ mpc_reg_out(&regs->mcr, I2C_EN|I2C_STA|I2C_TX, I2C_INIT_MASK);
+ udelay(delay);
+ mpc_reg_out(&regs->mcr, 0, I2C_INIT_MASK);
+ udelay(delay);
+ }
+
+ mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
+}
+#endif /* CONFIG_SYS_I2c_INIT_MPC5XXX */
+
+/**************** I2C API ****************/
+
+void i2c_init(int speed, int saddr)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+
+ mpc_reg_out(&regs->mcr, 0, 0);
+ mpc_reg_out(&regs->madr, saddr << 1, 0);
+
+ /* Set clock
+ */
+ mpc_reg_out(&regs->mfdr, mpc_get_fdr(speed), 0);
+
+ /* Enable module
+ */
+ mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
+ mpc_reg_out(&regs->msr, 0, I2C_IF);
+
+#if defined(CONFIG_SYS_I2C_INIT_MPC5XXX)
+ send_reset();
+#endif
+ return;
+}
+
+static int mpc_get_fdr(int speed)
+{
+ static int fdr = -1;
+
+ if (fdr == -1) {
+ ulong best_speed = 0;
+ ulong divider;
+ ulong ipb, scl;
+ ulong bestmatch = 0xffffffffUL;
+ int best_i = 0, best_j = 0, i, j;
+ int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
+ struct mpc5xxx_i2c_tap scltap[] = {
+ {4, 1},
+ {4, 2},
+ {6, 4},
+ {6, 8},
+ {14, 16},
+ {30, 32},
+ {62, 64},
+ {126, 128}
+ };
+
+ ipb = gd->arch.ipb_clk;
+ for (i = 7; i >= 0; i--) {
+ for (j = 7; j >= 0; j--) {
+ scl = 2 * (scltap[j].scl2tap +
+ (SCL_Tap[i] - 1) * scltap[j].tap2tap + 2);
+ if (ipb <= speed*scl) {
+ if ((speed*scl - ipb) < bestmatch) {
+ bestmatch = speed*scl - ipb;
+ best_i = i;
+ best_j = j;
+ best_speed = ipb/scl;
+ }
+ }
+ }
+ }
+ divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+ if (gd->flags & GD_FLG_RELOC) {
+ fdr = divider;
+ } else {
+ printf("%ld kHz, ", best_speed / 1000);
+ return divider;
+ }
+ }
+
+ return fdr;
+}
+
+int i2c_probe(uchar chip)
+{
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int i;
+
+ for (i = 0; i < I2C_RETRIES; i++) {
+ mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+
+ if (! do_address(chip, 0)) {
+ mpc_reg_out(&regs->mcr, 0, I2C_STA);
+ udelay(500);
+ break;
+ }
+
+ mpc_reg_out(&regs->mcr, 0, I2C_STA);
+ udelay(500);
+ }
+
+ return (i == I2C_RETRIES);
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ char xaddr[4];
+ struct mpc5xxx_i2c * regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int ret = -1;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+ if (wait_for_bb()) {
+ printf("i2c_read: bus is busy\n");
+ goto Done;
+ }
+
+ mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+ if (do_address(chip, 0)) {
+ printf("i2c_read: failed to address chip\n");
+ goto Done;
+ }
+
+ if (send_bytes(chip, &xaddr[4-alen], alen)) {
+ printf("i2c_read: send_bytes failed\n");
+ goto Done;
+ }
+
+ mpc_reg_out(&regs->mcr, I2C_RSTA, I2C_RSTA);
+ if (do_address(chip, 1)) {
+ printf("i2c_read: failed to address chip\n");
+ goto Done;
+ }
+
+ if (receive_bytes(chip, (char *)buf, len)) {
+ printf("i2c_read: receive_bytes failed\n");
+ goto Done;
+ }
+
+ ret = 0;
+Done:
+ mpc_reg_out(&regs->mcr, 0, I2C_STA);
+ return ret;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ char xaddr[4];
+ struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
+ int ret = -1;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+ if (wait_for_bb()) {
+ printf("i2c_write: bus is busy\n");
+ goto Done;
+ }
+
+ mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+ if (do_address(chip, 0)) {
+ printf("i2c_write: failed to address chip\n");
+ goto Done;
+ }
+
+ if (send_bytes(chip, &xaddr[4-alen], alen)) {
+ printf("i2c_write: send_bytes failed\n");
+ goto Done;
+ }
+
+ if (send_bytes(chip, (char *)buf, len)) {
+ printf("i2c_write: send_bytes failed\n");
+ goto Done;
+ }
+
+ ret = 0;
+Done:
+ mpc_reg_out(&regs->mcr, 0, I2C_STA);
+ return ret;
+}
+
+#if defined(CONFIG_I2C_MULTI_BUS)
+int i2c_set_bus_num(unsigned int bus)
+{
+ if (bus > 1)
+ return -1;
+
+ i2c_bus_num = bus;
+ i2c_init(i2c_bus_speed[bus], CONFIG_SYS_I2C_SLAVE);
+ return 0;
+}
+
+int i2c_set_bus_speed(unsigned int speed)
+{
+ i2c_init(speed, CONFIG_SYS_I2C_SLAVE);
+ return 0;
+}
+
+unsigned int i2c_get_bus_num(void)
+{
+ return i2c_bus_num;
+}
+
+unsigned int i2c_get_bus_speed(void)
+{
+ return i2c_bus_speed[i2c_bus_num];
+}
+#endif
+
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc5xxx/ide.c b/arch/powerpc/cpu/mpc5xxx/ide.c
new file mode 100644
index 0000000..094f62b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/ide.c
@@ -0,0 +1,99 @@
+/*
+ * (C) Copyright 2004
+ * Pierre AUBERT, Staubli Faverges, <p.aubert@staubli.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Init is derived from Linux code.
+ */
+#include <common.h>
+
+#if defined(CONFIG_CMD_IDE)
+#include <mpc5xxx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define CALC_TIMING(t) (t + period - 1) / period
+
+#ifdef CONFIG_IDE_RESET
+extern void init_ide_reset (void);
+#endif
+
+int ide_preinit (void)
+{
+ long period, t0, t1, t2_8, t2_16, t4, ta;
+ vu_long reg;
+ struct mpc5xxx_sdma *psdma = (struct mpc5xxx_sdma *) MPC5XXX_SDMA;
+
+ reg = *(vu_long *) MPC5XXX_GPS_PORT_CONFIG;
+#if defined(CONFIG_SYS_ATA_CS_ON_I2C2)
+ /* ATA cs0/1 on i2c2 clk/io */
+ reg = (reg & ~0x03000000ul) | 0x02000000ul;
+#elif defined(CONFIG_SYS_ATA_CS_ON_TIMER01)
+ /* ATA cs0/1 on Timer 0/1 */
+ reg = (reg & ~0x03000000ul) | 0x03000000ul;
+#else
+ /* ATA cs0/1 on Local Plus cs4/5 */
+ reg = (reg & ~0x03000000ul) | 0x01000000ul;
+#endif /* CONFIG_TOTAL5200 */
+ *(vu_long *) MPC5XXX_GPS_PORT_CONFIG = reg;
+
+ /* All sample codes do that... */
+ *(vu_long *) MPC5XXX_ATA_SHARE_COUNT = 0;
+
+#if defined(CONFIG_UC101)
+ /* Configure and reset host */
+ *(vu_long *) MPC5XXX_ATA_HOST_CONFIG =
+ MPC5xxx_ATA_HOSTCONF_SMR | MPC5xxx_ATA_HOSTCONF_FR;
+ udelay (10);
+ *(vu_long *) MPC5XXX_ATA_HOST_CONFIG = 0;
+#else
+ /* Configure and reset host */
+ *(vu_long *) MPC5XXX_ATA_HOST_CONFIG = MPC5xxx_ATA_HOSTCONF_IORDY |
+ MPC5xxx_ATA_HOSTCONF_SMR | MPC5xxx_ATA_HOSTCONF_FR;
+ udelay (10);
+ *(vu_long *) MPC5XXX_ATA_HOST_CONFIG = MPC5xxx_ATA_HOSTCONF_IORDY;
+#endif
+
+ /* Disable prefetch on Commbus */
+ psdma->PtdCntrl |= 1;
+
+ /* Init timings : we use PIO mode 0 timings */
+ period = 1000000000 / gd->arch.ipb_clk; /* period in ns */
+
+ t0 = CALC_TIMING (600);
+ t2_8 = CALC_TIMING (290);
+ t2_16 = CALC_TIMING (165);
+ reg = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8);
+ *(vu_long *) MPC5XXX_ATA_PIO1 = reg;
+
+ t4 = CALC_TIMING (30);
+ t1 = CALC_TIMING (70);
+ ta = CALC_TIMING (35);
+ reg = (t4 << 24) | (t1 << 16) | (ta << 8);
+
+ *(vu_long *) MPC5XXX_ATA_PIO2 = reg;
+
+#ifdef CONFIG_IDE_RESET
+ init_ide_reset ();
+#endif /* CONFIG_IDE_RESET */
+
+ return (0);
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc5xxx/interrupts.c b/arch/powerpc/cpu/mpc5xxx/interrupts.c
new file mode 100644
index 0000000..50455d0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/interrupts.c
@@ -0,0 +1,346 @@
+/*
+ * (C) Copyright 2006
+ * Detlev Zundel, DENX Software Engineering, dzu@denx.de
+ *
+ * (C) Copyright -2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2001
+ * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* this section was ripped out of arch/powerpc/syslib/mpc52xx_pic.c in the
+ * Linux 2.6 source with the following copyright.
+ *
+ * Based on (well, mostly copied from) the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <command.h>
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ ulong count;
+};
+
+static struct irq_action irq_handlers[NR_IRQS];
+
+static struct mpc5xxx_intr *intr;
+static struct mpc5xxx_sdma *sdma;
+
+static void mpc5xxx_ic_disable(unsigned int irq)
+{
+ u32 val;
+
+ if (irq == MPC5XXX_IRQ0) {
+ val = in_be32(&intr->ctrl);
+ val &= ~(1 << 11);
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_IRQ1) {
+ BUG();
+ } else if (irq <= MPC5XXX_IRQ3) {
+ val = in_be32(&intr->ctrl);
+ val &= ~(1 << (10 - (irq - MPC5XXX_IRQ1)));
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_SDMA_IRQ_BASE) {
+ val = in_be32(&intr->main_mask);
+ val |= 1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE));
+ out_be32(&intr->main_mask, val);
+ } else if (irq < MPC5XXX_PERP_IRQ_BASE) {
+ val = in_be32(&sdma->IntMask);
+ val |= 1 << (irq - MPC5XXX_SDMA_IRQ_BASE);
+ out_be32(&sdma->IntMask, val);
+ } else {
+ val = in_be32(&intr->per_mask);
+ val |= 1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE));
+ out_be32(&intr->per_mask, val);
+ }
+}
+
+static void mpc5xxx_ic_enable(unsigned int irq)
+{
+ u32 val;
+
+ if (irq == MPC5XXX_IRQ0) {
+ val = in_be32(&intr->ctrl);
+ val |= 1 << 11;
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_IRQ1) {
+ BUG();
+ } else if (irq <= MPC5XXX_IRQ3) {
+ val = in_be32(&intr->ctrl);
+ val |= 1 << (10 - (irq - MPC5XXX_IRQ1));
+ out_be32(&intr->ctrl, val);
+ } else if (irq < MPC5XXX_SDMA_IRQ_BASE) {
+ val = in_be32(&intr->main_mask);
+ val &= ~(1 << (16 - (irq - MPC5XXX_MAIN_IRQ_BASE)));
+ out_be32(&intr->main_mask, val);
+ } else if (irq < MPC5XXX_PERP_IRQ_BASE) {
+ val = in_be32(&sdma->IntMask);
+ val &= ~(1 << (irq - MPC5XXX_SDMA_IRQ_BASE));
+ out_be32(&sdma->IntMask, val);
+ } else {
+ val = in_be32(&intr->per_mask);
+ val &= ~(1 << (31 - (irq - MPC5XXX_PERP_IRQ_BASE)));
+ out_be32(&intr->per_mask, val);
+ }
+}
+
+static void mpc5xxx_ic_ack(unsigned int irq)
+{
+ u32 val;
+
+ /*
+ * Only some irqs are reset here, others in interrupting hardware.
+ */
+
+ switch (irq) {
+ case MPC5XXX_IRQ0:
+ val = in_be32(&intr->ctrl);
+ val |= 0x08000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC5XXX_CCS_IRQ:
+ val = in_be32(&intr->enc_status);
+ val |= 0x00000400;
+ out_be32(&intr->enc_status, val);
+ break;
+ case MPC5XXX_IRQ1:
+ val = in_be32(&intr->ctrl);
+ val |= 0x04000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC5XXX_IRQ2:
+ val = in_be32(&intr->ctrl);
+ val |= 0x02000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ case MPC5XXX_IRQ3:
+ val = in_be32(&intr->ctrl);
+ val |= 0x01000000;
+ out_be32(&intr->ctrl, val);
+ break;
+ default:
+ if (irq >= MPC5XXX_SDMA_IRQ_BASE
+ && irq < (MPC5XXX_SDMA_IRQ_BASE + MPC5XXX_SDMA_IRQ_NUM)) {
+ out_be32(&sdma->IntPend,
+ 1 << (irq - MPC5XXX_SDMA_IRQ_BASE));
+ }
+ break;
+ }
+}
+
+static void mpc5xxx_ic_disable_and_ack(unsigned int irq)
+{
+ mpc5xxx_ic_disable(irq);
+ mpc5xxx_ic_ack(irq);
+}
+
+static void mpc5xxx_ic_end(unsigned int irq)
+{
+ mpc5xxx_ic_enable(irq);
+}
+
+void mpc5xxx_init_irq(void)
+{
+ u32 intr_ctrl;
+
+ /* Remap the necessary zones */
+ intr = (struct mpc5xxx_intr *)(MPC5XXX_ICTL);
+ sdma = (struct mpc5xxx_sdma *)(MPC5XXX_SDMA);
+
+ /* Disable all interrupt sources. */
+ out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
+ out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
+ out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
+ out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
+ intr_ctrl = in_be32(&intr->ctrl);
+ intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
+ 0x00ff0000 | /* IRQ 0-3 level sensitive low active */
+ 0x00001000 | /* MEE master external enable */
+ 0x00000000 | /* 0 means disable IRQ 0-3 */
+ 0x00000001; /* CEb route critical normally */
+ out_be32(&intr->ctrl, intr_ctrl);
+
+ /* Zero a bunch of the priority settings. */
+ out_be32(&intr->per_pri1, 0);
+ out_be32(&intr->per_pri2, 0);
+ out_be32(&intr->per_pri3, 0);
+ out_be32(&intr->main_pri1, 0);
+ out_be32(&intr->main_pri2, 0);
+}
+
+int mpc5xxx_get_irq(struct pt_regs *regs)
+{
+ u32 status;
+ int irq = -1;
+
+ status = in_be32(&intr->enc_status);
+
+ if (status & 0x00000400) { /* critical */
+ irq = (status >> 8) & 0x3;
+ if (irq == 2) /* high priority peripheral */
+ goto peripheral;
+ irq += MPC5XXX_CRIT_IRQ_BASE;
+ } else if (status & 0x00200000) { /* main */
+ irq = (status >> 16) & 0x1f;
+ if (irq == 4) /* low priority peripheral */
+ goto peripheral;
+ irq += MPC5XXX_MAIN_IRQ_BASE;
+ } else if (status & 0x20000000) { /* peripheral */
+ peripheral:
+ irq = (status >> 24) & 0x1f;
+ if (irq == 0) { /* bestcomm */
+ status = in_be32(&sdma->IntPend);
+ irq = ffs(status) + MPC5XXX_SDMA_IRQ_BASE - 1;
+ } else
+ irq += MPC5XXX_PERP_IRQ_BASE;
+ }
+
+ return irq;
+}
+
+/****************************************************************************/
+
+int interrupt_init_cpu(ulong * decrementer_count)
+{
+ *decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+ mpc5xxx_init_irq();
+
+ return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+ int irq, unmask = 1;
+
+ irq = mpc5xxx_get_irq(regs);
+
+ mpc5xxx_ic_disable_and_ack(irq);
+
+ enable_interrupts();
+
+ if (irq_handlers[irq].handler != NULL)
+ (*irq_handlers[irq].handler) (irq_handlers[irq].arg);
+ else {
+ printf("\nBogus External Interrupt IRQ %d\n", irq);
+ /*
+ * turn off the bogus interrupt, otherwise it
+ * might repeat forever
+ */
+ unmask = 0;
+ }
+
+ if (unmask)
+ mpc5xxx_ic_end(irq);
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free a interrupt handler.
+ */
+
+void irq_install_handler(int irq, interrupt_handler_t * handler, void *arg)
+{
+ if (irq < 0 || irq >= NR_IRQS) {
+ printf("irq_install_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ if (irq_handlers[irq].handler != NULL)
+ printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
+ (ulong) handler, (ulong) irq_handlers[irq].handler);
+
+ irq_handlers[irq].handler = handler;
+ irq_handlers[irq].arg = arg;
+
+ mpc5xxx_ic_enable(irq);
+}
+
+void irq_free_handler(int irq)
+{
+ if (irq < 0 || irq >= NR_IRQS) {
+ printf("irq_free_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ mpc5xxx_ic_disable(irq);
+
+ irq_handlers[irq].handler = NULL;
+ irq_handlers[irq].arg = NULL;
+}
+
+/****************************************************************************/
+
+#if defined(CONFIG_CMD_IRQ)
+void do_irqinfo(cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
+{
+ int irq, re_enable;
+ u32 intr_ctrl;
+ char *irq_config[] = { "level sensitive, active high",
+ "edge sensitive, rising active edge",
+ "edge sensitive, falling active edge",
+ "level sensitive, active low"
+ };
+
+ re_enable = disable_interrupts();
+
+ intr_ctrl = in_be32(&intr->ctrl);
+ printf("Interrupt configuration:\n");
+
+ for (irq = 0; irq <= 3; irq++) {
+ printf("IRQ%d: %s\n", irq,
+ irq_config[(intr_ctrl >> (22 - 2 * irq)) & 0x3]);
+ }
+
+ puts("\nInterrupt-Information:\n" "Nr Routine Arg Count\n");
+
+ for (irq = 0; irq < NR_IRQS; irq++)
+ if (irq_handlers[irq].handler != NULL)
+ printf("%02d %08lx %08lx %ld\n", irq,
+ (ulong) irq_handlers[irq].handler,
+ (ulong) irq_handlers[irq].arg,
+ irq_handlers[irq].count);
+
+ if (re_enable)
+ enable_interrupts();
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc5xxx/io.S b/arch/powerpc/cpu/mpc5xxx/io.S
new file mode 100644
index 0000000..2178a26
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/io.S
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ * Copyright (C) 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16 */
+/* Description: Input 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in16r */
+/* Description: Input 16 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0(3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: in32r */
+/* Description: Input 32 bits and byte reverse */
+/* ------------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,0,r3
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0(r3)
+ sync
+ blr
+
+/* ------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/* ------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,0,r3
+ sync
+ blr
diff --git a/arch/powerpc/cpu/mpc5xxx/loadtask.c b/arch/powerpc/cpu/mpc5xxx/loadtask.c
new file mode 100644
index 0000000..47e7b59
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/loadtask.c
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This file is based on code
+ * (C) Copyright Motorola, Inc., 2000
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+
+/* BestComm/SmartComm microcode */
+extern int taskTable;
+
+void loadtask(int basetask, int tasks)
+{
+ int *sram = (int *)MPC5XXX_SRAM;
+ int *task_org = &taskTable;
+ unsigned int start, offset, end;
+ int i;
+
+#ifdef DEBUG
+ printf("basetask = %d, tasks = %d\n", basetask, tasks);
+ printf("task_org = 0x%08x\n", (unsigned int)task_org);
+#endif
+
+ /* setup TaskBAR register */
+ *(vu_long *)MPC5XXX_SDMA = MPC5XXX_SRAM;
+
+ /* relocate task table entries */
+ offset = (unsigned int)sram;
+ for (i = basetask; i < basetask + tasks; i++) {
+ sram[i * 8 + 0] = task_org[i * 8 + 0] + offset;
+ sram[i * 8 + 1] = task_org[i * 8 + 1] + offset;
+ sram[i * 8 + 2] = task_org[i * 8 + 2] + offset;
+ sram[i * 8 + 3] = task_org[i * 8 + 3] + offset;
+ sram[i * 8 + 4] = task_org[i * 8 + 4];
+ sram[i * 8 + 5] = task_org[i * 8 + 5];
+ sram[i * 8 + 6] = task_org[i * 8 + 6] + offset;
+ sram[i * 8 + 7] = task_org[i * 8 + 7];
+ }
+
+ /* relocate task descriptors */
+ start = (sram[basetask * 8] - (unsigned int)sram);
+ end = (sram[(basetask + tasks - 1) * 8 + 1] - (unsigned int)sram);
+
+#ifdef DEBUG
+ printf ("TDT start = 0x%08x, end = 0x%08x\n", start, end);
+#endif
+
+ start /= 4;
+ end /= 4;
+ for (i = start; i <= end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ /* relocate variables */
+ start = (sram[basetask * 8 + 2] - (unsigned int)sram);
+ end = (sram[(basetask + tasks - 1) * 8 + 2] + 256 - (unsigned int)sram);
+ start /= 4;
+ end /= 4;
+ for (i = start; i < end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ /* relocate function decriptors */
+ start = ((sram[basetask * 8 + 3] & 0xfffffffc) - (unsigned int)sram);
+ end = ((sram[(basetask + tasks - 1) * 8 + 3] & 0xfffffffc) + 256 - (unsigned int)sram);
+ start /= 4;
+ end /= 4;
+ for (i = start; i < end; i++) {
+ sram[i] = task_org[i];
+ }
+
+ asm volatile ("sync");
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/pci_mpc5200.c b/arch/powerpc/cpu/mpc5xxx/pci_mpc5200.c
new file mode 100644
index 0000000..8268f8a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/pci_mpc5200.c
@@ -0,0 +1,187 @@
+/*
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_PCI)
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <mpc5xxx.h>
+
+/* System RAM mapped over PCI */
+#define CONFIG_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_MEMORY_PHYS CONFIG_SYS_SDRAM_BASE
+#define CONFIG_PCI_MEMORY_SIZE (1024 * 1024 * 1024)
+
+/* PCIIWCR bit fields */
+#define IWCR_MEM (0 << 3)
+#define IWCR_IO (1 << 3)
+#define IWCR_READ (0 << 1)
+#define IWCR_READLINE (1 << 1)
+#define IWCR_READMULT (2 << 1)
+#define IWCR_EN (1 << 0)
+
+static int mpc5200_read_config_dword(struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32* value)
+{
+ *(volatile u32 *)MPC5XXX_PCI_CAR = (1 << 31) | dev | offset;
+ eieio();
+ udelay(10);
+#if (defined CONFIG_PF5200 || defined CONFIG_CPCI5200)
+ if (dev & 0x00ff0000) {
+ u32 val;
+ val = in_le16((volatile u16 *)(CONFIG_PCI_IO_PHYS+2));
+ udelay(10);
+ val = val << 16;
+ val |= in_le16((volatile u16 *)(CONFIG_PCI_IO_PHYS+0));
+ *value = val;
+ } else {
+ *value = in_le32((volatile u32 *)CONFIG_PCI_IO_PHYS);
+ }
+ udelay(10);
+#else
+ *value = in_le32((volatile u32 *)CONFIG_PCI_IO_PHYS);
+#endif
+ eieio();
+ *(volatile u32 *)MPC5XXX_PCI_CAR = 0;
+ udelay(10);
+ return 0;
+}
+
+static int mpc5200_write_config_dword(struct pci_controller *hose,
+ pci_dev_t dev, int offset, u32 value)
+{
+ *(volatile u32 *)MPC5XXX_PCI_CAR = (1 << 31) | dev | offset;
+ eieio();
+ udelay(10);
+ out_le32((volatile u32 *)CONFIG_PCI_IO_PHYS, value);
+ eieio();
+ *(volatile u32 *)MPC5XXX_PCI_CAR = 0;
+ udelay(10);
+ return 0;
+}
+
+void pci_mpc5xxx_init (struct pci_controller *hose)
+{
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* System space */
+ pci_set_region(hose->regions + 0,
+ CONFIG_PCI_MEMORY_BUS,
+ CONFIG_PCI_MEMORY_PHYS,
+ CONFIG_PCI_MEMORY_SIZE,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + 1,
+ CONFIG_PCI_MEM_BUS,
+ CONFIG_PCI_MEM_PHYS,
+ CONFIG_PCI_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI IO space */
+ pci_set_region(hose->regions + 2,
+ CONFIG_PCI_IO_BUS,
+ CONFIG_PCI_IO_PHYS,
+ CONFIG_PCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 3;
+
+ pci_register_hose(hose);
+
+ /* GPIO Multiplexing - enable PCI */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~(1 << 15);
+
+ /* Set host bridge as pci master and enable memory decoding */
+ *(vu_long *)MPC5XXX_PCI_CMD |=
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+
+ /* Set maximum latency timer */
+ *(vu_long *)MPC5XXX_PCI_CFG |= (0xf800);
+
+ /* Set cache line size */
+ *(vu_long *)MPC5XXX_PCI_CFG = (*(vu_long *)MPC5XXX_PCI_CFG & ~0xff) |
+ (CONFIG_SYS_CACHELINE_SIZE / 4);
+
+ /* Map MBAR to PCI space */
+ *(vu_long *)MPC5XXX_PCI_BAR0 = CONFIG_SYS_MBAR;
+ *(vu_long *)MPC5XXX_PCI_TBATR0 = CONFIG_SYS_MBAR | 1;
+
+ /* Map RAM to PCI space */
+ *(vu_long *)MPC5XXX_PCI_BAR1 = CONFIG_PCI_MEMORY_BUS | (1 << 3);
+ *(vu_long *)MPC5XXX_PCI_TBATR1 = CONFIG_PCI_MEMORY_PHYS | 1;
+
+ /* Park XLB on PCI */
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) &= ~((7 << 8) | (3 << 5));
+ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (3 << 8) | (3 << 5);
+
+ /* Disable interrupts from PCI controller */
+ *(vu_long *)MPC5XXX_PCI_GSCR &= ~(7 << 12);
+ *(vu_long *)MPC5XXX_PCI_ICR &= ~(7 << 24);
+
+ /* Set PCI retry counter to 0 = infinite retry. */
+ /* The default of 255 is too short for slow devices. */
+ *(vu_long *)MPC5XXX_PCI_ICR &= 0xFFFFFF00;
+
+ /* Disable initiator windows */
+ *(vu_long *)MPC5XXX_PCI_IWCR = 0;
+
+ /* Map PCI memory to physical space */
+ *(vu_long *)MPC5XXX_PCI_IW0BTAR = CONFIG_PCI_MEM_PHYS |
+ (((CONFIG_PCI_MEM_SIZE - 1) >> 8) & 0x00ff0000) |
+ (CONFIG_PCI_MEM_BUS >> 16);
+ *(vu_long *)MPC5XXX_PCI_IWCR |= (IWCR_MEM | IWCR_READ | IWCR_EN) << 24;
+
+ /* Map PCI I/O to physical space */
+ *(vu_long *)MPC5XXX_PCI_IW1BTAR = CONFIG_PCI_IO_PHYS |
+ (((CONFIG_PCI_IO_SIZE - 1) >> 8) & 0x00ff0000) |
+ (CONFIG_PCI_IO_BUS >> 16);
+ *(vu_long *)MPC5XXX_PCI_IWCR |= (IWCR_IO | IWCR_READ | IWCR_EN) << 16;
+
+ /* Reset the PCI bus */
+ *(vu_long *)MPC5XXX_PCI_GSCR |= 1;
+ udelay(1000);
+ *(vu_long *)MPC5XXX_PCI_GSCR &= ~1;
+ udelay(1000);
+
+ pci_set_ops(hose,
+ pci_hose_read_config_byte_via_dword,
+ pci_hose_read_config_word_via_dword,
+ mpc5200_read_config_dword,
+ pci_hose_write_config_byte_via_dword,
+ pci_hose_write_config_word_via_dword,
+ mpc5200_write_config_dword);
+
+ udelay(1000);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+
+ hose->last_busno = pci_hose_scan(hose);
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/cpu/mpc5xxx/serial.c b/arch/powerpc/cpu/mpc5xxx/serial.c
new file mode 100644
index 0000000..1ccb4e3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/serial.c
@@ -0,0 +1,292 @@
+/*
+ * (C) Copyright 2000 - 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
+ * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
+ * Linux/PPC sources (m8260_tty.c had no copyright info in it).
+ *
+ * Martin Krause, 8 Jun 2006
+ * Added SERIAL_MULTI support
+ */
+
+/*
+ * Minimal serial functions needed to use one of the PSC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <mpc5xxx.h>
+#include <serial.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_PSC_CONSOLE)
+
+#if CONFIG_PSC_CONSOLE == 1
+#define PSC_BASE MPC5XXX_PSC1
+#elif CONFIG_PSC_CONSOLE == 2
+#define PSC_BASE MPC5XXX_PSC2
+#elif CONFIG_PSC_CONSOLE == 3
+#define PSC_BASE MPC5XXX_PSC3
+#elif CONFIG_PSC_CONSOLE == 4
+#define PSC_BASE MPC5XXX_PSC4
+#elif CONFIG_PSC_CONSOLE == 5
+#define PSC_BASE MPC5XXX_PSC5
+#elif CONFIG_PSC_CONSOLE == 6
+#define PSC_BASE MPC5XXX_PSC6
+#else
+#error CONFIG_PSC_CONSOLE must be in 1 ... 6
+#endif
+
+#if defined(CONFIG_PSC_CONSOLE2)
+
+#if CONFIG_PSC_CONSOLE2 == 1
+#define PSC_BASE2 MPC5XXX_PSC1
+#elif CONFIG_PSC_CONSOLE2 == 2
+#define PSC_BASE2 MPC5XXX_PSC2
+#elif CONFIG_PSC_CONSOLE2 == 3
+#define PSC_BASE2 MPC5XXX_PSC3
+#elif CONFIG_PSC_CONSOLE2 == 4
+#define PSC_BASE2 MPC5XXX_PSC4
+#elif CONFIG_PSC_CONSOLE2 == 5
+#define PSC_BASE2 MPC5XXX_PSC5
+#elif CONFIG_PSC_CONSOLE2 == 6
+#define PSC_BASE2 MPC5XXX_PSC6
+#else
+#error CONFIG_PSC_CONSOLE2 must be in 1 ... 6
+#endif
+
+#endif
+
+int serial_init_dev (unsigned long dev_base)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+ unsigned long baseclk;
+ int div;
+
+ /* reset PSC */
+ psc->command = PSC_SEL_MODE_REG_1;
+
+ /* select clock sources */
+ psc->psc_clock_select = 0;
+ baseclk = (gd->arch.ipb_clk + 16) / 32;
+
+ /* switch to UART mode */
+ psc->sicr = 0;
+
+ /* configure parity, bit length and so on */
+ psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
+ psc->mode = PSC_MODE_ONE_STOP;
+
+ /* set up UART divisor */
+ div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
+ psc->ctur = (div >> 8) & 0xff;
+ psc->ctlr = div & 0xff;
+
+ /* disable all interrupts */
+ psc->psc_imr = 0;
+
+ /* reset and enable Rx/Tx */
+ psc->command = PSC_RST_RX;
+ psc->command = PSC_RST_TX;
+ psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
+
+ return (0);
+}
+
+void serial_putc_dev (unsigned long dev_base, const char c)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+
+ if (c == '\n')
+ serial_putc_dev (dev_base, '\r');
+
+ /* Wait for last character to go. */
+ while (!(psc->psc_status & PSC_SR_TXEMP))
+ ;
+
+ psc->psc_buffer_8 = c;
+}
+
+void serial_putc_raw_dev(unsigned long dev_base, const char c)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+ /* Wait for last character to go. */
+ while (!(psc->psc_status & PSC_SR_TXEMP))
+ ;
+
+ psc->psc_buffer_8 = c;
+}
+
+
+void serial_puts_dev (unsigned long dev_base, const char *s)
+{
+ while (*s) {
+ serial_putc_dev (dev_base, *s++);
+ }
+}
+
+int serial_getc_dev (unsigned long dev_base)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+
+ /* Wait for a character to arrive. */
+ while (!(psc->psc_status & PSC_SR_RXRDY))
+ ;
+
+ return psc->psc_buffer_8;
+}
+
+int serial_tstc_dev (unsigned long dev_base)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+
+ return (psc->psc_status & PSC_SR_RXRDY);
+}
+
+void serial_setbrg_dev (unsigned long dev_base)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+ unsigned long baseclk, div;
+
+ baseclk = (gd->arch.ipb_clk + 16) / 32;
+
+ /* set up UART divisor */
+ div = (baseclk + (gd->baudrate/2)) / gd->baudrate;
+ psc->ctur = (div >> 8) & 0xFF;
+ psc->ctlr = div & 0xff;
+}
+
+void serial_setrts_dev (unsigned long dev_base, int s)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+
+ if (s) {
+ /* Assert RTS (become LOW) */
+ psc->op1 = 0x1;
+ }
+ else {
+ /* Negate RTS (become HIGH) */
+ psc->op0 = 0x1;
+ }
+}
+
+int serial_getcts_dev (unsigned long dev_base)
+{
+ volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)dev_base;
+
+ return (psc->ip & 0x1) ? 0 : 1;
+}
+
+int serial0_init(void)
+{
+ return (serial_init_dev(PSC_BASE));
+}
+
+void serial0_setbrg (void)
+{
+ serial_setbrg_dev(PSC_BASE);
+}
+
+void serial0_putc(const char c)
+{
+ serial_putc_dev(PSC_BASE,c);
+}
+
+void serial0_puts(const char *s)
+{
+ serial_puts_dev(PSC_BASE, s);
+}
+
+int serial0_getc(void)
+{
+ return(serial_getc_dev(PSC_BASE));
+}
+
+int serial0_tstc(void)
+{
+ return (serial_tstc_dev(PSC_BASE));
+}
+
+struct serial_device serial0_device =
+{
+ .name = "serial0",
+ .start = serial0_init,
+ .stop = NULL,
+ .setbrg = serial0_setbrg,
+ .getc = serial0_getc,
+ .tstc = serial0_tstc,
+ .putc = serial0_putc,
+ .puts = serial0_puts,
+};
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &serial0_device;
+}
+
+#ifdef CONFIG_PSC_CONSOLE2
+int serial1_init(void)
+{
+ return serial_init_dev(PSC_BASE2);
+}
+
+void serial1_setbrg(void)
+{
+ serial_setbrg_dev(PSC_BASE2);
+}
+
+void serial1_putc(const char c)
+{
+ serial_putc_dev(PSC_BASE2, c);
+}
+
+void serial1_puts(const char *s)
+{
+ serial_puts_dev(PSC_BASE2, s);
+}
+
+int serial1_getc(void)
+{
+ return serial_getc_dev(PSC_BASE2);
+}
+
+int serial1_tstc(void)
+{
+ return serial_tstc_dev(PSC_BASE2);
+}
+
+struct serial_device serial1_device =
+{
+ .name = "serial1",
+ .start = serial1_init,
+ .stop = NULL,
+ .setbrg = serial1_setbrg,
+ .getc = serial1_getc,
+ .tstc = serial1_tstc,
+ .putc = serial1_putc,
+ .puts = serial1_puts,
+};
+#endif /* CONFIG_PSC_CONSOLE2 */
+
+#endif /* CONFIG_PSC_CONSOLE */
diff --git a/arch/powerpc/cpu/mpc5xxx/speed.c b/arch/powerpc/cpu/mpc5xxx/speed.c
new file mode 100644
index 0000000..5353e3d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/speed.c
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc5xxx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+
+/* Bus-to-Core Multipliers */
+
+static int bus2core[] = {
+ 3, 2, 2, 2, 4, 4, 5, 9,
+ 6, 11, 8, 10, 3, 12, 7, 0,
+ 6, 5, 13, 2, 14, 4, 15, 9,
+ 0, 11, 8, 10, 16, 12, 7, 0
+};
+/* ------------------------------------------------------------------------- */
+
+/*
+ *
+ */
+
+int get_clocks (void)
+{
+ ulong val, vco;
+
+#if !defined(CONFIG_SYS_MPC5XXX_CLKIN)
+#error clock measuring not implemented yet - define CONFIG_SYS_MPC5XXX_CLKIN
+#endif
+
+ val = *(vu_long *)MPC5XXX_CDM_PORCFG;
+ if (val & (1 << 6)) {
+ vco = CONFIG_SYS_MPC5XXX_CLKIN * 12;
+ } else {
+ vco = CONFIG_SYS_MPC5XXX_CLKIN * 16;
+ }
+ if (val & (1 << 5)) {
+ gd->bus_clk = vco / 8;
+ } else {
+ gd->bus_clk = vco / 4;
+ }
+ gd->cpu_clk = gd->bus_clk * bus2core[val & 0x1f] / 2;
+
+ val = *(vu_long *)MPC5XXX_CDM_CFG;
+ if (val & (1 << 8)) {
+ gd->arch.ipb_clk = gd->bus_clk / 2;
+ } else {
+ gd->arch.ipb_clk = gd->bus_clk;
+ }
+ switch (val & 3) {
+ case 0:
+ gd->pci_clk = gd->arch.ipb_clk;
+ break;
+ case 1:
+ gd->pci_clk = gd->arch.ipb_clk / 2;
+ break;
+ default:
+ gd->pci_clk = gd->bus_clk / 4;
+ break;
+ }
+
+ return (0);
+}
+
+int prt_mpc5xxx_clks (void)
+{
+ char buf1[32], buf2[32], buf3[32];
+
+ printf (" Bus %s MHz, IPB %s MHz, PCI %s MHz\n",
+ strmhz(buf1, gd->bus_clk),
+ strmhz(buf2, gd->arch.ipb_clk),
+ strmhz(buf3, gd->pci_clk)
+ );
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/mpc5xxx/spl_boot.c b/arch/powerpc/cpu/mpc5xxx/spl_boot.c
new file mode 100644
index 0000000..35611cc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/spl_boot.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2012 Stefan Roese <sr@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Needed to align size SPL image to a 4-byte length
+ */
+u32 end_align __attribute__ ((section(".end_align")));
+
+/*
+ * Return selected boot device. On MPC5200 its only NOR flash right now.
+ */
+u32 spl_boot_device(void)
+{
+ return BOOT_DEVICE_NOR;
+}
+
+/*
+ * SPL version of board_init_f()
+ */
+void board_init_f(ulong bootflag)
+{
+ end_align = (u32)__spl_flash_end;
+
+ /*
+ * On MPC5200, the initial RAM (and gd) is located in the internal
+ * SRAM. So we can actually call the preloader console init code
+ * before calling initdram(). This makes serial output (printf)
+ * available very early, even before SDRAM init, which has been
+ * an U-Boot priciple from day 1.
+ */
+
+ /*
+ * Init global_data pointer. Has to be done before calling
+ * get_clocks(), as it stores some clock values into gd needed
+ * later on in the serial driver.
+ */
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *)(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+ /* Clear initial global data */
+ memset((void *)gd, 0, sizeof(gd_t));
+
+ /*
+ * get_clocks() needs to be called so that the serial driver
+ * works correctly
+ */
+ get_clocks();
+
+ /*
+ * Do rudimental console / serial setup
+ */
+ preloader_console_init();
+
+ /*
+ * First we need to initialize the SDRAM, so that the real
+ * U-Boot or the OS (Linux) can be loaded
+ */
+ initdram(0);
+
+ /* Clear bss */
+ memset(__bss_start, '\0', __bss_end - __bss_start);
+
+ /*
+ * Call board_init_r() (SPL framework version) to load and boot
+ * real U-Boot or OS
+ */
+ board_init_r(NULL, 0);
+ /* Does not return!!! */
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/start.S b/arch/powerpc/cpu/mpc5xxx/start.S
new file mode 100644
index 0000000..2b6a800
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/start.S
@@ -0,0 +1,783 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * U-Boot - Startup Code for MPC5xxx CPUs
+ */
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc5xxx.h>
+#include <version.h>
+
+#define CONFIG_MPC5xxx 1 /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+#endif
+
+/*
+ * Version string
+ */
+ .data
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+/*
+ * Exception vectors
+ */
+ .text
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+ /*
+ * This is the entry of the real U-Boot from a board port
+ * that supports SPL booting on the MPC5200. We only need
+ * to call board_init_f() here. Everything else has already
+ * been done in the SPL u-boot version.
+ */
+ GET_GOT /* initialize GOT access */
+ bl board_init_f /* run 1st part of board init code (in Flash)*/
+ /* NOTREACHED - board_init_f() does not return */
+#else
+ mfmsr r5 /* save msr contents */
+
+ /* Move CSBoot and adjust instruction pointer */
+ /*--------------------------------------------------------------*/
+
+#if defined(CONFIG_SYS_LOWBOOT)
+# if defined(CONFIG_SYS_RAMBOOT)
+# error CONFIG_SYS_LOWBOOT is incompatible with CONFIG_SYS_RAMBOOT
+# endif /* CONFIG_SYS_RAMBOOT */
+ lis r4, CONFIG_SYS_DEFAULT_MBAR@h
+ lis r3, START_REG(CONFIG_SYS_BOOTCS_START)@h
+ ori r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
+ stw r3, 0x4(r4) /* CS0 start */
+ lis r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
+ ori r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
+ stw r3, 0x8(r4) /* CS0 stop */
+ lis r3, 0x02010000@h
+ ori r3, r3, 0x02010000@l
+ stw r3, 0x54(r4) /* CS0 and Boot enable */
+
+ lis r3, lowboot_reentry@h /* jump from bootlow address space (0x0000xxxx) */
+ ori r3, r3, lowboot_reentry@l /* to the address space the linker used */
+ mtlr r3
+ blr
+
+lowboot_reentry:
+ lis r3, START_REG(CONFIG_SYS_BOOTCS_START)@h
+ ori r3, r3, START_REG(CONFIG_SYS_BOOTCS_START)@l
+ stw r3, 0x4c(r4) /* Boot start */
+ lis r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@h
+ ori r3, r3, STOP_REG(CONFIG_SYS_BOOTCS_START, CONFIG_SYS_BOOTCS_SIZE)@l
+ stw r3, 0x50(r4) /* Boot stop */
+ lis r3, 0x02000001@h
+ ori r3, r3, 0x02000001@l
+ stw r3, 0x54(r4) /* Boot enable, CS0 disable */
+#endif /* CONFIG_SYS_LOWBOOT */
+
+#if defined(CONFIG_SYS_DEFAULT_MBAR) && !defined(CONFIG_SYS_RAMBOOT)
+ lis r3, CONFIG_SYS_MBAR@h
+ ori r3, r3, CONFIG_SYS_MBAR@l
+ /* MBAR is mirrored into the MBAR SPR */
+ mtspr MBAR,r3
+ rlwinm r3, r3, 16, 16, 31
+ lis r4, CONFIG_SYS_DEFAULT_MBAR@h
+ stw r3, 0(r4)
+#endif /* CONFIG_SYS_DEFAULT_MBAR */
+
+ /* Initialise the MPC5xxx processor core */
+ /*--------------------------------------------------------------*/
+
+ bl init_5xxx_core
+
+ /* initialize some things that are hard to access from C */
+ /*--------------------------------------------------------------*/
+
+ /* set up stack in on-chip SRAM */
+ lis r3, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+ ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*--------------------------------------------------------------*/
+
+#ifndef CONFIG_SPL_BUILD
+ GET_GOT /* initialize GOT access */
+#endif
+
+ /* r3: IMMR */
+ bl cpu_init_f /* run low-level CPU init code (in Flash)*/
+
+ bl board_init_f /* run 1st part of board init code (in Flash)*/
+
+ /* NOTREACHED - board_init_f() does not return */
+#endif
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ * Vector Table
+ */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+ . = 0x1300
+ /*
+ * This exception occurs when the program counter matches the
+ * Instruction Address Breakpoint Register (IABR).
+ *
+ * I want the cpu to halt if this occurs so I can hunt around
+ * with the debugger and look at things.
+ *
+ * When DEBUG is defined, both machine check enable (in the MSR)
+ * and checkstop reset enable (in the reset mode register) are
+ * turned off and so a checkstop condition will result in the cpu
+ * halting.
+ *
+ * I force the cpu into a checkstop condition by putting an illegal
+ * instruction here (at least this is the theory).
+ *
+ * well - that didnt work, so just do an infinite loop!
+ */
+1: b 1b
+#else
+ STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+ STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+ STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+#endif /* CONFIG_SPL_BUILD */
+
+/*
+ * This code initialises the MPC5xxx processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+ .globl init_5xx_core
+init_5xxx_core:
+
+ /* Initialize machine status; enable machine check interrupt */
+ /*--------------------------------------------------------------*/
+
+ li r3, MSR_KERNEL /* Set ME and RI flags */
+ rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
+#endif
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ /* Initialize the Hardware Implementation-dependent Registers */
+ /* HID0 also contains cache control */
+ /*--------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_HID0_INIT@h
+ ori r3, r3, CONFIG_SYS_HID0_INIT@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CONFIG_SYS_HID0_FINAL@h
+ ori r3, r3, CONFIG_SYS_HID0_FINAL@l
+ SYNC
+ mtspr HID0, r3
+
+ /* clear all BAT's */
+ /*--------------------------------------------------------------*/
+
+ li r0, 0
+ mtspr DBAT0U, r0
+ mtspr DBAT0L, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT1L, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT2L, r0
+ mtspr DBAT3U, r0
+ mtspr DBAT3L, r0
+ mtspr DBAT4U, r0
+ mtspr DBAT4L, r0
+ mtspr DBAT5U, r0
+ mtspr DBAT5L, r0
+ mtspr DBAT6U, r0
+ mtspr DBAT6L, r0
+ mtspr DBAT7U, r0
+ mtspr DBAT7L, r0
+ mtspr IBAT0U, r0
+ mtspr IBAT0L, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT1L, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT2L, r0
+ mtspr IBAT3U, r0
+ mtspr IBAT3L, r0
+ mtspr IBAT4U, r0
+ mtspr IBAT4L, r0
+ mtspr IBAT5U, r0
+ mtspr IBAT5L, r0
+ mtspr IBAT6U, r0
+ mtspr IBAT6L, r0
+ mtspr IBAT7U, r0
+ mtspr IBAT7L, r0
+ SYNC
+
+ /* invalidate all tlb's */
+ /* */
+ /* From the 603e User Manual: "The 603e provides the ability to */
+ /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
+ /* instruction invalidates the TLB entry indexed by the EA, and */
+ /* operates on both the instruction and data TLBs simultaneously*/
+ /* invalidating four TLB entries (both sets in each TLB). The */
+ /* index corresponds to bits 15-19 of the EA. To invalidate all */
+ /* entries within both TLBs, 32 tlbie instructions should be */
+ /* issued, incrementing this field by one each time." */
+ /* */
+ /* "Note that the tlbia instruction is not implemented on the */
+ /* 603e." */
+ /* */
+ /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
+ /* incrementing by 0x1000 each time. The code below is sort of */
+ /* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S */
+ /* */
+ /*--------------------------------------------------------------*/
+
+ li r3, 32
+ mtctr r3
+ li r3, 0
+1: tlbie r3
+ addi r3, r3, 0x1000
+ bdnz 1b
+ SYNC
+
+ /* Done! */
+ /*--------------------------------------------------------------*/
+
+ blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICE
+ lis r4, 0
+ ori r4, r4, HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ICE|HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_DCE
+ lis r4, 0
+ ori r4, r4, HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_DCE|HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3, SVR
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+#ifndef CONFIG_SPL_BUILD
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
+ rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 9f
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
+ rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 7f
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mfmsr r3 /* now that the vectors have */
+ lis r7, MSR_IP@h /* relocated into low memory */
+ ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
+ andc r3, r3, r7 /* (if it was on) */
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+
+ mtlr r4 /* restore link register */
+ blr
+
+#endif /* CONFIG_SPL_BUILD */
diff --git a/arch/powerpc/cpu/mpc5xxx/traps.c b/arch/powerpc/cpu/mpc5xxx/traps.c
new file mode 100644
index 0000000..438f8d3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/traps.c
@@ -0,0 +1,236 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ * fixed Machine Check Reasons by Reinhard Meyer (r.meyer@emk-elektronik.de)
+ *
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ /* refer to 603e Manual (MPC603EUM/AD), chapter 4.5.2.1 */
+ switch( regs->msr & 0x000F0000)
+ {
+ case (0x80000000>>12) :
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13) :
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14) :
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000>>15) :
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void DebugException(struct pt_regs *regs)
+{
+
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds b/arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds
new file mode 100644
index 0000000..590952f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/u-boot-customlayout.lds
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .text :
+ {
+ /* WARNING - the following is hand-optimized to fit within */
+ /* the sector layout of our flash chips! XXX FIXME XXX */
+
+ arch/powerpc/cpu/mpc5xxx/start.o (.text*)
+ arch/powerpc/cpu/mpc5xxx/traps.o (.text*)
+
+ . = DEFINED(env_offset) ? env_offset : .;
+ common/env_embedded.o (.ppcenv*)
+
+ *(.text*)
+ . = ALIGN(16);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ KEEP(*(.got))
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/u-boot-spl.lds b/arch/powerpc/cpu/mpc5xxx/u-boot-spl.lds
new file mode 100644
index 0000000..0500739
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/u-boot-spl.lds
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+MEMORY
+{
+ sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
+ LENGTH = CONFIG_SPL_BSS_MAX_SIZE
+ flash : ORIGIN = CONFIG_SPL_TEXT_BASE,
+ LENGTH = CONFIG_SYS_SPL_MAX_LEN
+}
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start)
+SECTIONS
+{
+ .text :
+ {
+ __start = .;
+ arch/powerpc/cpu/mpc5xxx/start.o (.text)
+ *(.text*)
+ } > flash
+
+ . = ALIGN(4);
+ .data : { *(SORT_BY_ALIGNMENT(.data*)) } > flash
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } > flash
+
+ . = ALIGN(4);
+ .end_align : { *(.end_align*) } > flash
+ __spl_flash_end = .;
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start = .;
+ *(.bss*)
+ . = ALIGN(4);
+ __bss_end = .;
+ } > sdram
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/u-boot.lds b/arch/powerpc/cpu/mpc5xxx/u-boot.lds
new file mode 100644
index 0000000..06ece78
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/u-boot.lds
@@ -0,0 +1,92 @@
+/*
+ * (C) Copyright 2003-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .text :
+ {
+ arch/powerpc/cpu/mpc5xxx/start.o (.text*)
+ arch/powerpc/cpu/mpc5xxx/traps.o (.text*)
+ *(.text*)
+ . = ALIGN(16);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(COMMON)
+ *(.bss*)
+ *(.sbss*)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc5xxx/usb.c b/arch/powerpc/cpu/mpc5xxx/usb.c
new file mode 100644
index 0000000..bec7da3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/usb.c
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2007
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
+
+#include <mpc5xxx.h>
+
+int usb_cpu_init(void)
+{
+ /* Set the USB Clock */
+ *(vu_long *)MPC5XXX_CDM_48_FDC = CONFIG_USB_CLOCK;
+
+#ifdef CONFIG_PSC3_USB /* USB is using the alternate configuration */
+ /* remove all PSC3 USB bits first before ORing in ours */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00804f00;
+#else
+ /* remove all USB bits first before ORing in ours */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00807000;
+#endif
+ /* Activate USB port */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= CONFIG_USB_CONFIG;
+
+ return 0;
+}
+
+int usb_cpu_stop(void)
+{
+ return 0;
+}
+
+int usb_cpu_init_fail(void)
+{
+ return 0;
+}
+
+#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/arch/powerpc/cpu/mpc5xxx/usb_ohci.c b/arch/powerpc/cpu/mpc5xxx/usb_ohci.c
new file mode 100644
index 0000000..de07343
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/usb_ohci.c
@@ -0,0 +1,1644 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the MPC5200.
+ *
+ * (C) Copyright 2003-2004
+ * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Pierre Aubert, Staubli Faverges <p.aubert@staubli.com>
+ *
+ * Note: Much of this code has been derived from Linux 2.4
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - this driver is intended for use with USB Mass Storage Devices
+ * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_OHCI
+
+#include <malloc.h>
+#include <usb.h>
+#include "usb_ohci.h"
+
+#include <mpc5xxx.h>
+
+#define OHCI_USE_NPS /* force NoPowerSwitching mode */
+#undef OHCI_VERBOSE_DEBUG /* not always helpful */
+#undef DEBUG
+#undef SHOW_INFO
+#undef OHCI_FILL_TRACE
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#define readl(a) (*((volatile u32 *)(a)))
+#define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a))
+
+#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#ifdef DEBUG
+#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while(0)
+#endif /* DEBUG */
+#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
+#ifdef SHOW_INFO
+#define info(format, arg...) printf("INFO: " format "\n", ## arg)
+#else
+#define info(format, arg...) do {} while(0)
+#endif
+
+#define m16_swap(x) swap_16(x)
+#define m32_swap(x) swap_32(x)
+
+#define ohci_cpu_to_le16(x) (x)
+#define ohci_cpu_to_le32(x) (x)
+
+/* global ohci_t */
+static ohci_t gohci;
+/* this must be aligned to a 256 byte boundary */
+struct ohci_hcca ghcca[1];
+/* a pointer to the aligned storage */
+struct ohci_hcca *phcca;
+/* this allocates EDs for all possible endpoints */
+struct ohci_device ohci_dev;
+/* urb_priv */
+urb_priv_t urb_priv;
+/* RHSC flag */
+int got_rhsc;
+/* device which was disconnected */
+struct usb_device *devgone;
+/* flag guarding URB transation */
+int urb_finished = 0;
+
+/*-------------------------------------------------------------------------*/
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect. AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define OHCI_QUIRK_AMD756 0xabcd
+#define read_roothub(hc, register, mask) ({ \
+ u32 temp = readl (&hc->regs->roothub.register); \
+ if (hc->flags & OHCI_QUIRK_AMD756) \
+ while (temp & mask) \
+ temp = readl (&hc->regs->roothub.register); \
+ temp; })
+
+static u32 roothub_a (struct ohci *hc)
+ { return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci *hc)
+ { return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci *hc)
+ { return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci *hc, int i)
+ { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+
+/* forward declaration */
+static int hc_interrupt (void);
+static void
+td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval);
+
+/*-------------------------------------------------------------------------*
+ * URB support functions
+ *-------------------------------------------------------------------------*/
+
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv (urb_priv_t * urb)
+{
+ int i;
+ int last;
+ struct td * td;
+
+ last = urb->length - 1;
+ if (last >= 0) {
+ for (i = 0; i <= last; i++) {
+ td = urb->td[i];
+ if (td) {
+ td->usb_dev = NULL;
+ urb->td[i] = NULL;
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+static int sohci_get_current_frame_number (struct usb_device * dev);
+
+/* debug| print the main components of an URB
+ * small: 0) header + data packets 1) just header */
+
+static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, char * str, int small)
+{
+ urb_priv_t * purb = &urb_priv;
+
+ dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",
+ str,
+ sohci_get_current_frame_number (dev),
+ usb_pipedevice (pipe),
+ usb_pipeendpoint (pipe),
+ usb_pipeout (pipe)? 'O': 'I',
+ usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
+ (usb_pipecontrol (pipe)? "CTRL": "BULK"),
+ purb->actual_length,
+ transfer_len, dev->status);
+#ifdef OHCI_VERBOSE_DEBUG
+ if (!small) {
+ int i, len;
+
+ if (usb_pipecontrol (pipe)) {
+ printf (__FILE__ ": cmd(8):");
+ for (i = 0; i < 8 ; i++)
+ printf (" %02x", ((__u8 *) setup) [i]);
+ printf ("\n");
+ }
+ if (transfer_len > 0 && buffer) {
+ printf (__FILE__ ": data(%d/%d):",
+ purb->actual_length,
+ transfer_len);
+ len = usb_pipeout (pipe)?
+ transfer_len: purb->actual_length;
+ for (i = 0; i < 16 && i < len; i++)
+ printf (" %02x", ((__u8 *) buffer) [i]);
+ printf ("%s\n", i < len? "...": "");
+ }
+ }
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
+void ep_print_int_eds (ohci_t *ohci, char * str) {
+ int i, j;
+ __u32 * ed_p;
+ for (i= 0; i < 32; i++) {
+ j = 5;
+ ed_p = &(ohci->hcca->int_table [i]);
+ if (*ed_p == 0)
+ continue;
+ printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i);
+ while (*ed_p != 0 && j--) {
+ ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p);
+ printf (" ed: %4x;", ed->hwINFO);
+ ed_p = &ed->hwNextED;
+ }
+ printf ("\n");
+ }
+}
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+ dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+ label,
+ mask,
+ (mask & OHCI_INTR_MIE) ? " MIE" : "",
+ (mask & OHCI_INTR_OC) ? " OC" : "",
+ (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+ (mask & OHCI_INTR_FNO) ? " FNO" : "",
+ (mask & OHCI_INTR_UE) ? " UE" : "",
+ (mask & OHCI_INTR_RD) ? " RD" : "",
+ (mask & OHCI_INTR_SF) ? " SF" : "",
+ (mask & OHCI_INTR_WDH) ? " WDH" : "",
+ (mask & OHCI_INTR_SO) ? " SO" : ""
+ );
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+ ed_t *edp = (ed_t *)value;
+
+ if (value) {
+ dbg ("%s %08x", label, value);
+ dbg ("%08x", edp->hwINFO);
+ dbg ("%08x", edp->hwTailP);
+ dbg ("%08x", edp->hwHeadP);
+ dbg ("%08x", edp->hwNextED);
+ }
+}
+
+static char * hcfs2string (int state)
+{
+ switch (state) {
+ case OHCI_USB_RESET: return "reset";
+ case OHCI_USB_RESUME: return "resume";
+ case OHCI_USB_OPER: return "operational";
+ case OHCI_USB_SUSPEND: return "suspend";
+ }
+ return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status (ohci_t *controller)
+{
+ struct ohci_regs *regs = controller->regs;
+ __u32 temp;
+
+ temp = readl (&regs->revision) & 0xff;
+ if (temp != 0x10)
+ dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+ temp = readl (&regs->control);
+ dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+ (temp & OHCI_CTRL_RWE) ? " RWE" : "",
+ (temp & OHCI_CTRL_RWC) ? " RWC" : "",
+ (temp & OHCI_CTRL_IR) ? " IR" : "",
+ hcfs2string (temp & OHCI_CTRL_HCFS),
+ (temp & OHCI_CTRL_BLE) ? " BLE" : "",
+ (temp & OHCI_CTRL_CLE) ? " CLE" : "",
+ (temp & OHCI_CTRL_IE) ? " IE" : "",
+ (temp & OHCI_CTRL_PLE) ? " PLE" : "",
+ temp & OHCI_CTRL_CBSR
+ );
+
+ temp = readl (&regs->cmdstatus);
+ dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+ (temp & OHCI_SOC) >> 16,
+ (temp & OHCI_OCR) ? " OCR" : "",
+ (temp & OHCI_BLF) ? " BLF" : "",
+ (temp & OHCI_CLF) ? " CLF" : "",
+ (temp & OHCI_HCR) ? " HCR" : ""
+ );
+
+ ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+ ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+
+ maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+ maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+ maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+ maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+ maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+ maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (ohci_t *controller, int verbose)
+{
+ __u32 temp, ndp, i;
+
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+
+ if (verbose) {
+ dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+ ((temp & RH_A_POTPGT) >> 24) & 0xff,
+ (temp & RH_A_NOCP) ? " NOCP" : "",
+ (temp & RH_A_OCPM) ? " OCPM" : "",
+ (temp & RH_A_DT) ? " DT" : "",
+ (temp & RH_A_NPS) ? " NPS" : "",
+ (temp & RH_A_PSM) ? " PSM" : "",
+ ndp
+ );
+ temp = roothub_b (controller);
+ dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+ temp,
+ (temp & RH_B_PPCM) >> 16,
+ (temp & RH_B_DR)
+ );
+ temp = roothub_status (controller);
+ dbg ("roothub.status: %08x%s%s%s%s%s%s",
+ temp,
+ (temp & RH_HS_CRWE) ? " CRWE" : "",
+ (temp & RH_HS_OCIC) ? " OCIC" : "",
+ (temp & RH_HS_LPSC) ? " LPSC" : "",
+ (temp & RH_HS_DRWE) ? " DRWE" : "",
+ (temp & RH_HS_OCI) ? " OCI" : "",
+ (temp & RH_HS_LPS) ? " LPS" : ""
+ );
+ }
+
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+ i,
+ temp,
+ (temp & RH_PS_PRSC) ? " PRSC" : "",
+ (temp & RH_PS_OCIC) ? " OCIC" : "",
+ (temp & RH_PS_PSSC) ? " PSSC" : "",
+ (temp & RH_PS_PESC) ? " PESC" : "",
+ (temp & RH_PS_CSC) ? " CSC" : "",
+
+ (temp & RH_PS_LSDA) ? " LSDA" : "",
+ (temp & RH_PS_PPS) ? " PPS" : "",
+ (temp & RH_PS_PRS) ? " PRS" : "",
+ (temp & RH_PS_POCI) ? " POCI" : "",
+ (temp & RH_PS_PSS) ? " PSS" : "",
+
+ (temp & RH_PS_PES) ? " PES" : "",
+ (temp & RH_PS_CCS) ? " CCS" : ""
+ );
+ }
+}
+
+static void ohci_dump (ohci_t *controller, int verbose)
+{
+ dbg ("OHCI controller usb-%s state", controller->slot_name);
+
+ /* dumps some of the state we know about */
+ ohci_dump_status (controller);
+ if (verbose)
+ ep_print_int_eds (controller, "hcca");
+ dbg ("hcca frame #%04x", controller->hcca->frame_no);
+ ohci_dump_roothub (controller, 1);
+}
+
+
+#endif /* DEBUG */
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+
+int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, int interval)
+{
+ ohci_t *ohci;
+ ed_t * ed;
+ urb_priv_t *purb_priv;
+ int i, size = 0;
+
+ ohci = &gohci;
+
+ /* when controller's hung, permit only roothub cleanup attempts
+ * such as powering down ports */
+ if (ohci->disabled) {
+ err("sohci_submit_job: EPIPE");
+ return -1;
+ }
+
+ /* if we have an unfinished URB from previous transaction let's
+ * fail and scream as quickly as possible so as not to corrupt
+ * further communication */
+ if (!urb_finished) {
+ err("sohci_submit_job: URB NOT FINISHED");
+ return -1;
+ }
+ /* we're about to begin a new transaction here so mark the URB unfinished */
+ urb_finished = 0;
+
+ /* every endpoint has a ed, locate and fill it */
+ if (!(ed = ep_add_ed (dev, pipe))) {
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+
+ /* for the private part of the URB we need the number of TDs (size) */
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK: /* one TD for every 4096 Byte */
+ size = (transfer_len - 1) / 4096 + 1;
+ break;
+ case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+ size = (transfer_len == 0)? 2:
+ (transfer_len - 1) / 4096 + 3;
+ break;
+ }
+
+ if (size >= (N_URB_TD - 1)) {
+ err("need %d TDs, only have %d", size, N_URB_TD);
+ return -1;
+ }
+ purb_priv = &urb_priv;
+ purb_priv->pipe = pipe;
+
+ /* fill the private part of the URB */
+ purb_priv->length = size;
+ purb_priv->ed = ed;
+ purb_priv->actual_length = 0;
+
+ /* allocate the TDs */
+ /* note that td[0] was allocated in ep_add_ed */
+ for (i = 0; i < size; i++) {
+ purb_priv->td[i] = td_alloc (dev);
+ if (!purb_priv->td[i]) {
+ purb_priv->length = i;
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+ }
+
+ if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: EINVAL");
+ return -1;
+ }
+
+ /* link the ed into a chain if is not already */
+ if (ed->state != ED_OPER)
+ ep_link (ohci, ed);
+
+ /* fill the TDs and link it to the ed */
+ td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number (struct usb_device *usb_dev)
+{
+ ohci_t *ohci = &gohci;
+
+ return ohci_cpu_to_le16 (ohci->hcca->frame_no);
+}
+#endif
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+
+ ed->state = ED_OPER;
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ ed->hwNextED = 0;
+ if (ohci->ed_controltail == NULL) {
+ writel (ed, &ohci->regs->ed_controlhead);
+ } else {
+ ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_controltail;
+ if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_controltail = edi;
+ break;
+
+ case PIPE_BULK:
+ ed->hwNextED = 0;
+ if (ohci->ed_bulktail == NULL) {
+ writel (ed, &ohci->regs->ed_bulkhead);
+ } else {
+ ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_bulktail;
+ if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_bulktail = edi;
+ break;
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* unlink an ed from one of the HC chains.
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+
+ ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP);
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_controltail == ed) {
+ ohci->ed_controltail = ed->ed_prev;
+ } else {
+ ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+
+ case PIPE_BULK:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_bulktail == ed) {
+ ohci->ed_bulktail = ed->ed_prev;
+ } else {
+ ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+ }
+ ed->state = ED_UNLINK;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
+ * but the USB stack is a little bit stateless so we do it at every transaction
+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are setted anyway even though most of them should not change */
+
+static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
+{
+ td_t *td;
+ ed_t *ed_ret;
+ volatile ed_t *ed;
+
+ ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) |
+ (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))];
+
+ if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+ err("ep_add_ed: pending delete");
+ /* pending delete request */
+ return NULL;
+ }
+
+ if (ed->state == ED_NEW) {
+ ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
+ /* dummy td; end of td list for ed */
+ td = td_alloc (usb_dev);
+ ed->hwTailP = ohci_cpu_to_le32 ((unsigned long)td);
+ ed->hwHeadP = ed->hwTailP;
+ ed->state = ED_UNLINK;
+ ed->type = usb_pipetype (pipe);
+ ohci_dev.ed_cnt++;
+ }
+
+ ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe)
+ | usb_pipeendpoint (pipe) << 7
+ | (usb_pipeisoc (pipe)? 0x8000: 0)
+ | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
+ | (usb_dev->speed == USB_SPEED_LOW) << 13
+ | usb_maxpacket (usb_dev, pipe) << 16);
+
+ return ed_ret;
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void td_fill (ohci_t *ohci, unsigned int info,
+ void *data, int len,
+ struct usb_device *dev, int index, urb_priv_t *urb_priv)
+{
+ volatile td_t *td, *td_pt;
+#ifdef OHCI_FILL_TRACE
+ int i;
+#endif
+
+ if (index > urb_priv->length) {
+ err("index > length");
+ return;
+ }
+ /* use this td as the next dummy */
+ td_pt = urb_priv->td [index];
+ td_pt->hwNextTD = 0;
+
+ /* fill the old dummy TD */
+ td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf);
+
+ td->ed = urb_priv->ed;
+ td->next_dl_td = NULL;
+ td->index = index;
+ td->data = (__u32)data;
+#ifdef OHCI_FILL_TRACE
+ if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) {
+ for (i = 0; i < len; i++)
+ printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]);
+ printf("\n");
+ }
+#endif
+ if (!len)
+ data = 0;
+
+ td->hwINFO = ohci_cpu_to_le32 (info);
+ td->hwCBP = ohci_cpu_to_le32 ((unsigned long)data);
+ if (data)
+ td->hwBE = ohci_cpu_to_le32 ((unsigned long)(data + len - 1));
+ else
+ td->hwBE = 0;
+ td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt);
+
+ /* append to queue */
+ td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval)
+{
+ ohci_t *ohci = &gohci;
+ int data_len = transfer_len;
+ void *data;
+ int cnt = 0;
+ __u32 info = 0;
+ unsigned int toggle = 0;
+
+ /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
+ if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
+ toggle = TD_T_TOGGLE;
+ } else {
+ toggle = TD_T_DATA0;
+ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
+ }
+ urb->td_cnt = 0;
+ if (data_len)
+ data = buffer;
+ else
+ data = 0;
+
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK:
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+ while(data_len > 4096) {
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb);
+ data += 4096; data_len -= 4096; cnt++;
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb);
+ cnt++;
+
+ if (!ohci->sleeping)
+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+ break;
+
+ case PIPE_CONTROL:
+ info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+ td_fill (ohci, info, setup, 8, dev, cnt++, urb);
+ if (data_len > 0) {
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+ /* NOTE: mishandles transfers >8K, some >4K */
+ td_fill (ohci, info, data, data_len, dev, cnt++, urb);
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
+ td_fill (ohci, info, data, 0, dev, cnt++, urb);
+ if (!ohci->sleeping)
+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+ break;
+ }
+ if (urb->length != cnt)
+ dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+ __u32 tdBE, tdCBP;
+ urb_priv_t *lurb_priv = &urb_priv;
+
+ tdBE = ohci_cpu_to_le32 (td->hwBE);
+ tdCBP = ohci_cpu_to_le32 (td->hwCBP);
+
+
+ if (!(usb_pipecontrol(lurb_priv->pipe) &&
+ ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
+ if (tdBE != 0) {
+ if (td->hwCBP == 0)
+ lurb_priv->actual_length += tdBE - td->data + 1;
+ else
+ lurb_priv->actual_length += tdCBP - td->data;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+
+static td_t * dl_reverse_done_list (ohci_t *ohci)
+{
+ __u32 td_list_hc;
+ td_t *td_rev = NULL;
+ td_t *td_list = NULL;
+ urb_priv_t *lurb_priv = NULL;
+
+ td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0;
+ ohci->hcca->done_head = 0;
+
+ while (td_list_hc) {
+ td_list = (td_t *)td_list_hc;
+
+ if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) {
+ lurb_priv = &urb_priv;
+ dbg(" USB-error/status: %x : %p",
+ TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list);
+ if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) {
+ if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
+ td_list->ed->hwHeadP =
+ (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) |
+ (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2));
+ lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
+ } else
+ td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2);
+ }
+ td_list->hwNextTD = 0;
+ }
+
+ td_list->next_dl_td = td_rev;
+ td_rev = td_list;
+ td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0;
+ }
+ return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* td done list */
+static int dl_done_list (ohci_t *ohci, td_t *td_list)
+{
+ td_t *td_list_next = NULL;
+ ed_t *ed;
+ int cc = 0;
+ int stat = 0;
+ /* urb_t *urb; */
+ urb_priv_t *lurb_priv;
+ __u32 tdINFO, edHeadP, edTailP;
+
+ while (td_list) {
+ td_list_next = td_list->next_dl_td;
+
+ lurb_priv = &urb_priv;
+ tdINFO = ohci_cpu_to_le32 (td_list->hwINFO);
+
+ ed = td_list->ed;
+
+ dl_transfer_length(td_list);
+
+ /* error code of transfer */
+ cc = TD_CC_GET (tdINFO);
+ if (++(lurb_priv->td_cnt) == lurb_priv->length) {
+ if ((ed->state & (ED_OPER | ED_UNLINK))
+ && (lurb_priv->state != URB_DEL)) {
+ dbg("ConditionCode %#x", cc);
+ stat = cc_to_error[cc];
+ urb_finished = 1;
+ }
+ }
+
+ if (ed->state != ED_NEW) {
+ edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0;
+ edTailP = ohci_cpu_to_le32 (ed->hwTailP);
+
+ /* unlink eds if they are not busy */
+ if ((edHeadP == edTailP) && (ed->state == ED_OPER))
+ ep_unlink (ohci, ed);
+ }
+
+ td_list = td_list_next;
+ }
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x01, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+ 28, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'O', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'C', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'I', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x) len = (x); break
+#ifdef DEBUG
+#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);}
+#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);}
+#else
+#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status)
+#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1])
+#endif
+#define RD_RH_STAT roothub_status(&gohci)
+#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1)
+
+/* request to virtual root hub */
+
+int rh_check_port_status(ohci_t *controller)
+{
+ __u32 temp, ndp, i;
+ int res;
+
+ res = -1;
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ /* check for a device disconnect */
+ if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+ (RH_PS_PESC | RH_PS_CSC)) &&
+ ((temp & RH_PS_CCS) == 0)) {
+ res = i;
+ break;
+ }
+ }
+ return res;
+}
+
+static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len, struct devrequest *cmd)
+{
+ void * data = buffer;
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ __u32 datab[4];
+ __u8 *data_buf = (__u8 *)datab;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wIndex;
+ __u16 wLength;
+
+#ifdef DEBUG
+urb_priv.actual_length = 0;
+pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
+#endif
+ if (usb_pipeint(pipe)) {
+ info("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = m16_swap (cmd->value);
+ wIndex = m16_swap (cmd->index);
+ wLength = m16_swap (cmd->length);
+
+ info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
+ dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+ switch (bmRType_bReq) {
+ /* Request Destination:
+ without flags: Device,
+ RH_INTERFACE: interface,
+ RH_ENDPOINT: endpoint,
+ RH_CLASS means HUB here,
+ RH_OTHER | RH_CLASS almost ever means HUB_PORT here
+ */
+
+ case RH_GET_STATUS:
+ *(__u16 *) data_buf = m16_swap (1); OK (2);
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *) data_buf = m16_swap (0); OK (2);
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *) data_buf = m16_swap (0); OK (2);
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *) data_buf = m32_swap (
+ RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+ OK (4);
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4);
+
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ switch (wValue) {
+ case (RH_ENDPOINT_STALL): OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ switch (wValue) {
+ case RH_C_HUB_LOCAL_POWER:
+ OK(0);
+ case (RH_C_HUB_OVER_CURRENT):
+ WR_RH_STAT(RH_HS_OCIC); OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
+ case (RH_C_PORT_CONNECTION):
+ WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
+ case (RH_C_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
+ case (RH_C_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
+ case (RH_C_PORT_OVER_CURRENT):
+ WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
+ case (RH_C_PORT_RESET):
+ WR_RH_PORTSTAT (RH_PS_PRSC); OK (0);
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSS ); OK (0);
+ case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PRS);
+ OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_PPS ); OK (0);
+ case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PES );
+ OK (0);
+ }
+ break;
+
+ case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0);
+
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_dev_des),
+ wLength));
+ data_buf = root_hub_dev_des; OK(len);
+ case (0x02): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_config_des),
+ wLength));
+ data_buf = root_hub_config_des; OK(len);
+ case (0x03): /* string descriptors */
+ if(wValue==0x0300) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index0),
+ wLength));
+ data_buf = root_hub_str_index0;
+ OK(len);
+ }
+ if(wValue==0x0301) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index1),
+ wLength));
+ data_buf = root_hub_str_index1;
+ OK(len);
+ }
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ {
+ __u32 temp = roothub_a (&gohci);
+
+ data_buf [0] = 9; /* min length; */
+ data_buf [1] = 0x29;
+ data_buf [2] = temp & RH_A_NDP;
+ data_buf [3] = 0;
+ if (temp & RH_A_PSM) /* per-port power switching? */
+ data_buf [3] |= 0x1;
+ if (temp & RH_A_NOCP) /* no overcurrent reporting? */
+ data_buf [3] |= 0x10;
+ else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */
+ data_buf [3] |= 0x8;
+
+ /* corresponds to data_buf[4-7] */
+ datab [1] = 0;
+ data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+ temp = roothub_b (&gohci);
+ data_buf [7] = temp & RH_B_DR;
+ if (data_buf [2] < 7) {
+ data_buf [8] = 0xff;
+ } else {
+ data_buf [0] += 2;
+ data_buf [8] = (temp & RH_B_DR) >> 8;
+ data_buf [10] = data_buf [9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data_buf [0], wLength));
+ OK (len);
+ }
+
+ case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1);
+
+ case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0);
+
+ default:
+ dbg ("unsupported root hub command");
+ stat = USB_ST_STALLED;
+ }
+
+#ifdef DEBUG
+ ohci_dump_roothub (&gohci, 1);
+#endif
+
+ len = min_t(int, len, leni);
+ if (data != data_buf)
+ memcpy (data, data_buf, len);
+ dev->act_len = len;
+ dev->status = stat;
+
+#ifdef DEBUG
+ if (transfer_len)
+ urb_priv.actual_length = transfer_len;
+ pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
+#endif
+
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* common code for handling submit messages - used for all but root hub */
+/* accesses. */
+int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, int interval)
+{
+ int stat = 0;
+ int maxsize = usb_maxpacket(dev, pipe);
+ int timeout;
+
+ /* device pulled? Shortcut the action. */
+ if (devgone == dev) {
+ dev->status = USB_ST_CRC_ERR;
+ return 0;
+ }
+
+#ifdef DEBUG
+ urb_priv.actual_length = 0;
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+ if (!maxsize) {
+ err("submit_common_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+
+ if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) {
+ err("sohci_submit_job failed");
+ return -1;
+ }
+
+ /* allow more time for a BULK device to react - some are slow */
+#define BULK_TO 5000 /* timeout in milliseconds */
+ if (usb_pipebulk(pipe))
+ timeout = BULK_TO;
+ else
+ timeout = 100;
+
+ /* wait for it to complete */
+ for (;;) {
+ /* check whether the controller is done */
+ stat = hc_interrupt();
+ if (stat < 0) {
+ stat = USB_ST_CRC_ERR;
+ break;
+ }
+
+ /* NOTE: since we are not interrupt driven in U-Boot and always
+ * handle only one URB at a time, we cannot assume the
+ * transaction finished on the first successful return from
+ * hc_interrupt().. unless the flag for current URB is set,
+ * meaning that all TD's to/from device got actually
+ * transferred and processed. If the current URB is not
+ * finished we need to re-iterate this loop so as
+ * hc_interrupt() gets called again as there needs to be some
+ * more TD's to process still */
+ if ((stat >= 0) && (stat != 0xff) && (urb_finished)) {
+ /* 0xff is returned for an SF-interrupt */
+ break;
+ }
+
+ if (--timeout) {
+ mdelay(1);
+ if (!urb_finished)
+ dbg("\%");
+
+ } else {
+ err("CTL:TIMEOUT ");
+ dbg("submit_common_msg: TO status %x\n", stat);
+ stat = USB_ST_CRC_ERR;
+ urb_finished = 1;
+ break;
+ }
+ }
+#if 0
+ /* we got an Root Hub Status Change interrupt */
+ if (got_rhsc) {
+#ifdef DEBUG
+ ohci_dump_roothub (&gohci, 1);
+#endif
+ got_rhsc = 0;
+ /* abuse timeout */
+ timeout = rh_check_port_status(&gohci);
+ if (timeout >= 0) {
+#if 0 /* this does nothing useful, but leave it here in case that changes */
+ /* the called routine adds 1 to the passed value */
+ usb_hub_port_connect_change(gohci.rh.dev, timeout - 1);
+#endif
+ /*
+ * XXX
+ * This is potentially dangerous because it assumes
+ * that only one device is ever plugged in!
+ */
+ devgone = dev;
+ }
+ }
+#endif
+
+ dev->status = stat;
+ dev->act_len = transfer_len;
+
+#ifdef DEBUG
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
+#endif
+
+ /* free TDs in urb_priv */
+ urb_free_priv (&urb_priv);
+ return 0;
+}
+
+/* submit routines called from usb.c */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len)
+{
+ info("submit_bulk_msg");
+ return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup)
+{
+ int maxsize = usb_maxpacket(dev, pipe);
+
+ info("submit_control_msg");
+#ifdef DEBUG
+ urb_priv.actual_length = 0;
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+ if (!maxsize) {
+ err("submit_control_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+ if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
+ gohci.rh.dev = dev;
+ /* root hub - redirect */
+ return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
+ setup);
+ }
+
+ return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, int interval)
+{
+ info("submit_int_msg");
+ return -1;
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (ohci_t *ohci)
+{
+ int timeout = 30;
+ int smm_timeout = 50; /* 0,5 sec */
+
+ if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+ writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
+ info("USB HC TakeOver from SMM");
+ while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+ mdelay (10);
+ if (--smm_timeout == 0) {
+ err("USB HC TakeOver failed!");
+ return -1;
+ }
+ }
+ }
+
+ /* Disable HC interrupts */
+ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+ dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;",
+ ohci->slot_name,
+ readl (&ohci->regs->control));
+
+ /* Reset USB (needed by some controllers) */
+ ohci->hc_control = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* HC Reset requires max 10 us delay */
+ writel (OHCI_HCR, &ohci->regs->cmdstatus);
+ while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+ if (--timeout == 0) {
+ err("USB HC reset timed out!");
+ return -1;
+ }
+ udelay (1);
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts
+ * connect the virtual root hub */
+
+static int hc_start (ohci_t * ohci)
+{
+ __u32 mask;
+ unsigned int fminterval;
+
+ ohci->disabled = 1;
+
+ /* Tell the controller where the control and bulk lists are
+ * The lists are empty now. */
+
+ writel (0, &ohci->regs->ed_controlhead);
+ writel (0, &ohci->regs->ed_bulkhead);
+
+ writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
+
+ fminterval = 0x2edf;
+ writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+ fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
+ writel (fminterval, &ohci->regs->fminterval);
+ writel (0x628, &ohci->regs->lsthresh);
+
+ /* start controller operations */
+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ ohci->disabled = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* disable all interrupts */
+ mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
+ OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
+ OHCI_INTR_OC | OHCI_INTR_MIE);
+ writel (mask, &ohci->regs->intrdisable);
+ /* clear all interrupts */
+ mask &= ~OHCI_INTR_MIE;
+ writel (mask, &ohci->regs->intrstatus);
+ /* Choose the interrupts we care about now - but w/o MIE */
+ mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+ writel (mask, &ohci->regs->intrenable);
+
+#ifdef OHCI_USE_NPS
+ /* required for AMD-756 and some Mac platforms */
+ writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+ &ohci->regs->roothub.a);
+ writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif /* OHCI_USE_NPS */
+
+ /* POTPGT delay is bits 24-31, in 2 ms units. */
+ mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+
+ /* connect the virtual root hub */
+ ohci->rh.devnum = 0;
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* an interrupt happens */
+
+static int
+hc_interrupt (void)
+{
+ ohci_t *ohci = &gohci;
+ struct ohci_regs *regs = ohci->regs;
+ int ints;
+ int stat = -1;
+
+ if ((ohci->hcca->done_head != 0) &&
+ !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) {
+
+ ints = OHCI_INTR_WDH;
+
+ } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+ ohci->disabled++;
+ err ("%s device removed!", ohci->slot_name);
+ return -1;
+
+ } else if ((ints &= readl (&regs->intrenable)) == 0) {
+ dbg("hc_interrupt: returning..\n");
+ return 0xff;
+ }
+
+ /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
+
+ if (ints & OHCI_INTR_RHSC) {
+ got_rhsc = 1;
+ stat = 0xff;
+ }
+
+ if (ints & OHCI_INTR_UE) {
+ ohci->disabled++;
+ err ("OHCI Unrecoverable Error, controller usb-%s disabled",
+ ohci->slot_name);
+ /* e.g. due to PCI Master/Target Abort */
+
+#ifdef DEBUG
+ ohci_dump (ohci, 1);
+#endif
+ /* FIXME: be optimistic, hope that bug won't repeat often. */
+ /* Make some non-interrupt context restart the controller. */
+ /* Count and limit the retries though; either hardware or */
+ /* software errors can go forever... */
+ hc_reset (ohci);
+ return -1;
+ }
+
+ if (ints & OHCI_INTR_WDH) {
+ writel (OHCI_INTR_WDH, &regs->intrdisable);
+ stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
+ writel (OHCI_INTR_WDH, &regs->intrenable);
+ }
+
+ if (ints & OHCI_INTR_SO) {
+ dbg("USB Schedule overrun\n");
+ writel (OHCI_INTR_SO, &regs->intrenable);
+ stat = -1;
+ }
+
+ /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
+ if (ints & OHCI_INTR_SF) {
+ unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1;
+ mdelay(1);
+ writel (OHCI_INTR_SF, &regs->intrdisable);
+ if (ohci->ed_rm_list[frame] != NULL)
+ writel (OHCI_INTR_SF, &regs->intrenable);
+ stat = 0xff;
+ }
+
+ writel (ints, &regs->intrstatus);
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci (ohci_t *ohci)
+{
+ dbg ("USB HC release ohci usb-%s", ohci->slot_name);
+
+ if (!ohci->disabled)
+ hc_reset (ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(int index, void **controller)
+{
+
+ /* Set the USB Clock */
+ *(vu_long *)MPC5XXX_CDM_48_FDC = CONFIG_USB_CLOCK;
+
+#ifdef CONFIG_PSC3_USB /* USB is using the alternate configuration */
+ /* remove all PSC3 USB bits first before ORing in ours */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00804f00;
+#else
+ /* remove all USB bits first before ORing in ours */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG &= ~0x00807000;
+#endif
+ /* Activate USB port */
+ *(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= CONFIG_USB_CONFIG;
+
+ memset (&gohci, 0, sizeof (ohci_t));
+ memset (&urb_priv, 0, sizeof (urb_priv_t));
+
+ /* align the storage */
+ if ((__u32)&ghcca[0] & 0xff) {
+ err("HCCA not aligned!!");
+ return -1;
+ }
+ phcca = &ghcca[0];
+ info("aligned ghcca %p", phcca);
+ memset(&ohci_dev, 0, sizeof(struct ohci_device));
+ if ((__u32)&ohci_dev.ed[0] & 0x7) {
+ err("EDs not aligned!!");
+ return -1;
+ }
+ memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
+ if ((__u32)gtd & 0x7) {
+ err("TDs not aligned!!");
+ return -1;
+ }
+ ptd = gtd;
+ gohci.hcca = phcca;
+ memset (phcca, 0, sizeof (struct ohci_hcca));
+
+ gohci.disabled = 1;
+ gohci.sleeping = 0;
+ gohci.irq = -1;
+ gohci.regs = (struct ohci_regs *)MPC5XXX_USB;
+
+ gohci.flags = 0;
+ gohci.slot_name = "mpc5200";
+
+ if (hc_reset (&gohci) < 0) {
+ hc_release_ohci (&gohci);
+ return -1;
+ }
+
+ if (hc_start (&gohci) < 0) {
+ err ("can't start usb-%s", gohci.slot_name);
+ hc_release_ohci (&gohci);
+ return -1;
+ }
+
+#ifdef DEBUG
+ ohci_dump (&gohci, 1);
+#endif
+ ohci_inited = 1;
+ urb_finished = 1;
+
+ return 0;
+}
+
+int usb_lowlevel_stop(int index)
+{
+ /* this gets called really early - before the controller has */
+ /* even been initialized! */
+ if (!ohci_inited)
+ return 0;
+ /* TODO release any interrupts, etc. */
+ /* call hc_release_ohci() here ? */
+ hc_reset (&gohci);
+ return 0;
+}
+
+#endif /* CONFIG_USB_OHCI */
diff --git a/arch/powerpc/cpu/mpc5xxx/usb_ohci.h b/arch/powerpc/cpu/mpc5xxx/usb_ohci.h
new file mode 100644
index 0000000..629b529
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/usb_ohci.h
@@ -0,0 +1,418 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * usb-ohci.h
+ */
+
+
+static int cc_to_error[16] = {
+
+/* mapping of the OHCI CC status to error codes */
+ /* No Error */ 0,
+ /* CRC Error */ USB_ST_CRC_ERR,
+ /* Bit Stuff */ USB_ST_BIT_ERR,
+ /* Data Togg */ USB_ST_CRC_ERR,
+ /* Stall */ USB_ST_STALLED,
+ /* DevNotResp */ -1,
+ /* PIDCheck */ USB_ST_BIT_ERR,
+ /* UnExpPID */ USB_ST_BIT_ERR,
+ /* DataOver */ USB_ST_BUF_ERR,
+ /* DataUnder */ USB_ST_BUF_ERR,
+ /* reservd */ -1,
+ /* reservd */ -1,
+ /* BufferOver */ USB_ST_BUF_ERR,
+ /* BuffUnder */ USB_ST_BUF_ERR,
+ /* Not Access */ -1,
+ /* Not Access */ -1
+};
+
+/* ED States */
+
+#define ED_NEW 0x00
+#define ED_UNLINK 0x01
+#define ED_OPER 0x02
+#define ED_DEL 0x04
+#define ED_URB_DEL 0x08
+
+/* usb_ohci_ed */
+struct ed {
+ __u32 hwINFO;
+ __u32 hwTailP;
+ __u32 hwHeadP;
+ __u32 hwNextED;
+
+ struct ed *ed_prev;
+ __u8 int_period;
+ __u8 int_branch;
+ __u8 int_load;
+ __u8 int_interval;
+ __u8 state;
+ __u8 type;
+ __u16 last_iso;
+ struct ed *ed_rm_list;
+
+ struct usb_device *usb_dev;
+ __u32 unused[3];
+} __attribute__((aligned(16)));
+typedef struct ed ed_t;
+
+
+/* TD info field */
+#define TD_CC 0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC 0x0C000000
+#define TD_T 0x03000000
+#define TD_T_DATA0 0x02000000
+#define TD_T_DATA1 0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R 0x00040000
+#define TD_DI 0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP 0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN 0x00100000
+#define TD_DP_OUT 0x00080000
+
+#define TD_ISO 0x00010000
+#define TD_DEL 0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR 0x00
+#define TD_CC_CRC 0x01
+#define TD_CC_BITSTUFFING 0x02
+#define TD_CC_DATATOGGLEM 0x03
+#define TD_CC_STALL 0x04
+#define TD_DEVNOTRESP 0x05
+#define TD_PIDCHECKFAIL 0x06
+#define TD_UNEXPECTEDPID 0x07
+#define TD_DATAOVERRUN 0x08
+#define TD_DATAUNDERRUN 0x09
+#define TD_BUFFEROVERRUN 0x0C
+#define TD_BUFFERUNDERRUN 0x0D
+#define TD_NOTACCESSED 0x0F
+
+
+#define MAXPSW 1
+
+struct td {
+ __u32 hwINFO;
+ __u32 hwCBP; /* Current Buffer Pointer */
+ __u32 hwNextTD; /* Next TD Pointer */
+ __u32 hwBE; /* Memory Buffer End Pointer */
+
+ __u8 unused;
+ __u8 index;
+ struct ed *ed;
+ struct td *next_dl_td;
+ struct usb_device *usb_dev;
+ int transfer_len;
+ __u32 data;
+
+ __u32 unused2[2];
+} __attribute__((aligned(32)));
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP (1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of. It must be 256-byte aligned.
+ */
+
+#define NUM_INTS 32 /* part of the OHCI standard */
+struct ohci_hcca {
+ __u32 int_table[NUM_INTS]; /* Interrupt ED table */
+ __u16 pad1; /* set to 0 on each frame_no change */
+ __u16 frame_no; /* current frame number */
+ __u32 done_head; /* info returned for an interrupt */
+ u8 reserved_for_hc[116];
+} __attribute__((aligned(256)));
+
+
+/*
+ * Maximum number of root hub ports.
+ */
+#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region. This is Memory Mapped I/O. You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+ /* control and status registers */
+ __u32 revision;
+ __u32 control;
+ __u32 cmdstatus;
+ __u32 intrstatus;
+ __u32 intrenable;
+ __u32 intrdisable;
+ /* memory pointers */
+ __u32 hcca;
+ __u32 ed_periodcurrent;
+ __u32 ed_controlhead;
+ __u32 ed_controlcurrent;
+ __u32 ed_bulkhead;
+ __u32 ed_bulkcurrent;
+ __u32 donehead;
+ /* frame counters */
+ __u32 fminterval;
+ __u32 fmremaining;
+ __u32 fmnumber;
+ __u32 periodicstart;
+ __u32 lsthresh;
+ /* Root hub ports */
+ struct ohci_roothub_regs {
+ __u32 a;
+ __u32 b;
+ __u32 status;
+ __u32 portstatus[MAX_ROOT_PORTS];
+ } roothub;
+} __attribute__((aligned(32)));
+
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
+#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
+#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
+#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
+#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
+#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
+#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
+#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
+#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+# define OHCI_USB_RESET (0 << 6)
+# define OHCI_USB_RESUME (1 << 6)
+# define OHCI_USB_OPER (2 << 6)
+# define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR (1 << 0) /* host controller reset */
+#define OHCI_CLF (1 << 1) /* control list filled */
+#define OHCI_BLF (1 << 2) /* bulk list filled */
+#define OHCI_OCR (1 << 3) /* ownership change request */
+#define OHCI_SOC (3 << 16) /* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
+#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
+#define OHCI_INTR_SF (1 << 2) /* start frame */
+#define OHCI_INTR_RD (1 << 3) /* resume detect */
+#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
+#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
+#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
+#define OHCI_INTR_OC (1 << 30) /* ownership change */
+#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
+
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+ int devnum; /* Address of Root Hub endpoint */
+ void *dev; /* was urb */
+ void *int_addr;
+ int send;
+ int interval;
+};
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status*/
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS 0x00000001 /* local power status */
+#define RH_HS_OCI 0x00000002 /* over current indicator */
+#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
+#define RH_HS_LPSC 0x00010000 /* local power status change */
+#define RH_HS_OCIC 0x00020000 /* over current indicator change */
+#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+/* urb */
+#define N_URB_TD 48
+typedef struct
+{
+ ed_t *ed;
+ __u16 length; /* number of tds associated with this request */
+ __u16 td_cnt; /* number of tds already serviced */
+ int state;
+ unsigned long pipe;
+ int actual_length;
+ td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
+} urb_priv_t;
+#define URB_DEL 1
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+
+typedef struct ohci {
+ struct ohci_hcca *hcca; /* hcca */
+ /*dma_addr_t hcca_dma;*/
+
+ int irq;
+ int disabled; /* e.g. got a UE, we're hung */
+ int sleeping;
+ unsigned long flags; /* for HC bugs */
+
+ struct ohci_regs *regs; /* OHCI controller's memory */
+
+ ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
+ ed_t *ed_bulktail; /* last endpoint of bulk list */
+ ed_t *ed_controltail; /* last endpoint of control list */
+ int intrstatus;
+ __u32 hc_control; /* copy of the hc control reg */
+ struct usb_device *dev[32];
+ struct virt_root_hub rh;
+
+ const char *slot_name;
+} ohci_t;
+
+#define NUM_EDS 8 /* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+ ed_t ed[NUM_EDS];
+ int ed_cnt;
+};
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe);
+
+/*-------------------------------------------------------------------------*/
+
+/* we need more TDs than EDs */
+#define NUM_TD 64
+
+/* +1 so we can align the storage */
+td_t gtd[NUM_TD+1];
+/* pointers to aligned storage */
+td_t *ptd;
+
+/* TDs ... */
+static inline struct td *
+td_alloc (struct usb_device *usb_dev)
+{
+ int i;
+ struct td *td;
+
+ td = NULL;
+ for (i = 0; i < NUM_TD; i++)
+ {
+ if (ptd[i].usb_dev == NULL)
+ {
+ td = &ptd[i];
+ td->usb_dev = usb_dev;
+ break;
+ }
+ }
+
+ return td;
+}
+
+static inline void
+ed_free (struct ed *ed)
+{
+ ed->usb_dev = NULL;
+}
diff --git a/arch/powerpc/cpu/mpc824x/.gitignore b/arch/powerpc/cpu/mpc824x/.gitignore
new file mode 100644
index 0000000..2d79931
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/.gitignore
@@ -0,0 +1 @@
+/bedbug_603e.c
diff --git a/arch/powerpc/cpu/mpc824x/Makefile b/arch/powerpc/cpu/mpc824x/Makefile
new file mode 100644
index 0000000..ebf4cb2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/Makefile
@@ -0,0 +1,55 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+ifneq ($(OBJTREE),$(SRCTREE))
+$(shell mkdir -p $(obj)drivers/epic $(obj)drivers/i2c)
+endif
+
+LIB = $(obj)lib$(CPU).o
+
+START = start.o
+COBJS = traps.o cpu.o cpu_init.o interrupts.o speed.o \
+ drivers/epic/epic1.o drivers/i2c/i2c.o pci.o
+COBJS_LN = bedbug_603e.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) $(addprefix $(obj),$(COBJS_LN:.o=.c))
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS) $(COBJS_LN))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+$(obj)bedbug_603e.c:
+ ln -sf $(src)../mpc8260/bedbug_603e.c $(obj)bedbug_603e.c
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc824x/config.mk b/arch/powerpc/cpu/mpc824x/config.mk
new file mode 100644
index 0000000..82b8cc6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2000-2010
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC824X -ffixed-r2 -mstring -mcpu=603e -msoft-float
diff --git a/arch/powerpc/cpu/mpc824x/cpu.c b/arch/powerpc/cpu/mpc824x/cpu.c
new file mode 100644
index 0000000..44f91b2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/cpu.c
@@ -0,0 +1,280 @@
+/*
+ * (C) Copyright 2000 - 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <mpc824x.h>
+#include <common.h>
+#include <command.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu (void)
+{
+ unsigned int pvr = get_pvr ();
+ unsigned int version = pvr >> 16;
+ unsigned char revision;
+ ulong clock = gd->cpu_clk;
+ char buf[32];
+
+ puts ("CPU: ");
+
+ switch (version) {
+ case CPU_TYPE_8240:
+ puts ("MPC8240");
+ break;
+
+ case CPU_TYPE_8245:
+ puts ("MPC8245");
+ break;
+
+ default:
+ return -1; /*not valid for this source */
+ }
+
+ CONFIG_READ_BYTE (REVID, revision);
+
+ if (revision) {
+ printf (" Revision %d.%d",
+ (revision & 0xf0) >> 4,
+ (revision & 0x0f));
+ } else {
+ return -1; /* no valid CPU revision info */
+ }
+
+ printf (" at %s MHz:", strmhz (buf, clock));
+
+ printf (" %u kB I-Cache", checkicache () >> 10);
+ printf (" %u kB D-Cache", checkdcache () >> 10);
+
+ puts ("\n");
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache */
+
+int checkicache (void)
+{
+ /*TODO*/
+ return 128 * 4 * 32;
+};
+
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache */
+
+int checkdcache (void)
+{
+ /*TODO*/
+ return 128 * 4 * 32;
+
+};
+
+/*------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong msr, addr;
+
+ /* Interrupts and MMU off */
+ __asm__ ("mtspr 81, 0");
+
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~0x1030;
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /*
+ * Trying to execute the next instruction at a non-existing address
+ * should cause a machine check, resulting in reset
+ */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+ addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+ /*
+ * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address,
+ * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid
+ * address. Better pick an address known to be invalid on
+ * your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+ * "(ulong)-1" used to be a good choice for many systems...
+ */
+ addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+ ((void (*)(void)) addr) ();
+ return 1;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ * This is the sys_logic_clk (memory bus) divided by 4
+ */
+unsigned long get_tbclk (void)
+{
+ return ((get_bus_freq (0) + 2L) / 4L);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The MPC824x has an integrated PCI controller known as the MPC107.
+ * The following are MPC107 Bridge Controller and PCI Support functions
+ *
+ */
+
+/*
+ * This procedure reads a 32-bit address MPC107 register, and returns
+ * a 32 bit value. It swaps the address to little endian before
+ * writing it to config address, and swaps the value to big endian
+ * before returning to the caller.
+ */
+unsigned int mpc824x_mpc107_getreg (unsigned int regNum)
+{
+ unsigned int temp;
+
+ /* swap the addr. to little endian */
+ *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
+ temp = *(volatile unsigned int *) CHRP_REG_DATA;
+ return PCISWAP (temp); /* swap the data upon return */
+}
+
+/*
+ * This procedure writes a 32-bit address MPC107 register. It swaps
+ * the address to little endian before writing it to config address.
+ */
+
+void mpc824x_mpc107_setreg (unsigned int regNum, unsigned int regVal)
+{
+ /* swap the addr. to little endian */
+ *(volatile unsigned int *) CHRP_REG_ADDR = PCISWAP (regNum);
+ *(volatile unsigned int *) CHRP_REG_DATA = PCISWAP (regVal);
+ return;
+}
+
+
+/*
+ * Write a byte (8 bits) to a memory location.
+ */
+void mpc824x_mpc107_write8 (unsigned int addr, unsigned char data)
+{
+ *(unsigned char *) addr = data;
+ __asm__ ("sync");
+}
+
+/*
+ * Write a word (16 bits) to a memory location after the value
+ * has been byte swapped (big to little endian or vice versa)
+ */
+
+void mpc824x_mpc107_write16 (unsigned int address, unsigned short data)
+{
+ *(volatile unsigned short *) address = BYTE_SWAP_16_BIT (data);
+ __asm__ ("sync");
+}
+
+/*
+ * Write a long word (32 bits) to a memory location after the value
+ * has been byte swapped (big to little endian or vice versa)
+ */
+
+void mpc824x_mpc107_write32 (unsigned int address, unsigned int data)
+{
+ *(volatile unsigned int *) address = LONGSWAP (data);
+ __asm__ ("sync");
+}
+
+/*
+ * Read a byte (8 bits) from a memory location.
+ */
+unsigned char mpc824x_mpc107_read8 (unsigned int addr)
+{
+ return *(volatile unsigned char *) addr;
+}
+
+
+/*
+ * Read a word (16 bits) from a memory location, and byte swap the
+ * value before returning to the caller.
+ */
+unsigned short mpc824x_mpc107_read16 (unsigned int address)
+{
+ unsigned short retVal;
+
+ retVal = BYTE_SWAP_16_BIT (*(unsigned short *) address);
+ return retVal;
+}
+
+
+/*
+ * Read a long word (32 bits) from a memory location, and byte
+ * swap the value before returning to the caller.
+ */
+unsigned int mpc824x_mpc107_read32 (unsigned int address)
+{
+ unsigned int retVal;
+
+ retVal = LONGSWAP (*(unsigned int *) address);
+ return (retVal);
+}
+
+
+/*
+ * Read a register in the Embedded Utilities Memory Block address
+ * space.
+ * Input: regNum - register number + utility base address. Example,
+ * the base address of EPIC is 0x40000, the register number
+ * being passed is 0x40000+the address of the target register.
+ * (See epic.h for register addresses).
+ * Output: The 32 bit little endian value of the register.
+ */
+
+unsigned int mpc824x_eummbar_read (unsigned int regNum)
+{
+ unsigned int temp;
+
+ temp = *(volatile unsigned int *) (EUMBBAR_VAL + regNum);
+ temp = PCISWAP (temp);
+ return temp;
+}
+
+
+/*
+ * Write a value to a register in the Embedded Utilities Memory
+ * Block address space.
+ * Input: regNum - register number + utility base address. Example,
+ * the base address of EPIC is 0x40000, the register
+ * number is 0x40000+the address of the target register.
+ * (See epic.h for register addresses).
+ * regVal - value to be written to the register.
+ */
+
+void mpc824x_eummbar_write (unsigned int regNum, unsigned int regVal)
+{
+ *(volatile unsigned int *) (EUMBBAR_VAL + regNum) = PCISWAP (regVal);
+ return;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/mpc824x/cpu_init.c b/arch/powerpc/cpu/mpc824x/cpu_init.c
new file mode 100644
index 0000000..cfc665d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/cpu_init.c
@@ -0,0 +1,417 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor. Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <mpc824x.h>
+
+#ifndef CONFIG_SYS_BANK0_ROW
+#define CONFIG_SYS_BANK0_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK1_ROW
+#define CONFIG_SYS_BANK1_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK2_ROW
+#define CONFIG_SYS_BANK2_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK3_ROW
+#define CONFIG_SYS_BANK3_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK4_ROW
+#define CONFIG_SYS_BANK4_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK5_ROW
+#define CONFIG_SYS_BANK5_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK6_ROW
+#define CONFIG_SYS_BANK6_ROW 0
+#endif
+#ifndef CONFIG_SYS_BANK7_ROW
+#define CONFIG_SYS_BANK7_ROW 0
+#endif
+#ifndef CONFIG_SYS_DBUS_SIZE2
+#define CONFIG_SYS_DBUS_SIZE2 0
+#endif
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ */
+void
+cpu_init_f (void)
+{
+/* MOUSSE board is initialized in asm */
+#if !defined(CONFIG_MOUSSE)
+ register unsigned long val;
+ CONFIG_WRITE_HALFWORD(PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/
+/* CONFIG_WRITE_HALFWORD(PCISR, 0xffff); */ /*reset PCISR*/
+
+#if defined(CONFIG_MUSENKI) || defined(CONFIG_PN62)
+/* Why is this here, you ask? Try, just try setting 0x8000
+ * in PCIACR with CONFIG_WRITE_HALFWORD()
+ * this one was a stumper, and we are annoyed
+ */
+
+#define M_CONFIG_WRITE_HALFWORD( addr, data ) \
+ __asm__ __volatile__(" \
+ stw %2,0(%0)\n \
+ sync\n \
+ sth %3,2(%1)\n \
+ sync\n \
+ " \
+ : /* no output */ \
+ : "r" (CONFIG_ADDR), "r" (CONFIG_DATA), \
+ "r" (PCISWAP(addr & ~3)), "r" (PCISWAP(data << 16)) \
+ );
+
+ M_CONFIG_WRITE_HALFWORD(PCIACR, 0x8000);
+#endif
+
+ CONFIG_WRITE_BYTE(PCLSR, 0x8); /* set PCI cache line size */
+ CONFIG_WRITE_BYTE (PLTR, 0x40); /* set PCI latency timer */
+ /*
+ * Note that although this bit is cleared after a hard reset, it
+ * must be explicitly set and then cleared by software during
+ * initialization in order to guarantee correct operation of the
+ * DLL and the SDRAM_CLK[0:3] signals (if they are used).
+ */
+ CONFIG_READ_BYTE (AMBOR, val);
+ CONFIG_WRITE_BYTE(AMBOR, val & 0xDF);
+ CONFIG_WRITE_BYTE(AMBOR, val | 0x20);
+ CONFIG_WRITE_BYTE(AMBOR, val & 0xDF);
+#ifdef CONFIG_MPC8245
+ /* silicon bug 28 MPC8245 */
+ CONFIG_READ_BYTE(AMBOR,val);
+ CONFIG_WRITE_BYTE(AMBOR,val|0x1);
+
+#if 0
+ /*
+ * The following bug only affects older (XPC8245) processors.
+ * DMA transfers initiated by external devices get corrupted due
+ * to a hardware scheduling problem.
+ *
+ * The effect is:
+ * when transferring X words, the first 32 words are transferred
+ * OK, the next 3 x 32 words are 'old' data (from previous DMA)
+ * while the rest of the X words is xferred fine.
+ *
+ * Disabling 3 of the 4 32 word hardware buffers solves the problem
+ * with no significant performance loss.
+ */
+
+ CONFIG_READ_BYTE(PCMBCR,val);
+ /* in order not to corrupt data which is being read over the PCI bus
+ * with the PPC as slave, we need to reduce the number of PCMRBs to 1,
+ * 4.11 in the processor user manual
+ * */
+
+#if 1
+ CONFIG_WRITE_BYTE(PCMBCR,(val|0xC0)); /* 1 PCMRB */
+#else
+ CONFIG_WRITE_BYTE(PCMBCR,(val|0x80)); /* 2 PCMRBs */
+ CONFIG_WRITE_BYTE(PCMBCR,(val|0x40)); /* 3 PCMRBs */
+ /* default, 4 PCMRBs are used */
+#endif
+#endif
+#endif
+
+ CONFIG_READ_WORD(PICR1, val);
+#if defined(CONFIG_MPC8240)
+ CONFIG_WRITE_WORD( PICR1,
+ (val & (PICR1_ADDRESS_MAP | PICR1_RCS0)) |
+ PIRC1_MSK | PICR1_PROC_TYPE_603E |
+ PICR1_FLASH_WR_EN | PICR1_MCP_EN |
+ PICR1_CF_DPARK | PICR1_EN_PCS |
+ PICR1_CF_APARK );
+#elif defined(CONFIG_MPC8245)
+ CONFIG_WRITE_WORD( PICR1,
+ (val & (PICR1_RCS0)) |
+ PICR1_PROC_TYPE_603E |
+ PICR1_FLASH_WR_EN | PICR1_MCP_EN |
+ PICR1_CF_DPARK | PICR1_NO_BUSW_CK |
+ PICR1_DEC| PICR1_CF_APARK | 0x10); /* 8245 UM says bit 4 must be set */
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+ CONFIG_READ_WORD(PICR2, val);
+ val= val & ~ (PICR2_CF_SNOOP_WS_MASK | PICR2_CF_APHASE_WS_MASK); /*mask off waitstate bits*/
+#ifndef CONFIG_PN62
+ val |= PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS; /*1 wait state*/
+#endif
+ CONFIG_WRITE_WORD(PICR2, val);
+
+ CONFIG_WRITE_WORD(EUMBBAR, CONFIG_SYS_EUMB_ADDR);
+#ifndef CONFIG_SYS_RAMBOOT
+ CONFIG_WRITE_WORD(MCCR1, (CONFIG_SYS_ROMNAL << MCCR1_ROMNAL_SHIFT) |
+ (CONFIG_SYS_BANK0_ROW) |
+ (CONFIG_SYS_BANK1_ROW << MCCR1_BANK1ROW_SHIFT) |
+ (CONFIG_SYS_BANK2_ROW << MCCR1_BANK2ROW_SHIFT) |
+ (CONFIG_SYS_BANK3_ROW << MCCR1_BANK3ROW_SHIFT) |
+ (CONFIG_SYS_BANK4_ROW << MCCR1_BANK4ROW_SHIFT) |
+ (CONFIG_SYS_BANK5_ROW << MCCR1_BANK5ROW_SHIFT) |
+ (CONFIG_SYS_BANK6_ROW << MCCR1_BANK6ROW_SHIFT) |
+ (CONFIG_SYS_BANK7_ROW << MCCR1_BANK7ROW_SHIFT) |
+ (CONFIG_SYS_ROMFAL << MCCR1_ROMFAL_SHIFT));
+#endif
+
+#if defined(CONFIG_SYS_ASRISE) && defined(CONFIG_SYS_ASFALL)
+ CONFIG_WRITE_WORD(MCCR2, CONFIG_SYS_REFINT << MCCR2_REFINT_SHIFT |
+ CONFIG_SYS_ASRISE << MCCR2_ASRISE_SHIFT |
+ CONFIG_SYS_ASFALL << MCCR2_ASFALL_SHIFT);
+#else
+ CONFIG_WRITE_WORD(MCCR2, CONFIG_SYS_REFINT << MCCR2_REFINT_SHIFT);
+#endif
+
+#if defined(CONFIG_MPC8240)
+ CONFIG_WRITE_WORD(MCCR3,
+ (((CONFIG_SYS_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) |
+ (CONFIG_SYS_REFREC << MCCR3_REFREC_SHIFT) |
+ (CONFIG_SYS_RDLAT << MCCR3_RDLAT_SHIFT));
+#elif defined(CONFIG_MPC8245)
+ CONFIG_WRITE_WORD(MCCR3,
+ (((CONFIG_SYS_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) |
+ (CONFIG_SYS_REFREC << MCCR3_REFREC_SHIFT));
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+/* this is gross. We think these should all be the same, and various boards
+ * should define CONFIG_SYS_ACTORW to 0 if they don't want to set it, or even, if
+ * its not set, we define it to zero in this file
+ */
+#if defined(CONFIG_CU824) || defined(CONFIG_PN62)
+ CONFIG_WRITE_WORD(MCCR4,
+ (CONFIG_SYS_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+ (CONFIG_SYS_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+ MCCR4_BIT21 |
+ (CONFIG_SYS_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+ ((CONFIG_SYS_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+ (((CONFIG_SYS_SDMODE_CAS_LAT <<4) | (CONFIG_SYS_SDMODE_WRAP <<3) |
+ CONFIG_SYS_SDMODE_BURSTLEN) << MCCR4_SDMODE_SHIFT) |
+ (CONFIG_SYS_ACTORW << MCCR4_ACTTORW_SHIFT) |
+ (((CONFIG_SYS_BSTOPRE & 0x03c0) >> 6) << MCCR4_BSTOPRE6TO9_SHIFT));
+#elif defined(CONFIG_MPC8240)
+ CONFIG_WRITE_WORD(MCCR4,
+ (CONFIG_SYS_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+ (CONFIG_SYS_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+ MCCR4_BIT21 |
+ (CONFIG_SYS_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+ ((CONFIG_SYS_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+ (((CONFIG_SYS_SDMODE_CAS_LAT <<4) | (CONFIG_SYS_SDMODE_WRAP <<3) |
+ (CONFIG_SYS_SDMODE_BURSTLEN)) <<MCCR4_SDMODE_SHIFT) |
+ (((CONFIG_SYS_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT ));
+#elif defined(CONFIG_MPC8245)
+ CONFIG_READ_WORD(MCCR1, val);
+ val &= MCCR1_DBUS_SIZE0; /* test for 64-bit mem bus */
+
+ CONFIG_WRITE_WORD(MCCR4,
+ (CONFIG_SYS_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+ (CONFIG_SYS_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+ (CONFIG_SYS_EXTROM ? MCCR4_EXTROM : 0) |
+ (CONFIG_SYS_REGDIMM ? MCCR4_REGDIMM : 0) |
+ (CONFIG_SYS_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+ ((CONFIG_SYS_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+ (CONFIG_SYS_DBUS_SIZE2 << MCCR4_DBUS_SIZE2_SHIFT) |
+ (((CONFIG_SYS_SDMODE_CAS_LAT <<4) | (CONFIG_SYS_SDMODE_WRAP <<3) |
+ (val ? 2 : 3)) << MCCR4_SDMODE_SHIFT) |
+ (CONFIG_SYS_ACTORW << MCCR4_ACTTORW_SHIFT) |
+ (((CONFIG_SYS_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT ));
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+
+ CONFIG_WRITE_WORD(MSAR1,
+ ( (CONFIG_SYS_BANK0_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+ (((CONFIG_SYS_BANK1_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK2_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK3_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+ CONFIG_WRITE_WORD(EMSAR1,
+ ( (CONFIG_SYS_BANK0_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+ (((CONFIG_SYS_BANK1_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK2_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK3_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+ CONFIG_WRITE_WORD(MSAR2,
+ ( (CONFIG_SYS_BANK4_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+ (((CONFIG_SYS_BANK5_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK6_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK7_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+ CONFIG_WRITE_WORD(EMSAR2,
+ ( (CONFIG_SYS_BANK4_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+ (((CONFIG_SYS_BANK5_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK6_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK7_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+ CONFIG_WRITE_WORD(MEAR1,
+ ( (CONFIG_SYS_BANK0_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+ (((CONFIG_SYS_BANK1_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK2_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK3_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+ CONFIG_WRITE_WORD(EMEAR1,
+ ( (CONFIG_SYS_BANK0_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+ (((CONFIG_SYS_BANK1_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK2_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK3_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+ CONFIG_WRITE_WORD(MEAR2,
+ ( (CONFIG_SYS_BANK4_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) |
+ (((CONFIG_SYS_BANK5_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK6_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK7_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24));
+ CONFIG_WRITE_WORD(EMEAR2,
+ ( (CONFIG_SYS_BANK4_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) |
+ (((CONFIG_SYS_BANK5_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) |
+ (((CONFIG_SYS_BANK6_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) |
+ (((CONFIG_SYS_BANK7_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24));
+
+ CONFIG_WRITE_BYTE(ODCR, CONFIG_SYS_ODCR);
+#ifdef CONFIG_SYS_DLL_MAX_DELAY
+ CONFIG_WRITE_BYTE(MIOCR1, CONFIG_SYS_DLL_MAX_DELAY); /* needed to make DLL lock */
+#endif
+#if defined(CONFIG_SYS_DLL_EXTEND) && defined(CONFIG_SYS_PCI_HOLD_DEL)
+ CONFIG_WRITE_BYTE(PMCR2, CONFIG_SYS_DLL_EXTEND | CONFIG_SYS_PCI_HOLD_DEL);
+#endif
+#if defined(MIOCR2) && defined(CONFIG_SYS_SDRAM_DSCD)
+ CONFIG_WRITE_BYTE(MIOCR2, CONFIG_SYS_SDRAM_DSCD); /* change memory input */
+#endif /* setup & hold time */
+
+ CONFIG_WRITE_BYTE(MBER,
+ CONFIG_SYS_BANK0_ENABLE |
+ (CONFIG_SYS_BANK1_ENABLE << 1) |
+ (CONFIG_SYS_BANK2_ENABLE << 2) |
+ (CONFIG_SYS_BANK3_ENABLE << 3) |
+ (CONFIG_SYS_BANK4_ENABLE << 4) |
+ (CONFIG_SYS_BANK5_ENABLE << 5) |
+ (CONFIG_SYS_BANK6_ENABLE << 6) |
+ (CONFIG_SYS_BANK7_ENABLE << 7));
+
+#ifdef CONFIG_SYS_PGMAX
+ CONFIG_WRITE_BYTE(MPMR, CONFIG_SYS_PGMAX);
+#endif
+
+ /* ! Wait 200us before initialize other registers */
+ /*FIXME: write a decent udelay wait */
+ __asm__ __volatile__(
+ " mtctr %0 \n \
+ 0: bdnz 0b\n"
+ :
+ : "r" (0x10000));
+
+ CONFIG_READ_WORD(MCCR1, val);
+ CONFIG_WRITE_WORD(MCCR1, val | MCCR1_MEMGO); /* set memory access going */
+ __asm__ __volatile__("eieio");
+
+#endif /* !CONFIG_MOUSSE */
+}
+
+
+#ifdef CONFIG_MOUSSE
+#ifdef INCLUDE_MPC107_REPORT
+struct MPC107_s {
+ unsigned int iobase;
+ char desc[120];
+} MPC107Regs[] = {
+ { BMC_BASE + 0x00, "MPC107 Vendor/Device ID" },
+ { BMC_BASE + 0x04, "MPC107 PCI Command/Status Register" },
+ { BMC_BASE + 0x08, "MPC107 Revision" },
+ { BMC_BASE + 0x0C, "MPC107 Cache Line Size" },
+ { BMC_BASE + 0x10, "MPC107 LMBAR" },
+ { BMC_BASE + 0x14, "MPC824x PCSR" },
+ { BMC_BASE + 0xA8, "MPC824x PICR1" },
+ { BMC_BASE + 0xAC, "MPC824x PICR2" },
+ { BMC_BASE + 0x46, "MPC824x PACR" },
+ { BMC_BASE + 0x310, "MPC824x ITWR" },
+ { BMC_BASE + 0x300, "MPC824x OMBAR" },
+ { BMC_BASE + 0x308, "MPC824x OTWR" },
+ { BMC_BASE + 0x14, "MPC107 Peripheral Control and Status Register" },
+ { BMC_BASE + 0x78, "MPC107 EUMBAR" },
+ { BMC_BASE + 0xC0, "MPC107 Processor Bus Error Status" },
+ { BMC_BASE + 0xC4, "MPC107 PCI Bus Error Status" },
+ { BMC_BASE + 0xC8, "MPC107 Processor/PCI Error Address" },
+ { BMC_BASE + 0xE0, "MPC107 AMBOR Register" },
+ { BMC_BASE + 0xF0, "MPC107 MCCR1 Register" },
+ { BMC_BASE + 0xF4, "MPC107 MCCR2 Register" },
+ { BMC_BASE + 0xF8, "MPC107 MCCR3 Register" },
+ { BMC_BASE + 0xFC, "MPC107 MCCR4 Register" },
+};
+#define N_MPC107_Regs (sizeof(MPC107Regs)/sizeof(MPC107Regs[0]))
+#endif /* INCLUDE_MPC107_REPORT */
+#endif /* CONFIG_MOUSSE */
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+#ifdef CONFIG_MOUSSE
+#ifdef INCLUDE_MPC107_REPORT
+ unsigned int tmp = 0, i;
+#endif
+ /*
+ * Initialize the EUMBBAR (Embedded Util Mem Block Base Addr Reg).
+ * This is necessary before the EPIC, DMA ctlr, I2C ctlr, etc. can
+ * be accessed.
+ */
+
+#ifdef CONFIG_MPC8240 /* only on MPC8240 */
+ mpc824x_mpc107_setreg (EUMBBAR, EUMBBAR_VAL);
+ /* MOT/SPS: Issue #10002, PCI (FD Alias enable) */
+ mpc824x_mpc107_setreg (AMBOR, 0x000000C0);
+#endif
+
+
+#ifdef INCLUDE_MPC107_REPORT
+ /* Check MPC824x PCI Device and Vendor ID */
+ while ((tmp = mpc824x_mpc107_getreg (BMC_BASE)) != 0x31057) {
+ printf (" MPC107: offset=0x%x, val = 0x%x\n",
+ BMC_BASE,
+ tmp);
+ }
+
+ for (i = 0; i < N_MPC107_Regs; i++) {
+ printf (" 0x%x/%s = 0x%x\n",
+ MPC107Regs[i].iobase,
+ MPC107Regs[i].desc,
+ mpc824x_mpc107_getreg (MPC107Regs[i].iobase));
+ }
+
+ printf ("IBAT0L = 0x%08X\n", mfspr (IBAT0L));
+ printf ("IBAT0U = 0x%08X\n", mfspr (IBAT0U));
+ printf ("IBAT1L = 0x%08X\n", mfspr (IBAT1L));
+ printf ("IBAT1U = 0x%08X\n", mfspr (IBAT1U));
+ printf ("IBAT2L = 0x%08X\n", mfspr (IBAT2L));
+ printf ("IBAT2U = 0x%08X\n", mfspr (IBAT2U));
+ printf ("IBAT3L = 0x%08X\n", mfspr (IBAT3L));
+ printf ("IBAT3U = 0x%08X\n", mfspr (IBAT3U));
+ printf ("DBAT0L = 0x%08X\n", mfspr (DBAT0L));
+ printf ("DBAT0U = 0x%08X\n", mfspr (DBAT0U));
+ printf ("DBAT1L = 0x%08X\n", mfspr (DBAT1L));
+ printf ("DBAT1U = 0x%08X\n", mfspr (DBAT1U));
+ printf ("DBAT2L = 0x%08X\n", mfspr (DBAT2L));
+ printf ("DBAT2U = 0x%08X\n", mfspr (DBAT2U));
+ printf ("DBAT3L = 0x%08X\n", mfspr (DBAT3L));
+ printf ("DBAT3U = 0x%08X\n", mfspr (DBAT3U));
+#endif /* INCLUDE_MPC107_REPORT */
+#endif /* CONFIG_MOUSSE */
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic.h b/arch/powerpc/cpu/mpc824x/drivers/epic.h
new file mode 100644
index 0000000..2803f63
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic.h
@@ -0,0 +1 @@
+#include "epic/epic.h"
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/README b/arch/powerpc/cpu/mpc824x/drivers/epic/README
new file mode 100644
index 0000000..5798996
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/README
@@ -0,0 +1,102 @@
+CONTENT:
+
+ epic.h
+ epic1.c
+ epic2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) EPIC
+driver routines. The driver routines are not
+written for any specific operating system.
+They serves the purpose of code sample, and
+jump-start for using the MPC8240 EPIC unit.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240
+ shall link the files listed here. The memory
+ location of driver routines shall take into
+ account of that driver routines need to run
+ in supervisor mode and they process external
+ interrupts.
+
+ The routine epic_exception shall be called by
+ exception vector at location 0x500, i.e.,
+ 603e core external exception vector.
+
+2. The host system is responsible for configuring
+ the MPC8240 including Embedded Utilities Memory
+ Block. All EPIC driver functions require the
+ content of Embedded Utilities Memory Block
+ Base Address Register, EUMBBAR, as the first
+ parameter.
+
+3. Before EPIC unit of MPC8240 can be used,
+ initialize EPIC unit by calling epicInit
+ with the corresponding parameters.
+
+ The initialization shall disable the 603e
+ core External Exception by calling CoreExtIntDisable( ).
+ Next, call epicInit( ). Last, enable the 603e core
+ External Exception by calling CoreExtIntEnable( ).
+
+4. After EPIC unit has been successfully initialized,
+ epicIntSourceSet( ) shall be used to register each
+ external interrupt source. Anytime, an external
+ interrupt source can be disabled or enabled by
+ calling corresponding function, epicIntDisable( ),
+ or epicIntEnable( ).
+
+ Global Timers' resource, base count and frequency,
+ can be changed by calling epicTmFrequencySet( )
+ and epicTmBaseSet( ).
+
+ To stop counting a specific global timer, use
+ the function, epicTmInhibit while epicTmEnable
+ can be used to start counting a timer.
+
+5. To mask a set of external interrupts that are
+ are certain level below, epicIntPrioritySet( )
+ can be used. For example, if the processor's
+ current task priority register is set to 0x7,
+ only interrupts of priority 0x8 or higher will
+ be passed to the processor.
+
+ Be careful when using this function. It may
+ corrupt the current interrupt pending, selector,
+ and request registers, resulting an invalid vetor.
+
+ After enabling an interrupt, disable it may also
+ cause an invalid vector. User may consider using
+ the spurious vector interrupt service routine to
+ handle this case.
+
+6. The EPIC driver routines contains a set
+ of utilities, Set and Get, for host system
+ to query and modify the desired EPIC source
+ registers.
+
+7. Each external interrupt source shall register
+ its interrupt service routine. The routine
+ shall contain all interrupt source specific
+ processes and keep as short as possible.
+
+ Special customized end of interrupt routine
+ is optional. If it is needed, it shall contain
+ the external interrupt source specific end of
+ interrupt process.
+
+ External interrupt exception vector at 0x500
+ shall always call the epicEOI just before
+ rfi instruction. Refer to the routine,
+ epic_exception, for a code sample.
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h b/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h
new file mode 100644
index 0000000..58f81c5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic.h
@@ -0,0 +1,163 @@
+/*********************************************************************
+ * mpc8240epic.h - EPIC module of the MPC8240 micro-controller
+ *
+ * Copyrigh 1999 Motorola Inc.
+ *
+ * Modification History:
+ * =====================
+ * 01a,04Feb99,My Created.
+ * 15Nov200, robt -modified to use in U-Boot
+ *
+*/
+
+#ifndef __INCEPICh
+#define __INCEPICh
+
+#define ULONG unsigned long
+#define MAXVEC 20
+#define MAXIRQ 5 /* IRQs */
+#define EPIC_DIRECT_IRQ 0 /* Direct interrupt type */
+
+/* EPIC register addresses */
+
+#define EPIC_EUMBBAR 0x40000 /* EUMBBAR of EPIC */
+#define EPIC_FEATURES_REG (EPIC_EUMBBAR + 0x01000)/* Feature reporting */
+#define EPIC_GLOBAL_REG (EPIC_EUMBBAR + 0x01020)/* Global config. */
+#define EPIC_INT_CONF_REG (EPIC_EUMBBAR + 0x01030)/* Interrupt config. */
+#define EPIC_VENDOR_ID_REG (EPIC_EUMBBAR + 0x01080)/* Vendor id */
+#define EPIC_PROC_INIT_REG (EPIC_EUMBBAR + 0x01090)/* Processor init. */
+#define EPIC_SPUR_VEC_REG (EPIC_EUMBBAR + 0x010e0)/* Spurious vector */
+#define EPIC_TM_FREQ_REG (EPIC_EUMBBAR + 0x010f0)/* Timer Frequency */
+
+#define EPIC_TM0_CUR_COUNT_REG (EPIC_EUMBBAR + 0x01100)/* Gbl TM0 Cur. Count*/
+#define EPIC_TM0_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01110)/* Gbl TM0 Base Count*/
+#define EPIC_TM0_VEC_REG (EPIC_EUMBBAR + 0x01120)/* Gbl TM0 Vector Pri*/
+#define EPIC_TM0_DES_REG (EPIC_EUMBBAR + 0x01130)/* Gbl TM0 Dest. */
+
+#define EPIC_TM1_CUR_COUNT_REG (EPIC_EUMBBAR + 0x01140)/* Gbl TM1 Cur. Count*/
+#define EPIC_TM1_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01150)/* Gbl TM1 Base Count*/
+#define EPIC_TM1_VEC_REG (EPIC_EUMBBAR + 0x01160)/* Gbl TM1 Vector Pri*/
+#define EPIC_TM1_DES_REG (EPIC_EUMBBAR + 0x01170)/* Gbl TM1 Dest. */
+
+#define EPIC_TM2_CUR_COUNT_REG (EPIC_EUMBBAR + 0x01180)/* Gbl TM2 Cur. Count*/
+#define EPIC_TM2_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01190)/* Gbl TM2 Base Count*/
+#define EPIC_TM2_VEC_REG (EPIC_EUMBBAR + 0x011a0)/* Gbl TM2 Vector Pri*/
+#define EPIC_TM2_DES_REG (EPIC_EUMBBAR + 0x011b0)/* Gbl TM2 Dest */
+
+#define EPIC_TM3_CUR_COUNT_REG (EPIC_EUMBBAR + 0x011c0)/* Gbl TM3 Cur. Count*/
+#define EPIC_TM3_BASE_COUNT_REG (EPIC_EUMBBAR + 0x011d0)/* Gbl TM3 Base Count*/
+#define EPIC_TM3_VEC_REG (EPIC_EUMBBAR + 0x011e0)/* Gbl TM3 Vector Pri*/
+#define EPIC_TM3_DES_REG (EPIC_EUMBBAR + 0x011f0)/* Gbl TM3 Dest. */
+
+#define EPIC_EX_INT0_VEC_REG (EPIC_EUMBBAR + 0x10200)/* Ext. Int. Sr0 Des */
+#define EPIC_EX_INT0_DES_REG (EPIC_EUMBBAR + 0x10210)/* Ext. Int. Sr0 Vect*/
+#define EPIC_EX_INT1_VEC_REG (EPIC_EUMBBAR + 0x10220)/* Ext. Int. Sr1 Des */
+#define EPIC_EX_INT1_DES_REG (EPIC_EUMBBAR + 0x10230)/* Ext. Int. Sr1 Vect*/
+#define EPIC_EX_INT2_VEC_REG (EPIC_EUMBBAR + 0x10240)/* Ext. Int. Sr2 Des */
+#define EPIC_EX_INT2_DES_REG (EPIC_EUMBBAR + 0x10250)/* Ext. Int. Sr2 Vect*/
+#define EPIC_EX_INT3_VEC_REG (EPIC_EUMBBAR + 0x10260)/* Ext. Int. Sr3 Des */
+#define EPIC_EX_INT3_DES_REG (EPIC_EUMBBAR + 0x10270)/* Ext. Int. Sr3 Vect*/
+#define EPIC_EX_INT4_VEC_REG (EPIC_EUMBBAR + 0x10280)/* Ext. Int. Sr4 Des */
+#define EPIC_EX_INT4_DES_REG (EPIC_EUMBBAR + 0x10290)/* Ext. Int. Sr4 Vect*/
+
+#define EPIC_SR_INT0_VEC_REG (EPIC_EUMBBAR + 0x10200)/* Sr. Int. Sr0 Des */
+#define EPIC_SR_INT0_DES_REG (EPIC_EUMBBAR + 0x10210)/* Sr. Int. Sr0 Vect */
+#define EPIC_SR_INT1_VEC_REG (EPIC_EUMBBAR + 0x10220)/* Sr. Int. Sr1 Des */
+#define EPIC_SR_INT1_DES_REG (EPIC_EUMBBAR + 0x10230)/* Sr. Int. Sr1 Vect.*/
+#define EPIC_SR_INT2_VEC_REG (EPIC_EUMBBAR + 0x10240)/* Sr. Int. Sr2 Des */
+#define EPIC_SR_INT2_DES_REG (EPIC_EUMBBAR + 0x10250)/* Sr. Int. Sr2 Vect.*/
+#define EPIC_SR_INT3_VEC_REG (EPIC_EUMBBAR + 0x10260)/* Sr. Int. Sr3 Des */
+#define EPIC_SR_INT3_DES_REG (EPIC_EUMBBAR + 0x10270)/* Sr. Int. Sr3 Vect.*/
+#define EPIC_SR_INT4_VEC_REG (EPIC_EUMBBAR + 0x10280)/* Sr. Int. Sr4 Des */
+#define EPIC_SR_INT4_DES_REG (EPIC_EUMBBAR + 0x10290)/* Sr. Int. Sr4 Vect.*/
+
+#define EPIC_SR_INT5_VEC_REG (EPIC_EUMBBAR + 0x102a0)/* Sr. Int. Sr5 Des */
+#define EPIC_SR_INT5_DES_REG (EPIC_EUMBBAR + 0x102b0)/* Sr. Int. Sr5 Vect.*/
+#define EPIC_SR_INT6_VEC_REG (EPIC_EUMBBAR + 0x102c0)/* Sr. Int. Sr6 Des */
+#define EPIC_SR_INT6_DES_REG (EPIC_EUMBBAR + 0x102d0)/* Sr. Int. Sr6 Vect.*/
+#define EPIC_SR_INT7_VEC_REG (EPIC_EUMBBAR + 0x102e0)/* Sr. Int. Sr7 Des */
+#define EPIC_SR_INT7_DES_REG (EPIC_EUMBBAR + 0x102f0)/* Sr. Int. Sr7 Vect.*/
+#define EPIC_SR_INT8_VEC_REG (EPIC_EUMBBAR + 0x10300)/* Sr. Int. Sr8 Des */
+#define EPIC_SR_INT8_DES_REG (EPIC_EUMBBAR + 0x10310)/* Sr. Int. Sr8 Vect.*/
+#define EPIC_SR_INT9_VEC_REG (EPIC_EUMBBAR + 0x10320)/* Sr. Int. Sr9 Des */
+#define EPIC_SR_INT9_DES_REG (EPIC_EUMBBAR + 0x10330)/* Sr. Int. Sr9 Vect.*/
+
+#define EPIC_SR_INT10_VEC_REG (EPIC_EUMBBAR + 0x10340)/* Sr. Int. Sr10 Des */
+#define EPIC_SR_INT10_DES_REG (EPIC_EUMBBAR + 0x10350)/* Sr. Int. Sr10 Vect*/
+#define EPIC_SR_INT11_VEC_REG (EPIC_EUMBBAR + 0x10360)/* Sr. Int. Sr11 Des */
+#define EPIC_SR_INT11_DES_REG (EPIC_EUMBBAR + 0x10370)/* Sr. Int. Sr11 Vect*/
+#define EPIC_SR_INT12_VEC_REG (EPIC_EUMBBAR + 0x10380)/* Sr. Int. Sr12 Des */
+#define EPIC_SR_INT12_DES_REG (EPIC_EUMBBAR + 0x10390)/* Sr. Int. Sr12 Vect*/
+#define EPIC_SR_INT13_VEC_REG (EPIC_EUMBBAR + 0x103a0)/* Sr. Int. Sr13 Des */
+#define EPIC_SR_INT13_DES_REG (EPIC_EUMBBAR + 0x103b0)/* Sr. Int. Sr13 Vect*/
+#define EPIC_SR_INT14_VEC_REG (EPIC_EUMBBAR + 0x103c0)/* Sr. Int. Sr14 Des */
+#define EPIC_SR_INT14_DES_REG (EPIC_EUMBBAR + 0x103d0)/* Sr. Int. Sr14 Vect*/
+#define EPIC_SR_INT15_VEC_REG (EPIC_EUMBBAR + 0x103e0)/* Sr. Int. Sr15 Des */
+#define EPIC_SR_INT15_DES_REG (EPIC_EUMBBAR + 0x103f0)/* Sr. Int. Sr15 Vect*/
+
+#define EPIC_I2C_INT_VEC_REG (EPIC_EUMBBAR + 0x11020)/* I2C Int. Vect Pri.*/
+#define EPIC_I2C_INT_DES_REG (EPIC_EUMBBAR + 0x11030)/* I2C Int. Dest */
+#define EPIC_DMA0_INT_VEC_REG (EPIC_EUMBBAR + 0x11040)/* DMA0 Int. Vect Pri*/
+#define EPIC_DMA0_INT_DES_REG (EPIC_EUMBBAR + 0x11050)/* DMA0 Int. Dest */
+#define EPIC_DMA1_INT_VEC_REG (EPIC_EUMBBAR + 0x11060)/* DMA1 Int. Vect Pri*/
+#define EPIC_DMA1_INT_DES_REG (EPIC_EUMBBAR + 0x11070)/* DMA1 Int. Dest */
+#define EPIC_MSG_INT_VEC_REG (EPIC_EUMBBAR + 0x110c0)/* Msg Int. Vect Pri*/
+#define EPIC_MSG_INT_DES_REG (EPIC_EUMBBAR + 0x110d0)/* Msg Int. Dest */
+
+#define EPIC_PROC_CTASK_PRI_REG (EPIC_EUMBBAR + 0x20080)/* Proc. current task*/
+#define EPIC_PROC_INT_ACK_REG (EPIC_EUMBBAR + 0x200a0)/* Int. acknowledge */
+#define EPIC_PROC_EOI_REG (EPIC_EUMBBAR + 0x200b0)/* End of interrupt */
+
+#define EPIC_VEC_PRI_MASK 0x80000000 /* Mask Interrupt bit in IVPR */
+#define EPIC_VEC_PRI_DFLT_PRI 8 /* Interrupt Priority in IVPR */
+
+/* Error code */
+
+#define OK 0
+#define ERROR -1
+
+/* function prototypes */
+
+void epicVendorId( unsigned int *step,
+ unsigned int *devId,
+ unsigned int *venId
+ );
+void epicFeatures( unsigned int *noIRQs,
+ unsigned int *noCPUs,
+ unsigned int *VerId );
+extern void epicInit( unsigned int IRQType, unsigned int clkRatio);
+ULONG sysEUMBBARRead ( ULONG regNum );
+void sysEUMBBARWrite ( ULONG regNum, ULONG regVal);
+extern void epicTmFrequencySet( unsigned int frq );
+extern unsigned int epicTmFrequencyGet(void);
+extern unsigned int epicTmBaseSet( ULONG srcAddr,
+ unsigned int cnt,
+ unsigned int inhibit );
+extern unsigned int epicTmBaseGet ( ULONG srcAddr, unsigned int *val );
+extern unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val );
+extern unsigned int epicTmInhibit( unsigned int timer );
+extern unsigned int epicTmEnable( ULONG srcAdr );
+extern void CoreExtIntEnable(void); /* Enable 603e external interrupts */
+extern void CoreExtIntDisable(void); /* Disable 603e external interrupts */
+extern unsigned char epicIntTaskGet(void);
+extern void epicIntTaskSet( unsigned char val );
+extern unsigned int epicIntAck(void);
+extern void epicSprSet( unsigned int eumbbar, unsigned char );
+extern void epicConfigGet( unsigned int *clkRatio,
+ unsigned int *serEnable );
+extern void SrcVecTableInit(void);
+extern unsigned int epicModeGet(void);
+extern void epicIntEnable(int Vect);
+extern void epicIntDisable(int Vect);
+extern int epicIntSourceConfig(int Vect, int Polarity, int Sense, int Prio);
+extern unsigned int epicIntAck(void);
+extern void epicEOI(void);
+extern int epicCurTaskPrioSet(int Vect);
+
+struct SrcVecTable
+ {
+ ULONG srcAddr;
+ char srcName[40];
+ };
+
+#endif /* EPIC_H */
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c b/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c
new file mode 100644
index 0000000..ecbb42d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic1.c
@@ -0,0 +1,517 @@
+/**************************************************
+ *
+ * copyright @ motorola, 1999
+ *
+ *************************************************/
+#include <mpc824x.h>
+#include <common.h>
+#include "epic.h"
+
+
+#define PRINT(format, args...) printf(format , ## args)
+
+typedef void (*VOIDFUNCPTR) (void); /* ptr to function returning void */
+struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector cross-reference tbl */
+ {
+ { EPIC_EX_INT0_VEC_REG, "External Direct/Serial Source 0"},
+ { EPIC_EX_INT1_VEC_REG, "External Direct/Serial Source 1"},
+ { EPIC_EX_INT2_VEC_REG, "External Direct/Serial Source 2"},
+ { EPIC_EX_INT3_VEC_REG, "External Direct/Serial Source 3"},
+ { EPIC_EX_INT4_VEC_REG, "External Direct/Serial Source 4"},
+
+ { EPIC_SR_INT5_VEC_REG, "External Serial Source 5"},
+ { EPIC_SR_INT6_VEC_REG, "External Serial Source 6"},
+ { EPIC_SR_INT7_VEC_REG, "External Serial Source 7"},
+ { EPIC_SR_INT8_VEC_REG, "External Serial Source 8"},
+ { EPIC_SR_INT9_VEC_REG, "External Serial Source 9"},
+ { EPIC_SR_INT10_VEC_REG, "External Serial Source 10"},
+ { EPIC_SR_INT11_VEC_REG, "External Serial Source 11"},
+ { EPIC_SR_INT12_VEC_REG, "External Serial Source 12"},
+ { EPIC_SR_INT13_VEC_REG, "External Serial Source 13"},
+ { EPIC_SR_INT14_VEC_REG, "External Serial Source 14"},
+ { EPIC_SR_INT15_VEC_REG, "External Serial Source 15"},
+
+ { EPIC_I2C_INT_VEC_REG, "Internal I2C Source"},
+ { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source"},
+ { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source"},
+ { EPIC_MSG_INT_VEC_REG, "Internal Message Source"},
+ };
+
+VOIDFUNCPTR intVecTbl[MAXVEC]; /* Interrupt vector table */
+
+
+/****************************************************************************
+* epicInit - Initialize the EPIC registers
+*
+* This routine resets the Global Configuration Register, thus it:
+* - Disables all interrupts
+* - Sets epic registers to reset values
+* - Sets the value of the Processor Current Task Priority to the
+* highest priority (0xF).
+* epicInit then sets the EPIC operation mode to Mixed Mode (vs. Pass
+* Through or 8259 compatible mode).
+*
+* If IRQType (input) is Direct IRQs:
+* - IRQType is written to the SIE bit of the EPIC Interrupt
+* Configuration register (ICR).
+* - clkRatio is ignored.
+* If IRQType is Serial IRQs:
+* - both IRQType and clkRatio will be written to the ICR register
+*/
+
+void epicInit
+ (
+ unsigned int IRQType, /* Direct or Serial */
+ unsigned int clkRatio /* Clk Ratio for Serial IRQs */
+ )
+ {
+ ULONG tmp;
+
+ tmp = sysEUMBBARRead(EPIC_GLOBAL_REG);
+ tmp |= 0xa0000000; /* Set the Global Conf. register */
+ sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp);
+ /*
+ * Wait for EPIC to reset - CLH
+ */
+ while( (sysEUMBBARRead(EPIC_GLOBAL_REG) & 0x80000000) == 1);
+ sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000);
+ tmp = sysEUMBBARRead(EPIC_INT_CONF_REG); /* Read interrupt conf. reg */
+
+ if (IRQType == EPIC_DIRECT_IRQ) /* direct mode */
+ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff);
+ else /* Serial mode */
+ {
+ tmp = (clkRatio << 28) | 0x08000000; /* Set clock ratio */
+ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp);
+ }
+
+ while (epicIntAck() != 0xff) /* Clear all pending interrupts */
+ epicEOI();
+}
+
+/****************************************************************************
+ * epicIntEnable - Enable an interrupt source
+ *
+ * This routine clears the mask bit of an external, an internal or
+ * a Timer register to enable the interrupt.
+ *
+ * RETURNS: None
+ */
+void epicIntEnable(int intVec)
+{
+ ULONG tmp;
+ ULONG srAddr;
+
+ srAddr = SrcVecTable[intVec].srcAddr; /* Retrieve src Vec/Prio register */
+ tmp = sysEUMBBARRead(srAddr);
+ tmp &= ~EPIC_VEC_PRI_MASK; /* Clear the mask bit */
+ tmp |= (EPIC_VEC_PRI_DFLT_PRI << 16); /* Set priority to Default - CLH */
+ tmp |= intVec; /* Set Vector number */
+ sysEUMBBARWrite(srAddr, tmp);
+
+ return;
+ }
+
+/****************************************************************************
+ * epicIntDisable - Disable an interrupt source
+ *
+ * This routine sets the mask bit of an external, an internal or
+ * a Timer register to disable the interrupt.
+ *
+ * RETURNS: OK or ERROR
+ *
+ */
+
+void epicIntDisable
+ (
+ int intVec /* Interrupt vector number */
+ )
+ {
+
+ ULONG tmp, srAddr;
+
+ srAddr = SrcVecTable[intVec].srcAddr;
+ tmp = sysEUMBBARRead(srAddr);
+ tmp |= 0x80000000; /* Set the mask bit */
+ sysEUMBBARWrite(srAddr, tmp);
+ return;
+ }
+
+/****************************************************************************
+ * epicIntSourceConfig - Set properties of an interrupt source
+ *
+ * This function sets interrupt properites (Polarity, Sense, Interrupt
+ * Prority, and Interrupt Vector) of an Interrupt Source. The properties
+ * can be set when the current source is not in-request or in-service,
+ * which is determined by the Activity bit. This routine return ERROR
+ * if the the Activity bit is 1 (in-request or in-service).
+ *
+ * This function assumes that the Source Vector/Priority register (input)
+ * is a valid address.
+ *
+ * RETURNS: OK or ERROR
+ */
+
+int epicIntSourceConfig
+ (
+ int Vect, /* interrupt source vector number */
+ int Polarity, /* interrupt source polarity */
+ int Sense, /* interrupt source Sense */
+ int Prio /* interrupt source priority */
+ )
+
+ {
+ ULONG tmp, newVal;
+ ULONG actBit, srAddr;
+
+ srAddr = SrcVecTable[Vect].srcAddr;
+ tmp = sysEUMBBARRead(srAddr);
+ actBit = (tmp & 40000000) >> 30; /* retrieve activity bit - bit 30 */
+ if (actBit == 1)
+ return ERROR;
+
+ tmp &= 0xff30ff00; /* Erase previously set P,S,Prio,Vector bits */
+ newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect;
+ sysEUMBBARWrite(srAddr, tmp | newVal );
+ return (OK);
+ }
+
+/****************************************************************************
+ * epicIntAck - acknowledge an interrupt
+ *
+ * This function reads the Interrupt acknowldge register and return
+ * the vector number of the highest pending interrupt.
+ *
+ * RETURNS: Interrupt Vector number.
+ */
+
+unsigned int epicIntAck(void)
+{
+ return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG ));
+}
+
+/****************************************************************************
+ * epicEOI - signal an end of interrupt
+ *
+ * This function writes 0x0 to the EOI register to signal end of interrupt.
+ * It is usually called after an interrupt routine is served.
+ *
+ * RETURNS: None
+ */
+
+void epicEOI(void)
+ {
+ sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0);
+ }
+
+/****************************************************************************
+ * epicCurTaskPrioSet - sets the priority of the Processor Current Task
+ *
+ * This function should be called after epicInit() to lower the priority
+ * of the processor current task.
+ *
+ * RETURNS: OK or ERROR
+ */
+
+int epicCurTaskPrioSet
+ (
+ int prioNum /* New priority value */
+ )
+ {
+
+ if ( (prioNum < 0) || (prioNum > 0xF))
+ return ERROR;
+ sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum);
+ return OK;
+ }
+
+
+/************************************************************************
+ * function: epicIntTaskGet
+ *
+ * description: Get value of processor current interrupt task priority register
+ *
+ * note:
+ ***********************************************************************/
+unsigned char epicIntTaskGet()
+{
+ /* get the interrupt task priority register */
+ ULONG reg;
+ unsigned char rec;
+
+ reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG );
+ rec = ( reg & 0x0F );
+ return rec;
+}
+
+
+/**************************************************************
+ * function: epicISR
+ *
+ * description: EPIC service routine called by the core exception
+ * at 0x500
+ *
+ * note:
+ **************************************************************/
+unsigned int epicISR(void)
+{
+ return 0;
+}
+
+
+/************************************************************
+ * function: epicModeGet
+ *
+ * description: query EPIC mode, return 0 if pass through mode
+ * return 1 if mixed mode
+ *
+ * note:
+ *************************************************************/
+unsigned int epicModeGet(void)
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( EPIC_GLOBAL_REG );
+ return (( val & 0x20000000 ) >> 29);
+}
+
+
+/*********************************************
+ * function: epicConfigGet
+ *
+ * description: Get the EPIC interrupt Configuration
+ * return 0 if not error, otherwise return 1
+ *
+ * note:
+ ********************************************/
+void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable)
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( EPIC_INT_CONF_REG );
+ *clkRatio = ( val & 0x70000000 ) >> 28;
+ *serEnable = ( val & 0x8000000 ) >> 27;
+}
+
+
+/*******************************************************************
+ * sysEUMBBARRead - Read a 32-bit EUMBBAR register
+ *
+ * This routine reads the content of a register in the Embedded
+ * Utilities Memory Block, and swaps to big endian before returning
+ * the value.
+ *
+ * RETURNS: The content of the specified EUMBBAR register.
+ */
+
+ULONG sysEUMBBARRead
+ (
+ ULONG regNum
+ )
+ {
+ ULONG temp;
+
+ temp = *(ULONG *) (CONFIG_SYS_EUMB_ADDR + regNum);
+ return ( LONGSWAP(temp));
+ }
+
+/*******************************************************************
+ * sysEUMBBARWrite - Write a 32-bit EUMBBAR register
+ *
+ * This routine swaps the value to little endian then writes it to
+ * a register in the Embedded Utilities Memory Block address space.
+ *
+ * RETURNS: N/A
+ */
+
+void sysEUMBBARWrite
+ (
+ ULONG regNum, /* EUMBBAR register address */
+ ULONG regVal /* Value to be written */
+ )
+ {
+
+ *(ULONG *) (CONFIG_SYS_EUMB_ADDR + regNum) = LONGSWAP(regVal);
+ return ;
+ }
+
+
+/********************************************************
+ * function: epicVendorId
+ *
+ * description: return the EPIC Vendor Identification
+ * register:
+ *
+ * siliccon version, device id, and vendor id
+ *
+ * note:
+ ********************************************************/
+void epicVendorId
+ (
+ unsigned int *step,
+ unsigned int *devId,
+ unsigned int *venId
+ )
+ {
+ ULONG val;
+ val = sysEUMBBARRead( EPIC_VENDOR_ID_REG );
+ *step = ( val & 0x00FF0000 ) >> 16;
+ *devId = ( val & 0x0000FF00 ) >> 8;
+ *venId = ( val & 0x000000FF );
+ }
+
+/**************************************************
+ * function: epicFeatures
+ *
+ * description: return the number of IRQ supported,
+ * number of CPU, and the version of the
+ * OpenEPIC
+ *
+ * note:
+ *************************************************/
+void epicFeatures
+ (
+ unsigned int *noIRQs,
+ unsigned int *noCPUs,
+ unsigned int *verId
+ )
+ {
+ ULONG val;
+
+ val = sysEUMBBARRead( EPIC_FEATURES_REG );
+ *noIRQs = ( val & 0x07FF0000 ) >> 16;
+ *noCPUs = ( val & 0x00001F00 ) >> 8;
+ *verId = ( val & 0x000000FF );
+}
+
+
+/*********************************************************
+ * function: epciTmFrequncySet
+ *
+ * description: Set the timer frequency reporting register
+ ********************************************************/
+void epicTmFrequencySet( unsigned int frq )
+{
+ sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq);
+}
+
+/*******************************************************
+ * function: epicTmFrequncyGet
+ *
+ * description: Get the current value of the Timer Frequency
+ * Reporting register
+ *
+ ******************************************************/
+unsigned int epicTmFrequencyGet(void)
+{
+ return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ;
+}
+
+
+/****************************************************
+ * function: epicTmBaseSet
+ *
+ * description: Set the #n global timer base count register
+ * return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ****************************************************/
+unsigned int epicTmBaseSet
+ (
+ ULONG srcAddr, /* Address of the Timer Base register */
+ unsigned int cnt, /* Base count */
+ unsigned int inhibit /* 1 - count inhibit */
+ )
+{
+
+ unsigned int val = 0x80000000;
+ /* First inhibit counting the timer */
+ sysEUMBBARWrite(srcAddr, val) ;
+
+ /* set the new value */
+ val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31);
+ sysEUMBBARWrite(srcAddr, val) ;
+ return 0;
+}
+
+/***********************************************************************
+ * function: epicTmBaseGet
+ *
+ * description: Get the current value of the global timer base count register
+ * return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ***********************************************************************/
+unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val )
+{
+ *val = sysEUMBBARRead( srcAddr );
+ *val = *val & 0x7fffffff;
+ return 0;
+}
+
+/***********************************************************
+ * function: epicTmCountGet
+ *
+ * description: Get the value of a given global timer
+ * current count register
+ * return 0 if no error, otherwise return 1
+ * note:
+ **********************************************************/
+unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val )
+{
+ *val = sysEUMBBARRead( srcAddr );
+ *val = *val & 0x7fffffff;
+ return 0;
+}
+
+
+/***********************************************************
+ * function: epicTmInhibit
+ *
+ * description: Stop counting of a given global timer
+ * return 0 if no error, otherwise return 1
+ *
+ * note:
+ ***********************************************************/
+unsigned int epicTmInhibit( unsigned int srcAddr )
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( srcAddr );
+ val |= 0x80000000;
+ sysEUMBBARWrite( srcAddr, val );
+ return 0;
+}
+
+/******************************************************************
+ * function: epicTmEnable
+ *
+ * description: Enable counting of a given global timer
+ * return 0 if no error, otherwise return 1
+ *
+ * note:
+ *****************************************************************/
+unsigned int epicTmEnable( ULONG srcAddr )
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( srcAddr );
+ val &= 0x7fffffff;
+ sysEUMBBARWrite( srcAddr, val );
+ return 0;
+}
+
+void epicSourcePrint(int Vect)
+ {
+ ULONG srcVal;
+
+ srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr);
+ PRINT("%s\n", SrcVecTable[Vect].srcName);
+ PRINT("Address = 0x%lx\n", SrcVecTable[Vect].srcAddr);
+ PRINT("Vector = %ld\n", (srcVal & 0x000000FF) );
+ PRINT("Mask = %ld\n", srcVal >> 31);
+ PRINT("Activitiy = %ld\n", (srcVal & 40000000) >> 30);
+ PRINT("Polarity = %ld\n", (srcVal & 0x00800000) >> 23);
+ PRINT("Sense = %ld\n", (srcVal & 0x00400000) >> 22);
+ PRINT("Priority = %ld\n", (srcVal & 0x000F0000) >> 16);
+ }
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S b/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S
new file mode 100644
index 0000000..52d19aa
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epic2.S
@@ -0,0 +1,196 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/processor.h>
+
+/*********************************************
+ * function: CoreExtIntEnable
+ *
+ * description: Enable 603e core external interrupt
+ *
+ * note: mtmsr is context-synchronization
+ **********************************************/
+ .text
+ .align 2
+ .global CoreExtIntEnable
+CoreExtIntEnable:
+ mfmsr r3
+
+ ori r3,r3,0x8000 /* enable external interrupt */
+ mtmsr r3
+
+ bclr 20, 0
+
+/*******************************************
+ * function: CoreExtIntDisable
+ *
+ * description: Disable 603e core external interrupt
+ *
+ * note:
+ *******************************************/
+ .text
+ .align 2
+ .global CoreExtIntDisable
+CoreExtIntDisable:
+ mfmsr r4
+
+ xor r3,r3,r3
+ or r3,r3,r4
+
+ andis. r4,r4,0xffff
+ andi. r3,r3,0x7fff /* disable external interrupt */
+
+ or r3,r3,r4
+ mtmsr r3
+
+ bclr 20, 0
+
+/*********************************************************
+ * function: epicEOI
+ *
+ * description: signal the EOI and restore machine status
+ * Input: r3 - value of eumbbar
+ * Output: r3 - value of eumbbar
+ * r4 - ISR vector value
+ * note:
+ ********************************************************/
+ .text
+ .align 2
+ .global epicEOI
+epicEOI:
+ lis r5,0x0006 /* Build End Of Interrupt Register offset */
+ ori r5,r5,0x00b0
+ xor r7,r7,r7 /* Clear r7 */
+ stwbrx r7,r5,r3 /* Save r7, writing to this register will
+ * intidate the end of processing the
+ * highest interrupt.
+ */
+ sync
+
+ /* ---RESTORE MACHINE STATE */
+ mfmsr r13 /* Clear Recoverable Interrupt bit in MSR */
+ or r7,r7,r13
+
+ andis. r7,r7,0xffff
+ andi. r13,r13,0x7ffd /* (and disable interrupts) */
+ or r13,r13,r7
+ mtmsr r13
+
+ lwz r13,0x1c(r1) /* pull ctr */
+ mtctr r13
+
+ lwz r13,0x18(r1) /* pull xer */
+ mtctr r13
+
+ lwz r13,0x14(r1) /* pull lr */
+ mtctr r13
+
+ lwz r13,0x10(r1) /* Pull SRR1 from stack */
+ mtspr SRR1,r13 /* Restore SRR1 */
+
+ lwz r13,0xc(r1) /* Pull SRR0 from stack */
+ mtspr SRR0,r13 /* Restore SRR0 */
+
+ lwz r13,0x8(r1) /* Pull User stack pointer from stack */
+ mtspr SPRG1,r13 /* Restore SPRG1 */
+
+ lwz r4,0x4(r1) /* vector value */
+ lwz r3,0x0(r1) /* eumbbar */
+ sync
+
+ addi r1,r1,0x20 /* Deallocate stack */
+ mtspr SPRG0,r1 /* Save updated Supervisor stack pointer */
+ mfspr r1,SPRG1 /* Restore User stack pointer */
+
+ bclr 20,0
+
+/***********************************************************
+ * function: exception routine called by exception vector
+ * at 0x500, external interrupt
+ *
+ * description: Kahlua EPIC controller
+ *
+ * input: r3 - content of eumbbar
+ * output: r3 - ISR return value
+ * r4 - Interrupt vector number
+ * note:
+ ***********************************************************/
+
+ .text
+ .align 2
+ .global epic_exception
+
+epic_exception:
+
+ /*---SAVE MACHINE STATE TO A STACK */
+ mtspr SPRG1,r1 /* Save User stack pointer to SPRG1 */
+ mfspr r1,SPRG0 /* Load Supervisor stack pointer into r1 */
+
+ stwu r3,-0x20(r1) /* Push the value of eumbbar onto stack */
+
+ mfspr r3,SPRG1 /* Push User stack pointer onto stack */
+ stw r3,0x8(r1)
+ mfspr r3,SRR0 /* Push SRR0 onto stack */
+ stw r1,0xc(r1)
+ mfspr r3,SRR1 /* Push SRR1 onto stack */
+ stw r3,0x10(r1)
+ mflr r3
+ stw r3,0x14(r1) /* Push LR */
+ mfxer r3
+ stw r3,0x18(r1) /* Push Xer */
+ mfctr r3
+ stw r3,0x1c(r1) /* Push CTR */
+
+ mtspr SPRG0,r1 /* Save updated Supervisor stack pointer
+ * value to SPRG0
+ */
+ mfmsr r3
+ ori r3,r3,0x0002 /* Set Recoverable Interrupt bit in MSR */
+ mtmsr r3
+
+ /* ---READ IN THE EUMBAR REGISTER */
+ lwz r6,0(r1) /* this is eumbbar */
+ sync
+
+ /* ---READ EPIC REGISTER: PROCESSOR INTERRUPT ACKNOWLEDGE REGISTER */
+ lis r5,0x0006 /* Build Interrupt Acknowledge Register
+ * offset
+ */
+ ori r5,r5,0x00a0
+ lwbrx r7,r5,r6 /* Load interrupt vector into r7 */
+ sync
+
+ /* --MASK OFF ALL BITS EXCEPT THE VECTOR */
+ xor r3,r3,r3
+ xor r4,r4,r4
+ or r3, r3, r6 /* eumbbar in r3 */
+ andi. r4,r7,0x00ff /* Mask off bits, vector in r4 */
+
+ stw r4,0x04(r1) /* save the vector value */
+
+ lis r5,epicISR@ha
+ ori r5,r5,epicISR@l
+ mtlr r5
+ blrl
+
+ xor r30,r30,r30
+ or r30,r30,r3 /* save the r3 which containts the return value from epicISR */
+
+ /* ---READ IN THE EUMBAR REGISTER */
+ lwz r3,0(r1)
+ sync
+
+ lis r5,epicEOI@ha
+ ori r5,r5,epicEOI@l
+ mtlr r5
+ blrl
+
+ xor r3,r3,r3
+ or r3,r3,r30 /* restore the ISR return value */
+
+ bclr 20,0
diff --git a/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S b/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S
new file mode 100644
index 0000000..4877050
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/epic/epicutil.S
@@ -0,0 +1,57 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ *
+ * This file contains two commonly used
+ * lower level utility routines.
+ *
+ * The utility routines are also in other
+ * Kahlua device driver libraries. The
+ * need to be linked in only once.
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ * r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+ .text
+ .align 2
+ .global load_runtime_reg
+
+load_runtime_reg:
+
+ xor r5,r5,r5
+ or r5,r5,r3 /* save eumbbar */
+
+ lwbrx r3,r4,r5
+ sync
+
+ bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ * r4 - register offset in embedded utility space
+ * r5 - new value to be stored
+ *
+ ****************************************************************/
+ .text
+ .align 2
+ .global store_runtime_reg
+store_runtime_reg:
+
+ xor r0,r0,r0
+
+ stwbrx r5, r4, r3
+ sync
+
+ bclr 20,0
diff --git a/arch/powerpc/cpu/mpc824x/drivers/errors.h b/arch/powerpc/cpu/mpc824x/drivers/errors.h
new file mode 100644
index 0000000..20794a2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/errors.h
@@ -0,0 +1,212 @@
+/* Copyright Motorola, Inc. 1993, 1994
+ ALL RIGHTS RESERVED
+
+ You are hereby granted a copyright license to use, modify, and
+ distribute the SOFTWARE so long as this entire notice is retained
+ without alteration in any modified and/or redistributed versions,
+ and that such modified versions are clearly identified as such.
+ No licenses are granted by implication, estoppel or otherwise under
+ any patents or trademarks of Motorola, Inc.
+
+ The SOFTWARE is provided on an "AS IS" basis and without warranty.
+ To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+ ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+ PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+ REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+ THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+
+ To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+ MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+ (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+ BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+ INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+ INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility
+ for the maintenance and support of the SOFTWARE.
+
+*/
+
+
+#include "config.h"
+
+/*
+ 1 2 3 4 5 6 7 8
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+*/
+/* List define statements here */
+
+/* These are for all the toolboxes and functions to use. These will help
+to standardize the error handling in the current project */
+
+ /* this is the "data type" for the error
+ messages in the system */
+#define STATUS unsigned int
+
+ /* this is a success status code */
+#define SUCCESS 1
+
+ /* likewise this is failure */
+#define FAILURE 0
+
+#define NUM_ERRORS 47
+
+/* This first section of "defines" are for error codes ONLY. The called
+ routine will return one of these error codes to the caller. If the final
+ returned code is "VALID", then everything is a-okay. However, if one
+ of the functions returns a non-valid status, that error code should be
+ propogated back to all the callers. At the end, the last caller will
+ call an error_processing function, and send in the status which was
+ returned. It's up to the error_processing function to determine which
+ error occured (as indicated by the status), and print an appropriate
+ message back to the user.
+*/
+/*----------------------------------------------------------------------*/
+/* these are specifically for the parser routines */
+
+#define UNKNOWN_COMMAND 0xfb00 /* "unrecognized command " */
+#define UNKNOWN_REGISTER 0xfb01 /* "unknown register "*/
+#define ILLEGAL_RD_STAGE 0xfb02 /* cannot specify reg. family in range*/
+#define ILLEGAL_REG_FAMILY 0xfb03 /* "cannot specify a range of special
+ or miscellaneous registers"*/
+#define RANGE_CROSS_FAMILY 0xfb04 /* "cannot specify a range across
+ register families" */
+#define UNIMPLEMENTED_STAGE 0xfb05 /* invalid rd or rmm parameter format */
+#define REG_NOT_WRITEABLE 0xfb06 /* "unknown operator in arguements"*/
+#define INVALID_FILENAME 0xfb07 /* "invalid download filename" */
+#define INVALID_BAUD_RATE 0xfb08 /* invalid baud rate from sb command */
+#define UNSUPPORTED_REGISTER 0xfb09 /* Special register is not supported */
+#define FOR_BOARD_ONLY 0xfb0a /* "Not available for Unix." */
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the error checking toolbox */
+
+#define INVALID 0xfd00 /* NOT valid */
+#define VALID 0xfd01 /* valid */
+
+ /* This error is found in the fcn:
+ is_right_size_input() to indicate
+ that the input was not 8 characters
+ long. */
+#define INVALID_SIZE 0xfd02
+
+ /* This error is found in the fcn:
+ is_valid_address_range() to indicate
+ that the address given falls outside
+ of valid memory defined by MEM_START
+ to MEM_END.
+ */
+#define OUT_OF_BOUNDS_ADDRESS 0xfd03
+
+ /* This error is found in the fcn:
+ is_valid_hex_input() to indicate that
+ one of more of the characters entered
+ are not valid hex characters. Valid
+ hex characters are 0-9, A-F, a-f.
+ */
+#define INVALID_HEX_INPUT 0xfd04
+
+ /* This error is found in the fcn:
+ is_valid_register_number() to indicate
+ that a given register does not exist.
+ */
+#define REG_NOT_READABLE 0xfd05
+
+ /* This error is found in the fcn:
+ is_word_aligned_address() to indicate
+ that the given address is not word-
+ aligned. A word-aligned address ends
+ in 0x0,0x4,0x8,0xc.
+ */
+#define NOT_WORD_ALIGNED 0xfd07
+
+ /* This error is found in the fcn:
+ is_valid_address_range() to indicate
+ that the starting address is greater
+ than the ending address.
+ */
+#define REVERSED_ADDRESS 0xfd08
+
+ /* this error tells us that the address
+ specified as the destination is within
+ the source addresses */
+#define RANGE_OVERLAP 0xfd09
+
+
+#define ERROR 0xfd0a /* An error occured */
+#define INVALID_PARAM 0xfd0b /* "invalid input parameter " */
+
+
+#define INVALID_FLAG 0xfd0c /* invalid flag */
+
+/*----------------------------------------------------------------------*/
+/* these are for the getarg toolbox */
+
+#define INVALID_NUMBER_ARGS 0xFE00 /* invalid number of commd arguements */
+#define UNKNOWN_PARAMETER 0xFE01 /* "unknown type of parameter "*/
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the tokenizer toolbox */
+
+#define ILLEGAL_CHARACTER 0xFF00 /* unrecognized char. in input stream*/
+#define TTL_NOT_SORTED 0xFF01 /* token translation list not sorted */
+#define TTL_NOT_DEFINED 0xFF02 /* token translation list not assigned*/
+#define INVALID_STRING 0xFF03 /* unable to extract string from input */
+#define BUFFER_EMPTY 0xFF04 /* "input buffer is empty" */
+#define INVALID_MODE 0xFF05 /* input buf is in an unrecognized mode*/
+#define TOK_INTERNAL_ERROR 0xFF06 /* "internal tokenizer error" */
+#define TOO_MANY_IBS 0xFF07 /* "too many open input buffers" */
+#define NO_OPEN_IBS 0xFF08 /* "no open input buffers" */
+
+
+/* these are for the read from screen toolbox */
+
+#define RESERVED_WORD 0xFC00 /* used a reserved word as an arguement*/
+
+
+/* these are for the breakpoint routines */
+
+#define FULL_BPDS 0xFA00 /* breakpoint data structure is full */
+
+
+/* THESE are for the downloader */
+
+#define NOT_IN_S_RECORD_FORMAT 0xf900 /* "not in S-Record Format" */
+#define UNREC_RECORD_TYPE 0xf901 /* "unrecognized record type" */
+#define CONVERSION_ERROR 0xf902 /* "ascii to int conversion error" */
+#define INVALID_MEMORY 0xf903 /* "bad s-record memory address " */
+
+
+/* these are for the compression and decompression stuff */
+
+#define COMP_UNK_CHARACTER 0xf800 /* "unknown compressed character " */
+
+#define COMP_UNKNOWN_STATE 0xf801 /* "unknown binary state" */
+
+#define NOT_IN_COMPRESSED_FORMAT 0xf802 /* not in compressed S-Record format */
+
+
+/* these are for the DUART handling things */
+
+ /* "unrecognized serial port configuration" */
+#define UNKNOWN_PORT_STATE 0xf700
+
+
+/* these are for the register toolbox */
+
+ /* "cannot find register in special
+ purpose register file " */
+#define SPR_NOT_FOUND 0xf600
+
+
+/* these are for the duart specific stuff */
+
+ /* "transparent mode needs access to
+ two serial ports" */
+#define TM_NEEDS_BOTH_PORTS 0xf500
+
+
+/*----------------------------------------------------------------------*/
+/* these are specifically for the flash routines */
+#define FLASH_ERROR 0xf100 /* general flash error */
diff --git a/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c b/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c
new file mode 100644
index 0000000..637ae4c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.c
@@ -0,0 +1,270 @@
+/*
+ * (C) Copyright 2003
+ * Gleb Natapov <gnatapov@mrv.com>
+ * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
+ *
+ * Hardware I2C driver for MPC107 PCI bridge.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#undef I2CDBG
+
+#ifdef CONFIG_HARD_I2C
+#include <i2c.h>
+
+#define TIMEOUT (CONFIG_SYS_HZ/4)
+
+#define I2C_Addr ((unsigned *)(CONFIG_SYS_EUMB_ADDR + 0x3000))
+
+#define I2CADR &I2C_Addr[0]
+#define I2CFDR &I2C_Addr[1]
+#define I2CCCR &I2C_Addr[2]
+#define I2CCSR &I2C_Addr[3]
+#define I2CCDR &I2C_Addr[4]
+
+#define MPC107_CCR_MEN 0x80
+#define MPC107_CCR_MIEN 0x40
+#define MPC107_CCR_MSTA 0x20
+#define MPC107_CCR_MTX 0x10
+#define MPC107_CCR_TXAK 0x08
+#define MPC107_CCR_RSTA 0x04
+
+#define MPC107_CSR_MCF 0x80
+#define MPC107_CSR_MAAS 0x40
+#define MPC107_CSR_MBB 0x20
+#define MPC107_CSR_MAL 0x10
+#define MPC107_CSR_SRW 0x04
+#define MPC107_CSR_MIF 0x02
+#define MPC107_CSR_RXAK 0x01
+
+#define I2C_READ 1
+#define I2C_WRITE 0
+
+/* taken from linux include/asm-ppc/io.h */
+inline unsigned in_le32 (volatile unsigned *addr)
+{
+ unsigned ret;
+
+ __asm__ __volatile__ ("lwbrx %0,0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync":"=r" (ret): "r" (addr), "m" (*addr));
+ return ret;
+}
+
+inline void out_le32 (volatile unsigned *addr, int val)
+{
+ __asm__ __volatile__ ("stwbrx %1,0,%2; eieio":"=m" (*addr):"r" (val),
+ "r" (addr));
+}
+
+#define writel(val, addr) out_le32(addr, val)
+#define readl(addr) in_le32(addr)
+
+void i2c_init (int speed, int slaveadd)
+{
+ /* stop I2C controller */
+ writel (0x0, I2CCCR);
+ /* set clock */
+ writel (0x1020, I2CFDR);
+ /* write slave address */
+ writel (slaveadd, I2CADR);
+ /* clear status register */
+ writel (0x0, I2CCSR);
+ /* start I2C controller */
+ writel (MPC107_CCR_MEN, I2CCCR);
+
+ return;
+}
+
+static __inline__ int i2c_wait4bus (void)
+{
+ ulong timeval = get_timer (0);
+
+ while (readl (I2CCSR) & MPC107_CSR_MBB)
+ if (get_timer (timeval) > TIMEOUT)
+ return -1;
+
+ return 0;
+}
+
+static __inline__ int i2c_wait (int write)
+{
+ u32 csr;
+ ulong timeval = get_timer (0);
+
+ do {
+ csr = readl (I2CCSR);
+
+ if (!(csr & MPC107_CSR_MIF))
+ continue;
+
+ writel (0x0, I2CCSR);
+
+ if (csr & MPC107_CSR_MAL) {
+#ifdef I2CDBG
+ printf ("i2c_wait: MAL\n");
+#endif
+ return -1;
+ }
+
+ if (!(csr & MPC107_CSR_MCF)) {
+#ifdef I2CDBG
+ printf ("i2c_wait: unfinished\n");
+#endif
+ return -1;
+ }
+
+ if (write == I2C_WRITE && (csr & MPC107_CSR_RXAK)) {
+#ifdef I2CDBG
+ printf ("i2c_wait: No RXACK\n");
+#endif
+ return -1;
+ }
+
+ return 0;
+ } while (get_timer (timeval) < TIMEOUT);
+
+#ifdef I2CDBG
+ printf ("i2c_wait: timed out\n");
+#endif
+ return -1;
+}
+
+static __inline__ int i2c_write_addr (u8 dev, u8 dir, int rsta)
+{
+ writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX |
+ (rsta ? MPC107_CCR_RSTA : 0), I2CCCR);
+
+ writel ((dev << 1) | dir, I2CCDR);
+
+ if (i2c_wait (I2C_WRITE) < 0)
+ return 0;
+
+ return 1;
+}
+
+static __inline__ int __i2c_write (u8 * data, int length)
+{
+ int i;
+
+ writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX, I2CCCR);
+
+ for (i = 0; i < length; i++) {
+ writel (data[i], I2CCDR);
+
+ if (i2c_wait (I2C_WRITE) < 0)
+ break;
+ }
+
+ return i;
+}
+
+static __inline__ int __i2c_read (u8 * data, int length)
+{
+ int i;
+
+ writel (MPC107_CCR_MEN | MPC107_CCR_MSTA |
+ ((length == 1) ? MPC107_CCR_TXAK : 0), I2CCCR);
+
+ /* dummy read */
+ readl (I2CCDR);
+
+ for (i = 0; i < length; i++) {
+ if (i2c_wait (I2C_READ) < 0)
+ break;
+
+ /* Generate ack on last next to last byte */
+ if (i == length - 2)
+ writel (MPC107_CCR_MEN | MPC107_CCR_MSTA |
+ MPC107_CCR_TXAK, I2CCCR);
+
+ /* Generate stop on last byte */
+ if (i == length - 1)
+ writel (MPC107_CCR_MEN | MPC107_CCR_TXAK, I2CCCR);
+
+ data[i] = readl (I2CCDR);
+ }
+
+ return i;
+}
+
+int i2c_read (u8 dev, uint addr, int alen, u8 * data, int length)
+{
+ int i = 0;
+ u8 *a = (u8 *) & addr;
+
+ if (i2c_wait4bus () < 0)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+ goto exit;
+
+ if (__i2c_write (&a[4 - alen], alen) != alen)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_READ, 1) == 0)
+ goto exit;
+
+ i = __i2c_read (data, length);
+
+exit:
+ writel (MPC107_CCR_MEN, I2CCCR);
+
+ return !(i == length);
+}
+
+int i2c_write (u8 dev, uint addr, int alen, u8 * data, int length)
+{
+ int i = 0;
+ u8 *a = (u8 *) & addr;
+
+ if (i2c_wait4bus () < 0)
+ goto exit;
+
+ if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+ goto exit;
+
+ if (__i2c_write (&a[4 - alen], alen) != alen)
+ goto exit;
+
+ i = __i2c_write (data, length);
+
+exit:
+ writel (MPC107_CCR_MEN, I2CCCR);
+
+ return !(i == length);
+}
+
+int i2c_probe (uchar chip)
+{
+ int tmp;
+
+ /*
+ * Try to read the first location of the chip. The underlying
+ * driver doesn't appear to support sending just the chip address
+ * and looking for an <ACK> back.
+ */
+ udelay (10000);
+ return i2c_read (chip, 0, 1, (uchar *) &tmp, 1);
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h b/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h
new file mode 100644
index 0000000..6264d18
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/drivers/i2c_export.h
@@ -0,0 +1,103 @@
+#ifndef I2C_EXPORT_H
+#define I2C_EXPORT_H
+
+/****************************************************
+ *
+ * Copyright Motrola 1999
+ *
+ ****************************************************/
+
+/* These are the defined return values for the I2C_do_transaction function.
+ * Any non-zero value indicates failure. Failure modes can be added for
+ * more detailed error reporting.
+ */
+typedef enum _i2c_status
+{
+ I2C_SUCCESS = 0,
+ I2C_ERROR,
+} I2C_Status;
+
+/* These are the defined tasks for I2C_do_transaction.
+ * Modes for SLAVE_RCV and SLAVE_XMIT will be added.
+ */
+typedef enum _i2c_transaction_mode
+{
+ I2C_MASTER_RCV = 0,
+ I2C_MASTER_XMIT = 1,
+} I2C_TRANSACTION_MODE;
+
+typedef enum _i2c_interrupt_mode
+{
+ I2C_INT_DISABLE = 0,
+ I2C_INT_ENABLE = 1,
+} I2C_INTERRUPT_MODE;
+
+typedef enum _i2c_stop
+{
+ I2C_NO_STOP = 0,
+ I2C_STOP = 1,
+} I2C_STOP_MODE;
+
+typedef enum _i2c_restart
+{
+ I2C_NO_RESTART = 0,
+ I2C_RESTART = 1,
+} I2C_RESTART_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application
+ * to use the functionality provided by I2C driver.
+ * This is a "generic" I2C interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ *
+ * Note: Its App.s responsibility to swap the data
+ * byte. In our API, we just transfer whatever
+ * we are given
+ **************************************************/
+
+
+/* Initialize I2C unit with the following:
+ * driver's slave address
+ * interrupt enabled
+ * optional pointer to application layer print function
+ *
+ * These parameters may be added:
+ * desired clock rate
+ * digital filter frequency sampling rate
+ *
+ * This function must be called before I2C unit can be used.
+ */
+extern I2C_Status I2C_Initialize(
+ unsigned char addr, /* driver's I2C slave address */
+ I2C_INTERRUPT_MODE en_int, /* 1 - enable I2C interrupt
+ * 0 - disable I2C interrupt
+ */
+ int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+ * provided by application
+ */
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented. Both are only in polling mode.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ * I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ * I2C_RESTART, this is a continuation of existing transaction
+ */
+extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int,
+ I2C_TRANSACTION_MODE act,
+ unsigned char i2c_addr,
+ unsigned char data_addr,
+ int len,
+ char *buffer,
+ I2C_STOP_MODE stop,
+ int retry,
+ I2C_RESTART_MODE rsta);
+#endif
diff --git a/arch/powerpc/cpu/mpc824x/interrupts.c b/arch/powerpc/cpu/mpc824x/interrupts.c
new file mode 100644
index 0000000..139c52c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/interrupts.c
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+#include <asm/pci_io.h>
+#include <commproc.h>
+#include "drivers/epic.h"
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ *decrementer_count = (get_bus_freq (0) / 4) / CONFIG_SYS_HZ;
+
+ /*
+ * It's all broken at the moment and I currently don't need
+ * interrupts. If you want to fix it, have a look at the epic
+ * drivers in dink32 v12. They do everthing and Motorola said
+ * I could use the dink source in this project as long as
+ * copyright notices remain intact.
+ */
+
+ epicInit (EPIC_DIRECT_IRQ, 0);
+ /* EPIC won't generate INT unless Current Task Pri < 15 */
+ epicCurTaskPrioSet(0);
+
+ return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+ register unsigned long temp;
+
+ pci_readl (CONFIG_SYS_EUMB_ADDR + EPIC_PROC_INT_ACK_REG, temp);
+ sync (); /* i'm not convinced this is needed, but dink source has it */
+ temp &= 0xff; /*get vector */
+
+ /*TODO: handle them -... */
+ epicEOI ();
+}
+
+/****************************************************************************/
+
+/*
+ * blank int handlers.
+ */
+
+void
+irq_install_handler (int vec, interrupt_handler_t * handler, void *arg)
+{
+}
+
+void irq_free_handler (int vec)
+{
+
+}
+
+/*TODO: some handlers for winbond and 87308 interrupts
+ and what about generic pci inteerupts?
+ vga?
+ */
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
diff --git a/arch/powerpc/cpu/mpc824x/pci.c b/arch/powerpc/cpu/mpc824x/pci.c
new file mode 100644
index 0000000..72aaec7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/pci.c
@@ -0,0 +1,78 @@
+/*
+ * arch/powerpc/kernel/mpc10x_common.c
+ *
+ * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
+ * Mem ctlr, EPIC, etc.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+#include <mpc824x.h>
+
+void pci_mpc824x_init (struct pci_controller *hose)
+{
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* System memory space */
+ pci_set_region(hose->regions + 0,
+ CHRP_PCI_MEMORY_BUS,
+ CHRP_PCI_MEMORY_PHYS,
+ CHRP_PCI_MEMORY_SIZE,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + 1,
+ CHRP_PCI_MEM_BUS,
+ CHRP_PCI_MEM_PHYS,
+ CHRP_PCI_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* ISA/PCI memory space */
+ pci_set_region(hose->regions + 2,
+ CHRP_ISA_MEM_BUS,
+ CHRP_ISA_MEM_PHYS,
+ CHRP_ISA_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ /* PCI I/O space */
+ pci_set_region(hose->regions + 3,
+ CHRP_PCI_IO_BUS,
+ CHRP_PCI_IO_PHYS,
+ CHRP_PCI_IO_SIZE,
+ PCI_REGION_IO);
+
+ /* ISA/PCI I/O space */
+ pci_set_region(hose->regions + 4,
+ CHRP_ISA_IO_BUS,
+ CHRP_ISA_IO_PHYS,
+ CHRP_ISA_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 5;
+
+ pci_setup_indirect(hose,
+ CHRP_REG_ADDR,
+ CHRP_REG_DATA);
+
+ pci_register_hose(hose);
+
+ hose->last_busno = pci_hose_scan(hose);
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc824x/speed.c b/arch/powerpc/cpu/mpc824x/speed.c
new file mode 100644
index 0000000..fdcb972
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/speed.c
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002
+ * Gregory E. Allen, gallen@arlut.utexas.edu
+ * Applied Research Laboratories, The University of Texas at Austin
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc824x.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+/* NOTE: This describes the proper use of this file.
+ *
+ * CONFIG_SYS_CLK_FREQ should be defined as the input frequency on
+ * PCI_SYNC_IN .
+ *
+ * CONFIG_PLL_PCI_TO_MEM_MULTIPLIER is only required on MPC8240
+ * boards. It should be defined as the PCI to Memory Multiplier as
+ * documented in the MPC8240 Hardware Specs.
+ *
+ * Other mpc824x boards don't need CONFIG_PLL_PCI_TO_MEM_MULTIPLIER
+ * because they can determine it from the PCR.
+ *
+ * Gary Milliorn <gary.milliorn@motorola.com> (who should know since
+ * he designed the Sandpoint) told us that the PCR is not in all revs
+ * of the MPC8240 CPU, so it's not guaranteeable and we cannot do
+ * away with CONFIG_PLL_PCI_TO_MEM_MULTIPLIER altogether.
+ */
+/* ------------------------------------------------------------------------- */
+
+/* This gives the PCI to Memory multiplier times 10 */
+/* The index is the value of PLL_CFG[0:4] */
+/* This is documented in the MPC8240/5 Hardware Specs */
+
+short pll_pci_to_mem_multiplier[] = {
+#if defined(CONFIG_MPC8240)
+ 30, 30, 10, 10, 20, 10, 0, 10,
+ 10, 0, 20, 0, 20, 0, 20, 0,
+ 30, 0, 15, 0, 20, 0, 20, 0,
+ 25, 0, 10, 0, 15, 15, 0, 0,
+#elif defined(CONFIG_MPC8245)
+ 30, 30, 10, 10, 20, 10, 10, 10,
+ 10, 20, 20, 15, 20, 15, 20, 30,
+ 30, 40, 15, 40, 20, 25, 20, 40,
+ 25, 20, 10, 20, 15, 15, 15, 0,
+#else
+#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240)
+#endif
+};
+
+#define CU824_PLL_STATE_REG 0xFE80002F
+#define PCR 0x800000E2
+
+/* ------------------------------------------------------------------------- */
+
+/* compute the memory bus clock frequency */
+ulong get_bus_freq (ulong dummy)
+{
+ unsigned char pll_cfg;
+#if defined(CONFIG_MPC8240) && !defined(CONFIG_CU824)
+ return (CONFIG_SYS_CLK_FREQ) * (CONFIG_PLL_PCI_TO_MEM_MULTIPLIER);
+#elif defined(CONFIG_CU824)
+ pll_cfg = *(volatile unsigned char *) (CU824_PLL_STATE_REG);
+ pll_cfg &= 0x1f;
+#else
+ CONFIG_READ_BYTE(PCR, pll_cfg);
+ pll_cfg = (pll_cfg >> 3) & 0x1f;
+#endif
+ return ((CONFIG_SYS_CLK_FREQ) * pll_pci_to_mem_multiplier[pll_cfg] + 5) / 10;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+/* This gives the Memory to CPU Core multiplier times 10 */
+/* The index is the value of PLLRATIO in HID1 */
+/* This is documented in the MPC8240 Hardware Specs */
+/* This is not documented for MPC8245 ? FIXME */
+short pllratio_to_factor[] = {
+ 0, 0, 0, 10, 20, 20, 25, 45,
+ 30, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 10, 0, 0, 0, 45,
+ 30, 0, 40, 0, 0, 0, 35, 0,
+};
+
+/* compute the CPU and memory bus clock frequencies */
+int get_clocks (void)
+{
+ uint hid1 = mfspr(HID1);
+ hid1 = (hid1 >> (32-5)) & 0x1f;
+ gd->cpu_clk = (pllratio_to_factor[hid1] * get_bus_freq(0) + 5)
+ / 10;
+ gd->bus_clk = get_bus_freq(0);
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc824x/start.S b/arch/powerpc/cpu/mpc824x/start.S
new file mode 100644
index 0000000..0b9d898
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/start.S
@@ -0,0 +1,745 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0x00000100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating.
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ * This works because the cpu gives the FLASH (CS0) the whole
+ * address space at startup, and board_init lies as a echo of
+ * the flash somewhere up there in the memorymap.
+ *
+ * board_init will change CS0 to be positioned at the correct
+ * address and (s)dram will be positioned at address 0
+ */
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc824x.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* FP, Machine Check and Recoverable Interr. */
+#define MSR_KERNEL ( MSR_FP | MSR_ME | MSR_RI )
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+#if defined(CONFIG_FADS)
+ GOT_ENTRY(environment)
+#endif
+ END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+ .text
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ /* Initialize machine status; enable machine check interrupt */
+ /*----------------------------------------------------------------------*/
+ li r3, MSR_KERNEL /* Set FP, ME, RI flags */
+ mtmsr r3
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ addis r0,0,0x0000 /* lets make sure that r0 is really 0 */
+ mtspr HID0, r0 /* disable I and D caches */
+
+ mfspr r3, ICR /* clear Interrupt Cause Register */
+
+ mfmsr r3 /* turn off address translation */
+ addis r4,0,0xffff
+ ori r4,r4,0xffcf
+ and r3,r3,r4
+ mtmsr r3
+ isync
+ sync /* the MMU should be off... */
+
+
+in_flash:
+ /*
+ * Setup BATs - cannot be done in C since we don't have a stack yet
+ */
+ bl setup_bats
+
+ /* Enable MMU.
+ */
+ mfmsr r3
+ ori r3, r3, (MSR_IR | MSR_DR)
+ mtmsr r3
+
+ /* Enable and invalidate data cache.
+ */
+ mfspr r3, HID0
+ mr r2, r3
+ ori r3, r3, HID0_DCE | HID0_DCI
+ ori r2, r2, HID0_DCE
+ sync
+ mtspr HID0, r3
+ mtspr HID0, r2
+ sync
+
+ /* Allocate Initial RAM in data cache.
+ */
+ lis r3, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+ li r2, 128
+ mtctr r2
+1:
+ dcbz r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+
+ /* Lock way0 in data cache.
+ */
+ mfspr r3, 1011
+ lis r2, 0xffff
+ ori r2, r2, 0xff1f
+ and r3, r3, r2
+ ori r3, r3, 0x0080
+ sync
+ mtspr 1011, r3
+
+ /*
+ * Thisk the stack pointer *somewhere* sensible. Doesnt
+ * matter much where as we'll move it when we relocate
+ */
+ lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+ ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*----------------------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
+
+ bl board_init_f /* run 1st part of board init code (from Flash) */
+
+ /* NOTREACHED - board_init_f() does not return */
+
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(EXC_OFF_MACH_CHCK, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(EXC_OFF_DATA_STOR, DataStorage, UnknownException)
+
+/* Instruction Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(EXC_OFF_INS_STOR, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(EXC_OFF_EXTERNAL, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = EXC_OFF_ALIGN
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = EXC_OFF_PROGRAM
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* No FPU on MPC8xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(EXC_OFF_FPUNAVAIL, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(EXC_OFF_DECR, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+ STD_EXCEPTION(EXC_OFF_TRACE, SingleStep, UnknownException)
+
+ STD_EXCEPTION(EXC_OFF_FPUNASSIST, Trap_0e, UnknownException)
+ STD_EXCEPTION(EXC_OFF_PMI, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(EXC_OFF_ITME, InstructionTransMiss, UnknownException)
+ STD_EXCEPTION(EXC_OFF_DLTME, DataLoadTransMiss, UnknownException)
+ STD_EXCEPTION(EXC_OFF_DSTME, DataStoreTransMiss, UnknownException)
+ STD_EXCEPTION(EXC_OFF_IABE, InstructionBreakpoint, DebugException)
+ STD_EXCEPTION(EXC_OFF_SMIE, SysManageInt, UnknownException)
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+ STD_EXCEPTION(0x1c00, ReservedC, UnknownException)
+ STD_EXCEPTION(0x1d00, ReservedD, UnknownException)
+ STD_EXCEPTION(0x1e00, ReservedE, UnknownException)
+ STD_EXCEPTION(0x1f00, ReservedF, UnknownException)
+
+ STD_EXCEPTION(EXC_OFF_RMTE, RunModeTrace, UnknownException)
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+#if 0
+ andi. r23,r23,MSR_PR
+ mfspr r23,SPRG3 /* if from user, fix up tss.regs */
+ beq 2f
+ addi r24,r1,STACK_FRAME_OVERHEAD
+ stw r24,PT_REGS(r23)
+2: addi r2,r23,-TSS /* set r2 to current */
+ tovirt(r2,r2,r23)
+#endif
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+#if 0
+ addi r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
+ cmplw 0,r1,r2
+ cmplw 1,r1,r24
+ crand 1,1,4
+ bgt stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+#endif
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ ori r20,r20,0x30 /* enable IR, DR */
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/* Cache functions.
+*/
+ .globl icache_enable
+icache_enable:
+ mfspr r5,HID0 /* turn on the I cache. */
+ ori r5,r5,0x8800 /* Instruction cache only! */
+ addis r6,0,0xFFFF
+ ori r6,r6,0xF7FF
+ and r6,r5,r6 /* clear the invalidate bit */
+ sync
+ mtspr HID0,r5
+ mtspr HID0,r6
+ isync
+ sync
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r5,HID0
+ addis r6,0,0xFFFF
+ ori r6,r6,0x7FFF
+ and r5,r5,r6
+ sync
+ mtspr HID0,r5
+ isync
+ sync
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ srwi r3, r3, 15 /* >>15 & 1=> select bit 16 */
+ andi. r3, r3, 1
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r5,HID0 /* turn on the D cache. */
+ ori r5,r5,0x4400 /* Data cache only! */
+ mfspr r4, PVR /* read PVR */
+ srawi r3, r4, 16 /* shift off the least 16 bits */
+ cmpi 0, 0, r3, 0xC /* Check for Max pvr */
+ bne NotMax
+ ori r5,r5,0x0040 /* setting the DCFA bit, for Max rev 1 errata */
+NotMax:
+ addis r6,0,0xFFFF
+ ori r6,r6,0xFBFF
+ and r6,r5,r6 /* clear the invalidate bit */
+ sync
+ mtspr HID0,r5
+ mtspr HID0,r6
+ isync
+ sync
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r5,HID0
+ addis r6,0,0xFFFF
+ ori r6,r6,0xBFFF
+ and r5,r5,r6
+ sync
+ mtspr HID0,r5
+ isync
+ sync
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ srwi r3, r3, 14 /* >>14 & 1=> select bit 17 */
+ andi. r3, r3, 1
+ blr
+
+ .globl dc_read
+dc_read:
+/*TODO : who uses this, what should it do?
+*/
+ blr
+
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+#ifdef CONFIG_SYS_RAMBOOT
+ lis r4, CONFIG_SYS_SDRAM_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_SDRAM_BASE@l
+#else
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+#endif
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* the the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+4:
+/* Unlock the data cache and invalidate locked area */
+ xor r0, r0, r0
+ mtspr 1011, r0
+ lis r4, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r4, r4, CONFIG_SYS_INIT_RAM_ADDR@l
+ li r0, 128
+ mtctr r0
+41:
+ dcbi r0, r4
+ addi r4, r4, 32
+ bdnz 41b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+ cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ blt 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mtlr r4 /* restore link register */
+ blr
+
+ /* Setup the BAT registers.
+ */
+setup_bats:
+ lis r4, CONFIG_SYS_IBAT0L@h
+ ori r4, r4, CONFIG_SYS_IBAT0L@l
+ lis r3, CONFIG_SYS_IBAT0U@h
+ ori r3, r3, CONFIG_SYS_IBAT0U@l
+ mtspr IBAT0L, r4
+ mtspr IBAT0U, r3
+ isync
+
+ lis r4, CONFIG_SYS_DBAT0L@h
+ ori r4, r4, CONFIG_SYS_DBAT0L@l
+ lis r3, CONFIG_SYS_DBAT0U@h
+ ori r3, r3, CONFIG_SYS_DBAT0U@l
+ mtspr DBAT0L, r4
+ mtspr DBAT0U, r3
+ isync
+
+ lis r4, CONFIG_SYS_IBAT1L@h
+ ori r4, r4, CONFIG_SYS_IBAT1L@l
+ lis r3, CONFIG_SYS_IBAT1U@h
+ ori r3, r3, CONFIG_SYS_IBAT1U@l
+ mtspr IBAT1L, r4
+ mtspr IBAT1U, r3
+ isync
+
+ lis r4, CONFIG_SYS_DBAT1L@h
+ ori r4, r4, CONFIG_SYS_DBAT1L@l
+ lis r3, CONFIG_SYS_DBAT1U@h
+ ori r3, r3, CONFIG_SYS_DBAT1U@l
+ mtspr DBAT1L, r4
+ mtspr DBAT1U, r3
+ isync
+
+ lis r4, CONFIG_SYS_IBAT2L@h
+ ori r4, r4, CONFIG_SYS_IBAT2L@l
+ lis r3, CONFIG_SYS_IBAT2U@h
+ ori r3, r3, CONFIG_SYS_IBAT2U@l
+ mtspr IBAT2L, r4
+ mtspr IBAT2U, r3
+ isync
+
+ lis r4, CONFIG_SYS_DBAT2L@h
+ ori r4, r4, CONFIG_SYS_DBAT2L@l
+ lis r3, CONFIG_SYS_DBAT2U@h
+ ori r3, r3, CONFIG_SYS_DBAT2U@l
+ mtspr DBAT2L, r4
+ mtspr DBAT2U, r3
+ isync
+
+ lis r4, CONFIG_SYS_IBAT3L@h
+ ori r4, r4, CONFIG_SYS_IBAT3L@l
+ lis r3, CONFIG_SYS_IBAT3U@h
+ ori r3, r3, CONFIG_SYS_IBAT3U@l
+ mtspr IBAT3L, r4
+ mtspr IBAT3U, r3
+ isync
+
+ lis r4, CONFIG_SYS_DBAT3L@h
+ ori r4, r4, CONFIG_SYS_DBAT3L@l
+ lis r3, CONFIG_SYS_DBAT3U@h
+ ori r3, r3, CONFIG_SYS_DBAT3U@l
+ mtspr DBAT3L, r4
+ mtspr DBAT3U, r3
+ isync
+
+ /* Invalidate TLBs.
+ * -> for (val = 0; val < 0x20000; val+=0x1000)
+ * -> tlbie(val);
+ */
+ lis r3, 0
+ lis r5, 2
+
+1:
+ tlbie r3
+ addi r3, r3, 0x1000
+ cmp 0, 0, r3, r5
+ blt 1b
+
+ blr
diff --git a/arch/powerpc/cpu/mpc824x/traps.c b/arch/powerpc/cpu/mpc824x/traps.c
new file mode 100644
index 0000000..9bcdd8f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/traps.c
@@ -0,0 +1,210 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x00400000
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x000F0000) {
+ case (0x80000000>>12):
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13):
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14):
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000>>15):
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void DebugException(struct pt_regs *regs)
+{
+
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc824x/u-boot.lds b/arch/powerpc/cpu/mpc824x/u-boot.lds
new file mode 100644
index 0000000..4590fab
--- /dev/null
+++ b/arch/powerpc/cpu/mpc824x/u-boot.lds
@@ -0,0 +1,92 @@
+/*
+ * (C) Copyright 2001-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .text :
+ {
+ arch/powerpc/cpu/mpc824x/start.o (.text*)
+ *(.text*)
+ . = ALIGN(16);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc8260/Makefile b/arch/powerpc/cpu/mpc8260/Makefile
new file mode 100644
index 0000000..aa8b881
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/Makefile
@@ -0,0 +1,53 @@
+#
+# (C) Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+START = start.o kgdb.o
+COBJS = traps.o serial_smc.o serial_scc.o cpu.o cpu_init.o speed.o \
+ interrupts.o ether_fcc.o i2c.o commproc.o \
+ bedbug_603e.o pci.o spi.o
+
+COBJS-$(CONFIG_ETHER_ON_SCC) = ether_scc.o
+
+COBJS += $(COBJS-y)
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS) $(obj)kgdb.o)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc8260/bedbug_603e.c b/arch/powerpc/cpu/mpc8260/bedbug_603e.c
new file mode 100644
index 0000000..92f8957
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/bedbug_603e.c
@@ -0,0 +1,236 @@
+/*
+ * Bedbug Functions specific to the MPC603e core
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <bedbug/type.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+
+#if defined(CONFIG_CMD_BEDBUG) \
+ && (defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260))
+
+#define MAX_BREAK_POINTS 1
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug603e_init __P((void));
+void bedbug603e_do_break __P((cmd_tbl_t*,int,int,char*const[]));
+void bedbug603e_break_isr __P((struct pt_regs*));
+int bedbug603e_find_empty __P((void));
+int bedbug603e_set __P((int,unsigned long));
+int bedbug603e_clear __P((int));
+
+
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the processor. Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug603e_init( void )
+{
+ int i;
+ /* -------------------------------------------------- */
+
+ bug_ctx.hw_debug_enabled = 0;
+ bug_ctx.stopped = 0;
+ bug_ctx.current_bp = 0;
+ bug_ctx.regs = NULL;
+
+ bug_ctx.do_break = bedbug603e_do_break;
+ bug_ctx.break_isr = bedbug603e_break_isr;
+ bug_ctx.find_empty = bedbug603e_find_empty;
+ bug_ctx.set = bedbug603e_set;
+ bug_ctx.clear = bedbug603e_clear;
+
+ for( i = 1; i <= MAX_BREAK_POINTS; ++i )
+ (*bug_ctx.clear)( i );
+
+ puts ("BEDBUG:ready\n");
+ return;
+} /* bedbug_init_breakpoints */
+
+
+
+/* ======================================================================
+ * Set/clear/show the hardware breakpoint for the 603e. The "off"
+ * string will disable a specific breakpoint. The "show" string will
+ * display the current breakpoints. Otherwise an address will set a
+ * breakpoint at that address. Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug603e_do_break (cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ long addr; /* Address to break at */
+ int which_bp; /* Breakpoint number */
+ /* -------------------------------------------------- */
+
+ if (argc < 2) {
+ cmd_usage(cmdtp);
+ return;
+ }
+
+ /* Turn off a breakpoint */
+
+ if( strcmp( argv[ 1 ], "off" ) == 0 )
+ {
+ if( bug_ctx.hw_debug_enabled == 0 )
+ {
+ puts ( "No breakpoints enabled\n" );
+ return;
+ }
+
+ which_bp = simple_strtoul( argv[ 2 ], NULL, 10 );
+
+ if( bug_ctx.clear )
+ (*bug_ctx.clear)( which_bp );
+
+ printf( "Breakpoint %d removed\n", which_bp );
+ return;
+ }
+
+ /* Show a list of breakpoints */
+
+ if( strcmp( argv[ 1 ], "show" ) == 0 )
+ {
+ for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp )
+ {
+
+ addr = GET_IABR();
+
+ printf( "Breakpoint [%d]: ", which_bp );
+ if( (addr & 0x00000002) == 0 )
+ puts ( "NOT SET\n" );
+ else
+ disppc( (unsigned char *)(addr & 0xFFFFFFFC), 0, 1, bedbug_puts, F_RADHEX );
+ }
+ return;
+ }
+
+ /* Set a breakpoint at the address */
+
+ if(!(( isdigit( argv[ 1 ][ 0 ] )) ||
+ (( argv[ 1 ][ 0 ] >= 'a' ) && ( argv[ 1 ][ 0 ] <= 'f' )) ||
+ (( argv[ 1 ][ 0 ] >= 'A' ) && ( argv[ 1 ][ 0 ] <= 'F' )))) {
+ cmd_usage(cmdtp);
+ return;
+ }
+
+ addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+ if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 )
+ {
+ printf( "Breakpoint [%d]: ", which_bp );
+ disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+ }
+
+ return;
+} /* bedbug603e_do_break */
+
+
+
+/* ======================================================================
+ * Handle a breakpoint. Enter a mini main loop. Stay in the loop until
+ * the stopped flag in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug603e_break_isr( struct pt_regs *regs )
+{
+ unsigned long addr; /* Address stopped at */
+ /* -------------------------------------------------- */
+
+ bug_ctx.current_bp = 1;
+ addr = GET_IABR() & 0xFFFFFFFC;
+
+ bedbug_main_loop( addr, regs );
+ return;
+} /* bedbug603e_break_isr */
+
+
+
+/* ======================================================================
+ * See if the hardware breakpoint is available.
+ * ====================================================================== */
+
+int bedbug603e_find_empty( void )
+{
+ /* -------------------------------------------------- */
+
+ if( (GET_IABR() && 0x00000002) == 0 )
+ return 1;
+
+ return 0;
+} /* bedbug603e_find_empty */
+
+
+
+/* ======================================================================
+ * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint. If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0. Set the break
+ * address in the IABR register.
+ * ====================================================================== */
+
+int bedbug603e_set( int which_bp, unsigned long addr )
+{
+ /* -------------------------------------------------- */
+
+ if(( addr & 0x00000003 ) != 0 )
+ {
+ puts ( "Breakpoints must be on a 32 bit boundary\n" );
+ return 0;
+ }
+
+ /* Only look if which_bp == 0, else use which_bp */
+ if(( bug_ctx.find_empty ) && ( !which_bp ) &&
+ ( which_bp = (*bug_ctx.find_empty)()) == 0 )
+ {
+ puts ( "All breakpoints in use\n" );
+ return 0;
+ }
+
+ if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+ {
+ printf( "Invalid break point # %d\n", which_bp );
+ return 0;
+ }
+
+ if( ! bug_ctx.hw_debug_enabled )
+ {
+ bug_ctx.hw_debug_enabled = 1;
+ }
+
+ SET_IABR( addr | 0x00000002 );
+
+ return which_bp;
+} /* bedbug603e_set */
+
+
+
+/* ======================================================================
+ * Disable a specific breakoint by setting the IABR register to zero.
+ * ====================================================================== */
+
+int bedbug603e_clear( int which_bp )
+{
+ /* -------------------------------------------------- */
+
+ if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+ {
+ printf( "Invalid break point # (%d)\n", which_bp );
+ return -1;
+ }
+
+ SET_IABR( 0 );
+
+ return 0;
+} /* bedbug603e_clear */
+
+
+/* ====================================================================== */
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/commproc.c b/arch/powerpc/cpu/mpc8260/commproc.c
new file mode 100644
index 0000000..484bd17
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/commproc.c
@@ -0,0 +1,178 @@
+/*
+ * This file is based on "arch/powerpc/8260_io/commproc.c" - here is it's
+ * copyright notice:
+ *
+ * General Purpose functions for the global management of the
+ * 8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ * 2.3.99 Updates
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space. The allocator for that is here. When the communication
+ * process is reset, we reclaim the memory available. There is
+ * currently no deallocator for this memory.
+ */
+#include <common.h>
+#include <asm/cpm_8260.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void
+m8260_cpm_reset(void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile ulong count;
+
+ /* Reclaim the DP memory for our use.
+ */
+ gd->arch.dp_alloc_base = CPM_DATAONLY_BASE;
+ gd->arch.dp_alloc_top = gd->arch.dp_alloc_base + CPM_DATAONLY_SIZE;
+
+ /*
+ * Reset CPM
+ */
+ immr->im_cpm.cp_cpcr = CPM_CR_RST;
+ count = 0;
+ do { /* Spin until command processed */
+ __asm__ __volatile__ ("eieio");
+ } while ((immr->im_cpm.cp_cpcr & CPM_CR_FLG) && ++count < 1000000);
+
+#ifdef CONFIG_HARD_I2C
+ immr->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)] = 0;
+#endif
+}
+
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
+ */
+uint
+m8260_cpm_dpalloc(uint size, uint align)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ uint retloc;
+ uint align_mask, off;
+ uint savebase;
+
+ align_mask = align - 1;
+ savebase = gd->arch.dp_alloc_base;
+
+ off = gd->arch.dp_alloc_base & align_mask;
+ if (off != 0)
+ gd->arch.dp_alloc_base += (align - off);
+
+ if ((off = size & align_mask) != 0)
+ size += align - off;
+
+ if ((gd->arch.dp_alloc_base + size) >= gd->arch.dp_alloc_top) {
+ gd->arch.dp_alloc_base = savebase;
+ panic("m8260_cpm_dpalloc: ran out of dual port ram!");
+ }
+
+ retloc = gd->arch.dp_alloc_base;
+ gd->arch.dp_alloc_base += size;
+
+ memset((void *)&immr->im_dprambase[retloc], 0, size);
+
+ return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8260_cpm_hostalloc(uint size, uint align)
+{
+ /* the host might not even have RAM yet - just use dual port RAM */
+ return (m8260_cpm_dpalloc(size, align));
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK gd->arch.brg_clk
+#define BRG_UART_CLK (BRG_INT_CLK / 16)
+
+/* This function is used by UARTs, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+m8260_cpm_setbrg(uint brg, uint rate)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile uint *bp;
+ uint cd = BRG_UART_CLK / rate;
+
+ if ((BRG_UART_CLK % rate) < (rate / 2))
+ cd--;
+ if (brg < 4) {
+ bp = (uint *)&immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = (cd << 1) | CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+m8260_cpm_fastbrg(uint brg, uint rate, int div16)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+ if (div16)
+ *bp |= CPM_BRG_DIV16;
+}
+
+/* This function is used to set baud rate generators using an external
+ * clock source and 16x oversampling.
+ */
+
+void
+m8260_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile uint *bp;
+
+ if (brg < 4) {
+ bp = (uint *)&immr->im_brgc1;
+ }
+ else {
+ bp = (uint *)&immr->im_brgc5;
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+ if (pinsel == 0)
+ *bp |= CPM_BRG_EXTC_CLK3_9;
+ else
+ *bp |= CPM_BRG_EXTC_CLK5_15;
+}
diff --git a/arch/powerpc/cpu/mpc8260/config.mk b/arch/powerpc/cpu/mpc8260/config.mk
new file mode 100644
index 0000000..f091fa9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/config.mk
@@ -0,0 +1,27 @@
+#
+# (C) Copyright 2000-2010
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_8260 -DCONFIG_CPM2 -ffixed-r2 \
+ -mstring -mcpu=603e -mmultiple
diff --git a/arch/powerpc/cpu/mpc8260/cpu.c b/arch/powerpc/cpu/mpc8260/cpu.c
new file mode 100644
index 0000000..22e1a23
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/cpu.c
@@ -0,0 +1,337 @@
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC825x / MPC826x / MPC827x / MPC828x
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * modified by
+ * Wolfgang Denk <wd@denx.de>
+ *
+ * modified for 8260 by
+ * Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * added 8260 masks by
+ * Marius Groeger <mag@sysgo.de>
+ *
+ * added HiP7 (824x/827x/8280) processors support by
+ * Yuli Barcohen <yuli@arabellasw.com>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc8260.h>
+#include <netdev.h>
+#include <asm/processor.h>
+#include <asm/cpm_8260.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_GET_CPU_STR_F)
+extern int get_cpu_str_f (char *buf);
+#endif
+
+int checkcpu (void)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ ulong clock = gd->cpu_clk;
+ uint pvr = get_pvr ();
+ uint immr, rev, m, k;
+ char buf[32];
+
+ puts ("CPU: ");
+
+ switch (pvr) {
+ case PVR_8260:
+ case PVR_8260_HIP3:
+ k = 3;
+ break;
+ case PVR_8260_HIP4:
+ k = 4;
+ break;
+ case PVR_8260_HIP7R1:
+ case PVR_8260_HIP7RA:
+ case PVR_8260_HIP7:
+ k = 7;
+ break;
+ default:
+ return -1; /* whoops! not an MPC8260 */
+ }
+ rev = pvr & 0xff;
+
+ immr = immap->im_memctl.memc_immr;
+ if ((immr & IMMR_ISB_MSK) != CONFIG_SYS_IMMR)
+ return -1; /* whoops! someone moved the IMMR */
+
+#if defined(CONFIG_GET_CPU_STR_F)
+ get_cpu_str_f (buf);
+ printf ("%s (HiP%d Rev %02x, Mask ", buf, k, rev);
+#else
+ printf (CPU_ID_STR " (HiP%d Rev %02x, Mask ", k, rev);
+#endif
+
+ /*
+ * the bottom 16 bits of the immr are the Part Number and Mask Number
+ * (4-34); the 16 bits at PROFF_REVNUM (0x8af0) in dual port ram is the
+ * RISC Microcode Revision Number (13-10).
+ * For the 8260, Motorola doesn't include the Microcode Revision
+ * in the mask.
+ */
+ m = immr & (IMMR_PARTNUM_MSK | IMMR_MASKNUM_MSK);
+ k = immap->im_dprambase16[PROFF_REVNUM / sizeof(u16)];
+
+ switch (m) {
+ case 0x0000:
+ puts ("0.2 2J24M");
+ break;
+ case 0x0010:
+ puts ("A.0 K22A");
+ break;
+ case 0x0011:
+ puts ("A.1 1K22A-XC");
+ break;
+ case 0x0001:
+ puts ("B.1 1K23A");
+ break;
+ case 0x0021:
+ puts ("B.2 2K23A-XC");
+ break;
+ case 0x0023:
+ puts ("B.3 3K23A");
+ break;
+ case 0x0024:
+ puts ("C.2 6K23A");
+ break;
+ case 0x0060:
+ puts ("A.0(A) 2K25A");
+ break;
+ case 0x0062:
+ puts ("B.1 4K25A");
+ break;
+ case 0x0064:
+ puts ("C.0 5K25A");
+ break;
+ case 0x0A00:
+ puts ("0.0 0K49M");
+ break;
+ case 0x0A01:
+ puts ("0.1 1K49M");
+ break;
+ case 0x0A10:
+ puts ("1.0 1K49M");
+ break;
+ case 0x0C00:
+ puts ("0.0 0K50M");
+ break;
+ case 0x0C10:
+ puts ("1.0 1K50M");
+ break;
+ case 0x0D00:
+ puts ("0.0 0K50M");
+ break;
+ case 0x0D10:
+ puts ("1.0 1K50M");
+ break;
+ default:
+ printf ("unknown [immr=0x%04x,k=0x%04x]", m, k);
+ break;
+ }
+
+ printf (") at %s MHz\n", strmhz (buf, clock));
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* configures a UPM by writing into the UPM RAM array */
+/* uses bank 11 and a dummy physical address (=BRx_BA_MSK) */
+/* NOTE: the physical address chosen must not overlap into any other area */
+/* mapped by the memory controller because bank 11 has the lowest priority */
+
+void upmconfig (uint upm, uint * table, uint size)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile memctl8260_t *memctl = &immap->im_memctl;
+ volatile uchar *dummy = (uchar *) BRx_BA_MSK; /* set all BA bits */
+ uint i;
+
+ /* first set up bank 11 to reference the correct UPM at a dummy address */
+
+ memctl->memc_or11 = ORxU_AM_MSK; /* set all AM bits */
+
+ switch (upm) {
+
+ case UPMA:
+ memctl->memc_br11 =
+ ((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMA |
+ BRx_V;
+ memctl->memc_mamr = MxMR_OP_WARR;
+ break;
+
+ case UPMB:
+ memctl->memc_br11 =
+ ((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMB |
+ BRx_V;
+ memctl->memc_mbmr = MxMR_OP_WARR;
+ break;
+
+ case UPMC:
+ memctl->memc_br11 =
+ ((uint)dummy & BRx_BA_MSK) | BRx_PS_32 | BRx_MS_UPMC |
+ BRx_V;
+ memctl->memc_mcmr = MxMR_OP_WARR;
+ break;
+
+ default:
+ panic ("upmconfig passed invalid UPM number (%u)\n", upm);
+ break;
+
+ }
+
+ /*
+ * at this point, the dummy address is set up to access the selected UPM,
+ * the MAD pointer is zero, and the MxMR OP is set for writing to RAM
+ *
+ * now we simply load the mdr with each word and poke the dummy address.
+ * the MAD is incremented on each access.
+ */
+
+ for (i = 0; i < size; i++) {
+ memctl->memc_mdr = table[i];
+ *dummy = 0;
+ }
+
+ /* now kill bank 11 */
+ memctl->memc_br11 = 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if !defined(CONFIG_HAVE_OWN_RESET)
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong msr, addr;
+
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+ immap->im_clkrst.car_rmr = RMR_CSRE; /* Checkstop Reset enable */
+
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /*
+ * Trying to execute the next instruction at a non-existing address
+ * should cause a machine check, resulting in reset
+ */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+ addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+ /*
+ * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE
+ * - sizeof (ulong) is usually a valid address. Better pick an address
+ * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+ */
+ addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+ ((void (*)(void)) addr) ();
+ return 1;
+
+}
+#endif /* CONFIG_HAVE_OWN_RESET */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ */
+unsigned long get_tbclk (void)
+{
+ ulong tbclk;
+
+ tbclk = (gd->bus_clk + 3L) / 4L;
+
+ return (tbclk);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+ int re_enable = disable_interrupts ();
+
+ reset_8260_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+ if (re_enable)
+ enable_interrupts ();
+}
+#endif /* CONFIG_WATCHDOG */
+
+/* ------------------------------------------------------------------------- */
+#if defined(CONFIG_OF_LIBFDT) && defined (CONFIG_OF_BOARD_SETUP)
+void ft_cpu_setup (void *blob, bd_t *bd)
+{
+#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\
+ defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3)
+ fdt_fixup_ethernet(blob);
+#endif
+
+ do_fixup_by_compat_u32(blob, "fsl,cpm2-brg",
+ "clock-frequency", bd->bi_brgfreq, 1);
+
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", OF_TBCLK, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "clock-frequency", bd->bi_intfreq, 1);
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
+#endif /* CONFIG_OF_LIBFDT */
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_ETHER_ON_FCC)
+ fec_initialize(bis);
+#endif
+#if defined(CONFIG_ETHER_ON_SCC)
+ mpc82xx_scc_enet_initialize(bis);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8260/cpu_init.c b/arch/powerpc/cpu/mpc8260/cpu_init.c
new file mode 100644
index 0000000..3964e60
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/cpu_init.c
@@ -0,0 +1,292 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <ioports.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+extern unsigned long board_get_cpu_clk_f (void);
+#endif
+
+static void config_8260_ioports (volatile immap_t * immr)
+{
+ int portnum;
+
+ for (portnum = 0; portnum < 4; portnum++) {
+ uint pmsk = 0,
+ ppar = 0,
+ psor = 0,
+ pdir = 0,
+ podr = 0,
+ pdat = 0;
+ iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0];
+ iop_conf_t *eiopc = iopc + 32;
+ uint msk = 1;
+
+ /*
+ * NOTE:
+ * index 0 refers to pin 31,
+ * index 31 refers to pin 0
+ */
+ while (iopc < eiopc) {
+ if (iopc->conf) {
+ pmsk |= msk;
+ if (iopc->ppar)
+ ppar |= msk;
+ if (iopc->psor)
+ psor |= msk;
+ if (iopc->pdir)
+ pdir |= msk;
+ if (iopc->podr)
+ podr |= msk;
+ if (iopc->pdat)
+ pdat |= msk;
+ }
+
+ msk <<= 1;
+ iopc++;
+ }
+
+ if (pmsk != 0) {
+ volatile ioport_t *iop = ioport_addr (immr, portnum);
+ uint tpmsk = ~pmsk;
+
+ /*
+ * the (somewhat confused) paragraph at the
+ * bottom of page 35-5 warns that there might
+ * be "unknown behaviour" when programming
+ * PSORx and PDIRx, if PPARx = 1, so I
+ * decided this meant I had to disable the
+ * dedicated function first, and enable it
+ * last.
+ */
+ iop->ppar &= tpmsk;
+ iop->psor = (iop->psor & tpmsk) | psor;
+ iop->podr = (iop->podr & tpmsk) | podr;
+ iop->pdat = (iop->pdat & tpmsk) | pdat;
+ iop->pdir = (iop->pdir & tpmsk) | pdir;
+ iop->ppar |= ppar;
+ }
+ }
+}
+
+#define SET_VAL_MASK(a, b, mask) ((a & mask) | (b & ~mask))
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * immr)
+{
+#if !defined(CONFIG_COGENT) /* done in start.S for the cogent */
+ uint sccr;
+#endif
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+ unsigned long cpu_clk;
+#endif
+ volatile memctl8260_t *memctl = &immr->im_memctl;
+ extern void m8260_cpm_reset (void);
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ memset ((void *) gd, 0, sizeof (gd_t));
+
+ /* RSR - Reset Status Register - clear all status (5-4) */
+ gd->arch.reset_status = immr->im_clkrst.car_rsr;
+ immr->im_clkrst.car_rsr = RSR_ALLBITS;
+
+ /* RMR - Reset Mode Register - contains checkstop reset enable (5-5) */
+ immr->im_clkrst.car_rmr = CONFIG_SYS_RMR;
+
+ /* BCR - Bus Configuration Register (4-25) */
+#if defined(CONFIG_SYS_BCR_60x) && (CONFIG_SYS_BCR_SINGLE)
+ if (immr->im_siu_conf.sc_bcr & BCR_EBM) {
+ immr->im_siu_conf.sc_bcr = SET_VAL_MASK(immr->im_siu_conf.sc_bcr, CONFIG_SYS_BCR_60x, 0x80000010);
+ } else {
+ immr->im_siu_conf.sc_bcr = SET_VAL_MASK(immr->im_siu_conf.sc_bcr, CONFIG_SYS_BCR_SINGLE, 0x80000010);
+ }
+#else
+ immr->im_siu_conf.sc_bcr = CONFIG_SYS_BCR;
+#endif
+
+ /* SIUMCR - contains debug pin configuration (4-31) */
+#if defined(CONFIG_SYS_SIUMCR_LOW) && (CONFIG_SYS_SIUMCR_HIGH)
+ cpu_clk = board_get_cpu_clk_f ();
+ if (cpu_clk >= 100000000) {
+ immr->im_siu_conf.sc_siumcr = SET_VAL_MASK(immr->im_siu_conf.sc_siumcr, CONFIG_SYS_SIUMCR_HIGH, 0x9f3cc000);
+ } else {
+ immr->im_siu_conf.sc_siumcr = SET_VAL_MASK(immr->im_siu_conf.sc_siumcr, CONFIG_SYS_SIUMCR_LOW, 0x9f3cc000);
+ }
+#else
+ immr->im_siu_conf.sc_siumcr = CONFIG_SYS_SIUMCR;
+#endif
+
+ config_8260_ioports (immr);
+
+ /* initialize time counter status and control register (4-40) */
+ immr->im_sit.sit_tmcntsc = CONFIG_SYS_TMCNTSC;
+
+ /* initialize the PIT (4-42) */
+ immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+#if !defined(CONFIG_COGENT) /* done in start.S for the cogent */
+ /* System clock control register (9-8) */
+ sccr = immr->im_clkrst.car_sccr &
+ (SCCR_PCI_MODE | SCCR_PCI_MODCK | SCCR_PCIDF_MSK);
+ immr->im_clkrst.car_sccr = sccr |
+ (CONFIG_SYS_SCCR & ~(SCCR_PCI_MODE | SCCR_PCI_MODCK | SCCR_PCIDF_MSK) );
+#endif /* !CONFIG_COGENT */
+
+ /*
+ * Memory Controller:
+ */
+
+ /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+ * addresses - these have to be modified later when FLASH size
+ * has been determined
+ */
+
+#if defined(CONFIG_SYS_OR0_REMAP)
+ memctl->memc_or0 = CONFIG_SYS_OR0_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+ memctl->memc_or1 = CONFIG_SYS_OR1_REMAP;
+#endif
+
+ /* now restrict to preliminary range */
+ /* the PS came from the HRCW, don't change it */
+ memctl->memc_br0 = SET_VAL_MASK(memctl->memc_br0 , CONFIG_SYS_BR0_PRELIM, BRx_PS_MSK);
+ memctl->memc_or0 = CONFIG_SYS_OR0_PRELIM;
+
+#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM)
+ memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM;
+ memctl->memc_br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+ memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM;
+ memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM)
+ memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
+ memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM)
+ memctl->memc_or4 = CONFIG_SYS_OR4_PRELIM;
+ memctl->memc_br4 = CONFIG_SYS_BR4_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM)
+ memctl->memc_or5 = CONFIG_SYS_OR5_PRELIM;
+ memctl->memc_br5 = CONFIG_SYS_BR5_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM)
+ memctl->memc_or6 = CONFIG_SYS_OR6_PRELIM;
+ memctl->memc_br6 = CONFIG_SYS_BR6_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM)
+ memctl->memc_or7 = CONFIG_SYS_OR7_PRELIM;
+ memctl->memc_br7 = CONFIG_SYS_BR7_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR8_PRELIM) && defined(CONFIG_SYS_OR8_PRELIM)
+ memctl->memc_or8 = CONFIG_SYS_OR8_PRELIM;
+ memctl->memc_br8 = CONFIG_SYS_BR8_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR9_PRELIM) && defined(CONFIG_SYS_OR9_PRELIM)
+ memctl->memc_or9 = CONFIG_SYS_OR9_PRELIM;
+ memctl->memc_br9 = CONFIG_SYS_BR9_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR10_PRELIM) && defined(CONFIG_SYS_OR10_PRELIM)
+ memctl->memc_or10 = CONFIG_SYS_OR10_PRELIM;
+ memctl->memc_br10 = CONFIG_SYS_BR10_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_BR11_PRELIM) && defined(CONFIG_SYS_OR11_PRELIM)
+ memctl->memc_or11 = CONFIG_SYS_OR11_PRELIM;
+ memctl->memc_br11 = CONFIG_SYS_BR11_PRELIM;
+#endif
+
+ m8260_cpm_reset ();
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+ volatile immap_t *immr = (immap_t *) gd->bd->bi_immr_base;
+
+ immr->im_cpm.cp_rccr = CONFIG_SYS_RCCR;
+
+ return (0);
+}
+
+/*
+ * print out the reason for the reset
+ */
+int prt_8260_rsr (void)
+{
+ static struct {
+ ulong mask;
+ char *desc;
+ } bits[] = {
+ {
+ RSR_JTRS, "JTAG"}, {
+ RSR_CSRS, "Check Stop"}, {
+ RSR_SWRS, "Software Watchdog"}, {
+ RSR_BMRS, "Bus Monitor"}, {
+ RSR_ESRS, "External Soft"}, {
+ RSR_EHRS, "External Hard"}
+ };
+ static int n = sizeof bits / sizeof bits[0];
+ ulong rsr = gd->arch.reset_status;
+ int i;
+ char *sep;
+
+ puts (CPU_ID_STR " Reset Status:");
+
+ sep = " ";
+ for (i = 0; i < n; i++)
+ if (rsr & bits[i].mask) {
+ printf ("%s%s", sep, bits[i].desc);
+ sep = ", ";
+ }
+
+ puts ("\n\n");
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
new file mode 100644
index 0000000..1853451
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -0,0 +1,1188 @@
+/*
+ * MPC8260 FCC Fast Ethernet
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8260 FCC Fast Ethernet
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * This code will not perform the IO port configuration. This should be
+ * done in the iop_conf_t structure specific for the board.
+ *
+ * TODO:
+ * add a PHY driver to do the negotiation
+ * reflect negotiation results in FPSMR
+ * look for ways to configure the board specific stuff elsewhere, eg.
+ * config_xxx.h or the board directory
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/cpm_8260.h>
+#include <mpc8260.h>
+#include <command.h>
+#include <config.h>
+#include <net.h>
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET)
+
+static struct ether_fcc_info_s
+{
+ int ether_index;
+ int proff_enet;
+ ulong cpm_cr_enet_sblock;
+ ulong cpm_cr_enet_page;
+ ulong cmxfcr_mask;
+ ulong cmxfcr_value;
+}
+ ether_fcc_info[] =
+{
+#ifdef CONFIG_ETHER_ON_FCC1
+{
+ 0,
+ PROFF_FCC1,
+ CPM_CR_FCC1_SBLOCK,
+ CPM_CR_FCC1_PAGE,
+ CONFIG_SYS_CMXFCR_MASK1,
+ CONFIG_SYS_CMXFCR_VALUE1
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC2
+{
+ 1,
+ PROFF_FCC2,
+ CPM_CR_FCC2_SBLOCK,
+ CPM_CR_FCC2_PAGE,
+ CONFIG_SYS_CMXFCR_MASK2,
+ CONFIG_SYS_CMXFCR_VALUE2
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC3
+{
+ 2,
+ PROFF_FCC3,
+ CPM_CR_FCC3_SBLOCK,
+ CPM_CR_FCC3_PAGE,
+ CONFIG_SYS_CMXFCR_MASK3,
+ CONFIG_SYS_CMXFCR_VALUE3
+},
+#endif
+};
+
+/*---------------------------------------------------------------------*/
+
+/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */
+#define PKT_MAXDMA_SIZE 1520
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets. */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+
+/* Maximum input buffer size. Must be a multiple of 32. */
+#define PKT_MAXBLR_SIZE 1536
+
+#define TOUT_LOOP 1000000
+
+#define TX_BUF_CNT 2
+#ifdef __GNUC__
+static char txbuf[TX_BUF_CNT][PKT_MAXBLR_SIZE] __attribute__ ((aligned(8)));
+#else
+#error "txbuf must be 64-bit aligned"
+#endif
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * FCC Ethernet Tx and Rx buffer descriptors.
+ * Provide for Double Buffering
+ * Note: PKTBUFSRX is defined in net.h
+ */
+
+typedef volatile struct rtxbd {
+ cbd_t rxbd[PKTBUFSRX];
+ cbd_t txbd[TX_BUF_CNT];
+} RTXBD;
+
+/* Good news: the FCC supports external BDs! */
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+static int fec_send(struct eth_device *dev, void *packet, int length)
+{
+ int i;
+ int result = 0;
+
+ if (length <= 0) {
+ printf("fec: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ puts ("fec: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+ rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx.txbd[txIdx].cbd_datlen = length;
+ rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |
+ BD_ENET_TX_WRAP);
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ puts ("fec: tx error\n");
+ goto out;
+ }
+ }
+
+#ifdef ET_DEBUG
+ printf("cycles: %d status: %04x\n", i, rtx.txbd[txIdx].cbd_sc);
+#endif
+
+ /* return only status bits */
+ result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+
+out:
+ return result;
+}
+
+static int fec_recv(struct eth_device* dev)
+{
+ int length;
+
+ for (;;)
+ {
+ if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+ length = rtx.rxbd[rxIdx].cbd_datlen;
+
+ if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
+ printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
+ }
+ else {
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ }
+
+
+ /* Give the buffer back to the FCC. */
+ rtx.rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ }
+ else {
+ rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+ }
+ return length;
+}
+
+
+static int fec_init(struct eth_device* dev, bd_t *bis)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ int i;
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8260_t *cp = &(immr->im_cpm);
+ fcc_enet_t *pram_ptr;
+ unsigned long mem_addr;
+
+#if 0
+ mii_discover_phy();
+#endif
+
+ /* 28.9 - (1-2): ioports have been set up already */
+
+ /* 28.9 - (3): connect FCC's tx and rx clocks */
+ immr->im_cpmux.cmx_uar = 0;
+ immr->im_cpmux.cmx_fcr = (immr->im_cpmux.cmx_fcr & ~info->cmxfcr_mask) |
+ info->cmxfcr_value;
+
+ /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
+ immr->im_fcc[info->ether_index].fcc_gfmr =
+ FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+
+ /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet */
+ immr->im_fcc[info->ether_index].fcc_fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+
+ /* 28.9 - (6): FDSR: Ethernet Syn */
+ immr->im_fcc[info->ether_index].fcc_fdsr = 0xD555;
+
+ /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
+ rxIdx = 0;
+ txIdx = 0;
+
+ /* Setup Receiver Buffer Descriptors */
+ for (i = 0; i < PKTBUFSRX; i++)
+ {
+ rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ rtx.rxbd[i].cbd_datlen = 0;
+ rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+ }
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /* Setup Ethernet Transmitter Buffer Descriptors */
+ for (i = 0; i < TX_BUF_CNT; i++)
+ {
+ rtx.txbd[i].cbd_sc = (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+ rtx.txbd[i].cbd_datlen = 0;
+ rtx.txbd[i].cbd_bufaddr = (uint)&txbuf[i][0];
+ }
+ rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /* 28.9 - (7): initialise parameter ram */
+ pram_ptr = (fcc_enet_t *)&(immr->im_dprambase[info->proff_enet]);
+
+ /* clear whole structure to make sure all reserved fields are zero */
+ memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
+
+ /*
+ * common Parameter RAM area
+ *
+ * Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ */
+ mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
+ pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
+ pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
+ /*
+ * Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+ pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
+ CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+ pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
+ CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
+
+ /* protocol-specific area */
+ pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */
+ pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */
+ pram_ptr->fen_retlim = 15; /* Retry limit threshold */
+ pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ /*
+ * Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ * So, far we have only been given one Ethernet address. We make
+ * it unique by setting a few bits in the upper byte of the
+ * non-static part of the address.
+ */
+#define ea eth_get_dev()->enetaddr
+ pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
+ pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
+ pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+ pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+ /* pad pointer. use tiptr since we don't need a specific padding char */
+ pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
+ pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length */
+ pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length */
+ pram_ptr->fen_rfthr = 1;
+ pram_ptr->fen_rfcnt = 1;
+#if 0
+ printf("pram_ptr->fen_genfcc.fcc_rbase %08lx\n",
+ pram_ptr->fen_genfcc.fcc_rbase);
+ printf("pram_ptr->fen_genfcc.fcc_tbase %08lx\n",
+ pram_ptr->fen_genfcc.fcc_tbase);
+#endif
+
+ /* 28.9 - (8): clear out events in FCCE */
+ immr->im_fcc[info->ether_index].fcc_fcce = ~0x0;
+
+ /* 28.9 - (9): FCCM: mask all events */
+ immr->im_fcc[info->ether_index].fcc_fccm = 0;
+
+ /* 28.9 - (10-12): we don't use ethernet interrupts */
+
+ /* 28.9 - (13)
+ *
+ * Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cp->cp_cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
+ info->cpm_cr_enet_sblock,
+ 0x0c,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ do {
+ __asm__ __volatile__ ("eieio");
+ } while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* 28.9 - (14): enable tx/rx in gfmr */
+ immr->im_fcc[info->ether_index].fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+
+ return 1;
+}
+
+static void fec_halt(struct eth_device* dev)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ /* write GFMR: disable tx/rx */
+ immr->im_fcc[info->ether_index].fcc_gfmr &=
+ ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+}
+
+int fec_initialize(bd_t *bis)
+{
+ struct eth_device* dev;
+ int i;
+
+ for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+ {
+ dev = (struct eth_device*) malloc(sizeof *dev);
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "FCC%d",
+ ether_fcc_info[i].ether_index + 1);
+ dev->priv = &ether_fcc_info[i];
+ dev->init = fec_init;
+ dev->halt = fec_halt;
+ dev->send = fec_send;
+ dev->recv = fec_recv;
+
+ eth_register(dev);
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
+ && defined(CONFIG_BITBANGMII)
+ miiphy_register(dev->name,
+ bb_miiphy_read, bb_miiphy_write);
+#endif
+ }
+
+ return 1;
+}
+
+#ifdef CONFIG_ETHER_LOOPBACK_TEST
+
+#define ELBT_BUFSZ 1024 /* must be multiple of 32 */
+
+#define ELBT_CRCSZ 4
+
+#define ELBT_NRXBD 4 /* must be at least 2 */
+#define ELBT_NTXBD 4
+
+#define ELBT_MAXRXERR 32
+#define ELBT_MAXTXERR 32
+
+#define ELBT_CLSWAIT 1000 /* msec to wait for further input frames */
+
+typedef
+ struct {
+ uint off;
+ char *lab;
+ }
+elbt_prdesc;
+
+typedef
+ struct {
+ uint _l, _f, m, bc, mc, lg, no, sh, cr, ov, cl;
+ uint badsrc, badtyp, badlen, badbit;
+ }
+elbt_rxeacc;
+
+static elbt_prdesc rxeacc_descs[] = {
+ { offsetof(elbt_rxeacc, _l), "Not Last in Frame" },
+ { offsetof(elbt_rxeacc, _f), "Not First in Frame" },
+ { offsetof(elbt_rxeacc, m), "Address Miss" },
+ { offsetof(elbt_rxeacc, bc), "Broadcast Address" },
+ { offsetof(elbt_rxeacc, mc), "Multicast Address" },
+ { offsetof(elbt_rxeacc, lg), "Frame Length Violation"},
+ { offsetof(elbt_rxeacc, no), "Non-Octet Alignment" },
+ { offsetof(elbt_rxeacc, sh), "Short Frame" },
+ { offsetof(elbt_rxeacc, cr), "CRC Error" },
+ { offsetof(elbt_rxeacc, ov), "Overrun" },
+ { offsetof(elbt_rxeacc, cl), "Collision" },
+ { offsetof(elbt_rxeacc, badsrc), "Bad Src Address" },
+ { offsetof(elbt_rxeacc, badtyp), "Bad Frame Type" },
+ { offsetof(elbt_rxeacc, badlen), "Bad Frame Length" },
+ { offsetof(elbt_rxeacc, badbit), "Data Compare Errors" },
+};
+static int rxeacc_ndesc = sizeof (rxeacc_descs) / sizeof (rxeacc_descs[0]);
+
+typedef
+ struct {
+ uint def, hb, lc, rl, rc, un, csl;
+ }
+elbt_txeacc;
+
+static elbt_prdesc txeacc_descs[] = {
+ { offsetof(elbt_txeacc, def), "Defer Indication" },
+ { offsetof(elbt_txeacc, hb), "Heartbeat" },
+ { offsetof(elbt_txeacc, lc), "Late Collision" },
+ { offsetof(elbt_txeacc, rl), "Retransmission Limit" },
+ { offsetof(elbt_txeacc, rc), "Retry Count" },
+ { offsetof(elbt_txeacc, un), "Underrun" },
+ { offsetof(elbt_txeacc, csl), "Carrier Sense Lost" },
+};
+static int txeacc_ndesc = sizeof (txeacc_descs) / sizeof (txeacc_descs[0]);
+
+typedef
+ struct {
+ uchar rxbufs[ELBT_NRXBD][ELBT_BUFSZ];
+ uchar txbufs[ELBT_NTXBD][ELBT_BUFSZ];
+ cbd_t rxbd[ELBT_NRXBD];
+ cbd_t txbd[ELBT_NTXBD];
+ enum { Idle, Running, Closing, Closed } state;
+ int proff, page, sblock;
+ uint clstime, nsent, ntxerr, nrcvd, nrxerr;
+ ushort rxerrs[ELBT_MAXRXERR], txerrs[ELBT_MAXTXERR];
+ elbt_rxeacc rxeacc;
+ elbt_txeacc txeacc;
+ } __attribute__ ((aligned(8)))
+elbt_chan;
+
+static uchar patbytes[ELBT_NTXBD] = {
+ 0xff, 0xaa, 0x55, 0x00
+};
+static uint patwords[ELBT_NTXBD] = {
+ 0xffffffff, 0xaaaaaaaa, 0x55555555, 0x00000000
+};
+
+#ifdef __GNUC__
+static elbt_chan elbt_chans[3] __attribute__ ((aligned(8)));
+#else
+#error "elbt_chans must be 64-bit aligned"
+#endif
+
+#define CPM_CR_GRACEFUL_STOP_TX ((ushort)0x0005)
+
+static elbt_prdesc epram_descs[] = {
+ { offsetof(fcc_enet_t, fen_crcec), "CRC Errors" },
+ { offsetof(fcc_enet_t, fen_alec), "Alignment Errors" },
+ { offsetof(fcc_enet_t, fen_disfc), "Discarded Frames" },
+ { offsetof(fcc_enet_t, fen_octc), "Octets" },
+ { offsetof(fcc_enet_t, fen_colc), "Collisions" },
+ { offsetof(fcc_enet_t, fen_broc), "Broadcast Frames" },
+ { offsetof(fcc_enet_t, fen_mulc), "Multicast Frames" },
+ { offsetof(fcc_enet_t, fen_uspc), "Undersize Frames" },
+ { offsetof(fcc_enet_t, fen_frgc), "Fragments" },
+ { offsetof(fcc_enet_t, fen_ospc), "Oversize Frames" },
+ { offsetof(fcc_enet_t, fen_jbrc), "Jabbers" },
+ { offsetof(fcc_enet_t, fen_p64c), "64 Octet Frames" },
+ { offsetof(fcc_enet_t, fen_p65c), "65-127 Octet Frames" },
+ { offsetof(fcc_enet_t, fen_p128c), "128-255 Octet Frames" },
+ { offsetof(fcc_enet_t, fen_p256c), "256-511 Octet Frames" },
+ { offsetof(fcc_enet_t, fen_p512c), "512-1023 Octet Frames" },
+ { offsetof(fcc_enet_t, fen_p1024c), "1024-1518 Octet Frames"},
+};
+static int epram_ndesc = sizeof (epram_descs) / sizeof (epram_descs[0]);
+
+/*
+ * given an elbt_prdesc array and an array of base addresses, print
+ * each prdesc down the screen with the values fetched from each
+ * base address across the screen
+ */
+static void
+print_desc (elbt_prdesc descs[], int ndesc, uchar *bases[], int nbase)
+{
+ elbt_prdesc *dp = descs, *edp = dp + ndesc;
+ int i;
+
+ printf ("%32s", "");
+
+ for (i = 0; i < nbase; i++)
+ printf (" Channel %d", i);
+
+ putc ('\n');
+
+ while (dp < edp) {
+
+ printf ("%-32s", dp->lab);
+
+ for (i = 0; i < nbase; i++) {
+ uint val = *(uint *)(bases[i] + dp->off);
+
+ printf (" %10u", val);
+ }
+
+ putc ('\n');
+
+ dp++;
+ }
+}
+
+/*
+ * return number of bits that are set in a value; value contains
+ * nbits (right-justified) bits.
+ */
+static uint __inline__
+nbs (uint value, uint nbits)
+{
+ uint cnt = 0;
+#if 1
+ uint pos = sizeof (uint) * 8;
+
+ __asm__ __volatile__ ("\
+ mtctr %2\n\
+1: rlwnm. %2,%1,%4,31,31\n\
+ beq 2f\n\
+ addi %0,%0,1\n\
+2: subi %4,%4,1\n\
+ bdnz 1b"
+ : "=r"(cnt)
+ : "r"(value), "r"(nbits), "r"(cnt), "r"(pos)
+ : "ctr", "cc" );
+#else
+ uint mask = 1;
+
+ do {
+ if (value & mask)
+ cnt++;
+ mask <<= 1;
+ } while (--nbits);
+#endif
+
+ return (cnt);
+}
+
+static ulong
+badbits (uchar *bp, int n, ulong pat)
+{
+ ulong *lp, cnt = 0;
+ int nl;
+
+ while (n > 0 && ((ulong)bp & (sizeof (ulong) - 1)) != 0) {
+ uchar diff;
+
+ diff = *bp++ ^ (uchar)pat;
+
+ if (diff)
+ cnt += nbs ((ulong)diff, 8);
+
+ n--;
+ }
+
+ lp = (ulong *)bp;
+ nl = n / sizeof (ulong);
+ n -= nl * sizeof (ulong);
+
+ while (nl > 0) {
+ ulong diff;
+
+ diff = *lp++ ^ pat;
+
+ if (diff)
+ cnt += nbs (diff, 32);
+
+ nl--;
+ }
+
+ bp = (uchar *)lp;
+
+ while (n > 0) {
+ uchar diff;
+
+ diff = *bp++ ^ (uchar)pat;
+
+ if (diff)
+ cnt += nbs ((ulong)diff, 8);
+
+ n--;
+ }
+
+ return (cnt);
+}
+
+static inline unsigned short
+swap16 (unsigned short x)
+{
+ return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
+}
+
+/* broadcast is not an error - we send them like that */
+#define BD_ENET_RX_ERRS (BD_ENET_RX_STATS & ~BD_ENET_RX_BC)
+
+void
+eth_loopback_test (void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8260_t *cp = &(immr->im_cpm);
+ int c, nclosed;
+ ulong runtime, nmsec;
+ uchar *bases[3];
+
+ puts ("FCC Ethernet External loopback test\n");
+
+ eth_getenv_enetaddr("ethaddr", NetOurEther);
+
+ /*
+ * global initialisations for all FCC channels
+ */
+
+ /* 28.9 - (1-2): ioports have been set up already */
+
+#if defined(CONFIG_HYMOD)
+ /*
+ * Attention: this is board-specific
+ * 0, FCC1
+ * 1, FCC2
+ * 2, FCC3
+ */
+# define FCC_START_LOOP 0
+# define FCC_END_LOOP 2
+
+ /*
+ * Attention: this is board-specific
+ * - FCC1 Rx-CLK is CLK10
+ * - FCC1 Tx-CLK is CLK11
+ * - FCC2 Rx-CLK is CLK13
+ * - FCC2 Tx-CLK is CLK14
+ * - FCC3 Rx-CLK is CLK15
+ * - FCC3 Tx-CLK is CLK16
+ */
+
+ /* 28.9 - (3): connect FCC's tx and rx clocks */
+ immr->im_cpmux.cmx_uar = 0;
+ immr->im_cpmux.cmx_fcr = CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK11|\
+ CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14|\
+ CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16;
+#elif defined(CONFIG_SACSng)
+ /*
+ * Attention: this is board-specific
+ * 1, FCC2
+ */
+# define FCC_START_LOOP 1
+# define FCC_END_LOOP 1
+
+ /*
+ * Attention: this is board-specific
+ * - FCC2 Rx-CLK is CLK13
+ * - FCC2 Tx-CLK is CLK14
+ */
+
+ /* 28.9 - (3): connect FCC's tx and rx clocks */
+ immr->im_cpmux.cmx_uar = 0;
+ immr->im_cpmux.cmx_fcr = CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14;
+#else
+#error "eth_loopback_test not supported on your board"
+#endif
+
+ puts ("Initialise FCC channels:");
+
+ for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
+ elbt_chan *ecp = &elbt_chans[c];
+ volatile fcc_t *fcp = &immr->im_fcc[c];
+ volatile fcc_enet_t *fpp;
+ int i;
+ ulong addr;
+
+ /*
+ * initialise channel data
+ */
+
+ printf (" %d", c);
+
+ memset ((void *)ecp, 0, sizeof (*ecp));
+
+ ecp->state = Idle;
+
+ switch (c) {
+
+ case 0: /* FCC1 */
+ ecp->proff = PROFF_FCC1;
+ ecp->page = CPM_CR_FCC1_PAGE;
+ ecp->sblock = CPM_CR_FCC1_SBLOCK;
+ break;
+
+ case 1: /* FCC2 */
+ ecp->proff = PROFF_FCC2;
+ ecp->page = CPM_CR_FCC2_PAGE;
+ ecp->sblock = CPM_CR_FCC2_SBLOCK;
+ break;
+
+ case 2: /* FCC3 */
+ ecp->proff = PROFF_FCC3;
+ ecp->page = CPM_CR_FCC3_PAGE;
+ ecp->sblock = CPM_CR_FCC3_SBLOCK;
+ break;
+ }
+
+ /*
+ * set up tx buffers and bds
+ */
+
+ for (i = 0; i < ELBT_NTXBD; i++) {
+ cbd_t *bdp = &ecp->txbd[i];
+ uchar *bp = &ecp->txbufs[i][0];
+
+ bdp->cbd_bufaddr = (uint)bp;
+ /* room for crc */
+ bdp->cbd_datlen = ELBT_BUFSZ - ELBT_CRCSZ;
+ bdp->cbd_sc = BD_ENET_TX_READY | BD_ENET_TX_PAD | \
+ BD_ENET_TX_LAST | BD_ENET_TX_TC;
+
+ memset ((void *)bp, patbytes[i], ELBT_BUFSZ);
+ NetSetEther (bp, NetBcastAddr, 0x8000);
+ }
+ ecp->txbd[ELBT_NTXBD - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /*
+ * set up rx buffers and bds
+ */
+
+ for (i = 0; i < ELBT_NRXBD; i++) {
+ cbd_t *bdp = &ecp->rxbd[i];
+ uchar *bp = &ecp->rxbufs[i][0];
+
+ bdp->cbd_bufaddr = (uint)bp;
+ bdp->cbd_datlen = 0;
+ bdp->cbd_sc = BD_ENET_RX_EMPTY;
+
+ memset ((void *)bp, 0, ELBT_BUFSZ);
+ }
+ ecp->rxbd[ELBT_NRXBD - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /*
+ * set up the FCC channel hardware
+ */
+
+ /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
+ fcp->fcc_gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+
+ /* 28.9 - (5): FPSMR: fd, enet CRC, Promis, RMON, Rx SHort */
+ fcp->fcc_fpsmr = FCC_PSMR_FDE | FCC_PSMR_LPB | \
+ FCC_PSMR_ENCRC | FCC_PSMR_PRO | \
+ FCC_PSMR_MON | FCC_PSMR_RSH;
+
+ /* 28.9 - (6): FDSR: Ethernet Syn */
+ fcp->fcc_fdsr = 0xD555;
+
+ /* 29.9 - (7): initialise parameter ram */
+ fpp = (fcc_enet_t *)&(immr->im_dprambase[ecp->proff]);
+
+ /* clear whole struct to make sure all resv fields are zero */
+ memset ((void *)fpp, 0, sizeof (fcc_enet_t));
+
+ /*
+ * common Parameter RAM area
+ *
+ * Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ */
+ addr = CPM_FCC_SPECIAL_BASE + (c * 64);
+ fpp->fen_genfcc.fcc_riptr = addr;
+ fpp->fen_genfcc.fcc_tiptr = addr + 32;
+
+ /*
+ * Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ * buffers are in 60x bus memory.
+ */
+ fpp->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+ fpp->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+ fpp->fen_genfcc.fcc_rbase = (unsigned int)(&ecp->rxbd[0]);
+ fpp->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
+ fpp->fen_genfcc.fcc_tbase = (unsigned int)(&ecp->txbd[0]);
+
+ /* protocol-specific area */
+ fpp->fen_cmask = 0xdebb20e3; /* CRC mask */
+ fpp->fen_cpres = 0xffffffff; /* CRC preset */
+ fpp->fen_retlim = 15; /* Retry limit threshold */
+ fpp->fen_mflr = PKT_MAXBUF_SIZE;/* max frame length register */
+
+ /*
+ * Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ * So, far we have only been given one Ethernet address. We use
+ * the same address for all channels
+ */
+#define ea NetOurEther
+ fpp->fen_paddrh = (ea[5] << 8) + ea[4];
+ fpp->fen_paddrm = (ea[3] << 8) + ea[2];
+ fpp->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+
+ fpp->fen_minflr = PKT_MINBUF_SIZE; /* min frame len register */
+ /*
+ * pad pointer. use tiptr since we don't need
+ * a specific padding char
+ */
+ fpp->fen_padptr = fpp->fen_genfcc.fcc_tiptr;
+ fpp->fen_maxd1 = PKT_MAXDMA_SIZE; /* max DMA1 length */
+ fpp->fen_maxd2 = PKT_MAXDMA_SIZE; /* max DMA2 length */
+ fpp->fen_rfthr = 1;
+ fpp->fen_rfcnt = 1;
+
+ /* 28.9 - (8): clear out events in FCCE */
+ fcp->fcc_fcce = ~0x0;
+
+ /* 28.9 - (9): FCCM: mask all events */
+ fcp->fcc_fccm = 0;
+
+ /* 28.9 - (10-12): we don't use ethernet interrupts */
+
+ /* 28.9 - (13)
+ *
+ * Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cp->cp_cpcr = mk_cr_cmd (ecp->page, ecp->sblock, \
+ 0x0c, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ do {
+ __asm__ __volatile__ ("eieio");
+ } while (cp->cp_cpcr & CPM_CR_FLG);
+ }
+
+ puts (" done\nStarting test... (Ctrl-C to Finish)\n");
+
+ /*
+ * Note: don't want serial output from here until the end of the
+ * test - the delays would probably stuff things up.
+ */
+
+ clear_ctrlc ();
+ runtime = get_timer (0);
+
+ do {
+ nclosed = 0;
+
+ for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
+ volatile fcc_t *fcp = &immr->im_fcc[c];
+ elbt_chan *ecp = &elbt_chans[c];
+ int i;
+
+ switch (ecp->state) {
+
+ case Idle:
+ /*
+ * set the channel Running ...
+ */
+
+ /* 28.9 - (14): enable tx/rx in gfmr */
+ fcp->fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+
+ ecp->state = Running;
+ break;
+
+ case Running:
+ /*
+ * (while Running only) check for
+ * termination of the test
+ */
+
+ (void)ctrlc ();
+
+ if (had_ctrlc ()) {
+ /*
+ * initiate a "graceful stop transmit"
+ * on the channel
+ */
+ cp->cp_cpcr = mk_cr_cmd (ecp->page, \
+ ecp->sblock, 0x0c, \
+ CPM_CR_GRACEFUL_STOP_TX) | \
+ CPM_CR_FLG;
+ do {
+ __asm__ __volatile__ ("eieio");
+ } while (cp->cp_cpcr & CPM_CR_FLG);
+
+ ecp->clstime = get_timer (0);
+ ecp->state = Closing;
+ }
+ /* fall through ... */
+
+ case Closing:
+ /*
+ * (while Running or Closing) poll the channel:
+ * - check for any non-READY tx buffers and
+ * make them ready
+ * - check for any non-EMPTY rx buffers and
+ * check that they were received correctly,
+ * adjust counters etc, then make empty
+ */
+
+ for (i = 0; i < ELBT_NTXBD; i++) {
+ cbd_t *bdp = &ecp->txbd[i];
+ ushort sc = bdp->cbd_sc;
+
+ if ((sc & BD_ENET_TX_READY) != 0)
+ continue;
+
+ /*
+ * this frame has finished
+ * transmitting
+ */
+ ecp->nsent++;
+
+ if (sc & BD_ENET_TX_STATS) {
+ ulong n;
+
+ /*
+ * we had an error on
+ * the transmission
+ */
+ n = ecp->ntxerr++;
+ if (n < ELBT_MAXTXERR)
+ ecp->txerrs[n] = sc;
+
+ if (sc & BD_ENET_TX_DEF)
+ ecp->txeacc.def++;
+ if (sc & BD_ENET_TX_HB)
+ ecp->txeacc.hb++;
+ if (sc & BD_ENET_TX_LC)
+ ecp->txeacc.lc++;
+ if (sc & BD_ENET_TX_RL)
+ ecp->txeacc.rl++;
+ if (sc & BD_ENET_TX_RCMASK)
+ ecp->txeacc.rc++;
+ if (sc & BD_ENET_TX_UN)
+ ecp->txeacc.un++;
+ if (sc & BD_ENET_TX_CSL)
+ ecp->txeacc.csl++;
+
+ bdp->cbd_sc &= \
+ ~BD_ENET_TX_STATS;
+ }
+
+ if (ecp->state == Closing)
+ ecp->clstime = get_timer (0);
+
+ /* make it ready again */
+ bdp->cbd_sc |= BD_ENET_TX_READY;
+ }
+
+ for (i = 0; i < ELBT_NRXBD; i++) {
+ cbd_t *bdp = &ecp->rxbd[i];
+ ushort sc = bdp->cbd_sc, mask;
+
+ if ((sc & BD_ENET_RX_EMPTY) != 0)
+ continue;
+
+ /* we have a new frame in this buffer */
+ ecp->nrcvd++;
+
+ mask = BD_ENET_RX_LAST|BD_ENET_RX_FIRST;
+ if ((sc & mask) != mask) {
+ /* somethings wrong here ... */
+ if (!(sc & BD_ENET_RX_LAST))
+ ecp->rxeacc._l++;
+ if (!(sc & BD_ENET_RX_FIRST))
+ ecp->rxeacc._f++;
+ }
+
+ if (sc & BD_ENET_RX_ERRS) {
+ ulong n;
+
+ /*
+ * we had some sort of error
+ * on the frame
+ */
+ n = ecp->nrxerr++;
+ if (n < ELBT_MAXRXERR)
+ ecp->rxerrs[n] = sc;
+
+ if (sc & BD_ENET_RX_MISS)
+ ecp->rxeacc.m++;
+ if (sc & BD_ENET_RX_BC)
+ ecp->rxeacc.bc++;
+ if (sc & BD_ENET_RX_MC)
+ ecp->rxeacc.mc++;
+ if (sc & BD_ENET_RX_LG)
+ ecp->rxeacc.lg++;
+ if (sc & BD_ENET_RX_NO)
+ ecp->rxeacc.no++;
+ if (sc & BD_ENET_RX_SH)
+ ecp->rxeacc.sh++;
+ if (sc & BD_ENET_RX_CR)
+ ecp->rxeacc.cr++;
+ if (sc & BD_ENET_RX_OV)
+ ecp->rxeacc.ov++;
+ if (sc & BD_ENET_RX_CL)
+ ecp->rxeacc.cl++;
+
+ bdp->cbd_sc &= \
+ ~BD_ENET_RX_ERRS;
+ }
+ else {
+ ushort datlen = bdp->cbd_datlen;
+ struct ethernet_hdr *ehp;
+ ushort prot;
+ int ours, tb, n, nbytes;
+
+ ehp = (struct ethernet_hdr *) \
+ &ecp->rxbufs[i][0];
+
+ ours = memcmp (ehp->et_src, \
+ NetOurEther, 6);
+
+ prot = swap16 (ehp->et_protlen);
+ tb = prot & 0x8000;
+ n = prot & 0x7fff;
+
+ nbytes = ELBT_BUFSZ -
+ ETHER_HDR_SIZE -
+ ELBT_CRCSZ;
+
+ /* check the frame is correct */
+ if (datlen != ELBT_BUFSZ)
+ ecp->rxeacc.badlen++;
+ else if (!ours)
+ ecp->rxeacc.badsrc++;
+ else if (!tb || n >= ELBT_NTXBD)
+ ecp->rxeacc.badtyp++;
+ else {
+ ulong patword = \
+ patwords[n];
+ uint nbb;
+
+ nbb = badbits(
+ ((uchar *)&ehp) +
+ ETHER_HDR_SIZE,
+ nbytes, patword);
+
+ ecp->rxeacc.badbit += \
+ nbb;
+ }
+ }
+
+ if (ecp->state == Closing)
+ ecp->clstime = get_timer (0);
+
+ /* make it empty again */
+ bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+ }
+
+ if (ecp->state != Closing)
+ break;
+
+ /*
+ * (while Closing) check to see if
+ * waited long enough
+ */
+
+ if (get_timer (ecp->clstime) >= ELBT_CLSWAIT) {
+ /* write GFMR: disable tx/rx */
+ fcp->fcc_gfmr &= \
+ ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ ecp->state = Closed;
+ }
+
+ break;
+
+ case Closed:
+ nclosed++;
+ break;
+ }
+ }
+
+ } while (nclosed < (FCC_END_LOOP - FCC_START_LOOP + 1));
+
+ runtime = get_timer (runtime);
+ if (runtime <= ELBT_CLSWAIT) {
+ printf ("Whoops! somehow elapsed time (%ld) is wrong (<= %d)\n",
+ runtime, ELBT_CLSWAIT);
+ return;
+ }
+ nmsec = runtime - ELBT_CLSWAIT;
+
+ printf ("Test Finished in %ldms (plus %dms close wait period)!\n\n",
+ nmsec, ELBT_CLSWAIT);
+
+ /*
+ * now print stats
+ */
+
+ for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
+ elbt_chan *ecp = &elbt_chans[c];
+ uint rxpps, txpps, nerr;
+
+ rxpps = (ecp->nrcvd * 1000) / nmsec;
+ txpps = (ecp->nsent * 1000) / nmsec;
+
+ printf ("Channel %d: %d rcvd (%d pps, %d rxerrs), "
+ "%d sent (%d pps, %d txerrs)\n\n", c,
+ ecp->nrcvd, rxpps, ecp->nrxerr,
+ ecp->nsent, txpps, ecp->ntxerr);
+
+ if ((nerr = ecp->nrxerr) > 0) {
+ ulong i;
+
+ printf ("\tFirst %d rx errs:", nerr);
+ for (i = 0; i < nerr; i++)
+ printf (" %04x", ecp->rxerrs[i]);
+ putc ('\n');
+ }
+
+ if ((nerr = ecp->ntxerr) > 0) {
+ ulong i;
+
+ printf ("\tFirst %d tx errs:", nerr);
+ for (i = 0; i < nerr; i++)
+ printf (" %04x", ecp->txerrs[i]);
+ putc ('\n');
+ }
+ }
+
+ puts ("Receive Error Counts:\n");
+ for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
+ bases[c] = (uchar *)&elbt_chans[c].rxeacc;
+ print_desc (rxeacc_descs, rxeacc_ndesc, bases, 3);
+
+ puts ("\nTransmit Error Counts:\n");
+ for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
+ bases[c] = (uchar *)&elbt_chans[c].txeacc;
+ print_desc (txeacc_descs, txeacc_ndesc, bases, 3);
+
+ puts ("\nRMON(-like) Counters:\n");
+ for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
+ bases[c] = (uchar *)&immr->im_dprambase[elbt_chans[c].proff];
+ print_desc (epram_descs, epram_ndesc, bases, 3);
+}
+
+#endif /* CONFIG_ETHER_LOOPBACK_TEST */
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/ether_scc.c b/arch/powerpc/cpu/mpc8260/ether_scc.c
new file mode 100644
index 0000000..3c71219
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/ether_scc.c
@@ -0,0 +1,383 @@
+/*
+ * MPC8260 SCC Ethernet
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright (c) 2001
+ * Advent Networks, Inc. <http://www.adventnetworks.com>
+ * Jay Monkman <jtm@smoothsmoothie.com>
+ *
+ * Modified so that it plays nicely when more than one ETHERNET interface
+ * is in use a la ether_fcc.c.
+ * (C) Copyright 2008
+ * DENX Software Engineerin GmbH
+ * Gary Jennejohn <garyj@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/cpm_8260.h>
+#include <mpc8260.h>
+#include <malloc.h>
+#include <net.h>
+#include <command.h>
+#include <config.h>
+
+#if (CONFIG_ETHER_INDEX == 1)
+# define PROFF_ENET PROFF_SCC1
+# define CPM_CR_ENET_PAGE CPM_CR_SCC1_PAGE
+# define CPM_CR_ENET_SBLOCK CPM_CR_SCC1_SBLOCK
+# define CMXSCR_MASK (CMXSCR_SC1 |\
+ CMXSCR_RS1CS_MSK |\
+ CMXSCR_TS1CS_MSK)
+
+#elif (CONFIG_ETHER_INDEX == 2)
+# define PROFF_ENET PROFF_SCC2
+# define CPM_CR_ENET_PAGE CPM_CR_SCC2_PAGE
+# define CPM_CR_ENET_SBLOCK CPM_CR_SCC2_SBLOCK
+# define CMXSCR_MASK (CMXSCR_SC2 |\
+ CMXSCR_RS2CS_MSK |\
+ CMXSCR_TS2CS_MSK)
+
+#elif (CONFIG_ETHER_INDEX == 3)
+# define PROFF_ENET PROFF_SCC3
+# define CPM_CR_ENET_PAGE CPM_CR_SCC3_PAGE
+# define CPM_CR_ENET_SBLOCK CPM_CR_SCC3_SBLOCK
+# define CMXSCR_MASK (CMXSCR_SC3 |\
+ CMXSCR_RS3CS_MSK |\
+ CMXSCR_TS3CS_MSK)
+#elif (CONFIG_ETHER_INDEX == 4)
+# define PROFF_ENET PROFF_SCC4
+# define CPM_CR_ENET_PAGE CPM_CR_SCC4_PAGE
+# define CPM_CR_ENET_SBLOCK CPM_CR_SCC4_SBLOCK
+# define CMXSCR_MASK (CMXSCR_SC4 |\
+ CMXSCR_RS4CS_MSK |\
+ CMXSCR_TS4CS_MSK)
+
+#endif
+
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH 1520
+
+#define TX_BUF_CNT 2
+
+#if !defined(CONFIG_SYS_SCC_TOUT_LOOP)
+ #define CONFIG_SYS_SCC_TOUT_LOOP 1000000
+#endif
+
+static char txbuf[TX_BUF_CNT][ DBUF_LENGTH ];
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * SCC Ethernet Tx and Rx buffer descriptors allocated at the
+ * immr->udata_bd address on Dual-Port RAM
+ * Provide for Double Buffering
+ */
+
+typedef volatile struct CommonBufferDescriptor {
+ cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
+ cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx;
+
+
+static int sec_send(struct eth_device *dev, void *packet, int length)
+{
+ int i;
+ int result = 0;
+
+ if (length <= 0) {
+ printf("scc: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= CONFIG_SYS_SCC_TOUT_LOOP) {
+ puts ("scc: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+ rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx->txbd[txIdx].cbd_datlen = length;
+ rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |
+ BD_ENET_TX_WRAP);
+
+ for(i=0; rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= CONFIG_SYS_SCC_TOUT_LOOP) {
+ puts ("scc: tx error\n");
+ goto out;
+ }
+ }
+
+ /* return only status bits */
+ result = rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+
+ out:
+ return result;
+}
+
+
+static int sec_rx(struct eth_device *dev)
+{
+ int length;
+
+ for (;;)
+ {
+ if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+
+ length = rtx->rxbd[rxIdx].cbd_datlen;
+
+ if (rtx->rxbd[rxIdx].cbd_sc & 0x003f)
+ {
+ printf("err: %x\n", rtx->rxbd[rxIdx].cbd_sc);
+ }
+ else
+ {
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ }
+
+
+ /* Give the buffer back to the SCC. */
+ rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP |
+ BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ }
+ else {
+ rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+ }
+ return length;
+}
+
+/**************************************************************
+ *
+ * SCC Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+static int sec_init(struct eth_device *dev, bd_t *bis)
+{
+ int i;
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ scc_enet_t *pram_ptr;
+ uint dpaddr;
+ uchar ea[6];
+
+ rxIdx = 0;
+ txIdx = 0;
+
+ /*
+ * Assign static pointer to BD area.
+ * Avoid exhausting DPRAM, which would cause a panic.
+ */
+ if (rtx == NULL) {
+ dpaddr = m8260_cpm_dpalloc(sizeof(RTXBD) + 2, 16);
+ rtx = (RTXBD *)&immr->im_dprambase[dpaddr];
+ }
+
+ /* 24.21 - (1-3): ioports have been set up already */
+
+ /* 24.21 - (4,5): connect SCC's tx and rx clocks, use NMSI for SCC */
+ immr->im_cpmux.cmx_uar = 0;
+ immr->im_cpmux.cmx_scr = ( (immr->im_cpmux.cmx_scr & ~CMXSCR_MASK) |
+ CONFIG_SYS_CMXSCR_VALUE);
+
+
+ /* 24.21 (6) write RBASE and TBASE to parameter RAM */
+ pram_ptr = (scc_enet_t *)&(immr->im_dprambase[PROFF_ENET]);
+ pram_ptr->sen_genscc.scc_rbase = (unsigned int)(&rtx->rxbd[0]);
+ pram_ptr->sen_genscc.scc_tbase = (unsigned int)(&rtx->txbd[0]);
+
+ pram_ptr->sen_genscc.scc_rfcr = 0x18; /* Nrml Ops and Mot byte ordering */
+ pram_ptr->sen_genscc.scc_tfcr = 0x18; /* Mot byte ordering, Nrml access */
+
+ pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH; /* max. package len 1520 */
+
+ pram_ptr->sen_cpres = ~(0x0); /* Preset CRC */
+ pram_ptr->sen_cmask = 0xdebb20e3; /* Constant Mask for CRC */
+
+
+ /* 24.21 - (7): Write INIT RX AND TX PARAMETERS to CPCR */
+ while(immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+ immr->im_cpm.cp_cpcr = mk_cr_cmd(CPM_CR_ENET_PAGE,
+ CPM_CR_ENET_SBLOCK,
+ 0x0c,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ /* 24.21 - (8-18): Set up parameter RAM */
+ pram_ptr->sen_crcec = 0x0; /* Error Counter CRC (unused) */
+ pram_ptr->sen_alec = 0x0; /* Align Error Counter (unused) */
+ pram_ptr->sen_disfc = 0x0; /* Discard Frame Counter (unused) */
+
+ pram_ptr->sen_pads = 0x8888; /* Short Frame PAD Characters */
+
+ pram_ptr->sen_retlim = 15; /* Retry Limit Threshold */
+
+ pram_ptr->sen_maxflr = 1518; /* MAX Frame Length Register */
+ pram_ptr->sen_minflr = 64; /* MIN Frame Length Register */
+
+ pram_ptr->sen_maxd1 = DBUF_LENGTH; /* MAX DMA1 Length Register */
+ pram_ptr->sen_maxd2 = DBUF_LENGTH; /* MAX DMA2 Length Register */
+
+ pram_ptr->sen_gaddr1 = 0x0; /* Group Address Filter 1 (unused) */
+ pram_ptr->sen_gaddr2 = 0x0; /* Group Address Filter 2 (unused) */
+ pram_ptr->sen_gaddr3 = 0x0; /* Group Address Filter 3 (unused) */
+ pram_ptr->sen_gaddr4 = 0x0; /* Group Address Filter 4 (unused) */
+
+ eth_getenv_enetaddr("ethaddr", ea);
+ pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
+ pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
+ pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
+
+ pram_ptr->sen_pper = 0x0; /* Persistence (unused) */
+
+ pram_ptr->sen_iaddr1 = 0x0; /* Individual Address Filter 1 (unused) */
+ pram_ptr->sen_iaddr2 = 0x0; /* Individual Address Filter 2 (unused) */
+ pram_ptr->sen_iaddr3 = 0x0; /* Individual Address Filter 3 (unused) */
+ pram_ptr->sen_iaddr4 = 0x0; /* Individual Address Filter 4 (unused) */
+
+ pram_ptr->sen_taddrh = 0x0; /* Tmp Address (MSB) (unused) */
+ pram_ptr->sen_taddrm = 0x0; /* Tmp Address (unused) */
+ pram_ptr->sen_taddrl = 0x0; /* Tmp Address (LSB) (unused) */
+
+ /* 24.21 - (19): Initialize RxBD */
+ for (i = 0; i < PKTBUFSRX; i++)
+ {
+ rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ rtx->rxbd[i].cbd_datlen = 0; /* Reset */
+ rtx->rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+ }
+
+ rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /* 24.21 - (20): Initialize TxBD */
+ for (i = 0; i < TX_BUF_CNT; i++)
+ {
+ rtx->txbd[i].cbd_sc = (BD_ENET_TX_PAD |
+ BD_ENET_TX_LAST |
+ BD_ENET_TX_TC);
+ rtx->txbd[i].cbd_datlen = 0; /* Reset */
+ rtx->txbd[i].cbd_bufaddr = (uint)&txbuf[i][0];
+ }
+
+ rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /* 24.21 - (21): Write 0xffff to SCCE */
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_scce = ~(0x0);
+
+ /* 24.21 - (22): Write to SCCM to enable TXE, RXF, TXB events */
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_sccm = (SCCE_ENET_TXE |
+ SCCE_ENET_RXF |
+ SCCE_ENET_TXB);
+
+ /* 24.21 - (23): we don't use ethernet interrupts */
+
+ /* 24.21 - (24): Clear GSMR_H to enable normal operations */
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrh = 0;
+
+ /* 24.21 - (25): Clear GSMR_L to enable normal operations */
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl = (SCC_GSMRL_TCI |
+ SCC_GSMRL_TPL_48 |
+ SCC_GSMRL_TPP_10 |
+ SCC_GSMRL_MODE_ENET);
+
+ /* 24.21 - (26): Initialize DSR */
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_dsr = 0xd555;
+
+ /* 24.21 - (27): Initialize PSMR2
+ *
+ * Settings:
+ * CRC = 32-Bit CCITT
+ * NIB = Begin searching for SFD 22 bits after RENA
+ * FDE = Full Duplex Enable
+ * BRO = Reject broadcast packets
+ * PROMISCOUS = Catch all packets regardless of dest. MAC adress
+ */
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_psmr = SCC_PSMR_ENCRC |
+ SCC_PSMR_NIB22 |
+#if defined(CONFIG_SCC_ENET_FULL_DUPLEX)
+ SCC_PSMR_FDE |
+#endif
+#if defined(CONFIG_SCC_ENET_NO_BROADCAST)
+ SCC_PSMR_BRO |
+#endif
+#if defined(CONFIG_SCC_ENET_PROMISCOUS)
+ SCC_PSMR_PRO |
+#endif
+ 0;
+
+ /* 24.21 - (28): Write to GSMR_L to enable SCC */
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl |= (SCC_GSMRL_ENR |
+ SCC_GSMRL_ENT);
+
+ return 0;
+}
+
+
+static void sec_halt(struct eth_device *dev)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ immr->im_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl &= ~(SCC_GSMRL_ENR |
+ SCC_GSMRL_ENT);
+}
+
+#if 0
+static void sec_restart(void)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ immr->im_cpm.cp_scc[CONFIG_ETHER_INDEX-1].scc_gsmrl |= (SCC_GSMRL_ENR |
+ SCC_GSMRL_ENT);
+}
+#endif
+
+int mpc82xx_scc_enet_initialize(bd_t *bis)
+{
+ struct eth_device *dev;
+
+ dev = (struct eth_device *) malloc(sizeof *dev);
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "SCC");
+ dev->init = sec_init;
+ dev->halt = sec_halt;
+ dev->send = sec_send;
+ dev->recv = sec_rx;
+
+ eth_register(dev);
+
+ return 1;
+}
diff --git a/arch/powerpc/cpu/mpc8260/i2c.c b/arch/powerpc/cpu/mpc8260/i2c.c
new file mode 100644
index 0000000..e2341e9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/i2c.c
@@ -0,0 +1,770 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_HARD_I2C)
+
+#include <asm/cpm_8260.h>
+#include <i2c.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_I2C_MULTI_BUS)
+static unsigned int i2c_bus_num __attribute__ ((section(".data"))) = 0;
+#endif /* CONFIG_I2C_MULTI_BUS */
+
+/* uSec to wait between polls of the i2c */
+#define DELAY_US 100
+/* uSec to wait for the CPM to start processing the buffer */
+#define START_DELAY_US 1000
+
+/*
+ * tx/rx per-byte timeout: we delay DELAY_US uSec between polls so the
+ * timeout will be (tx_length + rx_length) * DELAY_US * TOUT_LOOP
+ */
+#define TOUT_LOOP 5
+
+/*
+ * Set default values
+ */
+#ifndef CONFIG_SYS_I2C_SPEED
+#define CONFIG_SYS_I2C_SPEED 50000
+#endif
+
+
+typedef void (*i2c_ecb_t) (int, int, void *); /* error callback function */
+
+/* This structure keeps track of the bd and buffer space usage. */
+typedef struct i2c_state {
+ int rx_idx; /* index to next free Rx BD */
+ int tx_idx; /* index to next free Tx BD */
+ void *rxbd; /* pointer to next free Rx BD */
+ void *txbd; /* pointer to next free Tx BD */
+ int tx_space; /* number of Tx bytes left */
+ unsigned char *tx_buf; /* pointer to free Tx area */
+ i2c_ecb_t err_cb; /* error callback function */
+ void *cb_data; /* private data to be passed */
+} i2c_state_t;
+
+/* flags for i2c_send() and i2c_receive() */
+#define I2CF_ENABLE_SECONDARY 0x01 /* secondary_address is valid */
+#define I2CF_START_COND 0x02 /* tx: generate start condition */
+#define I2CF_STOP_COND 0x04 /* tx: generate stop condition */
+
+/* return codes */
+#define I2CERR_NO_BUFFERS 1 /* no more BDs or buffer space */
+#define I2CERR_MSG_TOO_LONG 2 /* tried to send/receive to much data */
+#define I2CERR_TIMEOUT 3 /* timeout in i2c_doio() */
+#define I2CERR_QUEUE_EMPTY 4 /* i2c_doio called without send/rcv */
+#define I2CERR_IO_ERROR 5 /* had an error during comms */
+
+/* error callback flags */
+#define I2CECB_RX_ERR 0x10 /* this is a receive error */
+#define I2CECB_RX_OV 0x02 /* receive overrun error */
+#define I2CECB_RX_MASK 0x0f /* mask for error bits */
+#define I2CECB_TX_ERR 0x20 /* this is a transmit error */
+#define I2CECB_TX_CL 0x01 /* transmit collision error */
+#define I2CECB_TX_UN 0x02 /* transmit underflow error */
+#define I2CECB_TX_NAK 0x04 /* transmit no ack error */
+#define I2CECB_TX_MASK 0x0f /* mask for error bits */
+#define I2CECB_TIMEOUT 0x40 /* this is a timeout error */
+
+#define ERROR_I2C_NONE 0
+#define ERROR_I2C_LENGTH 1
+
+#define I2C_WRITE_BIT 0x00
+#define I2C_READ_BIT 0x01
+
+#define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */
+
+
+#define NUM_RX_BDS 4
+#define NUM_TX_BDS 4
+#define MAX_TX_SPACE 256
+
+typedef struct I2C_BD {
+ unsigned short status;
+ unsigned short length;
+ unsigned char *addr;
+} I2C_BD;
+
+#define BD_I2C_TX_START 0x0400 /* special status for i2c: Start condition */
+
+#define BD_I2C_TX_CL 0x0001 /* collision error */
+#define BD_I2C_TX_UN 0x0002 /* underflow error */
+#define BD_I2C_TX_NAK 0x0004 /* no acknowledge error */
+#define BD_I2C_TX_ERR (BD_I2C_TX_NAK|BD_I2C_TX_UN|BD_I2C_TX_CL)
+
+#define BD_I2C_RX_ERR BD_SC_OV
+
+/*
+ * Returns the best value of I2BRG to meet desired clock speed of I2C with
+ * input parameters (clock speed, filter, and predivider value).
+ * It returns computer speed value and the difference between it and desired
+ * speed.
+ */
+static inline int
+i2c_roundrate(int hz, int speed, int filter, int modval,
+ int *brgval, int *totspeed)
+{
+ int moddiv = 1 << (5 - (modval & 3)), brgdiv, div;
+
+ debug("\t[I2C] trying hz=%d, speed=%d, filter=%d, modval=%d\n",
+ hz, speed, filter, modval);
+
+ div = moddiv * speed;
+ brgdiv = (hz + div - 1) / div;
+
+ debug("\t\tmoddiv=%d, brgdiv=%d\n", moddiv, brgdiv);
+
+ *brgval = ((brgdiv + 1) / 2) - 3 - (2 * filter);
+
+ if ((*brgval < 0) || (*brgval > 255)) {
+ debug("\t\trejected brgval=%d\n", *brgval);
+ return -1;
+ }
+
+ brgdiv = 2 * (*brgval + 3 + (2 * filter));
+ div = moddiv * brgdiv;
+ *totspeed = hz / div;
+
+ debug("\t\taccepted brgval=%d, totspeed=%d\n", *brgval, *totspeed);
+
+ return 0;
+}
+
+/*
+ * Sets the I2C clock predivider and divider to meet required clock speed.
+ */
+static int i2c_setrate(int hz, int speed)
+{
+ immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
+ int brgval,
+ modval, /* 0-3 */
+ bestspeed_diff = speed,
+ bestspeed_brgval = 0,
+ bestspeed_modval = 0,
+ bestspeed_filter = 0,
+ totspeed,
+ filter = 0; /* Use this fixed value */
+
+ for (modval = 0; modval < 4; modval++) {
+ if (i2c_roundrate(hz, speed, filter, modval, &brgval, &totspeed)
+ == 0) {
+ int diff = speed - totspeed;
+
+ if ((diff >= 0) && (diff < bestspeed_diff)) {
+ bestspeed_diff = diff;
+ bestspeed_modval = modval;
+ bestspeed_brgval = brgval;
+ bestspeed_filter = filter;
+ }
+ }
+ }
+
+ debug("[I2C] Best is:\n");
+ debug("[I2C] CPU=%dhz RATE=%d F=%d I2MOD=%08x I2BRG=%08x DIFF=%dhz\n",
+ hz, speed, bestspeed_filter, bestspeed_modval, bestspeed_brgval,
+ bestspeed_diff);
+
+ i2c->i2c_i2mod |= ((bestspeed_modval & 3) << 1) |
+ (bestspeed_filter << 3);
+ i2c->i2c_i2brg = bestspeed_brgval & 0xff;
+
+ debug("[I2C] i2mod=%08x i2brg=%08x\n", i2c->i2c_i2mod,
+ i2c->i2c_i2brg);
+
+ return 1;
+}
+
+void i2c_init(int speed, int slaveadd)
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8260_t *cp = (cpm8260_t *)&immap->im_cpm;
+ volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
+ volatile iic_t *iip;
+ ulong rbase, tbase;
+ volatile I2C_BD *rxbd, *txbd;
+ uint dpaddr;
+
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+ /*
+ * call board specific i2c bus reset routine before accessing the
+ * environment, which might be in a chip on that bus. For details
+ * about this problem see doc/I2C_Edge_Conditions.
+ */
+ i2c_init_board();
+#endif
+
+ dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)];
+ if (dpaddr == 0) {
+ /* need to allocate dual port ram */
+ dpaddr = m8260_cpm_dpalloc(64 +
+ (NUM_RX_BDS * sizeof(I2C_BD)) +
+ (NUM_TX_BDS * sizeof(I2C_BD)) +
+ MAX_TX_SPACE, 64);
+ immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)] =
+ dpaddr;
+ }
+
+ /*
+ * initialise data in dual port ram:
+ *
+ * dpaddr -> parameter ram (64 bytes)
+ * rbase -> rx BD (NUM_RX_BDS * sizeof(I2C_BD) bytes)
+ * tbase -> tx BD (NUM_TX_BDS * sizeof(I2C_BD) bytes)
+ * tx buffer (MAX_TX_SPACE bytes)
+ */
+
+ iip = (iic_t *)&immap->im_dprambase[dpaddr];
+ memset((void *)iip, 0, sizeof(iic_t));
+
+ rbase = dpaddr + 64;
+ tbase = rbase + NUM_RX_BDS * sizeof(I2C_BD);
+
+ /* Disable interrupts */
+ i2c->i2c_i2mod = 0x00;
+ i2c->i2c_i2cmr = 0x00;
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2add = slaveadd;
+
+ /*
+ * Set the I2C BRG Clock division factor from desired i2c rate
+ * and current CPU rate (we assume sccr dfbgr field is 0;
+ * divide BRGCLK by 1)
+ */
+ debug("[I2C] Setting rate...\n");
+ i2c_setrate(gd->arch.brg_clk, CONFIG_SYS_I2C_SPEED);
+
+ /* Set I2C controller in master mode */
+ i2c->i2c_i2com = 0x01;
+
+ /* Initialize Tx/Rx parameters */
+ iip->iic_rbase = rbase;
+ iip->iic_tbase = tbase;
+ rxbd = (I2C_BD *)((unsigned char *) &immap->
+ im_dprambase[iip->iic_rbase]);
+ txbd = (I2C_BD *)((unsigned char *) &immap->
+ im_dprambase[iip->iic_tbase]);
+
+ debug("[I2C] rbase = %04x\n", iip->iic_rbase);
+ debug("[I2C] tbase = %04x\n", iip->iic_tbase);
+ debug("[I2C] rxbd = %08x\n", (int) rxbd);
+ debug("[I2C] txbd = %08x\n", (int) txbd);
+
+ /* Set big endian byte order */
+ iip->iic_tfcr = 0x10;
+ iip->iic_rfcr = 0x10;
+
+ /* Set maximum receive size. */
+ iip->iic_mrblr = I2C_RXTX_LEN;
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_I2C_PAGE,
+ CPM_CR_I2C_SBLOCK,
+ 0x00, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ do {
+ __asm__ __volatile__("eieio");
+ } while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* Clear events and interrupts */
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2cmr = 0x00;
+}
+
+static
+void i2c_newio(i2c_state_t *state)
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile iic_t *iip;
+ uint dpaddr;
+
+ debug("[I2C] i2c_newio\n");
+
+ dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)];
+ iip = (iic_t *)&immap->im_dprambase[dpaddr];
+ state->rx_idx = 0;
+ state->tx_idx = 0;
+ state->rxbd = (void *)&immap->im_dprambase[iip->iic_rbase];
+ state->txbd = (void *)&immap->im_dprambase[iip->iic_tbase];
+ state->tx_space = MAX_TX_SPACE;
+ state->tx_buf = (uchar *)state->txbd + NUM_TX_BDS * sizeof(I2C_BD);
+ state->err_cb = NULL;
+ state->cb_data = NULL;
+
+ debug("[I2C] rxbd = %08x\n", (int)state->rxbd);
+ debug("[I2C] txbd = %08x\n", (int)state->txbd);
+ debug("[I2C] tx_buf = %08x\n", (int)state->tx_buf);
+
+ /* clear the buffer memory */
+ memset((char *) state->tx_buf, 0, MAX_TX_SPACE);
+}
+
+static
+int i2c_send(i2c_state_t *state,
+ unsigned char address,
+ unsigned char secondary_address,
+ unsigned int flags, unsigned short size, unsigned char *dataout)
+{
+ volatile I2C_BD *txbd;
+ int i, j;
+
+ debug("[I2C] i2c_send add=%02d sec=%02d flag=%02d size=%d\n",
+ address, secondary_address, flags, size);
+
+ /* trying to send message larger than BD */
+ if (size > I2C_RXTX_LEN)
+ return I2CERR_MSG_TOO_LONG;
+
+ /* no more free bds */
+ if (state->tx_idx >= NUM_TX_BDS || state->tx_space < (2 + size))
+ return I2CERR_NO_BUFFERS;
+
+ txbd = (I2C_BD *)state->txbd;
+ txbd->addr = state->tx_buf;
+
+ debug("[I2C] txbd = %08x\n", (int) txbd);
+
+ if (flags & I2CF_START_COND) {
+ debug("[I2C] Formatting addresses...\n");
+ if (flags & I2CF_ENABLE_SECONDARY) {
+ /* Length of message plus dest addresses */
+ txbd->length = size + 2;
+ txbd->addr[0] = address << 1;
+ txbd->addr[1] = secondary_address;
+ i = 2;
+ } else {
+ /* Length of message plus dest address */
+ txbd->length = size + 1;
+ /* Write destination address to BD */
+ txbd->addr[0] = address << 1;
+ i = 1;
+ }
+ } else {
+ txbd->length = size; /* Length of message */
+ i = 0;
+ }
+
+ /* set up txbd */
+ txbd->status = BD_SC_READY;
+ if (flags & I2CF_START_COND)
+ txbd->status |= BD_I2C_TX_START;
+ if (flags & I2CF_STOP_COND)
+ txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+
+ /* Copy data to send into buffer */
+ debug("[I2C] copy data...\n");
+ for (j = 0; j < size; i++, j++)
+ txbd->addr[i] = dataout[j];
+
+ debug("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+ txbd->length, txbd->status, txbd->addr[0], txbd->addr[1]);
+
+ /* advance state */
+ state->tx_buf += txbd->length;
+ state->tx_space -= txbd->length;
+ state->tx_idx++;
+ state->txbd = (void *) (txbd + 1);
+
+ return 0;
+}
+
+static
+int i2c_receive(i2c_state_t *state,
+ unsigned char address,
+ unsigned char secondary_address,
+ unsigned int flags,
+ unsigned short size_to_expect, unsigned char *datain)
+{
+ volatile I2C_BD *rxbd, *txbd;
+
+ debug("[I2C] i2c_receive %02d %02d %02d\n", address,
+ secondary_address, flags);
+
+ /* Expected to receive too much */
+ if (size_to_expect > I2C_RXTX_LEN)
+ return I2CERR_MSG_TOO_LONG;
+
+ /* no more free bds */
+ if (state->tx_idx >= NUM_TX_BDS || state->rx_idx >= NUM_RX_BDS
+ || state->tx_space < 2)
+ return I2CERR_NO_BUFFERS;
+
+ rxbd = (I2C_BD *) state->rxbd;
+ txbd = (I2C_BD *) state->txbd;
+
+ debug("[I2C] rxbd = %08x\n", (int) rxbd);
+ debug("[I2C] txbd = %08x\n", (int) txbd);
+
+ txbd->addr = state->tx_buf;
+
+ /* set up TXBD for destination address */
+ if (flags & I2CF_ENABLE_SECONDARY) {
+ txbd->length = 2;
+ txbd->addr[0] = address << 1; /* Write data */
+ txbd->addr[1] = secondary_address; /* Internal address */
+ txbd->status = BD_SC_READY;
+ } else {
+ txbd->length = 1 + size_to_expect;
+ txbd->addr[0] = (address << 1) | 0x01;
+ txbd->status = BD_SC_READY;
+ memset(&txbd->addr[1], 0, txbd->length);
+ }
+
+ /* set up rxbd for reception */
+ rxbd->status = BD_SC_EMPTY;
+ rxbd->length = size_to_expect;
+ rxbd->addr = datain;
+
+ txbd->status |= BD_I2C_TX_START;
+ if (flags & I2CF_STOP_COND) {
+ txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+ rxbd->status |= BD_SC_WRAP;
+ }
+
+ debug("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+ txbd->length, txbd->status, txbd->addr[0], txbd->addr[1]);
+ debug("[I2C] rxbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+ rxbd->length, rxbd->status, rxbd->addr[0], rxbd->addr[1]);
+
+ /* advance state */
+ state->tx_buf += txbd->length;
+ state->tx_space -= txbd->length;
+ state->tx_idx++;
+ state->txbd = (void *) (txbd + 1);
+ state->rx_idx++;
+ state->rxbd = (void *) (rxbd + 1);
+
+ return 0;
+}
+
+
+static
+int i2c_doio(i2c_state_t *state)
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile iic_t *iip;
+ volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c;
+ volatile I2C_BD *txbd, *rxbd;
+ int n, i, b, rxcnt = 0, rxtimeo = 0, txcnt = 0, txtimeo = 0, rc = 0;
+ uint dpaddr;
+
+ debug("[I2C] i2c_doio\n");
+
+ if (state->tx_idx <= 0 && state->rx_idx <= 0) {
+ debug("[I2C] No I/O is queued\n");
+ return I2CERR_QUEUE_EMPTY;
+ }
+
+ dpaddr = immap->im_dprambase16[PROFF_I2C_BASE / sizeof(u16)];
+ iip = (iic_t *)&immap->im_dprambase[dpaddr];
+ iip->iic_rbptr = iip->iic_rbase;
+ iip->iic_tbptr = iip->iic_tbase;
+
+ /* Enable I2C */
+ debug("[I2C] Enabling I2C...\n");
+ i2c->i2c_i2mod |= 0x01;
+
+ /* Begin transmission */
+ i2c->i2c_i2com |= 0x80;
+
+ /* Loop until transmit & receive completed */
+
+ n = state->tx_idx;
+
+ if (n > 0) {
+
+ txbd = ((I2C_BD *) state->txbd) - n;
+ for (i = 0; i < n; i++) {
+ txtimeo += TOUT_LOOP * txbd->length;
+ txbd++;
+ }
+
+ txbd--; /* wait until last in list is done */
+
+ debug("[I2C] Transmitting...(txbd=0x%08lx)\n",
+ (ulong) txbd);
+
+ udelay(START_DELAY_US); /* give it time to start */
+ while ((txbd->status & BD_SC_READY) && (++txcnt < txtimeo)) {
+ udelay(DELAY_US);
+ if (ctrlc())
+ return -1;
+ __asm__ __volatile__("eieio");
+ }
+ }
+
+ n = state->rx_idx;
+
+ if (txcnt < txtimeo && n > 0) {
+
+ rxbd = ((I2C_BD *) state->rxbd) - n;
+ for (i = 0; i < n; i++) {
+ rxtimeo += TOUT_LOOP * rxbd->length;
+ rxbd++;
+ }
+
+ rxbd--; /* wait until last in list is done */
+
+ debug("[I2C] Receiving...(rxbd=0x%08lx)\n", (ulong) rxbd);
+
+ udelay(START_DELAY_US); /* give it time to start */
+ while ((rxbd->status & BD_SC_EMPTY) && (++rxcnt < rxtimeo)) {
+ udelay(DELAY_US);
+ if (ctrlc())
+ return -1;
+ __asm__ __volatile__("eieio");
+ }
+ }
+
+ /* Turn off I2C */
+ i2c->i2c_i2mod &= ~0x01;
+
+ n = state->tx_idx;
+
+ if (n > 0) {
+ for (i = 0; i < n; i++) {
+ txbd = ((I2C_BD *) state->txbd) - (n - i);
+ b = txbd->status & BD_I2C_TX_ERR;
+ if (b != 0) {
+ if (state->err_cb != NULL)
+ (*state->err_cb) (I2CECB_TX_ERR | b,
+ i, state->cb_data);
+ if (rc == 0)
+ rc = I2CERR_IO_ERROR;
+ }
+ }
+ }
+
+ n = state->rx_idx;
+
+ if (n > 0) {
+ for (i = 0; i < n; i++) {
+ rxbd = ((I2C_BD *) state->rxbd) - (n - i);
+ b = rxbd->status & BD_I2C_RX_ERR;
+ if (b != 0) {
+ if (state->err_cb != NULL)
+ (*state->err_cb) (I2CECB_RX_ERR | b,
+ i, state->cb_data);
+ if (rc == 0)
+ rc = I2CERR_IO_ERROR;
+ }
+ }
+ }
+
+ if ((txtimeo > 0 && txcnt >= txtimeo) ||
+ (rxtimeo > 0 && rxcnt >= rxtimeo)) {
+ if (state->err_cb != NULL)
+ (*state->err_cb) (I2CECB_TIMEOUT, -1, state->cb_data);
+ if (rc == 0)
+ rc = I2CERR_TIMEOUT;
+ }
+
+ return rc;
+}
+
+static void i2c_probe_callback(int flags, int xnum, void *data)
+{
+ /*
+ * the only acceptable errors are a transmit NAK or a receive
+ * overrun - tx NAK means the device does not exist, rx OV
+ * means the device must have responded to the slave address
+ * even though the transfer failed
+ */
+ if (flags == (I2CECB_TX_ERR | I2CECB_TX_NAK))
+ *(int *) data |= 1;
+ if (flags == (I2CECB_RX_ERR | I2CECB_RX_OV))
+ *(int *) data |= 2;
+}
+
+int i2c_probe(uchar chip)
+{
+ i2c_state_t state;
+ int rc, err_flag;
+ uchar buf[1];
+
+ i2c_newio(&state);
+
+ state.err_cb = i2c_probe_callback;
+ state.cb_data = (void *) &err_flag;
+ err_flag = 0;
+
+ rc = i2c_receive(&state, chip, 0, I2CF_START_COND | I2CF_STOP_COND, 1,
+ buf);
+
+ if (rc != 0)
+ return rc; /* probe failed */
+
+ rc = i2c_doio(&state);
+
+ if (rc == 0)
+ return 0; /* device exists - read succeeded */
+
+ if (rc == I2CERR_TIMEOUT)
+ return -1; /* device does not exist - timeout */
+
+ if (rc != I2CERR_IO_ERROR || err_flag == 0)
+ return rc; /* probe failed */
+
+ if (err_flag & 1)
+ return -1; /* device does not exist - had transmit NAK */
+
+ return 0; /* device exists - had receive overrun */
+}
+
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ i2c_state_t state;
+ uchar xaddr[4];
+ int rc;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+ /*
+ * EEPROM chips that implement "address overflow" are ones
+ * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
+ * and the extra bits end up in the "chip address" bit slots.
+ * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
+ * chips.
+ *
+ * Note that we consider the length of the address field to still
+ * be one byte because the extra address bits are hidden in the
+ * chip address.
+ */
+ chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+ i2c_newio(&state);
+
+ rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen,
+ &xaddr[4 - alen]);
+ if (rc != 0) {
+ printf("i2c_read: i2c_send failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer);
+ if (rc != 0) {
+ printf("i2c_read: i2c_receive failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_doio(&state);
+ if (rc != 0) {
+ printf("i2c_read: i2c_doio failed (%d)\n", rc);
+ return 1;
+ }
+ return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ i2c_state_t state;
+ uchar xaddr[4];
+ int rc;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+ /*
+ * EEPROM chips that implement "address overflow" are ones
+ * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address
+ * and the extra bits end up in the "chip address" bit slots.
+ * This makes a 24WC08 (1Kbyte) chip look like four 256 byte
+ * chips.
+ *
+ * Note that we consider the length of the address field to still
+ * be one byte because the extra address bits are hidden in the
+ * chip address.
+ */
+ chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+ i2c_newio(&state);
+
+ rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen,
+ &xaddr[4 - alen]);
+ if (rc != 0) {
+ printf("i2c_write: first i2c_send failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
+ if (rc != 0) {
+ printf("i2c_write: second i2c_send failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_doio(&state);
+ if (rc != 0) {
+ printf("i2c_write: i2c_doio failed (%d)\n", rc);
+ return 1;
+ }
+ return 0;
+}
+
+#if defined(CONFIG_I2C_MULTI_BUS)
+/*
+ * Functions for multiple I2C bus handling
+ */
+unsigned int i2c_get_bus_num(void)
+{
+ return i2c_bus_num;
+}
+
+int i2c_set_bus_num(unsigned int bus)
+{
+#if defined(CONFIG_I2C_MUX)
+ if (bus < CONFIG_SYS_MAX_I2C_BUS) {
+ i2c_bus_num = bus;
+ } else {
+ int ret;
+
+ ret = i2x_mux_select_mux(bus);
+ if (ret == 0)
+ i2c_bus_num = bus;
+ else
+ return ret;
+ }
+#else
+ if (bus >= CONFIG_SYS_MAX_I2C_BUS)
+ return -1;
+ i2c_bus_num = bus;
+#endif
+ return 0;
+}
+
+#endif /* CONFIG_I2C_MULTI_BUS */
+#endif /* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc8260/interrupts.c b/arch/powerpc/cpu/mpc8260/interrupts.c
new file mode 100644
index 0000000..79178cc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/interrupts.c
@@ -0,0 +1,279 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 22-Oct-00
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc8260.h>
+#include <mpc8260_irq.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/****************************************************************************/
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ ulong count;
+};
+
+static struct irq_action irq_handlers[NR_IRQS];
+
+static ulong ppc_cached_irq_mask[NR_MASK_WORDS];
+
+/****************************************************************************/
+/* this section was ripped out of arch/powerpc/kernel/ppc8260_pic.c in the */
+/* Linux/PPC 2.4.x source. There was no copyright notice in that file. */
+
+/* The 8260 internal interrupt controller. It is usually
+ * the only interrupt controller.
+ * There are two 32-bit registers (high/low) for up to 64
+ * possible interrupts.
+ *
+ * Now, the fun starts.....Interrupt Numbers DO NOT MAP
+ * in a simple arithmetic fashion to mask or pending registers.
+ * That is, interrupt 4 does not map to bit position 4.
+ * We create two tables, indexed by vector number, to indicate
+ * which register to use and which bit in the register to use.
+ */
+static u_char irq_to_siureg[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static u_char irq_to_siubit[] = {
+ 31, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 29, 30, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 31,
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static void m8260_mask_irq (unsigned int irq_nr)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ int bit, word;
+ volatile uint *simr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_unmask_irq (unsigned int irq_nr)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ int bit, word;
+ volatile uint *simr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+}
+
+static void m8260_mask_and_ack (unsigned int irq_nr)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ int bit, word;
+ volatile uint *simr, *sipnr;
+
+ bit = irq_to_siubit[irq_nr];
+ word = irq_to_siureg[irq_nr];
+
+ simr = &(immr->im_intctl.ic_simrh);
+ sipnr = &(immr->im_intctl.ic_sipnrh);
+ ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ simr[word] = ppc_cached_irq_mask[word];
+ sipnr[word] = 1 << (31 - bit);
+}
+
+static int m8260_get_irq (struct pt_regs *regs)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ int irq;
+ unsigned long bits;
+
+ /* For MPC8260, read the SIVEC register and shift the bits down
+ * to get the irq number. */
+ bits = immr->im_intctl.ic_sivec;
+ irq = bits >> 26;
+ return irq;
+}
+
+/* end of code ripped out of arch/powerpc/kernel/ppc8260_pic.c */
+/****************************************************************************/
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ *decrementer_count = (gd->bus_clk / 4) / CONFIG_SYS_HZ;
+
+ /* Initialize the default interrupt mapping priorities */
+ immr->im_intctl.ic_sicr = 0;
+ immr->im_intctl.ic_siprr = 0x05309770;
+ immr->im_intctl.ic_scprrh = 0x05309770;
+ immr->im_intctl.ic_scprrl = 0x05309770;
+
+ /* disable all interrupts and clear all pending bits */
+ immr->im_intctl.ic_simrh = ppc_cached_irq_mask[0] = 0;
+ immr->im_intctl.ic_simrl = ppc_cached_irq_mask[1] = 0;
+ immr->im_intctl.ic_sipnrh = 0xffffffff;
+ immr->im_intctl.ic_sipnrl = 0xffffffff;
+
+#ifdef CONFIG_HYMOD
+ /*
+ * ensure all external interrupt sources default to trigger on
+ * high-to-low transition (i.e. edge triggered active low)
+ */
+ immr->im_intctl.ic_siexr = -1;
+#endif
+
+ return (0);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+ int irq, unmask = 1;
+
+ irq = m8260_get_irq (regs);
+
+ m8260_mask_and_ack (irq);
+
+ enable_interrupts ();
+
+ if (irq_handlers[irq].handler != NULL)
+ (*irq_handlers[irq].handler) (irq_handlers[irq].arg);
+ else {
+ printf ("\nBogus External Interrupt IRQ %d\n", irq);
+ /*
+ * turn off the bogus interrupt, otherwise it
+ * might repeat forever
+ */
+ unmask = 0;
+ }
+
+ if (unmask)
+ m8260_unmask_irq (irq);
+}
+
+/****************************************************************************/
+
+/*
+ * Install and free an interrupt handler.
+ */
+
+void
+irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
+{
+ if (irq < 0 || irq >= NR_IRQS) {
+ printf ("irq_install_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ if (irq_handlers[irq].handler != NULL)
+ printf ("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
+ (ulong) handler, (ulong) irq_handlers[irq].handler);
+
+ irq_handlers[irq].handler = handler;
+ irq_handlers[irq].arg = arg;
+
+ m8260_unmask_irq (irq);
+}
+
+void irq_free_handler (int irq)
+{
+ if (irq < 0 || irq >= NR_IRQS) {
+ printf ("irq_free_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ m8260_mask_irq (irq);
+
+ irq_handlers[irq].handler = NULL;
+ irq_handlers[irq].arg = NULL;
+}
+
+/****************************************************************************/
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
+
+/****************************************************************************/
+
+#if defined(CONFIG_CMD_IRQ)
+
+/* ripped this out of ppc4xx/interrupts.c */
+
+/*******************************************************************************
+*
+* irqinfo - print information about PCI devices
+*
+*/
+void
+do_irqinfo (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, char * const argv[])
+{
+ int irq, re_enable;
+
+ re_enable = disable_interrupts ();
+
+ puts ("\nInterrupt-Information:\n"
+ "Nr Routine Arg Count\n");
+
+ for (irq = 0; irq < 32; irq++)
+ if (irq_handlers[irq].handler != NULL)
+ printf ("%02d %08lx %08lx %ld\n", irq,
+ (ulong) irq_handlers[irq].handler,
+ (ulong) irq_handlers[irq].arg,
+ irq_handlers[irq].count);
+
+ if (re_enable)
+ enable_interrupts ();
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/kgdb.S b/arch/powerpc/cpu/mpc8260/kgdb.S
new file mode 100644
index 0000000..c5936c7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/kgdb.S
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2000 Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <mpc8260.h>
+#include <version.h>
+
+#define CONFIG_8260 1 /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+
+ /*
+ * cache flushing routines for kgdb
+ */
+
+ .globl kgdb_flush_cache_all
+kgdb_flush_cache_all:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICFI|HID0_DCI /* Invalidate All */
+ SYNC
+ mtspr HID0, r3
+ blr
+
+ .globl kgdb_flush_cache_range
+kgdb_flush_cache_range:
+ li r5,CONFIG_SYS_CACHELINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,CONFIG_SYS_CACHELINE_SHIFT
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 2b
+ SYNC
+ blr
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8260/pci.c b/arch/powerpc/cpu/mpc8260/pci.c
new file mode 100644
index 0000000..6a14ba4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/pci.c
@@ -0,0 +1,466 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ * Added support for PCI bridge on MPC8272ADS
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_PCI
+
+#include <pci.h>
+#include <mpc8260.h>
+#include <asm/m8260_pci.h>
+#include <asm/io.h>
+#ifdef CONFIG_OF_LIBFDT
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 || defined CONFIG_PM826
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+/*
+ * Local->PCI map (from CPU) controlled by
+ * MPC826x master window
+ *
+ * 0x80000000 - 0xBFFFFFFF CPU2PCI space PCIBR0
+ * 0xF4000000 - 0xF7FFFFFF CPU2PCI space PCIBR1
+ *
+ * 0x80000000 - 0x9FFFFFFF 0x80000000 - 0x9FFFFFFF (Outbound ATU #1)
+ * PCI Mem with prefetch
+ *
+ * 0xA0000000 - 0xBFFFFFFF 0xA0000000 - 0xBFFFFFFF (Outbound ATU #2)
+ * PCI Mem w/o prefetch
+ *
+ * 0xF4000000 - 0xF7FFFFFF 0x00000000 - 0x03FFFFFF (Outbound ATU #3)
+ * 32-bit PCI IO
+ *
+ * PCI->Local map (from PCI)
+ * MPC826x slave window controlled by
+ *
+ * 0x00000000 - 0x1FFFFFFF 0x00000000 - 0x1FFFFFFF (Inbound ATU #1)
+ * MPC826x local memory
+ */
+
+/*
+ * Slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+
+#ifndef CONFIG_SYS_PCI_SLV_MEM_LOCAL
+#define PCI_SLV_MEM_LOCAL CONFIG_SYS_SDRAM_BASE /* Local base */
+#else
+#define PCI_SLV_MEM_LOCAL CONFIG_SYS_PCI_SLV_MEM_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_SLV_MEM_BUS
+#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */
+#else
+#define PCI_SLV_MEM_BUS CONFIG_SYS_PCI_SLV_MEM_BUS
+#endif
+
+#ifndef CONFIG_SYS_PICMR0_MASK_ATTRIB
+#define PICMR0_MASK_ATTRIB (PICMR_MASK_512MB | PICMR_ENABLE | \
+ PICMR_PREFETCH_EN)
+#else
+#define PICMR0_MASK_ATTRIB CONFIG_SYS_PICMR0_MASK_ATTRIB
+#endif
+
+/*
+ * These are the windows that allow the CPU to access PCI address space.
+ * All three PCI master windows, which allow the CPU to access PCI
+ * prefetch, non prefetch, and IO space (see below), must all fit within
+ * these windows.
+ */
+
+/* PCIBR0 */
+#ifndef CONFIG_SYS_PCI_MSTR0_LOCAL
+#define PCI_MSTR0_LOCAL 0x80000000 /* Local base */
+#else
+#define PCI_MSTR0_LOCAL CONFIG_SYS_PCI_MSTR0_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCIMSK0_MASK
+#define PCIMSK0_MASK PCIMSK_1GB /* Size of window */
+#else
+#define PCIMSK0_MASK CONFIG_SYS_PCIMSK0_MASK
+#endif
+
+/* PCIBR1 */
+#ifndef CONFIG_SYS_PCI_MSTR1_LOCAL
+#define PCI_MSTR1_LOCAL 0xF4000000 /* Local base */
+#else
+#define PCI_MSTR1_LOCAL CONFIG_SYS_PCI_MSTR1_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCIMSK1_MASK
+#define PCIMSK1_MASK PCIMSK_64MB /* Size of window */
+#else
+#define PCIMSK1_MASK CONFIG_SYS_PCIMSK1_MASK
+#endif
+
+/*
+ * Master window that allows the CPU to access PCI Memory (prefetch).
+ * This window will be setup with the first set of Outbound ATU registers
+ * in the bridge.
+ */
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEM_LOCAL
+#define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */
+#else
+#define PCI_MSTR_MEM_LOCAL CONFIG_SYS_PCI_MSTR_MEM_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEM_BUS
+#define PCI_MSTR_MEM_BUS 0x80000000 /* PCI base */
+#else
+#define PCI_MSTR_MEM_BUS CONFIG_SYS_PCI_MSTR_MEM_BUS
+#endif
+
+#ifndef CONFIG_SYS_CPU_PCI_MEM_START
+#define CPU_PCI_MEM_START PCI_MSTR_MEM_LOCAL
+#else
+#define CPU_PCI_MEM_START CONFIG_SYS_CPU_PCI_MEM_START
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEM_SIZE
+#define PCI_MSTR_MEM_SIZE 0x10000000 /* 256MB */
+#else
+#define PCI_MSTR_MEM_SIZE CONFIG_SYS_PCI_MSTR_MEM_SIZE
+#endif
+
+#ifndef CONFIG_SYS_POCMR0_MASK_ATTRIB
+#define POCMR0_MASK_ATTRIB (POCMR_MASK_256MB | POCMR_ENABLE | POCMR_PREFETCH_EN)
+#else
+#define POCMR0_MASK_ATTRIB CONFIG_SYS_POCMR0_MASK_ATTRIB
+#endif
+
+/*
+ * Master window that allows the CPU to access PCI Memory (non-prefetch).
+ * This window will be setup with the second set of Outbound ATU registers
+ * in the bridge.
+ */
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEMIO_LOCAL
+#define PCI_MSTR_MEMIO_LOCAL 0x90000000 /* Local base */
+#else
+#define PCI_MSTR_MEMIO_LOCAL CONFIG_SYS_PCI_MSTR_MEMIO_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEMIO_BUS
+#define PCI_MSTR_MEMIO_BUS 0x90000000 /* PCI base */
+#else
+#define PCI_MSTR_MEMIO_BUS CONFIG_SYS_PCI_MSTR_MEMIO_BUS
+#endif
+
+#ifndef CONFIG_SYS_CPU_PCI_MEMIO_START
+#define CPU_PCI_MEMIO_START PCI_MSTR_MEMIO_LOCAL
+#else
+#define CPU_PCI_MEMIO_START CONFIG_SYS_CPU_PCI_MEMIO_START
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_MEMIO_SIZE
+#define PCI_MSTR_MEMIO_SIZE 0x10000000 /* 256 MB */
+#else
+#define PCI_MSTR_MEMIO_SIZE CONFIG_SYS_PCI_MSTR_MEMIO_SIZE
+#endif
+
+#ifndef CONFIG_SYS_POCMR1_MASK_ATTRIB
+#define POCMR1_MASK_ATTRIB (POCMR_MASK_512MB | POCMR_ENABLE)
+#else
+#define POCMR1_MASK_ATTRIB CONFIG_SYS_POCMR1_MASK_ATTRIB
+#endif
+
+/*
+ * Master window that allows the CPU to access PCI IO space.
+ * This window will be setup with the third set of Outbound ATU registers
+ * in the bridge.
+ */
+
+#ifndef CONFIG_SYS_PCI_MSTR_IO_LOCAL
+#define PCI_MSTR_IO_LOCAL 0xA0000000 /* Local base */
+#else
+#define PCI_MSTR_IO_LOCAL CONFIG_SYS_PCI_MSTR_IO_LOCAL
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_IO_BUS
+#define PCI_MSTR_IO_BUS 0xA0000000 /* PCI base */
+#else
+#define PCI_MSTR_IO_BUS CONFIG_SYS_PCI_MSTR_IO_BUS
+#endif
+
+#ifndef CONFIG_SYS_CPU_PCI_IO_START
+#define CPU_PCI_IO_START PCI_MSTR_IO_LOCAL
+#else
+#define CPU_PCI_IO_START CONFIG_SYS_CPU_PCI_IO_START
+#endif
+
+#ifndef CONFIG_SYS_PCI_MSTR_IO_SIZE
+#define PCI_MSTR_IO_SIZE 0x10000000 /* 256MB */
+#else
+#define PCI_MSTR_IO_SIZE CONFIG_SYS_PCI_MSTR_IO_SIZE
+#endif
+
+#ifndef CONFIG_SYS_POCMR2_MASK_ATTRIB
+#define POCMR2_MASK_ATTRIB (POCMR_MASK_256MB | POCMR_ENABLE | POCMR_PCI_IO)
+#else
+#define POCMR2_MASK_ATTRIB CONFIG_SYS_POCMR2_MASK_ATTRIB
+#endif
+
+/* PCI bus configuration registers.
+ */
+
+#define PCI_CLASS_BRIDGE_CTLR 0x06
+
+
+static inline void pci_outl (u32 addr, u32 data)
+{
+ *(volatile u32 *) addr = cpu_to_le32 (data);
+}
+
+void pci_mpc8250_init (struct pci_controller *hose)
+{
+ u16 tempShort;
+
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ pci_dev_t host_devno = PCI_BDF (0, 0, 0);
+
+ pci_setup_indirect (hose, CONFIG_SYS_IMMR + PCI_CFG_ADDR_REG,
+ CONFIG_SYS_IMMR + PCI_CFG_DATA_REG);
+
+ /*
+ * Setting required to enable local bus for PCI (SIUMCR [LBPC]).
+ */
+#ifdef CONFIG_MPC8266ADS
+ immap->im_siu_conf.sc_siumcr =
+ (immap->im_siu_conf.sc_siumcr & ~SIUMCR_LBPC11)
+ | SIUMCR_LBPC01;
+#elif defined(CONFIG_ADSTYPE) && CONFIG_ADSTYPE == CONFIG_SYS_PQ2FADS
+/* nothing to do for this board here */
+#elif defined CONFIG_MPC8272
+ immap->im_siu_conf.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
+ ~SIUMCR_BBD &
+ ~SIUMCR_ESE &
+ ~SIUMCR_PBSE &
+ ~SIUMCR_CDIS &
+ ~SIUMCR_DPPC11 &
+ ~SIUMCR_L2CPC11 &
+ ~SIUMCR_LBPC11 &
+ ~SIUMCR_APPC11 &
+ ~SIUMCR_CS10PC11 &
+ ~SIUMCR_BCTLC11 &
+ ~SIUMCR_MMR11)
+ | SIUMCR_DPPC11
+ | SIUMCR_L2CPC01
+ | SIUMCR_LBPC00
+ | SIUMCR_APPC10
+ | SIUMCR_CS10PC00
+ | SIUMCR_BCTLC00
+ | SIUMCR_MMR11;
+#elif defined(CONFIG_TQM8272)
+/* nothing to do for this Board here */
+#else
+ /*
+ * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+ * and local bus for PCI (SIUMCR [LBPC]).
+ */
+ immap->im_siu_conf.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
+ ~SIUMCR_LBPC11 &
+ ~SIUMCR_CS10PC11 &
+ ~SIUMCR_LBPC11) |
+ SIUMCR_LBPC01 |
+ SIUMCR_CS10PC01 |
+ SIUMCR_APPC10;
+#endif
+
+ /* Make PCI lowest priority */
+ /* Each 4 bits is a device bus request and the MS 4bits
+ is highest priority */
+ /* Bus 4bit value
+ --- ----------
+ CPM high 0b0000
+ CPM middle 0b0001
+ CPM low 0b0010
+ PCI reguest 0b0011
+ Reserved 0b0100
+ Reserved 0b0101
+ Internal Core 0b0110
+ External Master 1 0b0111
+ External Master 2 0b1000
+ External Master 3 0b1001
+ The rest are reserved */
+ immap->im_siu_conf.sc_ppc_alrh = 0x61207893;
+
+ /* Park bus on core while modifying PCI Bus accesses */
+ immap->im_siu_conf.sc_ppc_acr = 0x6;
+
+ /*
+ * Set up master windows that allow the CPU to access PCI space. These
+ * windows are set up using the two SIU PCIBR registers.
+ */
+ immap->im_memctl.memc_pcimsk0 = PCIMSK0_MASK;
+ immap->im_memctl.memc_pcibr0 = PCI_MSTR0_LOCAL | PCIBR_ENABLE;
+
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272
+ immap->im_memctl.memc_pcimsk1 = PCIMSK1_MASK;
+ immap->im_memctl.memc_pcibr1 = PCI_MSTR1_LOCAL | PCIBR_ENABLE;
+#endif
+
+ /* Release PCI RST (by default the PCI RST signal is held low) */
+ immap->im_pci.pci_gcr = cpu_to_le32 (PCIGCR_PCI_BUS_EN);
+
+ /* give it some time */
+ {
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272
+ /* Give the PCI cards more time to initialize before query
+ This might be good for other boards also
+ */
+ int i;
+
+ for (i = 0; i < 1000; ++i)
+#endif
+ udelay (1000);
+ }
+
+ /*
+ * Set up master window that allows the CPU to access PCI Memory (prefetch)
+ * space. This window is set up using the first set of Outbound ATU registers.
+ */
+ immap->im_pci.pci_potar0 = cpu_to_le32 (PCI_MSTR_MEM_BUS >> 12); /* PCI base */
+ immap->im_pci.pci_pobar0 = cpu_to_le32 (PCI_MSTR_MEM_LOCAL >> 12); /* Local base */
+ immap->im_pci.pci_pocmr0 = cpu_to_le32 (POCMR0_MASK_ATTRIB); /* Size & attribute */
+
+ /*
+ * Set up master window that allows the CPU to access PCI Memory (non-prefetch)
+ * space. This window is set up using the second set of Outbound ATU registers.
+ */
+ immap->im_pci.pci_potar1 = cpu_to_le32 (PCI_MSTR_MEMIO_BUS >> 12); /* PCI base */
+ immap->im_pci.pci_pobar1 = cpu_to_le32 (PCI_MSTR_MEMIO_LOCAL >> 12); /* Local base */
+ immap->im_pci.pci_pocmr1 = cpu_to_le32 (POCMR1_MASK_ATTRIB); /* Size & attribute */
+
+ /*
+ * Set up master window that allows the CPU to access PCI IO space. This window
+ * is set up using the third set of Outbound ATU registers.
+ */
+ immap->im_pci.pci_potar2 = cpu_to_le32 (PCI_MSTR_IO_BUS >> 12); /* PCI base */
+ immap->im_pci.pci_pobar2 = cpu_to_le32 (PCI_MSTR_IO_LOCAL >> 12); /* Local base */
+ immap->im_pci.pci_pocmr2 = cpu_to_le32 (POCMR2_MASK_ATTRIB); /* Size & attribute */
+
+ /*
+ * Set up slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+ immap->im_pci.pci_pitar0 = cpu_to_le32 (PCI_SLV_MEM_LOCAL >> 12); /* PCI base */
+ immap->im_pci.pci_pibar0 = cpu_to_le32 (PCI_SLV_MEM_BUS >> 12); /* Local base */
+ immap->im_pci.pci_picmr0 = cpu_to_le32 (PICMR0_MASK_ATTRIB); /* Size & attribute */
+
+ /* See above for description - puts PCI request as highest priority */
+#ifdef CONFIG_MPC8272
+ immap->im_siu_conf.sc_ppc_alrh = 0x01236745;
+#else
+ immap->im_siu_conf.sc_ppc_alrh = 0x03124567;
+#endif
+
+ /* Park the bus on the PCI */
+ immap->im_siu_conf.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+
+ /* Host mode - specify the bridge as a host-PCI bridge */
+
+ pci_hose_write_config_byte (hose, host_devno, PCI_CLASS_CODE,
+ PCI_CLASS_BRIDGE_CTLR);
+
+ /* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */
+ pci_hose_read_config_word (hose, host_devno, PCI_COMMAND, &tempShort);
+ pci_hose_write_config_word (hose, host_devno, PCI_COMMAND,
+ tempShort | PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY);
+
+ /* do some bridge init, should be done on all 8260 based bridges */
+ pci_hose_write_config_byte (hose, host_devno, PCI_CACHE_LINE_SIZE,
+ 0x08);
+ pci_hose_write_config_byte (hose, host_devno, PCI_LATENCY_TIMER,
+ 0xF8);
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* System memory space */
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272 || defined CONFIG_PM826
+ pci_set_region (hose->regions + 0,
+ PCI_SLV_MEM_BUS,
+ PCI_SLV_MEM_LOCAL,
+ gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+#else
+ pci_set_region (hose->regions + 0,
+ CONFIG_SYS_SDRAM_BASE,
+ CONFIG_SYS_SDRAM_BASE,
+ 0x4000000, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
+#endif
+
+ /* PCI memory space */
+#if defined CONFIG_MPC8266ADS || defined CONFIG_MPC8272
+ pci_set_region (hose->regions + 1,
+ PCI_MSTR_MEMIO_BUS,
+ PCI_MSTR_MEMIO_LOCAL,
+ PCI_MSTR_MEMIO_SIZE, PCI_REGION_MEM);
+#else
+ pci_set_region (hose->regions + 1,
+ PCI_MSTR_MEM_BUS,
+ PCI_MSTR_MEM_LOCAL,
+ PCI_MSTR_MEM_SIZE, PCI_REGION_MEM);
+#endif
+
+ /* PCI I/O space */
+ pci_set_region (hose->regions + 2,
+ PCI_MSTR_IO_BUS,
+ PCI_MSTR_IO_LOCAL, PCI_MSTR_IO_SIZE, PCI_REGION_IO);
+
+ hose->region_count = 3;
+
+ pci_register_hose (hose);
+ /* Mask off master abort machine checks */
+ immap->im_pci.pci_emr &= cpu_to_le32 (~PCI_ERROR_PCI_NO_RSP);
+ eieio ();
+
+ hose->last_busno = pci_hose_scan (hose);
+
+
+ /* clear the error in the error status register */
+ immap->im_pci.pci_esr = cpu_to_le32 (PCI_ERROR_PCI_NO_RSP);
+
+ /* unmask master abort machine checks */
+ immap->im_pci.pci_emr |= cpu_to_le32 (PCI_ERROR_PCI_NO_RSP);
+}
+
+#if defined(CONFIG_OF_LIBFDT)
+void ft_pci_setup(void *blob, bd_t *bd)
+{
+ do_fixup_by_prop_u32(blob, "device_type", "pci", 4,
+ "clock-frequency", gd->pci_clk, 1);
+}
+#endif
+
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/cpu/mpc8260/serial_scc.c b/arch/powerpc/cpu/mpc8260/serial_scc.c
new file mode 100644
index 0000000..ab2a2b2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/serial_scc.c
@@ -0,0 +1,508 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SCC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <serial.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SCC)
+
+#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
+
+#define SCC_INDEX 0
+#define PROFF_SCC PROFF_SCC1
+#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
+ CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
+
+#define SCC_INDEX 1
+#define PROFF_SCC PROFF_SCC2
+#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
+ CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
+
+#define SCC_INDEX 2
+#define PROFF_SCC PROFF_SCC3
+#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
+ CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
+
+#define SCC_INDEX 3
+#define PROFF_SCC PROFF_SCC4
+#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
+ CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+static int mpc8260_scc_serial_init(void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr;
+
+ /* initialize pointers to SCC */
+
+ sp = (scc_t *) &(im->im_scc[SCC_INDEX]);
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* put the SCC channel into NMSI (non multiplexd serial interface)
+ * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+ */
+ im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+ serial_setbrg ();
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+ up->scc_genscc.scc_rfcr = CPMFCR_EB;
+ up->scc_genscc.scc_tfcr = CPMFCR_EB;
+ up->scc_genscc.scc_mrblr = 1;
+ up->scc_maxidl = 0;
+ up->scc_brkcr = 1;
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+ up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->scc_sccm = 0;
+ sp->scc_scce = 0xffff;
+
+ /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+ */
+ sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
+ sp->scc_gsmrl = \
+ SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+ /* Set CTS flow control, 1 stop bit, 8 bit character length,
+ * normal async UART mode, no parity
+ */
+ sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
+
+ /* execute the "Init Rx and Tx params" CP command.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+ return (0);
+}
+
+static void mpc8260_scc_serial_setbrg(void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+ m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate,
+ CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(SCC_INDEX, gd->baudrate);
+#endif
+}
+
+static void mpc8260_scc_serial_putc(const char c)
+{
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf;
+ volatile immap_t *im;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ im = (immap_t *)CONFIG_SYS_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+ tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
+
+ /* Wait for last character to go.
+ */
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ /* Load the character into the transmit buffer.
+ */
+ *(volatile char *)tbdf->cbd_bufaddr = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+static int mpc8260_scc_serial_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+ unsigned char c;
+
+ im = (immap_t *)CONFIG_SYS_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+ rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+ /* Wait for character to show up.
+ */
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* Grab the char and clear the buffer again.
+ */
+ c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return (c);
+}
+
+static int mpc8260_scc_serial_tstc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+
+ im = (immap_t *)CONFIG_SYS_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+ rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+ return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+static struct serial_device mpc8260_scc_serial_drv = {
+ .name = "mpc8260_scc_uart",
+ .start = mpc8260_scc_serial_init,
+ .stop = NULL,
+ .setbrg = mpc8260_scc_serial_setbrg,
+ .putc = mpc8260_scc_serial_putc,
+ .puts = default_serial_puts,
+ .getc = mpc8260_scc_serial_getc,
+ .tstc = mpc8260_scc_serial_tstc,
+};
+
+void mpc8260_scc_serial_initialize(void)
+{
+ serial_register(&mpc8260_scc_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &mpc8260_scc_serial_drv;
+}
+#endif /* CONFIG_CONS_ON_SCC */
+
+#if defined(CONFIG_KGDB_ON_SCC)
+
+#if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
+#error Whoops! serial console and kgdb are on the same scc serial port
+#endif
+
+#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SCC1 */
+
+#define KGDB_SCC_INDEX 0
+#define KGDB_PROFF_SCC PROFF_SCC1
+#define KGDB_CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
+ CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SCC2 */
+
+#define KGDB_SCC_INDEX 1
+#define KGDB_PROFF_SCC PROFF_SCC2
+#define KGDB_CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
+ CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 3 /* KGDB Port on SCC3 */
+
+#define KGDB_SCC_INDEX 2
+#define KGDB_PROFF_SCC PROFF_SCC3
+#define KGDB_CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
+ CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 4 /* KGDB Port on SCC4 */
+
+#define KGDB_SCC_INDEX 3
+#define KGDB_PROFF_SCC PROFF_SCC4
+#define KGDB_CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
+ CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "kgdb serial port not correctly defined"
+
+#endif
+
+void
+kgdb_serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
+ char *s, *e;
+
+ if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
+ ulong rate = simple_strtoul(s, &e, 10);
+ if (e > s && *e == '\0')
+ speed = rate;
+ }
+
+ /* initialize pointers to SCC */
+
+ sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]);
+ up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* put the SCC channel into NMSI (non multiplexd serial interface)
+ * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+ */
+ im->im_cpmux.cmx_scr = \
+ (im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+#if defined(CONFIG_KGDB_USE_EXTC)
+ m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed,
+ CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(KGDB_SCC_INDEX, speed);
+#endif
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+ up->scc_genscc.scc_rfcr = CPMFCR_EB;
+ up->scc_genscc.scc_tfcr = CPMFCR_EB;
+ up->scc_genscc.scc_mrblr = 1;
+ up->scc_maxidl = 0;
+ up->scc_brkcr = 1;
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+ up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->scc_sccm = 0;
+ sp->scc_scce = 0xffff;
+
+ /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+ */
+ sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
+ sp->scc_gsmrl = \
+ SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+ /* Set CTS flow control, 1 stop bit, 8 bit character length,
+ * normal async UART mode, no parity
+ */
+ sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
+
+ /* execute the "Init Rx and Tx params" CP command.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+ printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
+}
+
+void
+putDebugChar(const char c)
+{
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf;
+ volatile immap_t *im;
+
+ if (c == '\n')
+ putDebugChar ('\r');
+
+ im = (immap_t *)CONFIG_SYS_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+ tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
+
+ /* Wait for last character to go.
+ */
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ /* Load the character into the transmit buffer.
+ */
+ *(volatile char *)tbdf->cbd_bufaddr = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+putDebugStr (const char *s)
+{
+ while (*s) {
+ putDebugChar (*s++);
+ }
+}
+
+int
+getDebugChar(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+ unsigned char c;
+
+ im = (immap_t *)CONFIG_SYS_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+ rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+ /* Wait for character to show up.
+ */
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* Grab the char and clear the buffer again.
+ */
+ c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return (c);
+}
+
+void
+kgdb_interruptible(int yes)
+{
+ return;
+}
+
+#endif /* CONFIG_KGDB_ON_SCC */
diff --git a/arch/powerpc/cpu/mpc8260/serial_smc.c b/arch/powerpc/cpu/mpc8260/serial_smc.c
new file mode 100644
index 0000000..9410e4c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/serial_smc.c
@@ -0,0 +1,477 @@
+/*
+ * (C) Copyright 2000, 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
+ * changes based on the file arch/powerpc/mbxboot/m8260_tty.c from the
+ * Linux/PPC sources (m8260_tty.c had no copyright info in it).
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+#include <serial.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SMC)
+
+#if CONFIG_CONS_INDEX == 1 /* Console on SMC1 */
+
+#define SMC_INDEX 0
+#define PROFF_SMC_BASE PROFF_SMC1_BASE
+#define PROFF_SMC PROFF_SMC1
+#define CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
+#define CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
+#define CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
+#define CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
+
+#elif CONFIG_CONS_INDEX == 2 /* Console on SMC2 */
+
+#define SMC_INDEX 1
+#define PROFF_SMC_BASE PROFF_SMC2_BASE
+#define PROFF_SMC PROFF_SMC2
+#define CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
+#define CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
+#define CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
+#define CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+#if !defined(CONFIG_SYS_SMC_RXBUFLEN)
+#define CONFIG_SYS_SMC_RXBUFLEN 1
+#define CONFIG_SYS_MAXIDLE 0
+#else
+#if !defined(CONFIG_SYS_MAXIDLE)
+#error "you must define CONFIG_SYS_MAXIDLE"
+#endif
+#endif
+
+typedef volatile struct serialbuffer {
+ cbd_t rxbd; /* Rx BD */
+ cbd_t txbd; /* Tx BD */
+ uint rxindex; /* index for next character to read */
+ volatile uchar rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */
+ volatile uchar txbuf; /* tx buffers */
+} serialbuffer_t;
+
+/* map rs_table index to baud rate generator index */
+static unsigned char brg_map[] = {
+ 6, /* BRG7 for SMC1 */
+ 7, /* BRG8 for SMC2 */
+ 0, /* BRG1 for SCC1 */
+ 1, /* BRG1 for SCC2 */
+ 2, /* BRG1 for SCC3 */
+ 3, /* BRG1 for SCC4 */
+};
+
+static int mpc8260_smc_serial_init(void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr;
+ volatile serialbuffer_t *rtx;
+
+ /* initialize pointers to SMC */
+
+ sp = (smc_t *) &(im->im_smc[SMC_INDEX]);
+ im->im_dprambase16[PROFF_SMC_BASE / sizeof(u16)] = PROFF_SMC;
+ up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC];
+
+ /* Disable transmitter/receiver. */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ /* allocate size of struct serialbuffer with bd rx/tx,
+ * buffer rx/tx and rx index
+ */
+ dpaddr = m8260_cpm_dpalloc((sizeof(serialbuffer_t)), 16);
+
+ rtx = (serialbuffer_t *)&im->im_dprambase[dpaddr];
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf;
+ rtx->rxbd.cbd_sc = 0;
+
+ rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf;
+ rtx->txbd.cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram. */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = CPMFCR_EB;
+ up->smc_tfcr = CPMFCR_EB;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
+ up->smc_brkcr = 0;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending. */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* put the SMC channel into NMSI (non multiplexd serial interface)
+ * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
+ */
+ im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr&~CMXSMR_MASK)|CMXSMR_VALUE;
+
+ /* Set up the baud rate generator. */
+ serial_setbrg ();
+
+ /* Make the first buffer the only buffer. */
+ rtx->txbd.cbd_sc |= BD_SC_WRAP;
+ rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* single/multi character receive. */
+ up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN;
+ up->smc_maxidl = CONFIG_SYS_MAXIDLE;
+ rtx->rxindex = 0;
+
+ /* Initialize Tx/Rx parameters. */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC_PAGE, CPM_CR_SMC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver. */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ return (0);
+}
+
+static void mpc8260_smc_serial_setbrg(void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+ m8260_cpm_extcbrg(brg_map[SMC_INDEX], gd->baudrate,
+ CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(brg_map[SMC_INDEX], gd->baudrate);
+#endif
+}
+
+static void mpc8260_smc_serial_putc(const char c)
+{
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile serialbuffer_t *rtx;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+
+ rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
+
+ /* Wait for last character to go. */
+ while (rtx->txbd.cbd_sc & BD_SC_READY & BD_SC_READY)
+ ;
+ rtx->txbuf = c;
+ rtx->txbd.cbd_datlen = 1;
+ rtx->txbd.cbd_sc |= BD_SC_READY;
+}
+
+static int mpc8260_smc_serial_getc(void)
+{
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile serialbuffer_t *rtx;
+ unsigned char c;
+
+ up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+
+ rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
+
+ /* Wait for character to show up. */
+ while (rtx->rxbd.cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* the characters are read one by one,
+ * use the rxindex to know the next char to deliver
+ */
+ c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr + rtx->rxindex);
+ rtx->rxindex++;
+
+ /* check if all char are readout, then make prepare for next receive */
+ if (rtx->rxindex >= rtx->rxbd.cbd_datlen) {
+ rtx->rxindex = 0;
+ rtx->rxbd.cbd_sc |= BD_SC_EMPTY;
+ }
+ return(c);
+}
+
+static int mpc8260_smc_serial_tstc(void)
+{
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile serialbuffer_t *rtx;
+
+ up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+ rtx = (serialbuffer_t *)&im->im_dprambase[up->smc_rbase];
+
+ return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY);
+}
+
+static struct serial_device mpc8260_smc_serial_drv = {
+ .name = "mpc8260_smc_uart",
+ .start = mpc8260_smc_serial_init,
+ .stop = NULL,
+ .setbrg = mpc8260_smc_serial_setbrg,
+ .putc = mpc8260_smc_serial_putc,
+ .puts = default_serial_puts,
+ .getc = mpc8260_smc_serial_getc,
+ .tstc = mpc8260_smc_serial_tstc,
+};
+
+void mpc8260_smc_serial_initialize(void)
+{
+ serial_register(&mpc8260_smc_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &mpc8260_smc_serial_drv;
+}
+#endif /* CONFIG_CONS_ON_SMC */
+
+#if defined(CONFIG_KGDB_ON_SMC)
+
+#if defined(CONFIG_CONS_ON_SMC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
+#error Whoops! serial console and kgdb are on the same smc serial port
+#endif
+
+#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SMC1 */
+
+#define KGDB_SMC_INDEX 0
+#define KGDB_PROFF_SMC_BASE PROFF_SMC1_BASE
+#define KGDB_PROFF_SMC PROFF_SMC1
+#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
+#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
+#define KGDB_CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
+#define KGDB_CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
+
+#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SMC2 */
+
+#define KGDB_SMC_INDEX 1
+#define KGDB_PROFF_SMC_BASE PROFF_SMC2_BASE
+#define KGDB_PROFF_SMC PROFF_SMC2
+#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
+#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
+#define KGDB_CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
+#define KGDB_CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+void
+kgdb_serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
+ char *s, *e;
+
+ if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
+ ulong rate = simple_strtoul(s, &e, 10);
+ if (e > s && *e == '\0')
+ speed = rate;
+ }
+
+ /* initialize pointers to SMC */
+
+ sp = (smc_t *) &(im->im_smc[KGDB_SMC_INDEX]);
+ im->im_dprambase16[KGDB_PROFF_SMC_BASE / sizeof(u16)] = KGDB_PROFF_SMC;
+ up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC];
+
+ /* Disable transmitter/receiver. */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram. */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = CPMFCR_EB;
+ up->smc_tfcr = CPMFCR_EB;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
+ up->smc_brkcr = 0;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending. */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* put the SMC channel into NMSI (non multiplexd serial interface)
+ * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
+ */
+ im->im_cpmux.cmx_smr =
+ (im->im_cpmux.cmx_smr & ~KGDB_CMXSMR_MASK) | KGDB_CMXSMR_VALUE;
+
+ /* Set up the baud rate generator. */
+#if defined(CONFIG_KGDB_USE_EXTC)
+ m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed,
+ CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed);
+#endif
+
+ /* Make the first buffer the only buffer. */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Single character receive. */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+
+ /* Initialize Tx/Rx parameters. */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SMC_PAGE, KGDB_CPM_CR_SMC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver. */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ printf("SMC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
+}
+
+void
+putDebugChar(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+
+ if (c == '\n')
+ putDebugChar ('\r');
+
+ up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
+
+ tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
+
+ /* Wait for last character to go. */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+putDebugStr (const char *s)
+{
+ while (*s) {
+ putDebugChar (*s++);
+ }
+}
+
+int
+getDebugChar(void)
+{
+ volatile cbd_t *rbdf;
+ volatile unsigned char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ unsigned char c;
+
+ up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
+
+ rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
+
+ /* Wait for character to show up. */
+ buf = (unsigned char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+void
+kgdb_interruptible(int yes)
+{
+ return;
+}
+
+#endif /* CONFIG_KGDB_ON_SMC */
diff --git a/arch/powerpc/cpu/mpc8260/speed.c b/arch/powerpc/cpu/mpc8260/speed.c
new file mode 100644
index 0000000..7841e8a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/speed.c
@@ -0,0 +1,244 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+extern unsigned long board_get_cpu_clk_f (void);
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ------------------------------------------------------------------------- */
+
+/* Bus-to-Core Multiplier */
+#define _1x 2
+#define _1_5x 3
+#define _2x 4
+#define _2_5x 5
+#define _3x 6
+#define _3_5x 7
+#define _4x 8
+#define _4_5x 9
+#define _5x 10
+#define _5_5x 11
+#define _6x 12
+#define _6_5x 13
+#define _7x 14
+#define _7_5x 15
+#define _8x 16
+#define _byp -1
+#define _off -2
+#define _unk -3
+
+typedef struct {
+ int b2c_mult;
+ int vco_div;
+ char *freq_60x;
+ char *freq_core;
+} corecnf_t;
+
+/*
+ * this table based on "Errata to MPC8260 PowerQUICC II User's Manual",
+ * Rev. 1, 8/2000, page 10.
+ */
+corecnf_t corecnf_tab[] = {
+ { _1_5x, 4, " 33-100", " 33-100" }, /* 0x00 */
+ { _1x, 4, " 50-150", " 50-150" }, /* 0x01 */
+ { _1x, 8, " 25-75 ", " 25-75 " }, /* 0x02 */
+ { _byp, -1, " ?-? ", " ?-? " }, /* 0x03 */
+ { _2x, 2, " 50-150", "100-300" }, /* 0x04 */
+ { _2x, 4, " 25-75 ", " 50-150" }, /* 0x05 */
+ { _2_5x, 2, " 40-120", "100-240" }, /* 0x06 */
+ { _4_5x, 2, " 22-65 ", "100-300" }, /* 0x07 */
+ { _3x, 2, " 33-100", "100-300" }, /* 0x08 */
+ { _5_5x, 2, " 18-55 ", "100-300" }, /* 0x09 */
+ { _4x, 2, " 25-75 ", "100-300" }, /* 0x0A */
+ { _5x, 2, " 20-60 ", "100-300" }, /* 0x0B */
+ { _1_5x, 8, " 16-50 ", " 16-50 " }, /* 0x0C */
+ { _6x, 2, " 16-50 ", "100-300" }, /* 0x0D */
+ { _3_5x, 2, " 30-85 ", "100-300" }, /* 0x0E */
+ { _off, -1, " ?-? ", " ?-? " }, /* 0x0F */
+ { _3x, 4, " 16-50 ", " 50-150" }, /* 0x10 */
+ { _2_5x, 4, " 20-60 ", " 50-120" }, /* 0x11 */
+ { _6_5x, 2, " 15-46 ", "100-300" }, /* 0x12 */
+ { _byp, -1, " ?-? ", " ?-? " }, /* 0x13 */
+ { _7x, 2, " 14-43 ", "100-300" }, /* 0x14 */
+ { _2x, 4, " 25-75 ", " 50-150" }, /* 0x15 */
+ { _7_5x, 2, " 13-40 ", "100-300" }, /* 0x16 */
+ { _4_5x, 2, " 22-65 ", "100-300" }, /* 0x17 */
+ { _unk, -1, " ?-? ", " ?-? " }, /* 0x18 */
+ { _5_5x, 2, " 18-55 ", "100-300" }, /* 0x19 */
+ { _4x, 2, " 25-75 ", "100-300" }, /* 0x1A */
+ { _5x, 2, " 20-60 ", "100-300" }, /* 0x1B */
+ { _8x, 2, " 12-38 ", "100-300" }, /* 0x1C */
+ { _6x, 2, " 16-50 ", "100-300" }, /* 0x1D */
+ { _3_5x, 2, " 30-85 ", "100-300" }, /* 0x1E */
+ { _off, -1, " ?-? ", " ?-? " }, /* 0x1F */
+};
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ *
+ */
+
+int get_clocks (void)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ ulong clkin;
+ ulong sccr, dfbrg;
+ ulong scmr, corecnf, plldf, pllmf;
+ corecnf_t *cp;
+
+#if !defined(CONFIG_8260_CLKIN)
+#error clock measuring not implemented yet - define CONFIG_8260_CLKIN
+#else
+#if defined(CONFIG_BOARD_GET_CPU_CLK_F)
+ clkin = board_get_cpu_clk_f ();
+#else
+ clkin = CONFIG_8260_CLKIN;
+#endif
+#endif
+
+ sccr = immap->im_clkrst.car_sccr;
+ dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+
+ scmr = immap->im_clkrst.car_scmr;
+ corecnf = (scmr & SCMR_CORECNF_MSK) >> SCMR_CORECNF_SHIFT;
+ cp = &corecnf_tab[corecnf];
+
+ /* HiP7, HiP7 Rev01, HiP7 RevA */
+ if ((get_pvr () == PVR_8260_HIP7) ||
+ (get_pvr () == PVR_8260_HIP7R1) ||
+ (get_pvr () == PVR_8260_HIP7RA)) {
+ pllmf = (scmr & SCMR_PLLMF_MSKH7) >> SCMR_PLLMF_SHIFT;
+ gd->arch.vco_out = clkin * (pllmf + 1);
+ } else { /* HiP3, HiP4 */
+ pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT;
+ plldf = (scmr & SCMR_PLLDF) ? 1 : 0;
+ gd->arch.vco_out = (clkin * 2 * (pllmf + 1)) / (plldf + 1);
+ }
+
+ gd->arch.cpm_clk = gd->arch.vco_out / 2;
+ gd->bus_clk = clkin;
+ gd->arch.scc_clk = gd->arch.vco_out / 4;
+ gd->arch.brg_clk = gd->arch.vco_out / (1 << (2 * (dfbrg + 1)));
+
+ if (cp->b2c_mult > 0) {
+ gd->cpu_clk = (clkin * cp->b2c_mult) / 2;
+ } else {
+ gd->cpu_clk = clkin;
+ }
+
+#ifdef CONFIG_PCI
+ gd->pci_clk = clkin;
+
+ if (sccr & SCCR_PCI_MODE) {
+ uint pci_div;
+ uint pcidf = (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT;
+
+ if (sccr & SCCR_PCI_MODCK) {
+ pci_div = 2;
+ if (pcidf == 9) {
+ pci_div *= 5;
+ } else if (pcidf == 0xB) {
+ pci_div *= 6;
+ } else {
+ pci_div *= (pcidf + 1);
+ }
+ } else {
+ pci_div = pcidf + 1;
+ }
+
+ gd->pci_clk = (gd->arch.cpm_clk * 2) / pci_div;
+ }
+#endif
+
+ return (0);
+}
+
+int prt_8260_clks (void)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ ulong sccr, dfbrg;
+ ulong scmr, corecnf, busdf, cpmdf, plldf, pllmf, pcidf;
+ corecnf_t *cp;
+
+ sccr = immap->im_clkrst.car_sccr;
+ dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+
+ scmr = immap->im_clkrst.car_scmr;
+ corecnf = (scmr & SCMR_CORECNF_MSK) >> SCMR_CORECNF_SHIFT;
+ busdf = (scmr & SCMR_BUSDF_MSK) >> SCMR_BUSDF_SHIFT;
+ cpmdf = (scmr & SCMR_CPMDF_MSK) >> SCMR_CPMDF_SHIFT;
+ plldf = (scmr & SCMR_PLLDF) ? 1 : 0;
+ pllmf = (scmr & SCMR_PLLMF_MSK) >> SCMR_PLLMF_SHIFT;
+ pcidf = (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT;
+
+ cp = &corecnf_tab[corecnf];
+
+ puts (CPU_ID_STR " Clock Configuration\n - Bus-to-Core Mult ");
+
+ switch (cp->b2c_mult) {
+ case _byp:
+ puts ("BYPASS");
+ break;
+
+ case _off:
+ puts ("OFF");
+ break;
+
+ case _unk:
+ puts ("UNKNOWN");
+ break;
+
+ default:
+ printf ("%d%sx",
+ cp->b2c_mult / 2,
+ (cp->b2c_mult % 2) ? ".5" : "");
+ break;
+ }
+
+ printf (", VCO Div %d, 60x Bus Freq %s, Core Freq %s\n",
+ cp->vco_div, cp->freq_60x, cp->freq_core);
+
+ printf (" - dfbrg %ld, corecnf 0x%02lx, busdf %ld, cpmdf %ld, "
+ "plldf %ld, pllmf %ld, pcidf %ld\n",
+ dfbrg, corecnf, busdf, cpmdf,
+ plldf, pllmf, pcidf);
+
+ printf (" - vco_out %10ld, scc_clk %10ld, brg_clk %10ld\n",
+ gd->arch.vco_out, gd->arch.scc_clk, gd->arch.brg_clk);
+
+ printf (" - cpu_clk %10ld, cpm_clk %10ld, bus_clk %10ld\n",
+ gd->cpu_clk, gd->arch.cpm_clk, gd->bus_clk);
+#ifdef CONFIG_PCI
+ printf (" - pci_clk %10ld\n", gd->pci_clk);
+#endif
+ putc ('\n');
+
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc8260/speed.h b/arch/powerpc/cpu/mpc8260/speed.h
new file mode 100644
index 0000000..3f32a14
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/speed.h
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*-----------------------------------------------------------------------
+ * Timer value for timer 2, ICLK = 10
+ *
+ * SPEED_FCOUNT2 = GCLK / (16 * (TIMER_TMR_PS + 1))
+ * SPEED_TMR3_PS = (GCLK / (16 * SPEED_FCOUNT3)) - 1
+ *
+ * SPEED_FCOUNT2 timer 2 counting frequency
+ * GCLK CPU clock
+ * SPEED_TMR2_PS prescaler
+ */
+#define SPEED_TMR2_PS (250 - 1) /* divide by 250 */
+
+/*-----------------------------------------------------------------------
+ * Timer value for PIT
+ *
+ * PIT_TIME = SPEED_PITC / PITRTCLK
+ * PITRTCLK = 8192
+ */
+#define SPEED_PITC (82 << 16) /* start counting from 82 */
+
+/*
+ * The new value for PTA is calculated from
+ *
+ * PTA = (gclk * Trefresh) / (2 ^ (2 * DFBRG) * PTP * NCS)
+ *
+ * gclk CPU clock (not bus clock !)
+ * Trefresh Refresh cycle * 4 (four word bursts used)
+ * DFBRG For normal mode (no clock reduction) always 0
+ * PTP Prescaler (already adjusted for no. of banks and 4K / 8K refresh)
+ * NCS Number of SDRAM banks (chip selects) on this UPM.
+ */
diff --git a/arch/powerpc/cpu/mpc8260/spi.c b/arch/powerpc/cpu/mpc8260/spi.c
new file mode 100644
index 0000000..01b492e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/spi.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2001 Navin Boppuri / Prashant Patel
+ * <nboppuri@trinetcommunication.com>,
+ * <pmpatel@trinetcommunication.com>
+ * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
+ * Copyright (c) 2001-2003 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8260 CPM SPI interface.
+ *
+ * Parts of this code are probably not portable and/or specific to
+ * the board which I used for the tests. Please send fixes/complaints
+ * to wd@denx.de
+ *
+ */
+
+#include <common.h>
+#include <asm/cpm_8260.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+#include <post.h>
+#include <net.h>
+
+#if defined(CONFIG_SPI)
+
+/* Warning:
+ * You cannot enable DEBUG for early system initalization, i. e. when
+ * this driver is used to read environment parameters like "baudrate"
+ * from EEPROM which are used to initialize the serial port which is
+ * needed to print the debug messages...
+ */
+#undef DEBUG
+
+#define SPI_EEPROM_WREN 0x06
+#define SPI_EEPROM_RDSR 0x05
+#define SPI_EEPROM_READ 0x03
+#define SPI_EEPROM_WRITE 0x02
+
+/* ---------------------------------------------------------------
+ * Offset for initial SPI buffers in DPRAM:
+ * We need a 520 byte scratch DPRAM area to use at an early stage.
+ * It is used between the two initialization calls (spi_init_f()
+ * and spi_init_r()).
+ * The value 0x2000 makes it far enough from the start of the data
+ * area (as well as from the stack pointer).
+ * --------------------------------------------------------------- */
+#ifndef CONFIG_SYS_SPI_INIT_OFFSET
+#define CONFIG_SYS_SPI_INIT_OFFSET 0x2000
+#endif
+
+#define CPM_SPI_BASE 0x100
+
+#ifdef DEBUG
+
+#define DPRINT(a) printf a;
+/* -----------------------------------------------
+ * Helper functions to peek into tx and rx buffers
+ * ----------------------------------------------- */
+static const char * const hex_digit = "0123456789ABCDEF";
+
+static char quickhex (int i)
+{
+ return hex_digit[i];
+}
+
+static void memdump (void *pv, int num)
+{
+ int i;
+ unsigned char *pc = (unsigned char *) pv;
+
+ for (i = 0; i < num; i++)
+ printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
+ printf ("\t");
+ for (i = 0; i < num; i++)
+ printf ("%c", isprint (pc[i]) ? pc[i] : '.');
+ printf ("\n");
+}
+#else /* !DEBUG */
+
+#define DPRINT(a)
+
+#endif /* DEBUG */
+
+/* -------------------
+ * Function prototypes
+ * ------------------- */
+void spi_init (void);
+
+ssize_t spi_read (uchar *, int, uchar *, int);
+ssize_t spi_write (uchar *, int, uchar *, int);
+ssize_t spi_xfer (size_t);
+
+/* -------------------
+ * Variables
+ * ------------------- */
+
+#define MAX_BUFFER 0x104
+
+/* ----------------------------------------------------------------------
+ * Initially we place the RX and TX buffers at a fixed location in DPRAM!
+ * ---------------------------------------------------------------------- */
+static uchar *rxbuf =
+ (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
+ [CONFIG_SYS_SPI_INIT_OFFSET];
+static uchar *txbuf =
+ (uchar *)&((immap_t *)CONFIG_SYS_IMMR)->im_dprambase
+ [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
+
+/* **************************************************************************
+ *
+ * Function: spi_init_f
+ *
+ * Description: Init SPI-Controller (ROM part)
+ *
+ * return: ---
+ *
+ * *********************************************************************** */
+void spi_init_f (void)
+{
+ unsigned int dpaddr;
+
+ volatile spi_t *spi;
+ volatile immap_t *immr;
+ volatile cpm8260_t *cp;
+ volatile cbd_t *tbdf, *rbdf;
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ cp = (cpm8260_t *) &immr->im_cpm;
+
+ immr->im_dprambase16[PROFF_SPI_BASE / sizeof(u16)] = PROFF_SPI;
+ spi = (spi_t *)&immr->im_dprambase[PROFF_SPI];
+
+/* 1 */
+ /* ------------------------------------------------
+ * Initialize Port D SPI pins
+ * (we are only in Master Mode !)
+ * ------------------------------------------------ */
+
+ /* --------------------------------------------
+ * GPIO or per. Function
+ * PPARD[16] = 1 [0x00008000] (SPIMISO)
+ * PPARD[17] = 1 [0x00004000] (SPIMOSI)
+ * PPARD[18] = 1 [0x00002000] (SPICLK)
+ * PPARD[12] = 0 [0x00080000] -> GPIO: (CS for ATC EEPROM)
+ * -------------------------------------------- */
+ immr->im_ioport.iop_ppard |= 0x0000E000; /* set bits */
+ immr->im_ioport.iop_ppard &= ~0x00080000; /* reset bit */
+
+ /* ----------------------------------------------
+ * In/Out or per. Function 0/1
+ * PDIRD[16] = 0 [0x00008000] -> PERI1: SPIMISO
+ * PDIRD[17] = 0 [0x00004000] -> PERI1: SPIMOSI
+ * PDIRD[18] = 0 [0x00002000] -> PERI1: SPICLK
+ * PDIRD[12] = 1 [0x00080000] -> GPIO OUT: CS for ATC EEPROM
+ * ---------------------------------------------- */
+ immr->im_ioport.iop_pdird &= ~0x0000E000;
+ immr->im_ioport.iop_pdird |= 0x00080000;
+
+ /* ----------------------------------------------
+ * special option reg.
+ * PSORD[16] = 1 [0x00008000] -> SPIMISO
+ * PSORD[17] = 1 [0x00004000] -> SPIMOSI
+ * PSORD[18] = 1 [0x00002000] -> SPICLK
+ * ---------------------------------------------- */
+ immr->im_ioport.iop_psord |= 0x0000E000;
+
+ /* Initialize the parameter ram.
+ * We need to make sure many things are initialized to zero
+ */
+ spi->spi_rstate = 0;
+ spi->spi_rdp = 0;
+ spi->spi_rbptr = 0;
+ spi->spi_rbc = 0;
+ spi->spi_rxtmp = 0;
+ spi->spi_tstate = 0;
+ spi->spi_tdp = 0;
+ spi->spi_tbptr = 0;
+ spi->spi_tbc = 0;
+ spi->spi_txtmp = 0;
+
+ /* Allocate space for one transmit and one receive buffer
+ * descriptor in the DP ram
+ */
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+ dpaddr = m8260_cpm_dpalloc (sizeof(cbd_t)*2, 8);
+#else
+ dpaddr = CPM_SPI_BASE;
+#endif
+
+/* 3 */
+ /* Set up the SPI parameters in the parameter ram */
+ spi->spi_rbase = dpaddr;
+ spi->spi_tbase = dpaddr + sizeof (cbd_t);
+
+ /***********IMPORTANT******************/
+
+ /*
+ * Setting transmit and receive buffer descriptor pointers
+ * initially to rbase and tbase. Only the microcode patches
+ * documentation talks about initializing this pointer. This
+ * is missing from the sample I2C driver. If you dont
+ * initialize these pointers, the kernel hangs.
+ */
+ spi->spi_rbptr = spi->spi_rbase;
+ spi->spi_tbptr = spi->spi_tbase;
+
+/* 4 */
+ /* Init SPI Tx + Rx Parameters */
+ while (cp->cp_cpcr & CPM_CR_FLG)
+ ;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG)
+ ;
+
+/* 6 */
+ /* Set to big endian. */
+ spi->spi_tfcr = CPMFCR_EB;
+ spi->spi_rfcr = CPMFCR_EB;
+
+/* 7 */
+ /* Set maximum receive size. */
+ spi->spi_mrblr = MAX_BUFFER;
+
+/* 8 + 9 */
+ /* tx and rx buffer descriptors */
+ tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
+ rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
+
+ tbdf->cbd_sc &= ~BD_SC_READY;
+ rbdf->cbd_sc &= ~BD_SC_EMPTY;
+
+ /* Set the bd's rx and tx buffer address pointers */
+ rbdf->cbd_bufaddr = (ulong) rxbuf;
+ tbdf->cbd_bufaddr = (ulong) txbuf;
+
+/* 10 + 11 */
+ immr->im_spi.spi_spie = SPI_EMASK; /* Clear all SPI events */
+ immr->im_spi.spi_spim = 0x00; /* Mask all SPI events */
+
+
+ return;
+}
+
+/* **************************************************************************
+ *
+ * Function: spi_init_r
+ *
+ * Description: Init SPI-Controller (RAM part) -
+ * The malloc engine is ready and we can move our buffers to
+ * normal RAM
+ *
+ * return: ---
+ *
+ * *********************************************************************** */
+void spi_init_r (void)
+{
+ volatile spi_t *spi;
+ volatile immap_t *immr;
+ volatile cbd_t *tbdf, *rbdf;
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ spi = (spi_t *)&immr->im_dprambase[PROFF_SPI];
+
+ /* tx and rx buffer descriptors */
+ tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
+ rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
+
+ /* Allocate memory for RX and TX buffers */
+ rxbuf = (uchar *) malloc (MAX_BUFFER);
+ txbuf = (uchar *) malloc (MAX_BUFFER);
+
+ rbdf->cbd_bufaddr = (ulong) rxbuf;
+ tbdf->cbd_bufaddr = (ulong) txbuf;
+
+ return;
+}
+
+/****************************************************************************
+ * Function: spi_write
+ **************************************************************************** */
+ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+ int i;
+
+ memset(rxbuf, 0, MAX_BUFFER);
+ memset(txbuf, 0, MAX_BUFFER);
+ *txbuf = SPI_EEPROM_WREN; /* write enable */
+ spi_xfer(1);
+ memcpy(txbuf, addr, alen);
+ *txbuf = SPI_EEPROM_WRITE; /* WRITE memory array */
+ memcpy(alen + txbuf, buffer, len);
+ spi_xfer(alen + len);
+ /* ignore received data */
+ for (i = 0; i < 1000; i++) {
+ *txbuf = SPI_EEPROM_RDSR; /* read status */
+ txbuf[1] = 0;
+ spi_xfer(2);
+ if (!(rxbuf[1] & 1)) {
+ break;
+ }
+ udelay(1000);
+ }
+ if (i >= 1000) {
+ printf ("*** spi_write: Time out while writing!\n");
+ }
+
+ return len;
+}
+
+/****************************************************************************
+ * Function: spi_read
+ **************************************************************************** */
+ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+ memset(rxbuf, 0, MAX_BUFFER);
+ memset(txbuf, 0, MAX_BUFFER);
+ memcpy(txbuf, addr, alen);
+ *txbuf = SPI_EEPROM_READ; /* READ memory array */
+
+ /*
+ * There is a bug in 860T (?) that cuts the last byte of input
+ * if we're reading into DPRAM. The solution we choose here is
+ * to always read len+1 bytes (we have one extra byte at the
+ * end of the buffer).
+ */
+ spi_xfer(alen + len + 1);
+ memcpy(buffer, alen + rxbuf, len);
+
+ return len;
+}
+
+/****************************************************************************
+ * Function: spi_xfer
+ **************************************************************************** */
+ssize_t spi_xfer (size_t count)
+{
+ volatile immap_t *immr;
+ volatile spi_t *spi;
+ cbd_t *tbdf, *rbdf;
+ int tm;
+
+ DPRINT (("*** spi_xfer entered ***\n"));
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ spi = (spi_t *)&immr->im_dprambase[PROFF_SPI];
+
+ tbdf = (cbd_t *) & immr->im_dprambase[spi->spi_tbase];
+ rbdf = (cbd_t *) & immr->im_dprambase[spi->spi_rbase];
+
+ /* Board-specific: Set CS for device (ATC EEPROM) */
+ immr->im_ioport.iop_pdatd &= ~0x00080000;
+
+ /* Setting tx bd status and data length */
+ tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
+ tbdf->cbd_datlen = count;
+
+ DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
+ tbdf->cbd_datlen));
+
+ /* Setting rx bd status and data length */
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ rbdf->cbd_datlen = 0; /* rx length has no significance */
+
+ immr->im_spi.spi_spmode = SPMODE_REV |
+ SPMODE_MSTR |
+ SPMODE_EN |
+ SPMODE_LEN(8) | /* 8 Bits per char */
+ SPMODE_PM(0x8) ; /* medium speed */
+ immr->im_spi.spi_spie = SPI_EMASK; /* Clear all SPI events */
+ immr->im_spi.spi_spim = 0x00; /* Mask all SPI events */
+
+ /* start spi transfer */
+ DPRINT (("*** spi_xfer: Performing transfer ...\n"));
+ immr->im_spi.spi_spcom |= SPI_STR; /* Start transmit */
+
+ /* --------------------------------
+ * Wait for SPI transmit to get out
+ * or time out (1 second = 1000 ms)
+ * -------------------------------- */
+ for (tm=0; tm<1000; ++tm) {
+ if (immr->im_spi.spi_spie & SPI_TXB) { /* Tx Buffer Empty */
+ DPRINT (("*** spi_xfer: Tx buffer empty\n"));
+ break;
+ }
+ if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
+ DPRINT (("*** spi_xfer: Tx BD done\n"));
+ break;
+ }
+ udelay (1000);
+ }
+ if (tm >= 1000) {
+ printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
+ }
+ DPRINT (("*** spi_xfer: ... transfer ended\n"));
+
+#ifdef DEBUG
+ printf ("\nspi_xfer: txbuf after xfer\n");
+ memdump ((void *) txbuf, 16); /* dump of txbuf before transmit */
+ printf ("spi_xfer: rxbuf after xfer\n");
+ memdump ((void *) rxbuf, 16); /* dump of rxbuf after transmit */
+ printf ("\n");
+#endif
+
+ /* Clear CS for device */
+ immr->im_ioport.iop_pdatd |= 0x00080000;
+
+ return count;
+}
+#endif /* CONFIG_SPI */
diff --git a/arch/powerpc/cpu/mpc8260/start.S b/arch/powerpc/cpu/mpc8260/start.S
new file mode 100644
index 0000000..bd8d7ac
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/start.S
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * U-Boot - Startup Code for MPC8260 PowerPC based Embedded Boards
+ */
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc8260.h>
+#include <version.h>
+
+#define CONFIG_8260 1 /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+/* Floating Point enable, Machine Check and Recoverable Interr. */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+#if defined(CONFIG_HYMOD)
+ GOT_ENTRY(environment)
+#endif
+ END_GOT
+
+/*
+ * Version string - must be in data segment because MPC8260 uses the first
+ * 256 bytes for the Hard Reset Configuration Word table (see below).
+ * Similarly, can't have the U-Boot Magic Number as the first thing in
+ * the image - don't know how this will affect the image tools, but I guess
+ * I'll find out soon
+ */
+ .data
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+/*
+ * Hard Reset Configuration Word (HRCW) table
+ *
+ * The Hard Reset Configuration Word (HRCW) sets a number of useful things
+ * such as whether there is an external memory controller, whether the
+ * PowerPC core is disabled (i.e. only the communications processor is
+ * active, accessed by another CPU on the bus), whether using external
+ * arbitration, external bus mode, boot port size, core initial prefix,
+ * internal space base, boot memory space, etc.
+ *
+ * These things dictate where the processor begins execution, where the
+ * boot ROM appears in memory, the memory controller setup when access
+ * boot ROM, etc. The HRCW is *extremely* important.
+ *
+ * The HRCW is read from the bus during reset. One CPU on the bus will
+ * be a hard reset configuration master, any others will be hard reset
+ * configuration slaves. The master reads eight HRCWs from flash during
+ * reset - the first it uses for itself, the other 7 it communicates to
+ * up to 7 configuration slaves by some complicated mechanism, which is
+ * not really important here.
+ *
+ * The configuration master performs 32 successive reads starting at address
+ * 0 and incrementing by 8 each read (i.e. on 64 bit boundaries) but only 8
+ * bits is read, and always from byte lane D[0-7] (so that port size of the
+ * boot device does not matter). The first four reads form the 32 bit HRCW
+ * for the master itself. The second four reads form the HRCW for the first
+ * slave, and so on, up to seven slaves. The 32 bit HRCW is formed by
+ * concatenating the four bytes, with the first read placed in byte 0 (the
+ * most significant byte), and so on with the fourth read placed in byte 3
+ * (the least significant byte).
+ */
+#define _HRCW_TABLE_ENTRY(w) \
+ .fill 8,1,(((w)>>24)&0xff); \
+ .fill 8,1,(((w)>>16)&0xff); \
+ .fill 8,1,(((w)>> 8)&0xff); \
+ .fill 8,1,(((w) )&0xff)
+ .text
+ .globl _hrcw_table
+_hrcw_table:
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_MASTER)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE1)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE2)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE3)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE4)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE5)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE6)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_SLAVE7)
+/*
+ * After configuration, a system reset exception is executed using the
+ * vector at offset 0x100 relative to the base set by MSR[IP]. If MSR[IP]
+ * is 0, the base address is 0x00000000. If MSR[IP] is 1, the base address
+ * is 0xfff00000. In the case of a Power On Reset or Hard Reset, the value
+ * of MSR[IP] is determined by the CIP field in the HRCW.
+ *
+ * Other bits in the HRCW set up the Base Address and Port Size in BR0.
+ * This determines the location of the boot ROM (flash or EPROM) in the
+ * processor's address space at boot time. As long as the HRCW is set up
+ * so that we eventually end up executing the code below when the processor
+ * executes the reset exception, the actual values used should not matter.
+ *
+ * Once we have got here, the address mask in OR0 is cleared so that the
+ * bottom 32K of the boot ROM is effectively repeated all throughout the
+ * processor's address space, after which we can jump to the absolute
+ * address at which the boot ROM was linked at compile time, and proceed
+ * to initialise the memory controller without worrying if the rug will be
+ * pulled out from under us, so to speak (it will be fine as long as we
+ * configure BR0 with the same boot ROM link address).
+ */
+ . = EXC_OFF_SYS_RESET
+
+ .globl _start
+_start:
+#if defined(CONFIG_MPC8260ADS) && defined(CONFIG_SYS_DEFAULT_IMMR)
+ lis r3, CONFIG_SYS_DEFAULT_IMMR@h
+ nop
+ lwz r4, 0(r3)
+ nop
+ rlwinm r4, r4, 0, 8, 5
+ nop
+ oris r4, r4, 0x0200
+ nop
+ stw r4, 0(r3)
+ nop
+#endif /* CONFIG_MPC8260ADS && CONFIG_SYS_DEFAULT_IMMR */
+
+ mfmsr r5 /* save msr contents */
+
+#if defined(CONFIG_COGENT)
+ /* this is what the cogent EPROM does */
+ li r0, 0
+ mtmsr r0
+ isync
+ bl cogent_init_8260
+#endif /* CONFIG_COGENT */
+
+#if defined(CONFIG_SYS_DEFAULT_IMMR)
+ lis r3, CONFIG_SYS_IMMR@h
+ ori r3, r3, CONFIG_SYS_IMMR@l
+ lis r4, CONFIG_SYS_DEFAULT_IMMR@h
+ stw r3, 0x1A8(r4)
+#endif /* CONFIG_SYS_DEFAULT_IMMR */
+
+ /* Initialise the MPC8260 processor core */
+ /*--------------------------------------------------------------*/
+
+ bl init_8260_core
+
+#ifndef CONFIG_SYS_RAMBOOT
+ /* When booting from ROM (Flash or EPROM), clear the */
+ /* Address Mask in OR0 so ROM appears everywhere */
+ /*--------------------------------------------------------------*/
+
+ lis r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+ lwz r4, IM_OR0@l(r3)
+ li r5, 0x7fff
+ and r4, r4, r5
+ stw r4, IM_OR0@l(r3)
+
+ /* Calculate absolute address in FLASH and jump there */
+ /*--------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_MONITOR_BASE@h
+ ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
+ addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r3
+ blr
+
+in_flash:
+#endif /* CONFIG_SYS_RAMBOOT */
+
+ /* initialize some things that are hard to access from C */
+ /*--------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_IMMR@h /* set up stack in internal DPRAM */
+ ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*--------------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ bl cpu_init_f /* run low-level CPU init code (in Flash)*/
+
+#ifdef DEBUG
+ bl init_debug /* set up debugging stuff */
+#endif
+
+ bl board_init_f /* run 1st part of board init code (in Flash)*/
+
+ /* NOTREACHED - board_init_f() does not return */
+
+/*
+ * Vector Table
+ */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+ . = 0x1300
+ /*
+ * This exception occurs when the program counter matches the
+ * Instruction Address Breakpoint Register (IABR).
+ *
+ * I want the cpu to halt if this occurs so I can hunt around
+ * with the debugger and look at things.
+ *
+ * When DEBUG is defined, both machine check enable (in the MSR)
+ * and checkstop reset enable (in the reset mode register) are
+ * turned off and so a checkstop condition will result in the cpu
+ * halting.
+ *
+ * I force the cpu into a checkstop condition by putting an illegal
+ * instruction here (at least this is the theory).
+ *
+ * well - that didnt work, so just do an infinite loop!
+ */
+1: b 1b
+#else
+ STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+ STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+ STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+#if defined(CONFIG_COGENT)
+
+/*
+ * This code initialises the MPC8260 processor core
+ * (conforms to PowerPC 603e spec)
+ */
+
+ .globl cogent_init_8260
+cogent_init_8260:
+
+ /* Taken from page 14 of CMA282 manual */
+ /*--------------------------------------------------------------*/
+
+ lis r4, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+ lis r3, CONFIG_SYS_IMMR@h
+ stw r3, IM_IMMR@l(r4)
+ lwz r3, IM_IMMR@l(r4)
+ stw r3, 0(r0)
+ lis r3, CONFIG_SYS_SYPCR@h
+ ori r3, r3, CONFIG_SYS_SYPCR@l
+ stw r3, IM_SYPCR@l(r4)
+ lwz r3, IM_SYPCR@l(r4)
+ stw r3, 4(r0)
+ lis r3, CONFIG_SYS_SCCR@h
+ ori r3, r3, CONFIG_SYS_SCCR@l
+ stw r3, IM_SCCR@l(r4)
+ lwz r3, IM_SCCR@l(r4)
+ stw r3, 8(r0)
+
+ /* the rest of this was disassembled from the */
+ /* EPROM code that came with my CMA282 CPU module */
+ /*--------------------------------------------------------------*/
+
+ lis r1, 0x1234
+ ori r1, r1, 0x5678
+ stw r1, 0x20(r0)
+ lwz r1, 0x20(r0)
+ stw r1, 0x24(r0)
+ lwz r1, 0x24(r0)
+ lis r3, 0x0e80
+ ori r3, r3, 0
+ stw r1, 4(r3)
+ lwz r1, 4(r3)
+
+ /* Done! */
+ /*--------------------------------------------------------------*/
+
+ blr
+
+#endif /* CONFIG_COGENT */
+
+/*
+ * This code initialises the MPC8260 processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+
+ .globl init_8260_core
+init_8260_core:
+
+ /* Initialize machine status; enable machine check interrupt */
+ /*--------------------------------------------------------------*/
+
+ li r3, MSR_KERNEL /* Set ME and RI flags */
+ rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
+#endif
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ /* Initialise the SYPCR early, and reset the watchdog (if req) */
+ /*--------------------------------------------------------------*/
+
+ lis r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+#if !defined(CONFIG_COGENT)
+ lis r4, CONFIG_SYS_SYPCR@h
+ ori r4, r4, CONFIG_SYS_SYPCR@l
+ stw r4, IM_SYPCR@l(r3)
+#endif /* !CONFIG_COGENT */
+#if defined(CONFIG_WATCHDOG)
+ li r4, 21868 /* = 0x556c */
+ sth r4, IM_SWSR@l(r3)
+ li r4, -21959 /* = 0xaa39 */
+ sth r4, IM_SWSR@l(r3)
+#endif /* CONFIG_WATCHDOG */
+
+ /* Initialize the Hardware Implementation-dependent Registers */
+ /* HID0 also contains cache control */
+ /*--------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_HID0_INIT@h
+ ori r3, r3, CONFIG_SYS_HID0_INIT@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CONFIG_SYS_HID0_FINAL@h
+ ori r3, r3, CONFIG_SYS_HID0_FINAL@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CONFIG_SYS_HID2@h
+ ori r3, r3, CONFIG_SYS_HID2@l
+ mtspr HID2, r3
+
+ /* clear all BAT's */
+ /*--------------------------------------------------------------*/
+
+ li r0, 0
+ mtspr DBAT0U, r0
+ mtspr DBAT0L, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT1L, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT2L, r0
+ mtspr DBAT3U, r0
+ mtspr DBAT3L, r0
+ mtspr IBAT0U, r0
+ mtspr IBAT0L, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT1L, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT2L, r0
+ mtspr IBAT3U, r0
+ mtspr IBAT3L, r0
+ SYNC
+
+ /* invalidate all tlb's */
+ /* */
+ /* From the 603e User Manual: "The 603e provides the ability to */
+ /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
+ /* instruction invalidates the TLB entry indexed by the EA, and */
+ /* operates on both the instruction and data TLBs simultaneously*/
+ /* invalidating four TLB entries (both sets in each TLB). The */
+ /* index corresponds to bits 15-19 of the EA. To invalidate all */
+ /* entries within both TLBs, 32 tlbie instructions should be */
+ /* issued, incrementing this field by one each time." */
+ /* */
+ /* "Note that the tlbia instruction is not implemented on the */
+ /* 603e." */
+ /* */
+ /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
+ /* incrementing by 0x1000 each time. The code below is sort of */
+ /* based on code in "flush_tlbs" from arch/powerpc/kernel/head.S */
+ /* */
+ /*--------------------------------------------------------------*/
+
+ li r3, 32
+ mtctr r3
+ li r3, 0
+1: tlbie r3
+ addi r3, r3, 0x1000
+ bdnz 1b
+ SYNC
+
+ /* Done! */
+ /*--------------------------------------------------------------*/
+
+ blr
+
+#ifdef DEBUG
+
+/*
+ * initialise things related to debugging.
+ *
+ * must be called after the global offset table (GOT) is initialised
+ * (GET_GOT) and after cpu_init_f() has executed.
+ */
+
+ .globl init_debug
+init_debug:
+
+ lis r3, (CONFIG_SYS_IMMR+IM_REGBASE)@h
+
+ /* Quick and dirty hack to enable the RAM and copy the */
+ /* vectors so that we can take exceptions. */
+ /*--------------------------------------------------------------*/
+ /* write Memory Refresh Prescaler */
+ li r4, CONFIG_SYS_MPTPR
+ sth r4, IM_MPTPR@l(r3)
+ /* write 60x Refresh Timer */
+ li r4, CONFIG_SYS_PSRT
+ stb r4, IM_PSRT@l(r3)
+ /* init the 60x SDRAM Mode Register */
+ lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@h
+ ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM)@l
+ stw r4, IM_PSDMR@l(r3)
+ /* write Precharge All Banks command */
+ lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@h
+ ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_PREA)@l
+ stw r4, IM_PSDMR@l(r3)
+ stb r0, 0(0)
+ /* write eight CBR Refresh commands */
+ lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@h
+ ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_CBRR)@l
+ stw r4, IM_PSDMR@l(r3)
+ stb r0, 0(0)
+ stb r0, 0(0)
+ stb r0, 0(0)
+ stb r0, 0(0)
+ stb r0, 0(0)
+ stb r0, 0(0)
+ stb r0, 0(0)
+ stb r0, 0(0)
+ /* write Mode Register Write command */
+ lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@h
+ ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_MRW)@l
+ stw r4, IM_PSDMR@l(r3)
+ stb r0, 0(0)
+ /* write Normal Operation command and enable Refresh */
+ lis r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@h
+ ori r4, r4, (CONFIG_SYS_PSDMR|PSDMR_OP_NORM|PSDMR_RFEN)@l
+ stw r4, IM_PSDMR@l(r3)
+ stb r0, 0(0)
+ /* RAM should now be operational */
+
+#define VEC_WRD_CNT ((_end_of_vectors - _start + EXC_OFF_SYS_RESET) / 4)
+ mflr r3
+ GET_GOT
+ mtlr r3
+ lwz r3, GOT(_end_of_vectors)
+ rlwinm r4, r3, 0, 18, 31 /* _end_of_vectors & 0x3FFF */
+ lis r5, VEC_WRD_CNT@h
+ ori r5, r5, VEC_WRD_CNT@l
+ mtctr r5
+1:
+ lwzu r5, -4(r3)
+ stwu r5, -4(r4)
+ bdnz 1b
+
+ /* Load the Instruction Address Breakpoint Register (IABR). */
+ /* */
+ /* The address to load is stored in the first word of dual port */
+ /* ram and should be preserved while the power is on, so you */
+ /* can plug addresses into that location then reset the cpu and */
+ /* this code will load that address into the IABR after the */
+ /* reset. */
+ /* */
+ /* When the program counter matches the contents of the IABR, */
+ /* an exception is generated (before the instruction at that */
+ /* location completes). The vector for this exception is 0x1300 */
+ /*--------------------------------------------------------------*/
+ lis r3, CONFIG_SYS_IMMR@h
+ lwz r3, 0(r3)
+ mtspr IABR, r3
+
+ /* Set the entire dual port RAM (where the initial stack */
+ /* resides) to a known value - makes it easier to see where */
+ /* the stack has been written */
+ /*--------------------------------------------------------------*/
+ lis r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@h
+ ori r3, r3, (CONFIG_SYS_IMMR + CONFIG_SYS_INIT_SP_OFFSET)@l
+ li r4, ((CONFIG_SYS_INIT_SP_OFFSET - 4) / 4)
+ mtctr r4
+ lis r4, 0xdeadbeaf@h
+ ori r4, r4, 0xdeadbeaf@l
+1:
+ stwu r4, -4(r3)
+ bdnz 1b
+
+ /* Done! */
+ /*--------------------------------------------------------------*/
+
+ blr
+#endif
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICE
+ lis r4, 0
+ ori r4, r4, HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ICE|HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_DCE
+ lis r4, 0
+ ori r4, r4, HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_DCE|HID0_DLOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_DCI
+ sync
+ mtspr HID0, r4 /* sets invalidate, clears enable and lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
+ rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 9f
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
+ rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
+ cmpwi r7,0
+ beq 7f
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+#if defined(CONFIG_HYMOD)
+ /*
+ * For HYMOD - the environment is the very last item in flash.
+ * The real .bss stops just before environment starts, so only
+ * clear up to that point.
+ *
+ * taken from mods for FADS board
+ */
+ lwz r4,GOT(environment)
+#else
+ lwz r4,GOT(__bss_end)
+#endif
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mfmsr r3 /* now that the vectors have */
+ lis r7, MSR_IP@h /* relocated into low memory */
+ ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
+ andc r3, r3, r7 /* (if it was on) */
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+
+ mtlr r4 /* restore link register */
+ blr
diff --git a/arch/powerpc/cpu/mpc8260/traps.c b/arch/powerpc/cpu/mpc8260/traps.c
new file mode 100644
index 0000000..e1e6845
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/traps.c
@@ -0,0 +1,264 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+#include <asm/m8260_pci.h>
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ puts ("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ putc ('\n');
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ putc ('\n');
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ putc ('\n');
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0) {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7) {
+ putc ('\n');
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+#ifdef CONFIG_PCI
+void dump_pci (void)
+{
+
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+ printf ("PCI: err status %x err mask %x err ctrl %x\n",
+ le32_to_cpu (immap->im_pci.pci_esr),
+ le32_to_cpu (immap->im_pci.pci_emr),
+ le32_to_cpu (immap->im_pci.pci_ecr));
+ printf (" error address %x error data %x ctrl %x\n",
+ le32_to_cpu (immap->im_pci.pci_eacr),
+ le32_to_cpu (immap->im_pci.pci_edcr),
+ le32_to_cpu (immap->im_pci.pci_eccr));
+
+}
+#endif
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+#ifdef CONFIG_PCI
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+#ifdef DEBUG
+ dump_pci();
+#endif
+ /* clear the error in the error status register */
+ if(immap->im_pci.pci_esr & cpu_to_le32(PCI_ERROR_PCI_NO_RSP)) {
+ immap->im_pci.pci_esr = cpu_to_le32(PCI_ERROR_PCI_NO_RSP);
+ return;
+ }
+#endif
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ puts ("Machine check in kernel mode.\n"
+ "Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x000F0000) {
+ case (0x80000000>>12):
+ puts ("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13):
+ puts ("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14):
+ puts ("Data parity signal\n");
+ break;
+ case (0x80000000>>15):
+ puts ("Address parity signal\n");
+ break;
+ default:
+ puts ("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+#ifdef CONFIG_PCI
+ dump_pci();
+#endif
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void DebugException(struct pt_regs *regs)
+{
+
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8260/u-boot.lds b/arch/powerpc/cpu/mpc8260/u-boot.lds
new file mode 100644
index 0000000..eb1c611
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8260/u-boot.lds
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 2001-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .text :
+ {
+ arch/powerpc/cpu/mpc8260/start.o (.text*)
+ *(.text*)
+ . = ALIGN(16);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/Makefile b/arch/powerpc/cpu/mpc83xx/Makefile
new file mode 100644
index 0000000..8a470b8
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/Makefile
@@ -0,0 +1,96 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+START = start.o
+
+ifdef MINIMAL
+
+COBJS-y += spl_minimal.o
+
+else
+
+COBJS-y += traps.o
+COBJS-y += cpu.o
+COBJS-y += cpu_init.o
+COBJS-y += speed.o
+COBJS-y += interrupts.o
+COBJS-y += ecc.o
+COBJS-$(CONFIG_QE) += qe_io.o
+COBJS-$(CONFIG_FSL_SERDES) += serdes.o
+COBJS-$(CONFIG_PCI) += pci.o
+COBJS-$(CONFIG_PCIE) += pcie.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+
+# Stub implementations of cache management functions for USB
+COBJS-y += cache.o
+
+ifdef CONFIG_FSL_DDR2
+COBJS_LN-$(CONFIG_MPC8349) += ddr-gen2.o
+else
+COBJS-y += spd_sdram.o
+endif
+COBJS-$(CONFIG_FSL_DDR2) += law.o
+
+endif # not minimal
+
+COBJS := $(COBJS-y)
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) $(addprefix $(obj),$(COBJS_LN-y:.o=.c))
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS) $(COBJS_LN-y))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+$(obj)ddr-gen1.c:
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/ddr-gen1.c $(obj)ddr-gen1.c
+
+$(obj)ddr-gen2.c:
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/ddr-gen2.c $(obj)ddr-gen2.c
+
+$(obj)ddr-gen3.c:
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/ddr-gen3.c $(obj)ddr-gen3.c
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc83xx/cache.c b/arch/powerpc/cpu/mpc83xx/cache.c
new file mode 100644
index 0000000..2a08b65
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/cache.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ *
+ * This file contains stub implementation of
+ * invalidate_dcache_range()
+ * flush_dcache_range()
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
diff --git a/arch/powerpc/cpu/mpc83xx/config.mk b/arch/powerpc/cpu/mpc83xx/config.mk
new file mode 100644
index 0000000..a79729e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/config.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2004 Freescale Semiconductor, Inc.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC83xx -DCONFIG_E300 \
+ -ffixed-r2 -msoft-float
diff --git a/arch/powerpc/cpu/mpc83xx/cpu.c b/arch/powerpc/cpu/mpc83xx/cpu.c
new file mode 100644
index 0000000..cc20234
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/cpu.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code for the MPC83xx family.
+ *
+ * Derived from the MPC8260 and MPC85xx.
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc83xx.h>
+#include <asm/processor.h>
+#include <libfdt.h>
+#include <tsec.h>
+#include <netdev.h>
+#include <fsl_esdhc.h>
+#ifdef CONFIG_BOOTCOUNT_LIMIT
+#include <asm/immap_qe.h>
+#include <asm/io.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int checkcpu(void)
+{
+ volatile immap_t *immr;
+ ulong clock = gd->cpu_clk;
+ u32 pvr = get_pvr();
+ u32 spridr;
+ char buf[32];
+ int i;
+
+ const struct cpu_type {
+ char name[15];
+ u32 partid;
+ } cpu_type_list [] = {
+ CPU_TYPE_ENTRY(8308),
+ CPU_TYPE_ENTRY(8309),
+ CPU_TYPE_ENTRY(8311),
+ CPU_TYPE_ENTRY(8313),
+ CPU_TYPE_ENTRY(8314),
+ CPU_TYPE_ENTRY(8315),
+ CPU_TYPE_ENTRY(8321),
+ CPU_TYPE_ENTRY(8323),
+ CPU_TYPE_ENTRY(8343),
+ CPU_TYPE_ENTRY(8347_TBGA_),
+ CPU_TYPE_ENTRY(8347_PBGA_),
+ CPU_TYPE_ENTRY(8349),
+ CPU_TYPE_ENTRY(8358_TBGA_),
+ CPU_TYPE_ENTRY(8358_PBGA_),
+ CPU_TYPE_ENTRY(8360),
+ CPU_TYPE_ENTRY(8377),
+ CPU_TYPE_ENTRY(8378),
+ CPU_TYPE_ENTRY(8379),
+ };
+
+ immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ puts("CPU: ");
+
+ switch (pvr & 0xffff0000) {
+ case PVR_E300C1:
+ printf("e300c1, ");
+ break;
+
+ case PVR_E300C2:
+ printf("e300c2, ");
+ break;
+
+ case PVR_E300C3:
+ printf("e300c3, ");
+ break;
+
+ case PVR_E300C4:
+ printf("e300c4, ");
+ break;
+
+ default:
+ printf("Unknown core, ");
+ }
+
+ spridr = immr->sysconf.spridr;
+
+ for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++)
+ if (cpu_type_list[i].partid == PARTID_NO_E(spridr)) {
+ puts("MPC");
+ puts(cpu_type_list[i].name);
+ if (IS_E_PROCESSOR(spridr))
+ puts("E");
+ if ((SPR_FAMILY(spridr) == SPR_834X_FAMILY ||
+ SPR_FAMILY(spridr) == SPR_836X_FAMILY) &&
+ REVID_MAJOR(spridr) >= 2)
+ puts("A");
+ printf(", Rev: %d.%d", REVID_MAJOR(spridr),
+ REVID_MINOR(spridr));
+ break;
+ }
+
+ if (i == ARRAY_SIZE(cpu_type_list))
+ printf("(SPRIDR %08x unknown), ", spridr);
+
+ printf(" at %s MHz, ", strmhz(buf, clock));
+
+ printf("CSB: %s MHz\n", strmhz(buf, gd->arch.csb_clk));
+
+ return 0;
+}
+
+int
+do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong msr;
+#ifndef MPC83xx_RESET
+ ulong addr;
+#endif
+
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+ puts("Resetting the board.\n");
+
+#ifdef MPC83xx_RESET
+
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~( MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /* enable Reset Control Reg */
+ immap->reset.rpr = 0x52535445;
+ __asm__ __volatile__ ("sync");
+ __asm__ __volatile__ ("isync");
+
+ /* confirm Reset Control Reg is enabled */
+ while(!((immap->reset.rcer) & RCER_CRE));
+
+ udelay(200);
+
+ /* perform reset, only one bit */
+ immap->reset.rcr = RCR_SWHR;
+
+#else /* ! MPC83xx_RESET */
+
+ immap->reset.rmr = RMR_CSRE; /* Checkstop Reset enable */
+
+ /* Interrupts and MMU off */
+ __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
+
+ msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
+ __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
+
+ /*
+ * Trying to execute the next instruction at a non-existing address
+ * should cause a machine check, resulting in reset
+ */
+ addr = CONFIG_SYS_RESET_ADDRESS;
+
+ ((void (*)(void)) addr) ();
+#endif /* MPC83xx_RESET */
+
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+
+unsigned long get_tbclk(void)
+{
+ ulong tbclk;
+
+ tbclk = (gd->bus_clk + 3L) / 4L;
+
+ return tbclk;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+ int re_enable = disable_interrupts();
+
+ /* Reset the 83xx watchdog */
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ immr->wdt.swsrr = 0x556c;
+ immr->wdt.swsrr = 0xaa39;
+
+ if (re_enable)
+ enable_interrupts ();
+}
+#endif
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_UEC_ETH)
+ uec_standard_init(bis);
+#endif
+
+#if defined(CONFIG_TSEC_ENET)
+ tsec_standard_init(bis);
+#endif
+ return 0;
+}
+
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_FSL_ESDHC
+ return fsl_esdhc_mmc_init(bis);
+#else
+ return 0;
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
new file mode 100644
index 0000000..5153351
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2004-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <ioports.h>
+#include <asm/io.h>
+#ifdef CONFIG_USB_EHCI_FSL
+#include <usb/ehci-fsl.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_QE
+extern qe_iop_conf_t qe_iop_conf_tab[];
+extern void qe_config_iopin(u8 port, u8 pin, int dir,
+ int open_drain, int assign);
+extern void qe_init(uint qe_base);
+extern void qe_reset(void);
+
+static void config_qe_ioports(void)
+{
+ u8 port, pin;
+ int dir, open_drain, assign;
+ int i;
+
+ for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) {
+ port = qe_iop_conf_tab[i].port;
+ pin = qe_iop_conf_tab[i].pin;
+ dir = qe_iop_conf_tab[i].dir;
+ open_drain = qe_iop_conf_tab[i].open_drain;
+ assign = qe_iop_conf_tab[i].assign;
+ qe_config_iopin(port, pin, dir, open_drain, assign);
+ }
+}
+#endif
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+ __be32 acr_mask =
+#ifdef CONFIG_SYS_ACR_PIPE_DEP /* Arbiter pipeline depth */
+ ACR_PIPE_DEP |
+#endif
+#ifdef CONFIG_SYS_ACR_RPTCNT /* Arbiter repeat count */
+ ACR_RPTCNT |
+#endif
+#ifdef CONFIG_SYS_ACR_APARK /* Arbiter address parking mode */
+ ACR_APARK |
+#endif
+#ifdef CONFIG_SYS_ACR_PARKM /* Arbiter parking master */
+ ACR_PARKM |
+#endif
+ 0;
+ __be32 acr_val =
+#ifdef CONFIG_SYS_ACR_PIPE_DEP /* Arbiter pipeline depth */
+ (CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_RPTCNT /* Arbiter repeat count */
+ (CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_APARK /* Arbiter address parking mode */
+ (CONFIG_SYS_ACR_APARK << ACR_APARK_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_ACR_PARKM /* Arbiter parking master */
+ (CONFIG_SYS_ACR_PARKM << ACR_PARKM_SHIFT) |
+#endif
+ 0;
+ __be32 spcr_mask =
+#ifdef CONFIG_SYS_SPCR_OPT /* Optimize transactions between CSB and other dev */
+ SPCR_OPT |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSECEP /* all eTSEC's Emergency priority */
+ SPCR_TSECEP |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC1EP /* TSEC1 Emergency priority */
+ SPCR_TSEC1EP |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC2EP /* TSEC2 Emergency priority */
+ SPCR_TSEC2EP |
+#endif
+ 0;
+ __be32 spcr_val =
+#ifdef CONFIG_SYS_SPCR_OPT
+ (CONFIG_SYS_SPCR_OPT << SPCR_OPT_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSECEP /* all eTSEC's Emergency priority */
+ (CONFIG_SYS_SPCR_TSECEP << SPCR_TSECEP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC1EP /* TSEC1 Emergency priority */
+ (CONFIG_SYS_SPCR_TSEC1EP << SPCR_TSEC1EP_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SPCR_TSEC2EP /* TSEC2 Emergency priority */
+ (CONFIG_SYS_SPCR_TSEC2EP << SPCR_TSEC2EP_SHIFT) |
+#endif
+ 0;
+ __be32 sccr_mask =
+#ifdef CONFIG_SYS_SCCR_ENCCM /* Encryption clock mode */
+ SCCR_ENCCM |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCICM /* PCI & DMA clock mode */
+ SCCR_PCICM |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCIEXP1CM /* PCIE1 clock mode */
+ SCCR_PCIEXP1CM |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCIEXP2CM /* PCIE2 clock mode */
+ SCCR_PCIEXP2CM |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSECCM /* all TSEC's clock mode */
+ SCCR_TSECCM |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1CM /* TSEC1 clock mode */
+ SCCR_TSEC1CM |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2CM /* TSEC2 clock mode */
+ SCCR_TSEC2CM |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1ON /* TSEC1 clock switch */
+ SCCR_TSEC1ON |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2ON /* TSEC2 clock switch */
+ SCCR_TSEC2ON |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBMPHCM /* USB MPH clock mode */
+ SCCR_USBMPHCM |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBDRCM /* USB DR clock mode */
+ SCCR_USBDRCM |
+#endif
+#ifdef CONFIG_SYS_SCCR_SATACM /* SATA controller clock mode */
+ SCCR_SATACM |
+#endif
+ 0;
+ __be32 sccr_val =
+#ifdef CONFIG_SYS_SCCR_ENCCM /* Encryption clock mode */
+ (CONFIG_SYS_SCCR_ENCCM << SCCR_ENCCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCICM /* PCI & DMA clock mode */
+ (CONFIG_SYS_SCCR_PCICM << SCCR_PCICM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCIEXP1CM /* PCIE1 clock mode */
+ (CONFIG_SYS_SCCR_PCIEXP1CM << SCCR_PCIEXP1CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_PCIEXP2CM /* PCIE2 clock mode */
+ (CONFIG_SYS_SCCR_PCIEXP2CM << SCCR_PCIEXP2CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSECCM /* all TSEC's clock mode */
+ (CONFIG_SYS_SCCR_TSECCM << SCCR_TSECCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1CM /* TSEC1 clock mode */
+ (CONFIG_SYS_SCCR_TSEC1CM << SCCR_TSEC1CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2CM /* TSEC2 clock mode */
+ (CONFIG_SYS_SCCR_TSEC2CM << SCCR_TSEC2CM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC1ON /* TSEC1 clock switch */
+ (CONFIG_SYS_SCCR_TSEC1ON << SCCR_TSEC1ON_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_TSEC2ON /* TSEC2 clock switch */
+ (CONFIG_SYS_SCCR_TSEC2ON << SCCR_TSEC2ON_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBMPHCM /* USB MPH clock mode */
+ (CONFIG_SYS_SCCR_USBMPHCM << SCCR_USBMPHCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_USBDRCM /* USB DR clock mode */
+ (CONFIG_SYS_SCCR_USBDRCM << SCCR_USBDRCM_SHIFT) |
+#endif
+#ifdef CONFIG_SYS_SCCR_SATACM /* SATA controller clock mode */
+ (CONFIG_SYS_SCCR_SATACM << SCCR_SATACM_SHIFT) |
+#endif
+ 0;
+ __be32 lcrr_mask =
+#ifdef CONFIG_SYS_LCRR_DBYP /* PLL bypass */
+ LCRR_DBYP |
+#endif
+#ifdef CONFIG_SYS_LCRR_EADC /* external address delay */
+ LCRR_EADC |
+#endif
+#ifdef CONFIG_SYS_LCRR_CLKDIV /* system clock divider */
+ LCRR_CLKDIV |
+#endif
+ 0;
+ __be32 lcrr_val =
+#ifdef CONFIG_SYS_LCRR_DBYP /* PLL bypass */
+ CONFIG_SYS_LCRR_DBYP |
+#endif
+#ifdef CONFIG_SYS_LCRR_EADC
+ CONFIG_SYS_LCRR_EADC |
+#endif
+#ifdef CONFIG_SYS_LCRR_CLKDIV /* system clock divider */
+ CONFIG_SYS_LCRR_CLKDIV |
+#endif
+ 0;
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ memset ((void *) gd, 0, sizeof (gd_t));
+
+ /* system performance tweaking */
+ clrsetbits_be32(&im->arbiter.acr, acr_mask, acr_val);
+
+ clrsetbits_be32(&im->sysconf.spcr, spcr_mask, spcr_val);
+
+ clrsetbits_be32(&im->clk.sccr, sccr_mask, sccr_val);
+
+ /* RSR - Reset Status Register - clear all status (4.6.1.3) */
+ gd->arch.reset_status = __raw_readl(&im->reset.rsr);
+ __raw_writel(~(RSR_RES), &im->reset.rsr);
+
+ /* AER - Arbiter Event Register - store status */
+ gd->arch.arbiter_event_attributes = __raw_readl(&im->arbiter.aeatr);
+ gd->arch.arbiter_event_address = __raw_readl(&im->arbiter.aeadr);
+
+ /*
+ * RMR - Reset Mode Register
+ * contains checkstop reset enable (4.6.1.4)
+ */
+ __raw_writel(RMR_CSRE & (1<<RMR_CSRE_SHIFT), &im->reset.rmr);
+
+ /* LCRR - Clock Ratio Register (10.3.1.16)
+ * write, read, and isync per MPC8379ERM rev.1 CLKDEV field description
+ */
+ clrsetbits_be32(&im->im_lbc.lcrr, lcrr_mask, lcrr_val);
+ __raw_readl(&im->im_lbc.lcrr);
+ isync();
+
+ /* Enable Time Base & Decrementer ( so we will have udelay() )*/
+ setbits_be32(&im->sysconf.spcr, SPCR_TBEN);
+
+ /* System General Purpose Register */
+#ifdef CONFIG_SYS_SICRH
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC8313)
+ /* regarding to MPC34x manual rev.1 bits 28..29 must be preserved */
+ __raw_writel((im->sysconf.sicrh & 0x0000000C) | CONFIG_SYS_SICRH,
+ &im->sysconf.sicrh);
+#else
+ __raw_writel(CONFIG_SYS_SICRH, &im->sysconf.sicrh);
+#endif
+#endif
+#ifdef CONFIG_SYS_SICRL
+ __raw_writel(CONFIG_SYS_SICRL, &im->sysconf.sicrl);
+#endif
+#ifdef CONFIG_SYS_GPR1
+ __raw_writel(CONFIG_SYS_GPR1, &im->sysconf.gpr1);
+#endif
+#ifdef CONFIG_SYS_DDRCDR /* DDR control driver register */
+ __raw_writel(CONFIG_SYS_DDRCDR, &im->sysconf.ddrcdr);
+#endif
+#ifdef CONFIG_SYS_OBIR /* Output buffer impedance register */
+ __raw_writel(CONFIG_SYS_OBIR, &im->sysconf.obir);
+#endif
+
+#ifdef CONFIG_QE
+ /* Config QE ioports */
+ config_qe_ioports();
+#endif
+ /* Set up preliminary BR/OR regs */
+ init_early_memctl_regs();
+
+ /* Local Access window setup */
+#if defined(CONFIG_SYS_LBLAWBAR0_PRELIM) && defined(CONFIG_SYS_LBLAWAR0_PRELIM)
+ im->sysconf.lblaw[0].bar = CONFIG_SYS_LBLAWBAR0_PRELIM;
+ im->sysconf.lblaw[0].ar = CONFIG_SYS_LBLAWAR0_PRELIM;
+#else
+#error CONFIG_SYS_LBLAWBAR0_PRELIM & CONFIG_SYS_LBLAWAR0_PRELIM must be defined
+#endif
+
+#if defined(CONFIG_SYS_LBLAWBAR1_PRELIM) && defined(CONFIG_SYS_LBLAWAR1_PRELIM)
+ im->sysconf.lblaw[1].bar = CONFIG_SYS_LBLAWBAR1_PRELIM;
+ im->sysconf.lblaw[1].ar = CONFIG_SYS_LBLAWAR1_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR2_PRELIM) && defined(CONFIG_SYS_LBLAWAR2_PRELIM)
+ im->sysconf.lblaw[2].bar = CONFIG_SYS_LBLAWBAR2_PRELIM;
+ im->sysconf.lblaw[2].ar = CONFIG_SYS_LBLAWAR2_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR3_PRELIM) && defined(CONFIG_SYS_LBLAWAR3_PRELIM)
+ im->sysconf.lblaw[3].bar = CONFIG_SYS_LBLAWBAR3_PRELIM;
+ im->sysconf.lblaw[3].ar = CONFIG_SYS_LBLAWAR3_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR4_PRELIM) && defined(CONFIG_SYS_LBLAWAR4_PRELIM)
+ im->sysconf.lblaw[4].bar = CONFIG_SYS_LBLAWBAR4_PRELIM;
+ im->sysconf.lblaw[4].ar = CONFIG_SYS_LBLAWAR4_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR5_PRELIM) && defined(CONFIG_SYS_LBLAWAR5_PRELIM)
+ im->sysconf.lblaw[5].bar = CONFIG_SYS_LBLAWBAR5_PRELIM;
+ im->sysconf.lblaw[5].ar = CONFIG_SYS_LBLAWAR5_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR6_PRELIM) && defined(CONFIG_SYS_LBLAWAR6_PRELIM)
+ im->sysconf.lblaw[6].bar = CONFIG_SYS_LBLAWBAR6_PRELIM;
+ im->sysconf.lblaw[6].ar = CONFIG_SYS_LBLAWAR6_PRELIM;
+#endif
+#if defined(CONFIG_SYS_LBLAWBAR7_PRELIM) && defined(CONFIG_SYS_LBLAWAR7_PRELIM)
+ im->sysconf.lblaw[7].bar = CONFIG_SYS_LBLAWBAR7_PRELIM;
+ im->sysconf.lblaw[7].ar = CONFIG_SYS_LBLAWAR7_PRELIM;
+#endif
+#ifdef CONFIG_SYS_GPIO1_PRELIM
+ im->gpio[0].dat = CONFIG_SYS_GPIO1_DAT;
+ im->gpio[0].dir = CONFIG_SYS_GPIO1_DIR;
+#endif
+#ifdef CONFIG_SYS_GPIO2_PRELIM
+ im->gpio[1].dat = CONFIG_SYS_GPIO2_DAT;
+ im->gpio[1].dir = CONFIG_SYS_GPIO2_DIR;
+#endif
+#if defined(CONFIG_USB_EHCI_FSL) && defined(CONFIG_MPC831x)
+ uint32_t temp;
+ struct usb_ehci *ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB_ADDR;
+
+ /* Configure interface. */
+ setbits_be32(&ehci->control, REFSEL_16MHZ | UTMI_PHY_EN);
+
+ /* Wait for clock to stabilize */
+ do {
+ temp = __raw_readl(&ehci->control);
+ udelay(1000);
+ } while (!(temp & PHY_CLK_VALID));
+#endif
+}
+
+int cpu_init_r (void)
+{
+#ifdef CONFIG_QE
+ uint qe_base = CONFIG_SYS_IMMR + 0x00100000; /* QE immr base */
+
+ qe_init(qe_base);
+ qe_reset();
+#endif
+ return 0;
+}
+
+/*
+ * Print out the bus arbiter event
+ */
+#if defined(CONFIG_DISPLAY_AER_FULL)
+static int print_83xx_arb_event(int force)
+{
+ static char* event[] = {
+ "Address Time Out",
+ "Data Time Out",
+ "Address Only Transfer Type",
+ "External Control Word Transfer Type",
+ "Reserved Transfer Type",
+ "Transfer Error",
+ "reserved",
+ "reserved"
+ };
+ static char* master[] = {
+ "e300 Core Data Transaction",
+ "reserved",
+ "e300 Core Instruction Fetch",
+ "reserved",
+ "TSEC1",
+ "TSEC2",
+ "USB MPH",
+ "USB DR",
+ "Encryption Core",
+ "I2C Boot Sequencer",
+ "JTAG",
+ "reserved",
+ "eSDHC",
+ "PCI1",
+ "PCI2",
+ "DMA",
+ "QUICC Engine 00",
+ "QUICC Engine 01",
+ "QUICC Engine 10",
+ "QUICC Engine 11",
+ "reserved",
+ "reserved",
+ "reserved",
+ "reserved",
+ "SATA1",
+ "SATA2",
+ "SATA3",
+ "SATA4",
+ "reserved",
+ "PCI Express 1",
+ "PCI Express 2",
+ "TDM-DMAC"
+ };
+ static char *transfer[] = {
+ "Address-only, Clean Block",
+ "Address-only, lwarx reservation set",
+ "Single-beat or Burst write",
+ "reserved",
+ "Address-only, Flush Block",
+ "reserved",
+ "Burst write",
+ "reserved",
+ "Address-only, sync",
+ "Address-only, tlbsync",
+ "Single-beat or Burst read",
+ "Single-beat or Burst read",
+ "Address-only, Kill Block",
+ "Address-only, icbi",
+ "Burst read",
+ "reserved",
+ "Address-only, eieio",
+ "reserved",
+ "Single-beat write",
+ "reserved",
+ "ecowx - Illegal single-beat write",
+ "reserved",
+ "reserved",
+ "reserved",
+ "Address-only, TLB Invalidate",
+ "reserved",
+ "Single-beat or Burst read",
+ "reserved",
+ "eciwx - Illegal single-beat read",
+ "reserved",
+ "Burst read",
+ "reserved"
+ };
+
+ int etype = (gd->arch.arbiter_event_attributes & AEATR_EVENT)
+ >> AEATR_EVENT_SHIFT;
+ int mstr_id = (gd->arch.arbiter_event_attributes & AEATR_MSTR_ID)
+ >> AEATR_MSTR_ID_SHIFT;
+ int tbst = (gd->arch.arbiter_event_attributes & AEATR_TBST)
+ >> AEATR_TBST_SHIFT;
+ int tsize = (gd->arch.arbiter_event_attributes & AEATR_TSIZE)
+ >> AEATR_TSIZE_SHIFT;
+ int ttype = (gd->arch.arbiter_event_attributes & AEATR_TTYPE)
+ >> AEATR_TTYPE_SHIFT;
+
+ if (!force && !gd->arch.arbiter_event_address)
+ return 0;
+
+ puts("Arbiter Event Status:\n");
+ printf(" Event Address: 0x%08lX\n",
+ gd->arch.arbiter_event_address);
+ printf(" Event Type: 0x%1x = %s\n", etype, event[etype]);
+ printf(" Master ID: 0x%02x = %s\n", mstr_id, master[mstr_id]);
+ printf(" Transfer Size: 0x%1x = %d bytes\n", (tbst<<3) | tsize,
+ tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize);
+ printf(" Transfer Type: 0x%02x = %s\n", ttype, transfer[ttype]);
+
+ return gd->arch.arbiter_event_address;
+}
+
+#elif defined(CONFIG_DISPLAY_AER_BRIEF)
+
+static int print_83xx_arb_event(int force)
+{
+ if (!force && !gd->arch.arbiter_event_address)
+ return 0;
+
+ printf("Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
+ gd->arch.arbiter_event_attributes,
+ gd->arch.arbiter_event_address);
+
+ return gd->arch.arbiter_event_address;
+}
+#endif /* CONFIG_DISPLAY_AER_xxxx */
+
+/*
+ * Figure out the cause of the reset
+ */
+int prt_83xx_rsr(void)
+{
+ static struct {
+ ulong mask;
+ char *desc;
+ } bits[] = {
+ {
+ RSR_SWSR, "Software Soft"}, {
+ RSR_SWHR, "Software Hard"}, {
+ RSR_JSRS, "JTAG Soft"}, {
+ RSR_CSHR, "Check Stop"}, {
+ RSR_SWRS, "Software Watchdog"}, {
+ RSR_BMRS, "Bus Monitor"}, {
+ RSR_SRS, "External/Internal Soft"}, {
+ RSR_HRS, "External/Internal Hard"}
+ };
+ static int n = sizeof bits / sizeof bits[0];
+ ulong rsr = gd->arch.reset_status;
+ int i;
+ char *sep;
+
+ puts("Reset Status:");
+
+ sep = " ";
+ for (i = 0; i < n; i++)
+ if (rsr & bits[i].mask) {
+ printf("%s%s", sep, bits[i].desc);
+ sep = ", ";
+ }
+ puts("\n");
+
+#if defined(CONFIG_DISPLAY_AER_FULL) || defined(CONFIG_DISPLAY_AER_BRIEF)
+ print_83xx_arb_event(rsr & RSR_BMRS);
+#endif
+ puts("\n");
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc83xx/ecc.c b/arch/powerpc/cpu/mpc83xx/ecc.c
new file mode 100644
index 0000000..717365c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/ecc.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on the contribution of Marian Balakowicz <m8@semihalf.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <command.h>
+
+#if defined(CONFIG_DDR_ECC) && defined(CONFIG_DDR_ECC_CMD)
+void ecc_print_status(void)
+{
+ immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+#ifdef CONFIG_FSL_DDR2
+ ccsr_ddr_t *ddr = &immap->ddr;
+#else
+ ddr83xx_t *ddr = &immap->ddr;
+#endif
+
+ printf("\nECC mode: %s\n\n",
+ (ddr->sdram_cfg & SDRAM_CFG_ECC_EN) ? "ON" : "OFF");
+
+ /* Interrupts */
+ printf("Memory Error Interrupt Enable:\n");
+ printf(" Multiple-Bit Error Interrupt Enable: %d\n",
+ (ddr->err_int_en & ECC_ERR_INT_EN_MBEE) ? 1 : 0);
+ printf(" Single-Bit Error Interrupt Enable: %d\n",
+ (ddr->err_int_en & ECC_ERR_INT_EN_SBEE) ? 1 : 0);
+ printf(" Memory Select Error Interrupt Enable: %d\n\n",
+ (ddr->err_int_en & ECC_ERR_INT_EN_MSEE) ? 1 : 0);
+
+ /* Error disable */
+ printf("Memory Error Disable:\n");
+ printf(" Multiple-Bit Error Disable: %d\n",
+ (ddr->err_disable & ECC_ERROR_DISABLE_MBED) ? 1 : 0);
+ printf(" Sinle-Bit Error Disable: %d\n",
+ (ddr->err_disable & ECC_ERROR_DISABLE_SBED) ? 1 : 0);
+ printf(" Memory Select Error Disable: %d\n\n",
+ (ddr->err_disable & ECC_ERROR_DISABLE_MSED) ? 1 : 0);
+
+ /* Error injection */
+ printf("Memory Data Path Error Injection Mask High/Low: %08x %08x\n",
+ ddr->data_err_inject_hi, ddr->data_err_inject_lo);
+
+ printf("Memory Data Path Error Injection Mask ECC:\n");
+ printf(" ECC Mirror Byte: %d\n",
+ (ddr->ecc_err_inject & ECC_ERR_INJECT_EMB) ? 1 : 0);
+ printf(" ECC Injection Enable: %d\n",
+ (ddr->ecc_err_inject & ECC_ERR_INJECT_EIEN) ? 1 : 0);
+ printf(" ECC Error Injection Mask: 0x%02x\n\n",
+ ddr->ecc_err_inject & ECC_ERR_INJECT_EEIM);
+
+ /* SBE counter/threshold */
+ printf("Memory Single-Bit Error Management (0..255):\n");
+ printf(" Single-Bit Error Threshold: %d\n",
+ (ddr->err_sbe & ECC_ERROR_MAN_SBET) >> ECC_ERROR_MAN_SBET_SHIFT);
+ printf(" Single-Bit Error Counter: %d\n\n",
+ (ddr->err_sbe & ECC_ERROR_MAN_SBEC) >> ECC_ERROR_MAN_SBEC_SHIFT);
+
+ /* Error detect */
+ printf("Memory Error Detect:\n");
+ printf(" Multiple Memory Errors: %d\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_MME) ? 1 : 0);
+ printf(" Multiple-Bit Error: %d\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_MBE) ? 1 : 0);
+ printf(" Single-Bit Error: %d\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_SBE) ? 1 : 0);
+ printf(" Memory Select Error: %d\n\n",
+ (ddr->err_detect & ECC_ERROR_DETECT_MSE) ? 1 : 0);
+
+ /* Capture data */
+ printf("Memory Error Address Capture: 0x%08x\n", ddr->capture_address);
+ printf("Memory Data Path Read Capture High/Low: %08x %08x\n",
+ ddr->capture_data_hi, ddr->capture_data_lo);
+ printf("Memory Data Path Read Capture ECC: 0x%02x\n\n",
+ ddr->capture_ecc & CAPTURE_ECC_ECE);
+
+ printf("Memory Error Attributes Capture:\n");
+ printf(" Data Beat Number: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_BNUM) >>
+ ECC_CAPT_ATTR_BNUM_SHIFT);
+ printf(" Transaction Size: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_TSIZ) >>
+ ECC_CAPT_ATTR_TSIZ_SHIFT);
+ printf(" Transaction Source: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_TSRC) >>
+ ECC_CAPT_ATTR_TSRC_SHIFT);
+ printf(" Transaction Type: %d\n",
+ (ddr->capture_attributes & ECC_CAPT_ATTR_TTYP) >>
+ ECC_CAPT_ATTR_TTYP_SHIFT);
+ printf(" Error Information Valid: %d\n\n",
+ ddr->capture_attributes & ECC_CAPT_ATTR_VLD);
+}
+
+int do_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+#ifdef CONFIG_FSL_DDR2
+ ccsr_ddr_t *ddr = &immap->ddr;
+#else
+ ddr83xx_t *ddr = &immap->ddr;
+#endif
+ volatile u32 val;
+ u64 *addr;
+ u32 count;
+ register u64 *i;
+ u32 ret[2];
+ u32 pattern[2];
+ u32 writeback[2];
+
+ /* The pattern is written into memory to generate error */
+ pattern[0] = 0xfedcba98UL;
+ pattern[1] = 0x76543210UL;
+
+ /* After injecting error, re-initialize the memory with the value */
+ writeback[0] = 0x01234567UL;
+ writeback[1] = 0x89abcdefUL;
+
+ if (argc > 4)
+ return cmd_usage(cmdtp);
+
+ if (argc == 2) {
+ if (strcmp(argv[1], "status") == 0) {
+ ecc_print_status();
+ return 0;
+ } else if (strcmp(argv[1], "captureclear") == 0) {
+ ddr->capture_address = 0;
+ ddr->capture_data_hi = 0;
+ ddr->capture_data_lo = 0;
+ ddr->capture_ecc = 0;
+ ddr->capture_attributes = 0;
+ return 0;
+ }
+ }
+ if (argc == 3) {
+ if (strcmp(argv[1], "sbecnt") == 0) {
+ val = simple_strtoul(argv[2], NULL, 10);
+ if (val > 255) {
+ printf("Incorrect Counter value, "
+ "should be 0..255\n");
+ return 1;
+ }
+
+ val = (val << ECC_ERROR_MAN_SBEC_SHIFT);
+ val |= (ddr->err_sbe & ECC_ERROR_MAN_SBET);
+
+ ddr->err_sbe = val;
+ return 0;
+ } else if (strcmp(argv[1], "sbethr") == 0) {
+ val = simple_strtoul(argv[2], NULL, 10);
+ if (val > 255) {
+ printf("Incorrect Counter value, "
+ "should be 0..255\n");
+ return 1;
+ }
+
+ val = (val << ECC_ERROR_MAN_SBET_SHIFT);
+ val |= (ddr->err_sbe & ECC_ERROR_MAN_SBEC);
+
+ ddr->err_sbe = val;
+ return 0;
+ } else if (strcmp(argv[1], "errdisable") == 0) {
+ val = ddr->err_disable;
+
+ if (strcmp(argv[2], "+sbe") == 0) {
+ val |= ECC_ERROR_DISABLE_SBED;
+ } else if (strcmp(argv[2], "+mbe") == 0) {
+ val |= ECC_ERROR_DISABLE_MBED;
+ } else if (strcmp(argv[2], "+mse") == 0) {
+ val |= ECC_ERROR_DISABLE_MSED;
+ } else if (strcmp(argv[2], "+all") == 0) {
+ val |= (ECC_ERROR_DISABLE_SBED |
+ ECC_ERROR_DISABLE_MBED |
+ ECC_ERROR_DISABLE_MSED);
+ } else if (strcmp(argv[2], "-sbe") == 0) {
+ val &= ~ECC_ERROR_DISABLE_SBED;
+ } else if (strcmp(argv[2], "-mbe") == 0) {
+ val &= ~ECC_ERROR_DISABLE_MBED;
+ } else if (strcmp(argv[2], "-mse") == 0) {
+ val &= ~ECC_ERROR_DISABLE_MSED;
+ } else if (strcmp(argv[2], "-all") == 0) {
+ val &= ~(ECC_ERROR_DISABLE_SBED |
+ ECC_ERROR_DISABLE_MBED |
+ ECC_ERROR_DISABLE_MSED);
+ } else {
+ printf("Incorrect err_disable field\n");
+ return 1;
+ }
+
+ ddr->err_disable = val;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+ return 0;
+ } else if (strcmp(argv[1], "errdetectclr") == 0) {
+ val = ddr->err_detect;
+
+ if (strcmp(argv[2], "mme") == 0) {
+ val |= ECC_ERROR_DETECT_MME;
+ } else if (strcmp(argv[2], "sbe") == 0) {
+ val |= ECC_ERROR_DETECT_SBE;
+ } else if (strcmp(argv[2], "mbe") == 0) {
+ val |= ECC_ERROR_DETECT_MBE;
+ } else if (strcmp(argv[2], "mse") == 0) {
+ val |= ECC_ERROR_DETECT_MSE;
+ } else if (strcmp(argv[2], "all") == 0) {
+ val |= (ECC_ERROR_DETECT_MME |
+ ECC_ERROR_DETECT_MBE |
+ ECC_ERROR_DETECT_SBE |
+ ECC_ERROR_DETECT_MSE);
+ } else {
+ printf("Incorrect err_detect field\n");
+ return 1;
+ }
+
+ ddr->err_detect = val;
+ return 0;
+ } else if (strcmp(argv[1], "injectdatahi") == 0) {
+ val = simple_strtoul(argv[2], NULL, 16);
+
+ ddr->data_err_inject_hi = val;
+ return 0;
+ } else if (strcmp(argv[1], "injectdatalo") == 0) {
+ val = simple_strtoul(argv[2], NULL, 16);
+
+ ddr->data_err_inject_lo = val;
+ return 0;
+ } else if (strcmp(argv[1], "injectecc") == 0) {
+ val = simple_strtoul(argv[2], NULL, 16);
+ if (val > 0xff) {
+ printf("Incorrect ECC inject mask, "
+ "should be 0x00..0xff\n");
+ return 1;
+ }
+ val |= (ddr->ecc_err_inject & ~ECC_ERR_INJECT_EEIM);
+
+ ddr->ecc_err_inject = val;
+ return 0;
+ } else if (strcmp(argv[1], "inject") == 0) {
+ val = ddr->ecc_err_inject;
+
+ if (strcmp(argv[2], "en") == 0)
+ val |= ECC_ERR_INJECT_EIEN;
+ else if (strcmp(argv[2], "dis") == 0)
+ val &= ~ECC_ERR_INJECT_EIEN;
+ else
+ printf("Incorrect command\n");
+
+ ddr->ecc_err_inject = val;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+ return 0;
+ } else if (strcmp(argv[1], "mirror") == 0) {
+ val = ddr->ecc_err_inject;
+
+ if (strcmp(argv[2], "en") == 0)
+ val |= ECC_ERR_INJECT_EMB;
+ else if (strcmp(argv[2], "dis") == 0)
+ val &= ~ECC_ERR_INJECT_EMB;
+ else
+ printf("Incorrect command\n");
+
+ ddr->ecc_err_inject = val;
+ return 0;
+ }
+ }
+ if (argc == 4) {
+ if (strcmp(argv[1], "testdw") == 0) {
+ addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
+ count = simple_strtoul(argv[3], NULL, 16);
+
+ if ((u32) addr % 8) {
+ printf("Address not alligned on "
+ "double word boundary\n");
+ return 1;
+ }
+ disable_interrupts();
+
+ for (i = addr; i < addr + count; i++) {
+
+ /* enable injects */
+ ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* write memory location injecting errors */
+ ppcDWstore((u32 *) i, pattern);
+ __asm__ __volatile__("sync");
+
+ /* disable injects */
+ ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* read data, this generates ECC error */
+ ppcDWload((u32 *) i, ret);
+ __asm__ __volatile__("sync");
+
+ /* re-initialize memory, double word write the location again,
+ * generates new ECC code this time */
+ ppcDWstore((u32 *) i, writeback);
+ __asm__ __volatile__("sync");
+ }
+ enable_interrupts();
+ return 0;
+ }
+ if (strcmp(argv[1], "testword") == 0) {
+ addr = (u64 *) simple_strtoul(argv[2], NULL, 16);
+ count = simple_strtoul(argv[3], NULL, 16);
+
+ if ((u32) addr % 8) {
+ printf("Address not alligned on "
+ "double word boundary\n");
+ return 1;
+ }
+ disable_interrupts();
+
+ for (i = addr; i < addr + count; i++) {
+
+ /* enable injects */
+ ddr->ecc_err_inject |= ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* write memory location injecting errors */
+ *(u32 *) i = 0xfedcba98UL;
+ __asm__ __volatile__("sync");
+
+ /* sub double word write,
+ * bus will read-modify-write,
+ * generates ECC error */
+ *((u32 *) i + 1) = 0x76543210UL;
+ __asm__ __volatile__("sync");
+
+ /* disable injects */
+ ddr->ecc_err_inject &= ~ECC_ERR_INJECT_EIEN;
+ __asm__ __volatile__("sync");
+ __asm__ __volatile__("isync");
+
+ /* re-initialize memory,
+ * double word write the location again,
+ * generates new ECC code this time */
+ ppcDWstore((u32 *) i, writeback);
+ __asm__ __volatile__("sync");
+ }
+ enable_interrupts();
+ return 0;
+ }
+ }
+ return cmd_usage(cmdtp);
+}
+
+U_BOOT_CMD(ecc, 4, 0, do_ecc,
+ "support for DDR ECC features",
+ "status - print out status info\n"
+ "ecc captureclear - clear capture regs data\n"
+ "ecc sbecnt <val> - set Single-Bit Error counter\n"
+ "ecc sbethr <val> - set Single-Bit Threshold\n"
+ "ecc errdisable <flag> - clear/set disable Memory Error Disable, flag:\n"
+ " [-|+]sbe - Single-Bit Error\n"
+ " [-|+]mbe - Multiple-Bit Error\n"
+ " [-|+]mse - Memory Select Error\n"
+ " [-|+]all - all errors\n"
+ "ecc errdetectclr <flag> - clear Memory Error Detect, flag:\n"
+ " mme - Multiple Memory Errors\n"
+ " sbe - Single-Bit Error\n"
+ " mbe - Multiple-Bit Error\n"
+ " mse - Memory Select Error\n"
+ " all - all errors\n"
+ "ecc injectdatahi <hi> - set Memory Data Path Error Injection Mask High\n"
+ "ecc injectdatalo <lo> - set Memory Data Path Error Injection Mask Low\n"
+ "ecc injectecc <ecc> - set ECC Error Injection Mask\n"
+ "ecc inject <en|dis> - enable/disable error injection\n"
+ "ecc mirror <en|dis> - enable/disable mirror byte\n"
+ "ecc testdw <addr> <cnt> - test mem region with double word access:\n"
+ " - enables injects\n"
+ " - writes pattern injecting errors with double word access\n"
+ " - disables injects\n"
+ " - reads pattern back with double word access, generates error\n"
+ " - re-inits memory\n"
+ "ecc testword <addr> <cnt> - test mem region with word access:\n"
+ " - enables injects\n"
+ " - writes pattern injecting errors with word access\n"
+ " - writes pattern with word access, generates error\n"
+ " - disables injects\n" " - re-inits memory");
+#endif
diff --git a/arch/powerpc/cpu/mpc83xx/fdt.c b/arch/powerpc/cpu/mpc83xx/fdt.c
new file mode 100644
index 0000000..fe553a7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/fdt.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/processor.h>
+
+extern void ft_qe_setup(void *blob);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_BOOTCOUNT_LIMIT) && \
+ (defined(CONFIG_QE))
+#include <asm/immap_qe.h>
+
+void fdt_fixup_muram (void *blob)
+{
+ ulong data[2];
+
+ data[0] = 0;
+ data[1] = QE_MURAM_SIZE - 2 * sizeof(unsigned long);
+ do_fixup_by_compat(blob, "fsl,qe-muram-data", "reg",
+ data, sizeof (data), 0);
+}
+#endif
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ int spridr = immr->sysconf.spridr;
+
+ /*
+ * delete crypto node if not on an E-processor
+ * initial revisions of the MPC834xE/6xE have the original SEC 2.0.
+ * EA revisions got the SEC uprevved to 2.4 but since the default device
+ * tree contains SEC 2.0 properties we uprev them here.
+ */
+ if (!IS_E_PROCESSOR(spridr))
+ fdt_fixup_crypto_node(blob, 0);
+ else if (IS_E_PROCESSOR(spridr) &&
+ (SPR_FAMILY(spridr) == SPR_834X_FAMILY ||
+ SPR_FAMILY(spridr) == SPR_836X_FAMILY) &&
+ REVID_MAJOR(spridr) >= 2)
+ fdt_fixup_crypto_node(blob, 0x0204);
+
+#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) ||\
+ defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) ||\
+ defined(CONFIG_HAS_ETH4) || defined(CONFIG_HAS_ETH5)
+ fdt_fixup_ethernet(blob);
+#ifdef CONFIG_MPC8313
+ /*
+ * mpc8313e erratum IPIC1 swapped TSEC interrupt ID numbers on rev. 1
+ * h/w (see AN3545). The base device tree in use has rev. 1 ID numbers,
+ * so if on Rev. 2 (and higher) h/w, we fix them up here
+ */
+ if (REVID_MAJOR(immr->sysconf.spridr) >= 2) {
+ int nodeoffset, path;
+ const char *prop;
+
+ nodeoffset = fdt_path_offset(blob, "/aliases");
+ if (nodeoffset >= 0) {
+#if defined(CONFIG_HAS_ETH0)
+ prop = fdt_getprop(blob, nodeoffset, "ethernet0", NULL);
+ if (prop) {
+ u32 tmp[] = { 32, 0x8, 33, 0x8, 34, 0x8 };
+
+ path = fdt_path_offset(blob, prop);
+ prop = fdt_getprop(blob, path, "interrupts",
+ NULL);
+ if (prop)
+ fdt_setprop(blob, path, "interrupts",
+ &tmp, sizeof(tmp));
+ }
+#endif
+#if defined(CONFIG_HAS_ETH1)
+ prop = fdt_getprop(blob, nodeoffset, "ethernet1", NULL);
+ if (prop) {
+ u32 tmp[] = { 35, 0x8, 36, 0x8, 37, 0x8 };
+
+ path = fdt_path_offset(blob, prop);
+ prop = fdt_getprop(blob, path, "interrupts",
+ NULL);
+ if (prop)
+ fdt_setprop(blob, path, "interrupts",
+ &tmp, sizeof(tmp));
+ }
+#endif
+ }
+ }
+#endif
+#endif
+
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", (bd->bi_busfreq / 4), 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "clock-frequency", gd->arch.core_clk, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,soc",
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,soc",
+ "clock-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,immr",
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,immr",
+ "clock-frequency", bd->bi_busfreq, 1);
+#ifdef CONFIG_QE
+ ft_qe_setup(blob);
+#endif
+
+#ifdef CONFIG_SYS_NS16550
+ do_fixup_by_compat_u32(blob, "ns16550",
+ "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+#if defined(CONFIG_BOOTCOUNT_LIMIT)
+ fdt_fixup_muram (blob);
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc83xx/interrupts.c b/arch/powerpc/cpu/mpc83xx/interrupts.c
new file mode 100644
index 0000000..446af27
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/interrupts.c
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc83xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ ulong count;
+};
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ *decrementer_count = (gd->bus_clk / 4) / CONFIG_SYS_HZ;
+
+ /* Enable e300 time base */
+
+ immr->sysconf.spcr |= 0x00400000;
+
+ return 0;
+}
+
+
+/*
+ * Handle external interrupts
+ */
+
+void external_interrupt (struct pt_regs *regs)
+{
+}
+
+
+/*
+ * Install and free an interrupt handler.
+ */
+
+void
+irq_install_handler (int irq, interrupt_handler_t * handler, void *arg)
+{
+}
+
+
+void irq_free_handler (int irq)
+{
+}
+
+
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
+
+
+#if defined(CONFIG_CMD_IRQ)
+
+/* ripped this out of ppc4xx/interrupts.c */
+
+/*
+ * irqinfo - print information about PCI devices
+ */
+
+void
+do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char * const argv[])
+{
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc83xx/law.c b/arch/powerpc/cpu/mpc83xx/law.c
new file mode 100644
index 0000000..66c88b6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/law.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+#include <asm/mmu.h>
+
+int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
+{
+ immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ law83xx_t *ecm = &immap->sysconf.ddrlaw[0];
+ u64 start_align, law_sz;
+ int law_sz_enc;
+
+ if (start == 0)
+ start_align = 1ull << (LAW_SIZE_2G + 1);
+ else
+ start_align = 1ull << (ffs64(start) - 1);
+ law_sz = min(start_align, sz);
+ law_sz_enc = __ilog2_u64(law_sz) - 1;
+
+ /*
+ * Set up LAWBAR for all of DDR.
+ */
+ ecm->bar = start & 0xfffff000;
+ ecm->ar = (LAWAR_EN | (id << 20) | (LAWAR_SIZE & law_sz_enc));
+ debug("DDR:bar=0x%08x\n", ecm->bar);
+ debug("DDR:ar=0x%08x\n", ecm->ar);
+
+ /* recalculate size based on what was actually covered by the law */
+ law_sz = 1ull << __ilog2_u64(law_sz);
+
+ /* do we still have anything to map */
+ sz = sz - law_sz;
+ if (sz) {
+ start += law_sz;
+
+ start_align = 1ull << (ffs64(start) - 1);
+ law_sz = min(start_align, sz);
+ law_sz_enc = __ilog2_u64(law_sz) - 1;
+ ecm = &immap->sysconf.ddrlaw[1];
+ ecm->bar = start & 0xfffff000;
+ ecm->ar = (LAWAR_EN | (id << 20) | (LAWAR_SIZE & law_sz_enc));
+ debug("DDR:bar=0x%08x\n", ecm->bar);
+ debug("DDR:ar=0x%08x\n", ecm->ar);
+ } else {
+ return 0;
+ }
+
+ /* do we still have anything to map */
+ sz = sz - law_sz;
+ if (sz)
+ return 1;
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc83xx/pci.c b/arch/powerpc/cpu/mpc83xx/pci.c
new file mode 100644
index 0000000..288d99f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/pci.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) Freescale Semiconductor, Inc. 2007
+ *
+ * Author: Scott Wood <scottwood@freescale.com>,
+ * with some bits from older board-specific PCI initialization.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <pci.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+#include <asm/mpc8349_pci.h>
+
+#define MAX_BUSES 2
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct pci_controller pci_hose[MAX_BUSES];
+static int pci_num_buses;
+
+static void pci_init_bus(int bus, struct pci_region *reg)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile pot83xx_t *pot = immr->ios.pot;
+ volatile pcictrl83xx_t *pci_ctrl = &immr->pci_ctrl[bus];
+ struct pci_controller *hose = &pci_hose[bus];
+ u32 dev;
+ u16 reg16;
+ int i;
+
+ if (bus == 1)
+ pot += 3;
+
+ /* Setup outbound translation windows */
+ for (i = 0; i < 3; i++, reg++, pot++) {
+ if (reg->size == 0)
+ break;
+
+ hose->regions[i] = *reg;
+ hose->region_count++;
+
+ pot->potar = reg->bus_start >> 12;
+ pot->pobar = reg->phys_start >> 12;
+ pot->pocmr = ~(reg->size - 1) >> 12;
+
+ if (reg->flags & PCI_REGION_IO)
+ pot->pocmr |= POCMR_IO;
+#ifdef CONFIG_83XX_PCI_STREAMING
+ else if (reg->flags & PCI_REGION_PREFETCH)
+ pot->pocmr |= POCMR_SE;
+#endif
+
+ if (bus == 1)
+ pot->pocmr |= POCMR_DST;
+
+ pot->pocmr |= POCMR_EN;
+ }
+
+ /* Point inbound translation at RAM */
+ pci_ctrl->pitar1 = 0;
+ pci_ctrl->pibar1 = 0;
+ pci_ctrl->piebar1 = 0;
+ pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
+ PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size - 1));
+
+ i = hose->region_count++;
+ hose->regions[i].bus_start = 0;
+ hose->regions[i].phys_start = 0;
+ hose->regions[i].size = gd->ram_size;
+ hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
+
+ hose->first_busno = pci_last_busno() + 1;
+ hose->last_busno = 0xff;
+
+ pci_setup_indirect(hose, CONFIG_SYS_IMMR + 0x8300 + bus * 0x80,
+ CONFIG_SYS_IMMR + 0x8304 + bus * 0x80);
+
+ pci_register_hose(hose);
+
+ /*
+ * Write to Command register
+ */
+ reg16 = 0xff;
+ dev = PCI_BDF(hose->first_busno, 0, 0);
+ pci_hose_read_config_word(hose, dev, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+ pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
+ pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+#ifndef CONFIG_PCISLAVE
+ /*
+ * Hose scan.
+ */
+ hose->last_busno = pci_hose_scan(hose);
+#endif
+}
+
+/*
+ * The caller must have already set OCCR, and the PCI_LAW BARs
+ * must have been set to cover all of the requested regions.
+ *
+ * If fewer than three regions are requested, then the region
+ * list is terminated with a region of size 0.
+ */
+void mpc83xx_pci_init(int num_buses, struct pci_region **reg)
+{
+ volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
+ int i;
+
+ if (num_buses > MAX_BUSES) {
+ printf("%d PCI buses requsted, %d supported\n",
+ num_buses, MAX_BUSES);
+
+ num_buses = MAX_BUSES;
+ }
+
+ pci_num_buses = num_buses;
+
+ /*
+ * Release PCI RST Output signal.
+ * Power on to RST high must be at least 100 ms as per PCI spec.
+ * On warm boots only 1 ms is required, but we play it safe.
+ */
+ udelay(100000);
+
+ for (i = 0; i < num_buses; i++)
+ immr->pci_ctrl[i].gcr = 1;
+
+ /*
+ * RST high to first config access must be at least 2^25 cycles
+ * as per PCI spec. This could be cut in half if we know we're
+ * running at 66MHz. This could be insufficiently long if we're
+ * running the PCI bus at significantly less than 33MHz.
+ */
+ udelay(1020000);
+
+ for (i = 0; i < num_buses; i++)
+ pci_init_bus(i, reg[i]);
+}
+
+#ifdef CONFIG_PCISLAVE
+
+#define PCI_FUNCTION_CONFIG 0x44
+#define PCI_FUNCTION_CFG_LOCK 0x20
+
+/*
+ * Unlock the configuration bit so that the host system can begin booting
+ *
+ * This should be used after you have:
+ * 1) Called mpc83xx_pci_init()
+ * 2) Set up your inbound translation windows to the appropriate size
+ */
+void mpc83xx_pcislave_unlock(int bus)
+{
+ struct pci_controller *hose = &pci_hose[bus];
+ u32 dev;
+ u16 reg16;
+
+ /* Unlock configuration lock in PCI function configuration register */
+ dev = PCI_BDF(hose->first_busno, 0, 0);
+ pci_hose_read_config_word (hose, dev, PCI_FUNCTION_CONFIG, &reg16);
+ reg16 &= ~(PCI_FUNCTION_CFG_LOCK);
+ pci_hose_write_config_word (hose, dev, PCI_FUNCTION_CONFIG, reg16);
+
+ /* The configuration bit is now unlocked, so we can scan the bus */
+ hose->last_busno = pci_hose_scan(hose);
+}
+#endif
+
+#if defined(CONFIG_OF_LIBFDT)
+void ft_pci_setup(void *blob, bd_t *bd)
+{
+ int nodeoffset;
+ int tmp[2];
+ const char *path;
+
+ if (pci_num_buses < 1)
+ return;
+
+ nodeoffset = fdt_path_offset(blob, "/aliases");
+ if (nodeoffset >= 0) {
+ path = fdt_getprop(blob, nodeoffset, "pci0", NULL);
+ if (path) {
+ tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
+ tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
+ do_fixup_by_path(blob, path, "bus-range",
+ &tmp, sizeof(tmp), 1);
+
+ tmp[0] = cpu_to_be32(gd->pci_clk);
+ do_fixup_by_path(blob, path, "clock-frequency",
+ &tmp, sizeof(tmp[0]), 1);
+ }
+
+ if (pci_num_buses < 2)
+ return;
+
+ path = fdt_getprop(blob, nodeoffset, "pci1", NULL);
+ if (path) {
+ tmp[0] = cpu_to_be32(pci_hose[1].first_busno);
+ tmp[1] = cpu_to_be32(pci_hose[1].last_busno);
+ do_fixup_by_path(blob, path, "bus-range",
+ &tmp, sizeof(tmp), 1);
+
+ tmp[0] = cpu_to_be32(gd->pci_clk);
+ do_fixup_by_path(blob, path, "clock-frequency",
+ &tmp, sizeof(tmp[0]), 1);
+ }
+ }
+}
+#endif /* CONFIG_OF_LIBFDT */
diff --git a/arch/powerpc/cpu/mpc83xx/pcie.c b/arch/powerpc/cpu/mpc83xx/pcie.c
new file mode 100644
index 0000000..609b133
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/pcie.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2007-2009 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2009 MontaVista Software, Inc.
+ *
+ * Authors: Tony Li <tony.li@freescale.com>
+ * Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <mpc83xx.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PCIE_MAX_BUSES 2
+
+static struct {
+ u32 base;
+ u32 size;
+} mpc83xx_pcie_cfg_space[] = {
+ {
+ .base = CONFIG_SYS_PCIE1_CFG_BASE,
+ .size = CONFIG_SYS_PCIE1_CFG_SIZE,
+ },
+#if defined(CONFIG_SYS_PCIE2_CFG_BASE) && defined(CONFIG_SYS_PCIE2_CFG_SIZE)
+ {
+ .base = CONFIG_SYS_PCIE2_CFG_BASE,
+ .size = CONFIG_SYS_PCIE2_CFG_SIZE,
+ },
+#endif
+};
+
+#ifdef CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES
+
+/* private structure for mpc83xx pcie hose */
+static struct mpc83xx_pcie_priv {
+ u8 index;
+} pcie_priv[PCIE_MAX_BUSES] = {
+ {
+ /* pcie controller 1 */
+ .index = 0,
+ },
+ {
+ /* pcie controller 2 */
+ .index = 1,
+ },
+};
+
+static int mpc83xx_pcie_remap_cfg(struct pci_controller *hose, pci_dev_t dev)
+{
+ int bus = PCI_BUS(dev) - hose->first_busno;
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ struct mpc83xx_pcie_priv *pcie_priv = hose->priv_data;
+ pex83xx_t *pex = &immr->pciexp[pcie_priv->index];
+ struct pex_outbound_window *out_win = &pex->bridge.pex_outbound_win[0];
+ u8 devfn = PCI_DEV(dev) << 3 | PCI_FUNC(dev);
+ u32 dev_base = bus << 24 | devfn << 16;
+
+ if (hose->indirect_type == INDIRECT_TYPE_NO_PCIE_LINK)
+ return -1;
+ /*
+ * Workaround for the HW bug: for Type 0 configure transactions the
+ * PCI-E controller does not check the device number bits and just
+ * assumes that the device number bits are 0.
+ */
+ if (devfn & 0xf8)
+ return -1;
+
+ out_le32(&out_win->tarl, dev_base);
+ return 0;
+}
+
+#define cfg_read(val, addr, type, op) \
+ do { *val = op((type)(addr)); } while (0)
+#define cfg_write(val, addr, type, op) \
+ do { op((type *)(addr), (val)); } while (0)
+
+#define cfg_read_err(val) do { *val = -1; } while (0)
+#define cfg_write_err(val) do { } while (0)
+
+#define PCIE_OP(rw, size, type, op) \
+static int pcie_##rw##_config_##size(struct pci_controller *hose, \
+ pci_dev_t dev, int offset, \
+ type val) \
+{ \
+ int ret; \
+ \
+ ret = mpc83xx_pcie_remap_cfg(hose, dev); \
+ if (ret) { \
+ cfg_##rw##_err(val); \
+ return ret; \
+ } \
+ cfg_##rw(val, (void *)hose->cfg_addr + offset, type, op); \
+ return 0; \
+}
+
+PCIE_OP(read, byte, u8 *, in_8)
+PCIE_OP(read, word, u16 *, in_le16)
+PCIE_OP(read, dword, u32 *, in_le32)
+PCIE_OP(write, byte, u8, out_8)
+PCIE_OP(write, word, u16, out_le16)
+PCIE_OP(write, dword, u32, out_le32)
+
+static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg,
+ u8 link)
+{
+ extern void disable_addr_trans(void); /* start.S */
+ static struct pci_controller pcie_hose[PCIE_MAX_BUSES];
+ struct pci_controller *hose = &pcie_hose[bus];
+ int i;
+
+ /*
+ * There are no spare BATs to remap all PCI-E windows for U-Boot, so
+ * disable translations. In general, this is not great solution, and
+ * that's why we don't register PCI-E hoses by default.
+ */
+ disable_addr_trans();
+
+ for (i = 0; i < 2; i++, reg++) {
+ if (reg->size == 0)
+ break;
+
+ hose->regions[i] = *reg;
+ hose->region_count++;
+ }
+
+ i = hose->region_count++;
+ hose->regions[i].bus_start = 0;
+ hose->regions[i].phys_start = 0;
+ hose->regions[i].size = gd->ram_size;
+ hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
+
+ i = hose->region_count++;
+ hose->regions[i].bus_start = CONFIG_SYS_IMMR;
+ hose->regions[i].phys_start = CONFIG_SYS_IMMR;
+ hose->regions[i].size = 0x100000;
+ hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
+
+ hose->first_busno = pci_last_busno() + 1;
+ hose->last_busno = 0xff;
+
+ hose->cfg_addr = (unsigned int *)mpc83xx_pcie_cfg_space[bus].base;
+
+ hose->priv_data = &pcie_priv[bus];
+
+ pci_set_ops(hose,
+ pcie_read_config_byte,
+ pcie_read_config_word,
+ pcie_read_config_dword,
+ pcie_write_config_byte,
+ pcie_write_config_word,
+ pcie_write_config_dword);
+
+ if (!link)
+ hose->indirect_type = INDIRECT_TYPE_NO_PCIE_LINK;
+
+ pci_register_hose(hose);
+
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+ /*
+ * Hose scan.
+ */
+ hose->last_busno = pci_hose_scan(hose);
+}
+
+#else
+
+static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg,
+ u8 link) {}
+
+#endif /* CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES */
+
+static void mpc83xx_pcie_init_bus(int bus, struct pci_region *reg)
+{
+ immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ pex83xx_t *pex = &immr->pciexp[bus];
+ struct pex_outbound_window *out_win;
+ struct pex_inbound_window *in_win;
+ void *hose_cfg_base;
+ unsigned int ram_sz;
+ unsigned int barl;
+ unsigned int tar;
+ u16 reg16;
+ int i;
+
+ /* Enable pex csb bridge inbound & outbound transactions */
+ out_le32(&pex->bridge.pex_csb_ctrl,
+ in_le32(&pex->bridge.pex_csb_ctrl) | PEX_CSB_CTRL_OBPIOE |
+ PEX_CSB_CTRL_IBPIOE);
+
+ /* Enable bridge outbound */
+ out_le32(&pex->bridge.pex_csb_obctrl, PEX_CSB_OBCTRL_PIOE |
+ PEX_CSB_OBCTRL_MEMWE | PEX_CSB_OBCTRL_IOWE |
+ PEX_CSB_OBCTRL_CFGWE);
+
+ out_win = &pex->bridge.pex_outbound_win[0];
+ out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG |
+ mpc83xx_pcie_cfg_space[bus].size);
+ out_le32(&out_win->bar, mpc83xx_pcie_cfg_space[bus].base);
+ out_le32(&out_win->tarl, 0);
+ out_le32(&out_win->tarh, 0);
+
+ for (i = 0; i < 2; i++) {
+ u32 ar;
+
+ if (reg[i].size == 0)
+ break;
+
+ out_win = &pex->bridge.pex_outbound_win[i + 1];
+ out_le32(&out_win->bar, reg[i].phys_start);
+ out_le32(&out_win->tarl, reg[i].bus_start);
+ out_le32(&out_win->tarh, 0);
+ ar = PEX_OWAR_EN | (reg[i].size & PEX_OWAR_SIZE);
+ if (reg[i].flags & PCI_REGION_IO)
+ ar |= PEX_OWAR_TYPE_IO;
+ else
+ ar |= PEX_OWAR_TYPE_MEM;
+ out_le32(&out_win->ar, ar);
+ }
+
+ out_le32(&pex->bridge.pex_csb_ibctrl, PEX_CSB_IBCTRL_PIOE);
+
+ ram_sz = gd->ram_size;
+ barl = 0;
+ tar = 0;
+ i = 0;
+ while (ram_sz > 0) {
+ in_win = &pex->bridge.pex_inbound_win[i];
+ out_le32(&in_win->barl, barl);
+ out_le32(&in_win->barh, 0x0);
+ out_le32(&in_win->tar, tar);
+ if (ram_sz >= 0x10000000) {
+ /* The maxium windows size is 256M */
+ out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV |
+ PEX_IWAR_TYPE_PF | 0x0FFFF000);
+ barl += 0x10000000;
+ tar += 0x10000000;
+ ram_sz -= 0x10000000;
+ } else {
+ /* The UM is not clear here.
+ * So, round up to even Mb boundary */
+
+ ram_sz = ram_sz >> (20 +
+ ((ram_sz & 0xFFFFF) ? 1 : 0));
+ if (!(ram_sz % 2))
+ ram_sz -= 1;
+ out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV |
+ PEX_IWAR_TYPE_PF | (ram_sz << 20) | 0xFF000);
+ ram_sz = 0;
+ }
+ i++;
+ }
+
+ in_win = &pex->bridge.pex_inbound_win[i];
+ out_le32(&in_win->barl, CONFIG_SYS_IMMR);
+ out_le32(&in_win->barh, 0);
+ out_le32(&in_win->tar, CONFIG_SYS_IMMR);
+ out_le32(&in_win->ar, PEX_IWAR_EN |
+ PEX_IWAR_TYPE_NO_PF | PEX_IWAR_SIZE_1M);
+
+ /* Enable the host virtual INTX interrupts */
+ out_le32(&pex->bridge.pex_int_axi_misc_enb,
+ in_le32(&pex->bridge.pex_int_axi_misc_enb) | 0x1E0);
+
+ /* Hose configure header is memory-mapped */
+ hose_cfg_base = (void *)pex;
+
+ get_clocks();
+ /* Configure the PCIE controller core clock ratio */
+ out_le32(hose_cfg_base + PEX_GCLK_RATIO,
+ (((bus ? gd->arch.pciexp2_clk : gd->arch.pciexp1_clk)
+ / 1000000) * 16) / 333);
+ udelay(1000000);
+
+ /* Do Type 1 bridge configuration */
+ out_8(hose_cfg_base + PCI_PRIMARY_BUS, 0);
+ out_8(hose_cfg_base + PCI_SECONDARY_BUS, 1);
+ out_8(hose_cfg_base + PCI_SUBORDINATE_BUS, 255);
+
+ /*
+ * Write to Command register
+ */
+ reg16 = in_le16(hose_cfg_base + PCI_COMMAND);
+ reg16 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO |
+ PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
+ out_le16(hose_cfg_base + PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ out_le16(hose_cfg_base + PCI_STATUS, 0xffff);
+ out_8(hose_cfg_base + PCI_LATENCY_TIMER, 0x80);
+ out_8(hose_cfg_base + PCI_CACHE_LINE_SIZE, 0x08);
+
+ printf("PCIE%d: ", bus);
+
+ reg16 = in_le16(hose_cfg_base + PCI_LTSSM);
+ if (reg16 >= PCI_LTSSM_L0)
+ printf("link\n");
+ else
+ printf("No link\n");
+
+ mpc83xx_pcie_register_hose(bus, reg, reg16 >= PCI_LTSSM_L0);
+}
+
+/*
+ * The caller must have already set SCCR, SERDES and the PCIE_LAW BARs
+ * must have been set to cover all of the requested regions.
+ */
+void mpc83xx_pcie_init(int num_buses, struct pci_region **reg)
+{
+ int i;
+
+ /*
+ * Release PCI RST Output signal.
+ * Power on to RST high must be at least 100 ms as per PCI spec.
+ * On warm boots only 1 ms is required, but we play it safe.
+ */
+ udelay(100000);
+
+ if (num_buses > ARRAY_SIZE(mpc83xx_pcie_cfg_space)) {
+ printf("Second PCIE host contoller not configured!\n");
+ num_buses = ARRAY_SIZE(mpc83xx_pcie_cfg_space);
+ }
+
+ for (i = 0; i < num_buses; i++)
+ mpc83xx_pcie_init_bus(i, reg[i]);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/qe_io.c b/arch/powerpc/cpu/mpc83xx/qe_io.c
new file mode 100644
index 0000000..db94f00
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/qe_io.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on source code of Shlomi Gridish
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "common.h"
+#include "asm/errno.h"
+#include "asm/io.h"
+#include "asm/immap_83xx.h"
+
+#define NUM_OF_PINS 32
+void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
+{
+ u32 pin_2bit_mask;
+ u32 pin_2bit_dir;
+ u32 pin_2bit_assign;
+ u32 pin_1bit_mask;
+ u32 tmp_val;
+ volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
+ volatile qepio83xx_t *par_io = (volatile qepio83xx_t *)&im->qepio;
+
+ /* Caculate pin location and 2bit mask and dir */
+ pin_2bit_mask = (u32)(0x3 << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+ pin_2bit_dir = (u32)(dir << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Setup the direction */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? \
+ in_be32(&par_io->ioport[port].dir2) :
+ in_be32(&par_io->ioport[port].dir1);
+
+ if (pin > (NUM_OF_PINS/2) -1) {
+ out_be32(&par_io->ioport[port].dir2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io->ioport[port].dir2, pin_2bit_dir | tmp_val);
+ } else {
+ out_be32(&par_io->ioport[port].dir1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io->ioport[port].dir1, pin_2bit_dir | tmp_val);
+ }
+
+ /* Calculate pin location for 1bit mask */
+ pin_1bit_mask = (u32)(1 << (NUM_OF_PINS - (pin+1)));
+
+ /* Setup the open drain */
+ tmp_val = in_be32(&par_io->ioport[port].podr);
+ if (open_drain) {
+ out_be32(&par_io->ioport[port].podr, pin_1bit_mask | tmp_val);
+ } else {
+ out_be32(&par_io->ioport[port].podr, ~pin_1bit_mask & tmp_val);
+ }
+
+ /* Setup the assignment */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ?
+ in_be32(&par_io->ioport[port].ppar2):
+ in_be32(&par_io->ioport[port].ppar1);
+ pin_2bit_assign = (u32)(assign
+ << (NUM_OF_PINS - (pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Clear and set 2 bits mask */
+ if (pin > (NUM_OF_PINS/2) - 1) {
+ out_be32(&par_io->ioport[port].ppar2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io->ioport[port].ppar2, pin_2bit_assign | tmp_val);
+ } else {
+ out_be32(&par_io->ioport[port].ppar1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io->ioport[port].ppar1, pin_2bit_assign | tmp_val);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc83xx/serdes.c b/arch/powerpc/cpu/mpc83xx/serdes.c
new file mode 100644
index 0000000..2d5ee03
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/serdes.c
@@ -0,0 +1,154 @@
+/*
+ * Freescale SerDes initialization routine
+ *
+ * Copyright 2007,2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 MontaVista Software, Inc.
+ *
+ * Author: Li Yang <leoli@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_mpc83xx_serdes.h>
+
+/* SerDes registers */
+#define FSL_SRDSCR0_OFFS 0x0
+#define FSL_SRDSCR0_DPP_1V2 0x00008800
+#define FSL_SRDSCR0_TXEQA_MASK 0x00007000
+#define FSL_SRDSCR0_TXEQA_SATA 0x00001000
+#define FSL_SRDSCR0_TXEQE_MASK 0x00000700
+#define FSL_SRDSCR0_TXEQE_SATA 0x00000100
+#define FSL_SRDSCR1_OFFS 0x4
+#define FSL_SRDSCR1_PLLBW 0x00000040
+#define FSL_SRDSCR2_OFFS 0x8
+#define FSL_SRDSCR2_VDD_1V2 0x00800000
+#define FSL_SRDSCR2_SEIC_MASK 0x00001c1c
+#define FSL_SRDSCR2_SEIC_SATA 0x00001414
+#define FSL_SRDSCR2_SEIC_PEX 0x00001010
+#define FSL_SRDSCR2_SEIC_SGMII 0x00000101
+#define FSL_SRDSCR3_OFFS 0xc
+#define FSL_SRDSCR3_KFR_SATA 0x10100000
+#define FSL_SRDSCR3_KPH_SATA 0x04040000
+#define FSL_SRDSCR3_SDFM_SATA_PEX 0x01010000
+#define FSL_SRDSCR3_SDTXL_SATA 0x00000505
+#define FSL_SRDSCR4_OFFS 0x10
+#define FSL_SRDSCR4_PROT_SATA 0x00000808
+#define FSL_SRDSCR4_PROT_PEX 0x00000101
+#define FSL_SRDSCR4_PROT_SGMII 0x00000505
+#define FSL_SRDSCR4_PLANE_X2 0x01000000
+#define FSL_SRDSRSTCTL_OFFS 0x20
+#define FSL_SRDSRSTCTL_RST 0x80000000
+#define FSL_SRDSRSTCTL_SATA_RESET 0xf
+
+void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd)
+{
+ void *regs = (void *)CONFIG_SYS_IMMR + offset;
+ u32 tmp;
+
+ /* 1.0V corevdd */
+ if (vdd) {
+ /* DPPE/DPPA = 0 */
+ tmp = in_be32(regs + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_DPP_1V2;
+ out_be32(regs + FSL_SRDSCR0_OFFS, tmp);
+
+ /* VDD = 0 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_VDD_1V2;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+ }
+
+ /* protocol specific configuration */
+ switch (proto) {
+ case FSL_SERDES_PROTO_SATA:
+ /* Set and clear reset bits */
+ tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+ tmp |= FSL_SRDSRSTCTL_SATA_RESET;
+ out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+ udelay(1000);
+ tmp &= ~FSL_SRDSRSTCTL_SATA_RESET;
+ out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+
+ /* Configure SRDSCR0 */
+ clrsetbits_be32(regs + FSL_SRDSCR0_OFFS,
+ FSL_SRDSCR0_TXEQA_MASK | FSL_SRDSCR0_TXEQE_MASK,
+ FSL_SRDSCR0_TXEQA_SATA | FSL_SRDSCR0_TXEQE_SATA);
+
+ /* Configure SRDSCR1 */
+ tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_PLLBW;
+ out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+ /* Configure SRDSCR2 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+ tmp |= FSL_SRDSCR2_SEIC_SATA;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+ /* Configure SRDSCR3 */
+ tmp = FSL_SRDSCR3_KFR_SATA | FSL_SRDSCR3_KPH_SATA |
+ FSL_SRDSCR3_SDFM_SATA_PEX |
+ FSL_SRDSCR3_SDTXL_SATA;
+ out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+ /* Configure SRDSCR4 */
+ tmp = rfcks | FSL_SRDSCR4_PROT_SATA;
+ out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+ break;
+ case FSL_SERDES_PROTO_PEX:
+ case FSL_SERDES_PROTO_PEX_X2:
+ /* Configure SRDSCR1 */
+ tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+ tmp |= FSL_SRDSCR1_PLLBW;
+ out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+ /* Configure SRDSCR2 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+ tmp |= FSL_SRDSCR2_SEIC_PEX;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+ /* Configure SRDSCR3 */
+ tmp = FSL_SRDSCR3_SDFM_SATA_PEX;
+ out_be32(regs + FSL_SRDSCR3_OFFS, tmp);
+
+ /* Configure SRDSCR4 */
+ tmp = rfcks | FSL_SRDSCR4_PROT_PEX;
+ if (proto == FSL_SERDES_PROTO_PEX_X2)
+ tmp |= FSL_SRDSCR4_PLANE_X2;
+ out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+ break;
+ case FSL_SERDES_PROTO_SGMII:
+ /* Configure SRDSCR1 */
+ tmp = in_be32(regs + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_PLLBW;
+ out_be32(regs + FSL_SRDSCR1_OFFS, tmp);
+
+ /* Configure SRDSCR2 */
+ tmp = in_be32(regs + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_SEIC_MASK;
+ tmp |= FSL_SRDSCR2_SEIC_SGMII;
+ out_be32(regs + FSL_SRDSCR2_OFFS, tmp);
+
+ /* Configure SRDSCR3 */
+ out_be32(regs + FSL_SRDSCR3_OFFS, 0);
+
+ /* Configure SRDSCR4 */
+ tmp = rfcks | FSL_SRDSCR4_PROT_SGMII;
+ out_be32(regs + FSL_SRDSCR4_OFFS, tmp);
+ break;
+ default:
+ return;
+ }
+
+ /* Do a software reset */
+ tmp = in_be32(regs + FSL_SRDSRSTCTL_OFFS);
+ tmp |= FSL_SRDSRSTCTL_RST;
+ out_be32(regs + FSL_SRDSRSTCTL_OFFS, tmp);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/spd_sdram.c b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
new file mode 100644
index 0000000..04d519a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
@@ -0,0 +1,943 @@
+/*
+ * (C) Copyright 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <i2c.h>
+#include <spd.h>
+#include <asm/mmu.h>
+#include <spd_sdram.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_add_ram_info(int use_default)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile ddr83xx_t *ddr = &immap->ddr;
+ char buf[32];
+
+ printf(" (DDR%d", ((ddr->sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK)
+ >> SDRAM_CFG_SDRAM_TYPE_SHIFT) - 1);
+
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x)
+ if ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK) == SDRAM_CFG_DBW_16)
+ puts(", 16-bit");
+ else if ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK) == SDRAM_CFG_DBW_32)
+ puts(", 32-bit");
+ else
+ puts(", unknown width");
+#else
+ if (ddr->sdram_cfg & SDRAM_CFG_32_BE)
+ puts(", 32-bit");
+ else
+ puts(", 64-bit");
+#endif
+
+ if (ddr->sdram_cfg & SDRAM_CFG_ECC_EN)
+ puts(", ECC on");
+ else
+ puts(", ECC off");
+
+ printf(", %s MHz)", strmhz(buf, gd->mem_clk));
+
+#if defined(CONFIG_SYS_LB_SDRAM) && defined(CONFIG_SYS_LBC_SDRAM_SIZE)
+ puts("\nSDRAM: ");
+ print_size (CONFIG_SYS_LBC_SDRAM_SIZE * 1024 * 1024, " (local bus)");
+#endif
+}
+
+#ifdef CONFIG_SPD_EEPROM
+#ifndef CONFIG_SYS_READ_SPD
+#define CONFIG_SYS_READ_SPD i2c_read
+#endif
+#ifndef SPD_EEPROM_OFFSET
+#define SPD_EEPROM_OFFSET 0
+#endif
+#ifndef SPD_EEPROM_ADDR_LEN
+#define SPD_EEPROM_ADDR_LEN 1
+#endif
+
+/*
+ * Convert picoseconds into clock cycles (rounding up if needed).
+ */
+int
+picos_to_clk(int picos)
+{
+ unsigned int mem_bus_clk;
+ int clks;
+
+ mem_bus_clk = gd->mem_clk >> 1;
+ clks = picos / (1000000000 / (mem_bus_clk / 1000));
+ if (picos % (1000000000 / (mem_bus_clk / 1000)) != 0)
+ clks++;
+
+ return clks;
+}
+
+unsigned int banksize(unsigned char row_dens)
+{
+ return ((row_dens >> 2) | ((row_dens & 3) << 6)) << 24;
+}
+
+int read_spd(uint addr)
+{
+ return ((int) addr);
+}
+
+#undef SPD_DEBUG
+#ifdef SPD_DEBUG
+static void spd_debug(spd_eeprom_t *spd)
+{
+ printf ("\nDIMM type: %-18.18s\n", spd->mpart);
+ printf ("SPD size: %d\n", spd->info_size);
+ printf ("EEPROM size: %d\n", 1 << spd->chip_size);
+ printf ("Memory type: %d\n", spd->mem_type);
+ printf ("Row addr: %d\n", spd->nrow_addr);
+ printf ("Column addr: %d\n", spd->ncol_addr);
+ printf ("# of rows: %d\n", spd->nrows);
+ printf ("Row density: %d\n", spd->row_dens);
+ printf ("# of banks: %d\n", spd->nbanks);
+ printf ("Data width: %d\n",
+ 256 * spd->dataw_msb + spd->dataw_lsb);
+ printf ("Chip width: %d\n", spd->primw);
+ printf ("Refresh rate: %02X\n", spd->refresh);
+ printf ("CAS latencies: %02X\n", spd->cas_lat);
+ printf ("Write latencies: %02X\n", spd->write_lat);
+ printf ("tRP: %d\n", spd->trp);
+ printf ("tRCD: %d\n", spd->trcd);
+ printf ("\n");
+}
+#endif /* SPD_DEBUG */
+
+long int spd_sdram()
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile ddr83xx_t *ddr = &immap->ddr;
+ volatile law83xx_t *ecm = &immap->sysconf.ddrlaw[0];
+ spd_eeprom_t spd;
+ unsigned int n_ranks;
+ unsigned int odt_rd_cfg, odt_wr_cfg;
+ unsigned char twr_clk, twtr_clk;
+ unsigned int sdram_type;
+ unsigned int memsize;
+ unsigned int law_size;
+ unsigned char caslat, caslat_ctrl;
+ unsigned int trfc, trfc_clk, trfc_low;
+ unsigned int trcd_clk, trtp_clk;
+ unsigned char cke_min_clk;
+ unsigned char add_lat, wr_lat;
+ unsigned char wr_data_delay;
+ unsigned char four_act;
+ unsigned char cpo;
+ unsigned char burstlen;
+ unsigned char odt_cfg, mode_odt_enable;
+ unsigned int max_bus_clk;
+ unsigned int max_data_rate, effective_data_rate;
+ unsigned int ddrc_clk;
+ unsigned int refresh_clk;
+ unsigned int sdram_cfg;
+ unsigned int ddrc_ecc_enable;
+ unsigned int pvr = get_pvr();
+
+ /*
+ * First disable the memory controller (could be enabled
+ * by the debugger)
+ */
+ clrsetbits_be32(&ddr->sdram_cfg, SDRAM_CFG_MEM_EN, 0);
+ sync();
+ isync();
+
+ /* Read SPD parameters with I2C */
+ CONFIG_SYS_READ_SPD(SPD_EEPROM_ADDRESS, SPD_EEPROM_OFFSET,
+ SPD_EEPROM_ADDR_LEN, (uchar *) &spd, sizeof(spd));
+#ifdef SPD_DEBUG
+ spd_debug(&spd);
+#endif
+ /* Check the memory type */
+ if (spd.mem_type != SPD_MEMTYPE_DDR && spd.mem_type != SPD_MEMTYPE_DDR2) {
+ debug("DDR: Module mem type is %02X\n", spd.mem_type);
+ return 0;
+ }
+
+ /* Check the number of physical bank */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ n_ranks = spd.nrows;
+ } else {
+ n_ranks = (spd.nrows & 0x7) + 1;
+ }
+
+ if (n_ranks > 2) {
+ printf("DDR: The number of physical bank is %02X\n", n_ranks);
+ return 0;
+ }
+
+ /* Check if the number of row of the module is in the range of DDRC */
+ if (spd.nrow_addr < 12 || spd.nrow_addr > 15) {
+ printf("DDR: Row number is out of range of DDRC, row=%02X\n",
+ spd.nrow_addr);
+ return 0;
+ }
+
+ /* Check if the number of col of the module is in the range of DDRC */
+ if (spd.ncol_addr < 8 || spd.ncol_addr > 11) {
+ printf("DDR: Col number is out of range of DDRC, col=%02X\n",
+ spd.ncol_addr);
+ return 0;
+ }
+
+#ifdef CONFIG_SYS_DDRCDR_VALUE
+ /*
+ * Adjust DDR II IO voltage biasing. It just makes it work.
+ */
+ if(spd.mem_type == SPD_MEMTYPE_DDR2) {
+ immap->sysconf.ddrcdr = CONFIG_SYS_DDRCDR_VALUE;
+ }
+ udelay(50000);
+#endif
+
+ /*
+ * ODT configuration recommendation from DDR Controller Chapter.
+ */
+ odt_rd_cfg = 0; /* Never assert ODT */
+ odt_wr_cfg = 0; /* Never assert ODT */
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ odt_wr_cfg = 1; /* Assert ODT on writes to CSn */
+ }
+
+ /* Setup DDR chip select register */
+#ifdef CONFIG_SYS_83XX_DDR_USES_CS0
+ ddr->csbnds[0].csbnds = (banksize(spd.row_dens) >> 24) - 1;
+ ddr->cs_config[0] = ( 1 << 31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | ((spd.nbanks == 8 ? 1 : 0) << 14)
+ | ((spd.nrow_addr - 12) << 8)
+ | (spd.ncol_addr - 8) );
+ debug("\n");
+ debug("cs0_bnds = 0x%08x\n",ddr->csbnds[0].csbnds);
+ debug("cs0_config = 0x%08x\n",ddr->cs_config[0]);
+
+ if (n_ranks == 2) {
+ ddr->csbnds[1].csbnds = ( (banksize(spd.row_dens) >> 8)
+ | ((banksize(spd.row_dens) >> 23) - 1) );
+ ddr->cs_config[1] = ( 1<<31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | ((spd.nbanks == 8 ? 1 : 0) << 14)
+ | ((spd.nrow_addr - 12) << 8)
+ | (spd.ncol_addr - 8) );
+ debug("cs1_bnds = 0x%08x\n",ddr->csbnds[1].csbnds);
+ debug("cs1_config = 0x%08x\n",ddr->cs_config[1]);
+ }
+
+#else
+ ddr->csbnds[2].csbnds = (banksize(spd.row_dens) >> 24) - 1;
+ ddr->cs_config[2] = ( 1 << 31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | ((spd.nbanks == 8 ? 1 : 0) << 14)
+ | ((spd.nrow_addr - 12) << 8)
+ | (spd.ncol_addr - 8) );
+ debug("\n");
+ debug("cs2_bnds = 0x%08x\n",ddr->csbnds[2].csbnds);
+ debug("cs2_config = 0x%08x\n",ddr->cs_config[2]);
+
+ if (n_ranks == 2) {
+ ddr->csbnds[3].csbnds = ( (banksize(spd.row_dens) >> 8)
+ | ((banksize(spd.row_dens) >> 23) - 1) );
+ ddr->cs_config[3] = ( 1<<31
+ | (odt_rd_cfg << 20)
+ | (odt_wr_cfg << 16)
+ | ((spd.nbanks == 8 ? 1 : 0) << 14)
+ | ((spd.nrow_addr - 12) << 8)
+ | (spd.ncol_addr - 8) );
+ debug("cs3_bnds = 0x%08x\n",ddr->csbnds[3].csbnds);
+ debug("cs3_config = 0x%08x\n",ddr->cs_config[3]);
+ }
+#endif
+
+ /*
+ * Figure out memory size in Megabytes.
+ */
+ memsize = n_ranks * banksize(spd.row_dens) / 0x100000;
+
+ /*
+ * First supported LAW size is 16M, at LAWAR_SIZE_16M == 23.
+ */
+ law_size = 19 + __ilog2(memsize);
+
+ /*
+ * Set up LAWBAR for all of DDR.
+ */
+ ecm->bar = CONFIG_SYS_DDR_SDRAM_BASE & 0xfffff000;
+ ecm->ar = (LAWAR_EN | LAWAR_TRGT_IF_DDR | (LAWAR_SIZE & law_size));
+ debug("DDR:bar=0x%08x\n", ecm->bar);
+ debug("DDR:ar=0x%08x\n", ecm->ar);
+
+ /*
+ * Find the largest CAS by locating the highest 1 bit
+ * in the spd.cas_lat field. Translate it to a DDR
+ * controller field value:
+ *
+ * CAS Lat DDR I DDR II Ctrl
+ * Clocks SPD Bit SPD Bit Value
+ * ------- ------- ------- -----
+ * 1.0 0 0001
+ * 1.5 1 0010
+ * 2.0 2 2 0011
+ * 2.5 3 0100
+ * 3.0 4 3 0101
+ * 3.5 5 0110
+ * 4.0 6 4 0111
+ * 4.5 1000
+ * 5.0 5 1001
+ */
+ caslat = __ilog2(spd.cas_lat);
+ if ((spd.mem_type == SPD_MEMTYPE_DDR)
+ && (caslat > 6)) {
+ printf("DDR I: Invalid SPD CAS Latency: 0x%x.\n", spd.cas_lat);
+ return 0;
+ } else if (spd.mem_type == SPD_MEMTYPE_DDR2
+ && (caslat < 2 || caslat > 5)) {
+ printf("DDR II: Invalid SPD CAS Latency: 0x%x.\n",
+ spd.cas_lat);
+ return 0;
+ }
+ debug("DDR: caslat SPD bit is %d\n", caslat);
+
+ max_bus_clk = 1000 *10 / (((spd.clk_cycle & 0xF0) >> 4) * 10
+ + (spd.clk_cycle & 0x0f));
+ max_data_rate = max_bus_clk * 2;
+
+ debug("DDR:Module maximum data rate is: %d MHz\n", max_data_rate);
+
+ ddrc_clk = gd->mem_clk / 1000000;
+ effective_data_rate = 0;
+
+ if (max_data_rate >= 460) { /* it is DDR2-800, 667, 533 */
+ if (spd.cas_lat & 0x08)
+ caslat = 3;
+ else
+ caslat = 4;
+ if (ddrc_clk <= 460 && ddrc_clk > 350)
+ effective_data_rate = 400;
+ else if (ddrc_clk <=350 && ddrc_clk > 280)
+ effective_data_rate = 333;
+ else if (ddrc_clk <= 280 && ddrc_clk > 230)
+ effective_data_rate = 266;
+ else
+ effective_data_rate = 200;
+ } else if (max_data_rate >= 390 && max_data_rate < 460) { /* it is DDR 400 */
+ if (ddrc_clk <= 460 && ddrc_clk > 350) {
+ /* DDR controller clk at 350~460 */
+ effective_data_rate = 400; /* 5ns */
+ caslat = caslat;
+ } else if (ddrc_clk <= 350 && ddrc_clk > 280) {
+ /* DDR controller clk at 280~350 */
+ effective_data_rate = 333; /* 6ns */
+ if (spd.clk_cycle2 == 0x60)
+ caslat = caslat - 1;
+ else
+ caslat = caslat;
+ } else if (ddrc_clk <= 280 && ddrc_clk > 230) {
+ /* DDR controller clk at 230~280 */
+ effective_data_rate = 266; /* 7.5ns */
+ if (spd.clk_cycle3 == 0x75)
+ caslat = caslat - 2;
+ else if (spd.clk_cycle2 == 0x75)
+ caslat = caslat - 1;
+ else
+ caslat = caslat;
+ } else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+ /* DDR controller clk at 90~230 */
+ effective_data_rate = 200; /* 10ns */
+ if (spd.clk_cycle3 == 0xa0)
+ caslat = caslat - 2;
+ else if (spd.clk_cycle2 == 0xa0)
+ caslat = caslat - 1;
+ else
+ caslat = caslat;
+ }
+ } else if (max_data_rate >= 323) { /* it is DDR 333 */
+ if (ddrc_clk <= 350 && ddrc_clk > 280) {
+ /* DDR controller clk at 280~350 */
+ effective_data_rate = 333; /* 6ns */
+ caslat = caslat;
+ } else if (ddrc_clk <= 280 && ddrc_clk > 230) {
+ /* DDR controller clk at 230~280 */
+ effective_data_rate = 266; /* 7.5ns */
+ if (spd.clk_cycle2 == 0x75)
+ caslat = caslat - 1;
+ else
+ caslat = caslat;
+ } else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+ /* DDR controller clk at 90~230 */
+ effective_data_rate = 200; /* 10ns */
+ if (spd.clk_cycle3 == 0xa0)
+ caslat = caslat - 2;
+ else if (spd.clk_cycle2 == 0xa0)
+ caslat = caslat - 1;
+ else
+ caslat = caslat;
+ }
+ } else if (max_data_rate >= 256) { /* it is DDR 266 */
+ if (ddrc_clk <= 350 && ddrc_clk > 280) {
+ /* DDR controller clk at 280~350 */
+ printf("DDR: DDR controller freq is more than "
+ "max data rate of the module\n");
+ return 0;
+ } else if (ddrc_clk <= 280 && ddrc_clk > 230) {
+ /* DDR controller clk at 230~280 */
+ effective_data_rate = 266; /* 7.5ns */
+ caslat = caslat;
+ } else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+ /* DDR controller clk at 90~230 */
+ effective_data_rate = 200; /* 10ns */
+ if (spd.clk_cycle2 == 0xa0)
+ caslat = caslat - 1;
+ }
+ } else if (max_data_rate >= 190) { /* it is DDR 200 */
+ if (ddrc_clk <= 350 && ddrc_clk > 230) {
+ /* DDR controller clk at 230~350 */
+ printf("DDR: DDR controller freq is more than "
+ "max data rate of the module\n");
+ return 0;
+ } else if (ddrc_clk <= 230 && ddrc_clk > 90) {
+ /* DDR controller clk at 90~230 */
+ effective_data_rate = 200; /* 10ns */
+ caslat = caslat;
+ }
+ }
+
+ debug("DDR:Effective data rate is: %dMHz\n", effective_data_rate);
+ debug("DDR:The MSB 1 of CAS Latency is: %d\n", caslat);
+
+ /*
+ * Errata DDR6 work around: input enable 2 cycles earlier.
+ * including MPC834x Rev1.0/1.1 and MPC8360 Rev1.1/1.2.
+ */
+ if(PVR_MAJ(pvr) <= 1 && spd.mem_type == SPD_MEMTYPE_DDR){
+ if (caslat == 2)
+ ddr->debug_reg = 0x201c0000; /* CL=2 */
+ else if (caslat == 3)
+ ddr->debug_reg = 0x202c0000; /* CL=2.5 */
+ else if (caslat == 4)
+ ddr->debug_reg = 0x202c0000; /* CL=3.0 */
+
+ __asm__ __volatile__ ("sync");
+
+ debug("Errata DDR6 (debug_reg=0x%08x)\n", ddr->debug_reg);
+ }
+
+ /*
+ * Convert caslat clocks to DDR controller value.
+ * Force caslat_ctrl to be DDR Controller field-sized.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ caslat_ctrl = (caslat + 1) & 0x07;
+ } else {
+ caslat_ctrl = (2 * caslat - 1) & 0x0f;
+ }
+
+ debug("DDR: effective data rate is %d MHz\n", effective_data_rate);
+ debug("DDR: caslat SPD bit is %d, controller field is 0x%x\n",
+ caslat, caslat_ctrl);
+
+ /*
+ * Timing Config 0.
+ * Avoid writing for DDR I.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ unsigned char taxpd_clk = 8; /* By the book. */
+ unsigned char tmrd_clk = 2; /* By the book. */
+ unsigned char act_pd_exit = 2; /* Empirical? */
+ unsigned char pre_pd_exit = 6; /* Empirical? */
+
+ ddr->timing_cfg_0 = (0
+ | ((act_pd_exit & 0x7) << 20) /* ACT_PD_EXIT */
+ | ((pre_pd_exit & 0x7) << 16) /* PRE_PD_EXIT */
+ | ((taxpd_clk & 0xf) << 8) /* ODT_PD_EXIT */
+ | ((tmrd_clk & 0xf) << 0) /* MRS_CYC */
+ );
+ debug("DDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+ }
+
+ /*
+ * For DDR I, WRREC(Twr) and WRTORD(Twtr) are not in SPD,
+ * use conservative value.
+ * For DDR II, they are bytes 36 and 37, in quarter nanos.
+ */
+
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ twr_clk = 3; /* Clocks */
+ twtr_clk = 1; /* Clocks */
+ } else {
+ twr_clk = picos_to_clk(spd.twr * 250);
+ twtr_clk = picos_to_clk(spd.twtr * 250);
+ if (twtr_clk < 2)
+ twtr_clk = 2;
+ }
+
+ /*
+ * Calculate Trfc, in picos.
+ * DDR I: Byte 42 straight up in ns.
+ * DDR II: Byte 40 and 42 swizzled some, in ns.
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ trfc = spd.trfc * 1000; /* up to ps */
+ } else {
+ unsigned int byte40_table_ps[8] = {
+ 0,
+ 250,
+ 330,
+ 500,
+ 660,
+ 750,
+ 0,
+ 0
+ };
+
+ trfc = (((spd.trctrfc_ext & 0x1) * 256) + spd.trfc) * 1000
+ + byte40_table_ps[(spd.trctrfc_ext >> 1) & 0x7];
+ }
+ trfc_clk = picos_to_clk(trfc);
+
+ /*
+ * Trcd, Byte 29, from quarter nanos to ps and clocks.
+ */
+ trcd_clk = picos_to_clk(spd.trcd * 250) & 0x7;
+
+ /*
+ * Convert trfc_clk to DDR controller fields. DDR I should
+ * fit in the REFREC field (16-19) of TIMING_CFG_1, but the
+ * 83xx controller has an extended REFREC field of three bits.
+ * The controller automatically adds 8 clocks to this value,
+ * so preadjust it down 8 first before splitting it up.
+ */
+ trfc_low = (trfc_clk - 8) & 0xf;
+
+ ddr->timing_cfg_1 =
+ (((picos_to_clk(spd.trp * 250) & 0x07) << 28 ) | /* PRETOACT */
+ ((picos_to_clk(spd.tras * 1000) & 0x0f ) << 24 ) | /* ACTTOPRE */
+ (trcd_clk << 20 ) | /* ACTTORW */
+ (caslat_ctrl << 16 ) | /* CASLAT */
+ (trfc_low << 12 ) | /* REFEC */
+ ((twr_clk & 0x07) << 8) | /* WRRREC */
+ ((picos_to_clk(spd.trrd * 250) & 0x07) << 4) | /* ACTTOACT */
+ ((twtr_clk & 0x07) << 0) /* WRTORD */
+ );
+
+ /*
+ * Additive Latency
+ * For DDR I, 0.
+ * For DDR II, with ODT enabled, use "a value" less than ACTTORW,
+ * which comes from Trcd, and also note that:
+ * add_lat + caslat must be >= 4
+ */
+ add_lat = 0;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2
+ && (odt_wr_cfg || odt_rd_cfg)
+ && (caslat < 4)) {
+ add_lat = 4 - caslat;
+ if ((add_lat + caslat) < 4) {
+ add_lat = 0;
+ }
+ }
+
+ /*
+ * Write Data Delay
+ * Historically 0x2 == 4/8 clock delay.
+ * Empirically, 0x3 == 6/8 clock delay is suggested for DDR I 266.
+ */
+ wr_data_delay = 2;
+#ifdef CONFIG_SYS_DDR_WRITE_DATA_DELAY
+ wr_data_delay = CONFIG_SYS_DDR_WRITE_DATA_DELAY;
+#endif
+
+ /*
+ * Write Latency
+ * Read to Precharge
+ * Minimum CKE Pulse Width.
+ * Four Activate Window
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ /*
+ * This is a lie. It should really be 1, but if it is
+ * set to 1, bits overlap into the old controller's
+ * otherwise unused ACSM field. If we leave it 0, then
+ * the HW will magically treat it as 1 for DDR 1. Oh Yea.
+ */
+ wr_lat = 0;
+
+ trtp_clk = 2; /* By the book. */
+ cke_min_clk = 1; /* By the book. */
+ four_act = 1; /* By the book. */
+
+ } else {
+ wr_lat = caslat - 1;
+
+ /* Convert SPD value from quarter nanos to picos. */
+ trtp_clk = picos_to_clk(spd.trtp * 250);
+ if (trtp_clk < 2)
+ trtp_clk = 2;
+ trtp_clk += add_lat;
+
+ cke_min_clk = 3; /* By the book. */
+ four_act = picos_to_clk(37500); /* By the book. 1k pages? */
+ }
+
+ /*
+ * Empirically set ~MCAS-to-preamble override for DDR 2.
+ * Your milage will vary.
+ */
+ cpo = 0;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+#ifdef CONFIG_SYS_DDR_CPO
+ cpo = CONFIG_SYS_DDR_CPO;
+#else
+ if (effective_data_rate == 266) {
+ cpo = 0x4; /* READ_LAT + 1/2 */
+ } else if (effective_data_rate == 333) {
+ cpo = 0x6; /* READ_LAT + 1 */
+ } else if (effective_data_rate == 400) {
+ cpo = 0x7; /* READ_LAT + 5/4 */
+ } else {
+ /* Automatic calibration */
+ cpo = 0x1f;
+ }
+#endif
+ }
+
+ ddr->timing_cfg_2 = (0
+ | ((add_lat & 0x7) << 28) /* ADD_LAT */
+ | ((cpo & 0x1f) << 23) /* CPO */
+ | ((wr_lat & 0x7) << 19) /* WR_LAT */
+ | ((trtp_clk & 0x7) << 13) /* RD_TO_PRE */
+ | ((wr_data_delay & 0x7) << 10) /* WR_DATA_DELAY */
+ | ((cke_min_clk & 0x7) << 6) /* CKE_PLS */
+ | ((four_act & 0x1f) << 0) /* FOUR_ACT */
+ );
+
+ debug("DDR:timing_cfg_1=0x%08x\n", ddr->timing_cfg_1);
+ debug("DDR:timing_cfg_2=0x%08x\n", ddr->timing_cfg_2);
+
+ /* Check DIMM data bus width */
+ if (spd.dataw_lsb < 64) {
+ if (spd.mem_type == SPD_MEMTYPE_DDR)
+ burstlen = 0x03; /* 32 bit data bus, burst len is 8 */
+ else
+ burstlen = 0x02; /* 32 bit data bus, burst len is 4 */
+ debug("\n DDR DIMM: data bus width is 32 bit");
+ } else {
+ burstlen = 0x02; /* Others act as 64 bit bus, burst len is 4 */
+ debug("\n DDR DIMM: data bus width is 64 bit");
+ }
+
+ /* Is this an ECC DDR chip? */
+ if (spd.config == 0x02)
+ debug(" with ECC\n");
+ else
+ debug(" without ECC\n");
+
+ /* Burst length is always 4 for 64 bit data bus, 8 for 32 bit data bus,
+ Burst type is sequential
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR) {
+ switch (caslat) {
+ case 1:
+ ddr->sdram_mode = 0x50 | burstlen; /* CL=1.5 */
+ break;
+ case 2:
+ ddr->sdram_mode = 0x20 | burstlen; /* CL=2.0 */
+ break;
+ case 3:
+ ddr->sdram_mode = 0x60 | burstlen; /* CL=2.5 */
+ break;
+ case 4:
+ ddr->sdram_mode = 0x30 | burstlen; /* CL=3.0 */
+ break;
+ default:
+ printf("DDR:only CL 1.5, 2.0, 2.5, 3.0 is supported\n");
+ return 0;
+ }
+ } else {
+ mode_odt_enable = 0x0; /* Default disabled */
+ if (odt_wr_cfg || odt_rd_cfg) {
+ /*
+ * Bits 6 and 2 in Extended MRS(1)
+ * Bit 2 == 0x04 == 75 Ohm, with 2 DIMM modules.
+ * Bit 6 == 0x40 == 150 Ohm, with 1 DIMM module.
+ */
+ mode_odt_enable = 0x40; /* 150 Ohm */
+ }
+
+ ddr->sdram_mode =
+ (0
+ | (1 << (16 + 10)) /* DQS Differential disable */
+#ifdef CONFIG_SYS_DDR_MODE_WEAK
+ | (1 << (16 + 1)) /* weak driver (~60%) */
+#endif
+ | (add_lat << (16 + 3)) /* Additive Latency in EMRS1 */
+ | (mode_odt_enable << 16) /* ODT Enable in EMRS1 */
+ | ((twr_clk - 1) << 9) /* Write Recovery Autopre */
+ | (caslat << 4) /* caslat */
+ | (burstlen << 0) /* Burst length */
+ );
+ }
+ debug("DDR:sdram_mode=0x%08x\n", ddr->sdram_mode);
+
+ /*
+ * Clear EMRS2 and EMRS3.
+ */
+ ddr->sdram_mode2 = 0;
+ debug("DDR: sdram_mode2 = 0x%08x\n", ddr->sdram_mode2);
+
+ switch (spd.refresh) {
+ case 0x00:
+ case 0x80:
+ refresh_clk = picos_to_clk(15625000);
+ break;
+ case 0x01:
+ case 0x81:
+ refresh_clk = picos_to_clk(3900000);
+ break;
+ case 0x02:
+ case 0x82:
+ refresh_clk = picos_to_clk(7800000);
+ break;
+ case 0x03:
+ case 0x83:
+ refresh_clk = picos_to_clk(31300000);
+ break;
+ case 0x04:
+ case 0x84:
+ refresh_clk = picos_to_clk(62500000);
+ break;
+ case 0x05:
+ case 0x85:
+ refresh_clk = picos_to_clk(125000000);
+ break;
+ default:
+ refresh_clk = 0x512;
+ break;
+ }
+
+ /*
+ * Set BSTOPRE to 0x100 for page mode
+ * If auto-charge is used, set BSTOPRE = 0
+ */
+ ddr->sdram_interval = ((refresh_clk & 0x3fff) << 16) | 0x100;
+ debug("DDR:sdram_interval=0x%08x\n", ddr->sdram_interval);
+
+ /*
+ * SDRAM Cfg 2
+ */
+ odt_cfg = 0;
+#ifndef CONFIG_NEVER_ASSERT_ODT_TO_CPU
+ if (odt_rd_cfg | odt_wr_cfg) {
+ odt_cfg = 0x2; /* ODT to IOs during reads */
+ }
+#endif
+ if (spd.mem_type == SPD_MEMTYPE_DDR2) {
+ ddr->sdram_cfg2 = (0
+ | (0 << 26) /* True DQS */
+ | (odt_cfg << 21) /* ODT only read */
+ | (1 << 12) /* 1 refresh at a time */
+ );
+
+ debug("DDR: sdram_cfg2 = 0x%08x\n", ddr->sdram_cfg2);
+ }
+
+#ifdef CONFIG_SYS_DDR_SDRAM_CLK_CNTL /* Optional platform specific value */
+ ddr->sdram_clk_cntl = CONFIG_SYS_DDR_SDRAM_CLK_CNTL;
+#endif
+ debug("DDR:sdram_clk_cntl=0x%08x\n", ddr->sdram_clk_cntl);
+
+ asm("sync;isync");
+
+ udelay(600);
+
+ /*
+ * Figure out the settings for the sdram_cfg register. Build up
+ * the value in 'sdram_cfg' before writing since the write into
+ * the register will actually enable the memory controller, and all
+ * settings must be done before enabling.
+ *
+ * sdram_cfg[0] = 1 (ddr sdram logic enable)
+ * sdram_cfg[1] = 1 (self-refresh-enable)
+ * sdram_cfg[5:7] = (SDRAM type = DDR SDRAM)
+ * 010 DDR 1 SDRAM
+ * 011 DDR 2 SDRAM
+ * sdram_cfg[12] = 0 (32_BE =0 , 64 bit bus mode)
+ * sdram_cfg[13] = 0 (8_BE =0, 4-beat bursts)
+ */
+ if (spd.mem_type == SPD_MEMTYPE_DDR)
+ sdram_type = SDRAM_CFG_SDRAM_TYPE_DDR1;
+ else
+ sdram_type = SDRAM_CFG_SDRAM_TYPE_DDR2;
+
+ sdram_cfg = (0
+ | SDRAM_CFG_MEM_EN /* DDR enable */
+ | SDRAM_CFG_SREN /* Self refresh */
+ | sdram_type /* SDRAM type */
+ );
+
+ /* sdram_cfg[3] = RD_EN - registered DIMM enable */
+ if (spd.mod_attr & 0x02)
+ sdram_cfg |= SDRAM_CFG_RD_EN;
+
+ /* The DIMM is 32bit width */
+ if (spd.dataw_lsb < 64) {
+ if (spd.mem_type == SPD_MEMTYPE_DDR)
+ sdram_cfg |= SDRAM_CFG_32_BE | SDRAM_CFG_8_BE;
+ if (spd.mem_type == SPD_MEMTYPE_DDR2)
+ sdram_cfg |= SDRAM_CFG_32_BE;
+ }
+
+ ddrc_ecc_enable = 0;
+
+#if defined(CONFIG_DDR_ECC)
+ /* Enable ECC with sdram_cfg[2] */
+ if (spd.config == 0x02) {
+ sdram_cfg |= 0x20000000;
+ ddrc_ecc_enable = 1;
+ /* disable error detection */
+ ddr->err_disable = ~ECC_ERROR_ENABLE;
+ /* set single bit error threshold to maximum value,
+ * reset counter to zero */
+ ddr->err_sbe = (255 << ECC_ERROR_MAN_SBET_SHIFT) |
+ (0 << ECC_ERROR_MAN_SBEC_SHIFT);
+ }
+
+ debug("DDR:err_disable=0x%08x\n", ddr->err_disable);
+ debug("DDR:err_sbe=0x%08x\n", ddr->err_sbe);
+#endif
+ debug(" DDRC ECC mode: %s\n", ddrc_ecc_enable ? "ON":"OFF");
+
+#if defined(CONFIG_DDR_2T_TIMING)
+ /*
+ * Enable 2T timing by setting sdram_cfg[16].
+ */
+ sdram_cfg |= SDRAM_CFG_2T_EN;
+#endif
+ /* Enable controller, and GO! */
+ ddr->sdram_cfg = sdram_cfg;
+ asm("sync;isync");
+ udelay(500);
+
+ debug("DDR:sdram_cfg=0x%08x\n", ddr->sdram_cfg);
+ return memsize; /*in MBytes*/
+}
+#endif /* CONFIG_SPD_EEPROM */
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+/*
+ * Use timebase counter, get_timer() is not availabe
+ * at this point of initialization yet.
+ */
+static __inline__ unsigned long get_tbms (void)
+{
+ unsigned long tbl;
+ unsigned long tbu1, tbu2;
+ unsigned long ms;
+ unsigned long long tmp;
+
+ ulong tbclk = get_tbclk();
+
+ /* get the timebase ticks */
+ do {
+ asm volatile ("mftbu %0":"=r" (tbu1):);
+ asm volatile ("mftb %0":"=r" (tbl):);
+ asm volatile ("mftbu %0":"=r" (tbu2):);
+ } while (tbu1 != tbu2);
+
+ /* convert ticks to ms */
+ tmp = (unsigned long long)(tbu1);
+ tmp = (tmp << 32);
+ tmp += (unsigned long long)(tbl);
+ ms = tmp/(tbclk/1000);
+
+ return ms;
+}
+
+/*
+ * Initialize all of memory for ECC, then enable errors.
+ */
+void ddr_enable_ecc(unsigned int dram_size)
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile ddr83xx_t *ddr= &immap->ddr;
+ unsigned long t_start, t_end;
+ register u64 *p;
+ register uint size;
+ unsigned int pattern[2];
+
+ icache_enable();
+ t_start = get_tbms();
+ pattern[0] = 0xdeadbeef;
+ pattern[1] = 0xdeadbeef;
+
+#if defined(CONFIG_DDR_ECC_INIT_VIA_DMA)
+ dma_meminit(pattern[0], dram_size);
+#else
+ debug("ddr init: CPU FP write method\n");
+ size = dram_size;
+ for (p = 0; p < (u64*)(size); p++) {
+ ppcDWstore((u32*)p, pattern);
+ }
+ __asm__ __volatile__ ("sync");
+#endif
+
+ t_end = get_tbms();
+ icache_disable();
+
+ debug("\nREADY!!\n");
+ debug("ddr init duration: %ld ms\n", t_end - t_start);
+
+ /* Clear All ECC Errors */
+ if ((ddr->err_detect & ECC_ERROR_DETECT_MME) == ECC_ERROR_DETECT_MME)
+ ddr->err_detect |= ECC_ERROR_DETECT_MME;
+ if ((ddr->err_detect & ECC_ERROR_DETECT_MBE) == ECC_ERROR_DETECT_MBE)
+ ddr->err_detect |= ECC_ERROR_DETECT_MBE;
+ if ((ddr->err_detect & ECC_ERROR_DETECT_SBE) == ECC_ERROR_DETECT_SBE)
+ ddr->err_detect |= ECC_ERROR_DETECT_SBE;
+ if ((ddr->err_detect & ECC_ERROR_DETECT_MSE) == ECC_ERROR_DETECT_MSE)
+ ddr->err_detect |= ECC_ERROR_DETECT_MSE;
+
+ /* Disable ECC-Interrupts */
+ ddr->err_int_en &= ECC_ERR_INT_DISABLE;
+
+ /* Enable errors for ECC */
+ ddr->err_disable &= ECC_ERROR_ENABLE;
+
+ __asm__ __volatile__ ("sync");
+ __asm__ __volatile__ ("isync");
+}
+#endif /* CONFIG_DDR_ECC */
diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
new file mode 100644
index 0000000..6be0e3a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/speed.c
@@ -0,0 +1,609 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+#include <command.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* ----------------------------------------------------------------- */
+
+typedef enum {
+ _unk,
+ _off,
+ _byp,
+ _x8,
+ _x4,
+ _x2,
+ _x1,
+ _1x,
+ _1_5x,
+ _2x,
+ _2_5x,
+ _3x
+} mult_t;
+
+typedef struct {
+ mult_t core_csb_ratio;
+ mult_t vco_divider;
+} corecnf_t;
+
+static corecnf_t corecnf_tab[] = {
+ {_byp, _byp}, /* 0x00 */
+ {_byp, _byp}, /* 0x01 */
+ {_byp, _byp}, /* 0x02 */
+ {_byp, _byp}, /* 0x03 */
+ {_byp, _byp}, /* 0x04 */
+ {_byp, _byp}, /* 0x05 */
+ {_byp, _byp}, /* 0x06 */
+ {_byp, _byp}, /* 0x07 */
+ {_1x, _x2}, /* 0x08 */
+ {_1x, _x4}, /* 0x09 */
+ {_1x, _x8}, /* 0x0A */
+ {_1x, _x8}, /* 0x0B */
+ {_1_5x, _x2}, /* 0x0C */
+ {_1_5x, _x4}, /* 0x0D */
+ {_1_5x, _x8}, /* 0x0E */
+ {_1_5x, _x8}, /* 0x0F */
+ {_2x, _x2}, /* 0x10 */
+ {_2x, _x4}, /* 0x11 */
+ {_2x, _x8}, /* 0x12 */
+ {_2x, _x8}, /* 0x13 */
+ {_2_5x, _x2}, /* 0x14 */
+ {_2_5x, _x4}, /* 0x15 */
+ {_2_5x, _x8}, /* 0x16 */
+ {_2_5x, _x8}, /* 0x17 */
+ {_3x, _x2}, /* 0x18 */
+ {_3x, _x4}, /* 0x19 */
+ {_3x, _x8}, /* 0x1A */
+ {_3x, _x8}, /* 0x1B */
+};
+
+/* ----------------------------------------------------------------- */
+
+/*
+ *
+ */
+int get_clocks(void)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ u32 pci_sync_in;
+ u8 spmf;
+ u8 clkin_div;
+ u32 sccr;
+ u32 corecnf_tab_index;
+ u8 corepll;
+ u32 lcrr;
+
+ u32 csb_clk;
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+ u32 tsec1_clk;
+ u32 tsec2_clk;
+ u32 usbdr_clk;
+#elif defined(CONFIG_MPC8309)
+ u32 usbdr_clk;
+#endif
+#ifdef CONFIG_MPC834x
+ u32 usbmph_clk;
+#endif
+ u32 core_clk;
+ u32 i2c1_clk;
+#if !defined(CONFIG_MPC832x)
+ u32 i2c2_clk;
+#endif
+#if defined(CONFIG_MPC8315)
+ u32 tdm_clk;
+#endif
+#if defined(CONFIG_FSL_ESDHC)
+ u32 sdhc_clk;
+#endif
+#if !defined(CONFIG_MPC8309)
+ u32 enc_clk;
+#endif
+ u32 lbiu_clk;
+ u32 lclk_clk;
+ u32 mem_clk;
+#if defined(CONFIG_MPC8360)
+ u32 mem_sec_clk;
+#endif
+#if defined(CONFIG_QE)
+ u32 qepmf;
+ u32 qepdf;
+ u32 qe_clk;
+ u32 brg_clk;
+#endif
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC837x)
+ u32 pciexp1_clk;
+ u32 pciexp2_clk;
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+ u32 sata_clk;
+#endif
+
+ if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32) im)
+ return -1;
+
+ clkin_div = ((im->clk.spmr & SPMR_CKID) >> SPMR_CKID_SHIFT);
+
+ if (im->reset.rcwh & HRCWH_PCI_HOST) {
+#if defined(CONFIG_83XX_CLKIN)
+ pci_sync_in = CONFIG_83XX_CLKIN / (1 + clkin_div);
+#else
+ pci_sync_in = 0xDEADBEEF;
+#endif
+ } else {
+#if defined(CONFIG_83XX_PCICLK)
+ pci_sync_in = CONFIG_83XX_PCICLK;
+#else
+ pci_sync_in = 0xDEADBEEF;
+#endif
+ }
+
+ spmf = (im->clk.spmr & SPMR_SPMF) >> SPMR_SPMF_SHIFT;
+ csb_clk = pci_sync_in * (1 + clkin_div) * spmf;
+
+ sccr = im->clk.sccr;
+
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+ switch ((sccr & SCCR_TSEC1CM) >> SCCR_TSEC1CM_SHIFT) {
+ case 0:
+ tsec1_clk = 0;
+ break;
+ case 1:
+ tsec1_clk = csb_clk;
+ break;
+ case 2:
+ tsec1_clk = csb_clk / 2;
+ break;
+ case 3:
+ tsec1_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_TSEC1CM value */
+ return -2;
+ }
+#endif
+
+#if defined(CONFIG_MPC830x) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+ switch ((sccr & SCCR_USBDRCM) >> SCCR_USBDRCM_SHIFT) {
+ case 0:
+ usbdr_clk = 0;
+ break;
+ case 1:
+ usbdr_clk = csb_clk;
+ break;
+ case 2:
+ usbdr_clk = csb_clk / 2;
+ break;
+ case 3:
+ usbdr_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_USBDRCM value */
+ return -3;
+ }
+#endif
+
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC8315) || \
+ defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+ switch ((sccr & SCCR_TSEC2CM) >> SCCR_TSEC2CM_SHIFT) {
+ case 0:
+ tsec2_clk = 0;
+ break;
+ case 1:
+ tsec2_clk = csb_clk;
+ break;
+ case 2:
+ tsec2_clk = csb_clk / 2;
+ break;
+ case 3:
+ tsec2_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_TSEC2CM value */
+ return -4;
+ }
+#elif defined(CONFIG_MPC8313)
+ tsec2_clk = tsec1_clk;
+
+ if (!(sccr & SCCR_TSEC1ON))
+ tsec1_clk = 0;
+ if (!(sccr & SCCR_TSEC2ON))
+ tsec2_clk = 0;
+#endif
+
+#if defined(CONFIG_MPC834x)
+ switch ((sccr & SCCR_USBMPHCM) >> SCCR_USBMPHCM_SHIFT) {
+ case 0:
+ usbmph_clk = 0;
+ break;
+ case 1:
+ usbmph_clk = csb_clk;
+ break;
+ case 2:
+ usbmph_clk = csb_clk / 2;
+ break;
+ case 3:
+ usbmph_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_USBMPHCM value */
+ return -5;
+ }
+
+ if (usbmph_clk != 0 && usbdr_clk != 0 && usbmph_clk != usbdr_clk) {
+ /* if USB MPH clock is not disabled and
+ * USB DR clock is not disabled then
+ * USB MPH & USB DR must have the same rate
+ */
+ return -6;
+ }
+#endif
+#if !defined(CONFIG_MPC8309)
+ switch ((sccr & SCCR_ENCCM) >> SCCR_ENCCM_SHIFT) {
+ case 0:
+ enc_clk = 0;
+ break;
+ case 1:
+ enc_clk = csb_clk;
+ break;
+ case 2:
+ enc_clk = csb_clk / 2;
+ break;
+ case 3:
+ enc_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_ENCCM value */
+ return -7;
+ }
+#endif
+
+#if defined(CONFIG_FSL_ESDHC)
+ switch ((sccr & SCCR_SDHCCM) >> SCCR_SDHCCM_SHIFT) {
+ case 0:
+ sdhc_clk = 0;
+ break;
+ case 1:
+ sdhc_clk = csb_clk;
+ break;
+ case 2:
+ sdhc_clk = csb_clk / 2;
+ break;
+ case 3:
+ sdhc_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_SDHCCM value */
+ return -8;
+ }
+#endif
+#if defined(CONFIG_MPC8315)
+ switch ((sccr & SCCR_TDMCM) >> SCCR_TDMCM_SHIFT) {
+ case 0:
+ tdm_clk = 0;
+ break;
+ case 1:
+ tdm_clk = csb_clk;
+ break;
+ case 2:
+ tdm_clk = csb_clk / 2;
+ break;
+ case 3:
+ tdm_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_TDMCM value */
+ return -8;
+ }
+#endif
+
+#if defined(CONFIG_MPC834x)
+ i2c1_clk = tsec2_clk;
+#elif defined(CONFIG_MPC8360)
+ i2c1_clk = csb_clk;
+#elif defined(CONFIG_MPC832x)
+ i2c1_clk = enc_clk;
+#elif defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x)
+ i2c1_clk = enc_clk;
+#elif defined(CONFIG_FSL_ESDHC)
+ i2c1_clk = sdhc_clk;
+#elif defined(CONFIG_MPC837x)
+ i2c1_clk = enc_clk;
+#elif defined(CONFIG_MPC8309)
+ i2c1_clk = csb_clk;
+#endif
+#if !defined(CONFIG_MPC832x)
+ i2c2_clk = csb_clk; /* i2c-2 clk is equal to csb clk */
+#endif
+
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC837x)
+ switch ((sccr & SCCR_PCIEXP1CM) >> SCCR_PCIEXP1CM_SHIFT) {
+ case 0:
+ pciexp1_clk = 0;
+ break;
+ case 1:
+ pciexp1_clk = csb_clk;
+ break;
+ case 2:
+ pciexp1_clk = csb_clk / 2;
+ break;
+ case 3:
+ pciexp1_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_PCIEXP1CM value */
+ return -9;
+ }
+
+ switch ((sccr & SCCR_PCIEXP2CM) >> SCCR_PCIEXP2CM_SHIFT) {
+ case 0:
+ pciexp2_clk = 0;
+ break;
+ case 1:
+ pciexp2_clk = csb_clk;
+ break;
+ case 2:
+ pciexp2_clk = csb_clk / 2;
+ break;
+ case 3:
+ pciexp2_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_PCIEXP2CM value */
+ return -10;
+ }
+#endif
+
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+ switch ((sccr & SCCR_SATA1CM) >> SCCR_SATA1CM_SHIFT) {
+ case 0:
+ sata_clk = 0;
+ break;
+ case 1:
+ sata_clk = csb_clk;
+ break;
+ case 2:
+ sata_clk = csb_clk / 2;
+ break;
+ case 3:
+ sata_clk = csb_clk / 3;
+ break;
+ default:
+ /* unkown SCCR_SATACM value */
+ return -11;
+ }
+#endif
+
+ lbiu_clk = csb_clk *
+ (1 + ((im->clk.spmr & SPMR_LBIUCM) >> SPMR_LBIUCM_SHIFT));
+ lcrr = (im->im_lbc.lcrr & LCRR_CLKDIV) >> LCRR_CLKDIV_SHIFT;
+ switch (lcrr) {
+ case 2:
+ case 4:
+ case 8:
+ lclk_clk = lbiu_clk / lcrr;
+ break;
+ default:
+ /* unknown lcrr */
+ return -12;
+ }
+
+ mem_clk = csb_clk *
+ (1 + ((im->clk.spmr & SPMR_DDRCM) >> SPMR_DDRCM_SHIFT));
+ corepll = (im->clk.spmr & SPMR_COREPLL) >> SPMR_COREPLL_SHIFT;
+
+#if defined(CONFIG_MPC8360)
+ mem_sec_clk = csb_clk * (1 +
+ ((im->clk.spmr & SPMR_LBIUCM) >> SPMR_LBIUCM_SHIFT));
+#endif
+
+ corecnf_tab_index = ((corepll & 0x1F) << 2) | ((corepll & 0x60) >> 5);
+ if (corecnf_tab_index > (sizeof(corecnf_tab) / sizeof(corecnf_t))) {
+ /* corecnf_tab_index is too high, possibly worng value */
+ return -11;
+ }
+ switch (corecnf_tab[corecnf_tab_index].core_csb_ratio) {
+ case _byp:
+ case _x1:
+ case _1x:
+ core_clk = csb_clk;
+ break;
+ case _1_5x:
+ core_clk = (3 * csb_clk) / 2;
+ break;
+ case _2x:
+ core_clk = 2 * csb_clk;
+ break;
+ case _2_5x:
+ core_clk = (5 * csb_clk) / 2;
+ break;
+ case _3x:
+ core_clk = 3 * csb_clk;
+ break;
+ default:
+ /* unkown core to csb ratio */
+ return -13;
+ }
+
+#if defined(CONFIG_QE)
+ qepmf = (im->clk.spmr & SPMR_CEPMF) >> SPMR_CEPMF_SHIFT;
+ qepdf = (im->clk.spmr & SPMR_CEPDF) >> SPMR_CEPDF_SHIFT;
+ qe_clk = (pci_sync_in * qepmf) / (1 + qepdf);
+ brg_clk = qe_clk / 2;
+#endif
+
+ gd->arch.csb_clk = csb_clk;
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+ gd->arch.tsec1_clk = tsec1_clk;
+ gd->arch.tsec2_clk = tsec2_clk;
+ gd->arch.usbdr_clk = usbdr_clk;
+#elif defined(CONFIG_MPC8309)
+ gd->arch.usbdr_clk = usbdr_clk;
+#endif
+#if defined(CONFIG_MPC834x)
+ gd->arch.usbmph_clk = usbmph_clk;
+#endif
+#if defined(CONFIG_MPC8315)
+ gd->arch.tdm_clk = tdm_clk;
+#endif
+#if defined(CONFIG_FSL_ESDHC)
+ gd->arch.sdhc_clk = sdhc_clk;
+#endif
+ gd->arch.core_clk = core_clk;
+ gd->arch.i2c1_clk = i2c1_clk;
+#if !defined(CONFIG_MPC832x)
+ gd->arch.i2c2_clk = i2c2_clk;
+#endif
+#if !defined(CONFIG_MPC8309)
+ gd->arch.enc_clk = enc_clk;
+#endif
+ gd->arch.lbiu_clk = lbiu_clk;
+ gd->arch.lclk_clk = lclk_clk;
+ gd->mem_clk = mem_clk;
+#if defined(CONFIG_MPC8360)
+ gd->arch.mem_sec_clk = mem_sec_clk;
+#endif
+#if defined(CONFIG_QE)
+ gd->arch.qe_clk = qe_clk;
+ gd->arch.brg_clk = brg_clk;
+#endif
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC837x)
+ gd->arch.pciexp1_clk = pciexp1_clk;
+ gd->arch.pciexp2_clk = pciexp2_clk;
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+ gd->arch.sata_clk = sata_clk;
+#endif
+ gd->pci_clk = pci_sync_in;
+ gd->cpu_clk = gd->arch.core_clk;
+ gd->bus_clk = gd->arch.csb_clk;
+ return 0;
+
+}
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq(ulong dummy)
+{
+ return gd->arch.csb_clk;
+}
+
+/********************************************
+ * get_ddr_freq
+ * return ddr bus freq in Hz
+ *********************************************/
+ulong get_ddr_freq(ulong dummy)
+{
+ return gd->mem_clk;
+}
+
+static int do_clocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ char buf[32];
+
+ printf("Clock configuration:\n");
+ printf(" Core: %-4s MHz\n",
+ strmhz(buf, gd->arch.core_clk));
+ printf(" Coherent System Bus: %-4s MHz\n",
+ strmhz(buf, gd->arch.csb_clk));
+#if defined(CONFIG_QE)
+ printf(" QE: %-4s MHz\n",
+ strmhz(buf, gd->arch.qe_clk));
+ printf(" BRG: %-4s MHz\n",
+ strmhz(buf, gd->arch.brg_clk));
+#endif
+ printf(" Local Bus Controller:%-4s MHz\n",
+ strmhz(buf, gd->arch.lbiu_clk));
+ printf(" Local Bus: %-4s MHz\n",
+ strmhz(buf, gd->arch.lclk_clk));
+ printf(" DDR: %-4s MHz\n", strmhz(buf, gd->mem_clk));
+#if defined(CONFIG_MPC8360)
+ printf(" DDR Secondary: %-4s MHz\n",
+ strmhz(buf, gd->arch.mem_sec_clk));
+#endif
+#if !defined(CONFIG_MPC8309)
+ printf(" SEC: %-4s MHz\n",
+ strmhz(buf, gd->arch.enc_clk));
+#endif
+ printf(" I2C1: %-4s MHz\n",
+ strmhz(buf, gd->arch.i2c1_clk));
+#if !defined(CONFIG_MPC832x)
+ printf(" I2C2: %-4s MHz\n",
+ strmhz(buf, gd->arch.i2c2_clk));
+#endif
+#if defined(CONFIG_MPC8315)
+ printf(" TDM: %-4s MHz\n",
+ strmhz(buf, gd->arch.tdm_clk));
+#endif
+#if defined(CONFIG_FSL_ESDHC)
+ printf(" SDHC: %-4s MHz\n",
+ strmhz(buf, gd->arch.sdhc_clk));
+#endif
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+ printf(" TSEC1: %-4s MHz\n",
+ strmhz(buf, gd->arch.tsec1_clk));
+ printf(" TSEC2: %-4s MHz\n",
+ strmhz(buf, gd->arch.tsec2_clk));
+ printf(" USB DR: %-4s MHz\n",
+ strmhz(buf, gd->arch.usbdr_clk));
+#elif defined(CONFIG_MPC8309)
+ printf(" USB DR: %-4s MHz\n",
+ strmhz(buf, gd->arch.usbdr_clk));
+#endif
+#if defined(CONFIG_MPC834x)
+ printf(" USB MPH: %-4s MHz\n",
+ strmhz(buf, gd->arch.usbmph_clk));
+#endif
+#if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC837x)
+ printf(" PCIEXP1: %-4s MHz\n",
+ strmhz(buf, gd->arch.pciexp1_clk));
+ printf(" PCIEXP2: %-4s MHz\n",
+ strmhz(buf, gd->arch.pciexp2_clk));
+#endif
+#if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+ printf(" SATA: %-4s MHz\n",
+ strmhz(buf, gd->arch.sata_clk));
+#endif
+ return 0;
+}
+
+U_BOOT_CMD(clocks, 1, 0, do_clocks,
+ "print clock configuration",
+ " clocks"
+);
diff --git a/arch/powerpc/cpu/mpc83xx/spl_minimal.c b/arch/powerpc/cpu/mpc83xx/spl_minimal.c
new file mode 100644
index 0000000..d1648b7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/spl_minimal.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2008 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc83xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * im)
+{
+ int i;
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ for (i = 0; i < sizeof(gd_t); i++)
+ ((char *)gd)[i] = 0;
+
+ /* system performance tweaking */
+
+#ifdef CONFIG_SYS_ACR_PIPE_DEP
+ /* Arbiter pipeline depth */
+ im->arbiter.acr = (im->arbiter.acr & ~ACR_PIPE_DEP) |
+ (CONFIG_SYS_ACR_PIPE_DEP << ACR_PIPE_DEP_SHIFT);
+#endif
+
+#ifdef CONFIG_SYS_ACR_RPTCNT
+ /* Arbiter repeat count */
+ im->arbiter.acr = (im->arbiter.acr & ~(ACR_RPTCNT)) |
+ (CONFIG_SYS_ACR_RPTCNT << ACR_RPTCNT_SHIFT);
+#endif
+
+#ifdef CONFIG_SYS_SPCR_OPT
+ /* Optimize transactions between CSB and other devices */
+ im->sysconf.spcr = (im->sysconf.spcr & ~SPCR_OPT) |
+ (CONFIG_SYS_SPCR_OPT << SPCR_OPT_SHIFT);
+#endif
+
+ /* Enable Time Base & Decrimenter (so we will have udelay()) */
+ im->sysconf.spcr |= SPCR_TBEN;
+
+ /* DDR control driver register */
+#ifdef CONFIG_SYS_DDRCDR
+ im->sysconf.ddrcdr = CONFIG_SYS_DDRCDR;
+#endif
+ /* Output buffer impedance register */
+#ifdef CONFIG_SYS_OBIR
+ im->sysconf.obir = CONFIG_SYS_OBIR;
+#endif
+
+ /*
+ * Memory Controller:
+ */
+
+ /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary
+ * addresses - these have to be modified later when FLASH size
+ * has been determined
+ */
+
+#if defined(CONFIG_SYS_NAND_BR_PRELIM) \
+ && defined(CONFIG_SYS_NAND_OR_PRELIM) \
+ && defined(CONFIG_SYS_NAND_LBLAWBAR_PRELIM) \
+ && defined(CONFIG_SYS_NAND_LBLAWAR_PRELIM)
+ set_lbc_br(0, CONFIG_SYS_NAND_BR_PRELIM);
+ set_lbc_or(0, CONFIG_SYS_NAND_OR_PRELIM);
+ im->sysconf.lblaw[0].bar = CONFIG_SYS_NAND_LBLAWBAR_PRELIM;
+ im->sysconf.lblaw[0].ar = CONFIG_SYS_NAND_LBLAWAR_PRELIM;
+#else
+#error CONFIG_SYS_NAND_BR_PRELIM, CONFIG_SYS_NAND_OR_PRELIM, CONFIG_SYS_NAND_LBLAWBAR_PRELIM & CONFIG_SYS_NAND_LBLAWAR_PRELIM must be defined
+#endif
+}
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ */
+unsigned long get_tbclk(void)
+{
+ return (gd->bus_clk + 3L) / 4L;
+}
+
+void puts(const char *str)
+{
+ while (*str)
+ putc(*str++);
+}
diff --git a/arch/powerpc/cpu/mpc83xx/start.S b/arch/powerpc/cpu/mpc83xx/start.S
new file mode 100644
index 0000000..1bfc971
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/start.S
@@ -0,0 +1,1211 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006, 2008.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * U-Boot - Startup Code for MPC83xx PowerPC based Embedded Boards
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc83xx.h>
+#ifndef CONFIG_IDENT_STRING
+#define CONFIG_IDENT_STRING "MPC83XX"
+#endif
+#include <version.h>
+
+#define CONFIG_83XX 1 /* needed for Linux kernel header files*/
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/* We don't want the MMU yet.
+ */
+#undef MSR_KERNEL
+
+/*
+ * Floating Point enable, Machine Check and Recoverable Interr.
+ */
+#ifdef DEBUG
+#define MSR_KERNEL (MSR_FP|MSR_RI)
+#else
+#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
+#endif
+
+#if defined(CONFIG_NAND_SPL) || \
+ (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_INIT_MINIMAL))
+#define MINIMAL_SPL
+#endif
+
+#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_NAND_SPL) && \
+ !defined(CONFIG_SYS_RAMBOOT)
+#define CONFIG_SYS_FLASHBOOT
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(__bss_start)
+ GOT_ENTRY(__bss_end)
+
+#ifndef MINIMAL_SPL
+ GOT_ENTRY(_FIXUP_TABLE_)
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+#endif
+ END_GOT
+
+/*
+ * The Hard Reset Configuration Word (HRCW) table is in the first 64
+ * (0x40) bytes of flash. It has 8 bytes, but each byte is repeated 8
+ * times so the processor can fetch it out of flash whether the flash
+ * is 8, 16, 32, or 64 bits wide (hardware trickery).
+ */
+ .text
+#define _HRCW_TABLE_ENTRY(w) \
+ .fill 8,1,(((w)>>24)&0xff); \
+ .fill 8,1,(((w)>>16)&0xff); \
+ .fill 8,1,(((w)>> 8)&0xff); \
+ .fill 8,1,(((w) )&0xff)
+
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_LOW)
+ _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_HIGH)
+
+/*
+ * Magic number and version string - put it after the HRCW since it
+ * cannot be first in flash like it is in many other processors.
+ */
+ .long 0x27051956 /* U-Boot Magic Number */
+
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ .align 2
+
+ .globl enable_addr_trans
+enable_addr_trans:
+ /* enable address translation */
+ mfmsr r5
+ ori r5, r5, (MSR_IR | MSR_DR)
+ mtmsr r5
+ isync
+ blr
+
+ .globl disable_addr_trans
+disable_addr_trans:
+ /* disable address translation */
+ mflr r4
+ mfmsr r3
+ andi. r0, r3, (MSR_IR | MSR_DR)
+ beqlr
+ andc r3, r3, r0
+ mtspr SRR0, r4
+ mtspr SRR1, r3
+ rfi
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+ .globl ppcDWstore
+ppcDWstore:
+ lfd 1, 0(r4)
+ stfd 1, 0(r3)
+ blr
+
+ .globl ppcDWload
+ppcDWload:
+ lfd 1, 0(r3)
+ stfd 1, 0(r4)
+ blr
+
+#ifndef CONFIG_DEFAULT_IMMR
+#error CONFIG_DEFAULT_IMMR must be defined
+#endif /* CONFIG_SYS_DEFAULT_IMMR */
+#ifndef CONFIG_SYS_IMMR
+#define CONFIG_SYS_IMMR CONFIG_DEFAULT_IMMR
+#endif /* CONFIG_SYS_IMMR */
+
+/*
+ * After configuration, a system reset exception is executed using the
+ * vector at offset 0x100 relative to the base set by MSR[IP]. If
+ * MSR[IP] is 0, the base address is 0x00000000. If MSR[IP] is 1, the
+ * base address is 0xfff00000. In the case of a Power On Reset or Hard
+ * Reset, the value of MSR[IP] is determined by the CIP field in the
+ * HRCW.
+ *
+ * Other bits in the HRCW set up the Base Address and Port Size in BR0.
+ * This determines the location of the boot ROM (flash or EPROM) in the
+ * processor's address space at boot time. As long as the HRCW is set up
+ * so that we eventually end up executing the code below when the
+ * processor executes the reset exception, the actual values used should
+ * not matter.
+ *
+ * Once we have got here, the address mask in OR0 is cleared so that the
+ * bottom 32K of the boot ROM is effectively repeated all throughout the
+ * processor's address space, after which we can jump to the absolute
+ * address at which the boot ROM was linked at compile time, and proceed
+ * to initialise the memory controller without worrying if the rug will
+ * be pulled out from under us, so to speak (it will be fine as long as
+ * we configure BR0 with the same boot ROM link address).
+ */
+ . = EXC_OFF_SYS_RESET
+
+ .globl _start
+_start: /* time t 0 */
+ lis r4, CONFIG_DEFAULT_IMMR@h
+ nop
+
+ mfmsr r5 /* save msr contents */
+
+ /* 83xx manuals prescribe a specific sequence for updating IMMRBAR. */
+ bl 1f
+1: mflr r7
+
+ lis r3, CONFIG_SYS_IMMR@h
+ ori r3, r3, CONFIG_SYS_IMMR@l
+
+ lwz r6, IMMRBAR(r4)
+ isync
+
+ stw r3, IMMRBAR(r4)
+ lwz r6, 0(r7) /* Arbitrary external load */
+ isync
+
+ lwz r6, IMMRBAR(r3)
+ isync
+
+ /* Initialise the E300 processor core */
+ /*------------------------------------------*/
+
+#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_MPC83XX_WAIT_FOR_NAND)) || \
+ defined(CONFIG_NAND_SPL)
+ /* The FCM begins execution after only the first page
+ * is loaded. Wait for the rest before branching
+ * to another flash page.
+ */
+1: lwz r6, 0x50b0(r3)
+ andi. r6, r6, 1
+ beq 1b
+#endif
+
+ bl init_e300_core
+
+#ifdef CONFIG_SYS_FLASHBOOT
+
+ /* Inflate flash location so it appears everywhere, calculate */
+ /* the absolute address in final location of the FLASH, jump */
+ /* there and deflate the flash size back to minimal size */
+ /*------------------------------------------------------------*/
+ bl map_flash_by_law1
+ lis r4, (CONFIG_SYS_MONITOR_BASE)@h
+ ori r4, r4, (CONFIG_SYS_MONITOR_BASE)@l
+ addi r5, r4, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r5
+ blr
+in_flash:
+#if 1 /* Remapping flash with LAW0. */
+ bl remap_flash_by_law0
+#endif
+#endif /* CONFIG_SYS_FLASHBOOT */
+
+ /* setup the bats */
+ bl setup_bats
+ sync
+
+ /*
+ * Cache must be enabled here for stack-in-cache trick.
+ * This means we need to enable the BATS.
+ * This means:
+ * 1) for the EVB, original gt regs need to be mapped
+ * 2) need to have an IBAT for the 0xf region,
+ * we are running there!
+ * Cache should be turned on after BATs, since by default
+ * everything is write-through.
+ * The init-mem BAT can be reused after reloc. The old
+ * gt-regs BAT can be reused after board_init_f calls
+ * board_early_init_f (EVB only).
+ */
+ /* enable address translation */
+ bl enable_addr_trans
+ sync
+
+ /* enable the data cache */
+ bl dcache_enable
+ sync
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+ bl lock_ram_in_cache
+ sync
+#endif
+
+ /* set up the stack pointer in our newly created
+ * cache-ram (r1) */
+ lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+ ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable & stack humble */
+ /*------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ lis r3, CONFIG_SYS_IMMR@h
+ /* run low-level CPU init code (in Flash)*/
+ bl cpu_init_f
+
+ /* run 1st part of board init code (in Flash)*/
+ bl board_init_f
+
+ /* NOTREACHED - board_init_f() does not return */
+
+#ifndef MINIMAL_SPL
+/*
+ * Vector Table
+ */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+#ifndef FIXME
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+#endif
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
+#ifdef DEBUG
+ . = 0x1300
+ /*
+ * This exception occurs when the program counter matches the
+ * Instruction Address Breakpoint Register (IABR).
+ *
+ * I want the cpu to halt if this occurs so I can hunt around
+ * with the debugger and look at things.
+ *
+ * When DEBUG is defined, both machine check enable (in the MSR)
+ * and checkstop reset enable (in the reset mode register) are
+ * turned off and so a checkstop condition will result in the cpu
+ * halting.
+ *
+ * I force the cpu into a checkstop condition by putting an illegal
+ * instruction here (at least this is the theory).
+ *
+ * well - that didnt work, so just do an infinite loop!
+ */
+1: b 1b
+#else
+ STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
+#endif
+ STD_EXCEPTION(0x1400, SMI, UnknownException)
+
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+ STD_EXCEPTION(0x2000, Trap_20, UnknownException)
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+#endif /* !MINIMAL_SPL */
+
+/*
+ * This code initialises the E300 processor core
+ * (conforms to PowerPC 603e spec)
+ * Note: expects original MSR contents to be in r5.
+ */
+ .globl init_e300_core
+init_e300_core: /* time t 10 */
+ /* Initialize machine status; enable machine check interrupt */
+ /*-----------------------------------------------------------*/
+
+ li r3, MSR_KERNEL /* Set ME and RI flags */
+ rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
+#ifdef DEBUG
+ rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
+#endif
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+
+ lis r3, CONFIG_SYS_IMMR@h
+#if defined(CONFIG_WATCHDOG)
+ /* Initialise the Watchdog values and reset it (if req) */
+ /*------------------------------------------------------*/
+ lis r4, CONFIG_SYS_WATCHDOG_VALUE
+ ori r4, r4, (SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR)
+ stw r4, SWCRR(r3)
+
+ /* and reset it */
+
+ li r4, 0x556C
+ sth r4, SWSRR@l(r3)
+ li r4, -0x55C7
+ sth r4, SWSRR@l(r3)
+#else
+ /* Disable Watchdog */
+ /*-------------------*/
+ lwz r4, SWCRR(r3)
+ /* Check to see if its enabled for disabling
+ once disabled by SW you can't re-enable */
+ andi. r4, r4, 0x4
+ beq 1f
+ xor r4, r4, r4
+ stw r4, SWCRR(r3)
+1:
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_MASK_AER_AO)
+ /* Write the Arbiter Event Enable to mask Address Only traps. */
+ /* This prevents the dcbz instruction from being trapped when */
+ /* HID0_ABE Address Broadcast Enable is set and the MEMORY */
+ /* COHERENCY bit is set in the WIMG bits, which is often */
+ /* needed for PCI operation. */
+ lwz r4, 0x0808(r3)
+ rlwinm r0, r4, 0, ~AER_AO
+ stw r0, 0x0808(r3)
+#endif /* CONFIG_MASK_AER_AO */
+
+ /* Initialize the Hardware Implementation-dependent Registers */
+ /* HID0 also contains cache control */
+ /* - force invalidation of data and instruction caches */
+ /*------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_HID0_INIT@h
+ ori r3, r3, (CONFIG_SYS_HID0_INIT | HID0_ICFI | HID0_DCFI)@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CONFIG_SYS_HID0_FINAL@h
+ ori r3, r3, (CONFIG_SYS_HID0_FINAL & ~(HID0_ICFI | HID0_DCFI))@l
+ SYNC
+ mtspr HID0, r3
+
+ lis r3, CONFIG_SYS_HID2@h
+ ori r3, r3, CONFIG_SYS_HID2@l
+ SYNC
+ mtspr HID2, r3
+
+ /* Done! */
+ /*------------------------------*/
+ blr
+
+ /* setup_bats - set them up to some initial state */
+ .globl setup_bats
+setup_bats:
+ addis r0, r0, 0x0000
+
+ /* IBAT 0 */
+ addis r4, r0, CONFIG_SYS_IBAT0L@h
+ ori r4, r4, CONFIG_SYS_IBAT0L@l
+ addis r3, r0, CONFIG_SYS_IBAT0U@h
+ ori r3, r3, CONFIG_SYS_IBAT0U@l
+ mtspr IBAT0L, r4
+ mtspr IBAT0U, r3
+
+ /* DBAT 0 */
+ addis r4, r0, CONFIG_SYS_DBAT0L@h
+ ori r4, r4, CONFIG_SYS_DBAT0L@l
+ addis r3, r0, CONFIG_SYS_DBAT0U@h
+ ori r3, r3, CONFIG_SYS_DBAT0U@l
+ mtspr DBAT0L, r4
+ mtspr DBAT0U, r3
+
+ /* IBAT 1 */
+ addis r4, r0, CONFIG_SYS_IBAT1L@h
+ ori r4, r4, CONFIG_SYS_IBAT1L@l
+ addis r3, r0, CONFIG_SYS_IBAT1U@h
+ ori r3, r3, CONFIG_SYS_IBAT1U@l
+ mtspr IBAT1L, r4
+ mtspr IBAT1U, r3
+
+ /* DBAT 1 */
+ addis r4, r0, CONFIG_SYS_DBAT1L@h
+ ori r4, r4, CONFIG_SYS_DBAT1L@l
+ addis r3, r0, CONFIG_SYS_DBAT1U@h
+ ori r3, r3, CONFIG_SYS_DBAT1U@l
+ mtspr DBAT1L, r4
+ mtspr DBAT1U, r3
+
+ /* IBAT 2 */
+ addis r4, r0, CONFIG_SYS_IBAT2L@h
+ ori r4, r4, CONFIG_SYS_IBAT2L@l
+ addis r3, r0, CONFIG_SYS_IBAT2U@h
+ ori r3, r3, CONFIG_SYS_IBAT2U@l
+ mtspr IBAT2L, r4
+ mtspr IBAT2U, r3
+
+ /* DBAT 2 */
+ addis r4, r0, CONFIG_SYS_DBAT2L@h
+ ori r4, r4, CONFIG_SYS_DBAT2L@l
+ addis r3, r0, CONFIG_SYS_DBAT2U@h
+ ori r3, r3, CONFIG_SYS_DBAT2U@l
+ mtspr DBAT2L, r4
+ mtspr DBAT2U, r3
+
+ /* IBAT 3 */
+ addis r4, r0, CONFIG_SYS_IBAT3L@h
+ ori r4, r4, CONFIG_SYS_IBAT3L@l
+ addis r3, r0, CONFIG_SYS_IBAT3U@h
+ ori r3, r3, CONFIG_SYS_IBAT3U@l
+ mtspr IBAT3L, r4
+ mtspr IBAT3U, r3
+
+ /* DBAT 3 */
+ addis r4, r0, CONFIG_SYS_DBAT3L@h
+ ori r4, r4, CONFIG_SYS_DBAT3L@l
+ addis r3, r0, CONFIG_SYS_DBAT3U@h
+ ori r3, r3, CONFIG_SYS_DBAT3U@l
+ mtspr DBAT3L, r4
+ mtspr DBAT3U, r3
+
+#ifdef CONFIG_HIGH_BATS
+ /* IBAT 4 */
+ addis r4, r0, CONFIG_SYS_IBAT4L@h
+ ori r4, r4, CONFIG_SYS_IBAT4L@l
+ addis r3, r0, CONFIG_SYS_IBAT4U@h
+ ori r3, r3, CONFIG_SYS_IBAT4U@l
+ mtspr IBAT4L, r4
+ mtspr IBAT4U, r3
+
+ /* DBAT 4 */
+ addis r4, r0, CONFIG_SYS_DBAT4L@h
+ ori r4, r4, CONFIG_SYS_DBAT4L@l
+ addis r3, r0, CONFIG_SYS_DBAT4U@h
+ ori r3, r3, CONFIG_SYS_DBAT4U@l
+ mtspr DBAT4L, r4
+ mtspr DBAT4U, r3
+
+ /* IBAT 5 */
+ addis r4, r0, CONFIG_SYS_IBAT5L@h
+ ori r4, r4, CONFIG_SYS_IBAT5L@l
+ addis r3, r0, CONFIG_SYS_IBAT5U@h
+ ori r3, r3, CONFIG_SYS_IBAT5U@l
+ mtspr IBAT5L, r4
+ mtspr IBAT5U, r3
+
+ /* DBAT 5 */
+ addis r4, r0, CONFIG_SYS_DBAT5L@h
+ ori r4, r4, CONFIG_SYS_DBAT5L@l
+ addis r3, r0, CONFIG_SYS_DBAT5U@h
+ ori r3, r3, CONFIG_SYS_DBAT5U@l
+ mtspr DBAT5L, r4
+ mtspr DBAT5U, r3
+
+ /* IBAT 6 */
+ addis r4, r0, CONFIG_SYS_IBAT6L@h
+ ori r4, r4, CONFIG_SYS_IBAT6L@l
+ addis r3, r0, CONFIG_SYS_IBAT6U@h
+ ori r3, r3, CONFIG_SYS_IBAT6U@l
+ mtspr IBAT6L, r4
+ mtspr IBAT6U, r3
+
+ /* DBAT 6 */
+ addis r4, r0, CONFIG_SYS_DBAT6L@h
+ ori r4, r4, CONFIG_SYS_DBAT6L@l
+ addis r3, r0, CONFIG_SYS_DBAT6U@h
+ ori r3, r3, CONFIG_SYS_DBAT6U@l
+ mtspr DBAT6L, r4
+ mtspr DBAT6U, r3
+
+ /* IBAT 7 */
+ addis r4, r0, CONFIG_SYS_IBAT7L@h
+ ori r4, r4, CONFIG_SYS_IBAT7L@l
+ addis r3, r0, CONFIG_SYS_IBAT7U@h
+ ori r3, r3, CONFIG_SYS_IBAT7U@l
+ mtspr IBAT7L, r4
+ mtspr IBAT7U, r3
+
+ /* DBAT 7 */
+ addis r4, r0, CONFIG_SYS_DBAT7L@h
+ ori r4, r4, CONFIG_SYS_DBAT7L@l
+ addis r3, r0, CONFIG_SYS_DBAT7U@h
+ ori r3, r3, CONFIG_SYS_DBAT7U@l
+ mtspr DBAT7L, r4
+ mtspr DBAT7U, r3
+#endif
+
+ isync
+
+ /* invalidate all tlb's
+ *
+ * From the 603e User Manual: "The 603e provides the ability to
+ * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
+ * instruction invalidates the TLB entry indexed by the EA, and
+ * operates on both the instruction and data TLBs simultaneously
+ * invalidating four TLB entries (both sets in each TLB). The
+ * index corresponds to bits 15-19 of the EA. To invalidate all
+ * entries within both TLBs, 32 tlbie instructions should be
+ * issued, incrementing this field by one each time."
+ *
+ * "Note that the tlbia instruction is not implemented on the
+ * 603e."
+ *
+ * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
+ * incrementing by 0x1000 each time. The code below is sort of
+ * based on code in "flush_tlbs" from arch/powerpc/kernel/head.S
+ *
+ */
+ lis r3, 0
+ lis r5, 2
+
+1:
+ tlbie r3
+ addi r3, r3, 0x1000
+ cmp 0, 0, r3, r5
+ blt 1b
+
+ blr
+
+/* Cache functions.
+ *
+ * Note: requires that all cache bits in
+ * HID0 are in the low half word.
+ */
+#ifndef MINIMAL_SPL
+ .globl icache_enable
+icache_enable:
+ mfspr r3, HID0
+ ori r3, r3, HID0_ICE
+ li r4, HID0_ICFI|HID0_ILOCK
+ andc r3, r3, r4
+ ori r4, r3, HID0_ICFI
+ isync
+ mtspr HID0, r4 /* sets enable and invalidate, clears lock */
+ isync
+ mtspr HID0, r3 /* clears invalidate */
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r3, HID0
+ lis r4, 0
+ ori r4, r4, HID0_ICE|HID0_ICFI|HID0_ILOCK
+ andc r3, r3, r4
+ isync
+ mtspr HID0, r3 /* clears invalidate, enable and lock */
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, (31 - HID0_ICE_SHIFT + 1), 31, 31
+ blr
+#endif /* !MINIMAL_SPL */
+
+ .globl dcache_enable
+dcache_enable:
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ ori r3, r3, HID0_DCE
+ sync
+ mtspr HID0, r3 /* enable, no invalidate */
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mflr r4
+ bl flush_dcache /* uses r3 and r5 */
+ mfspr r3, HID0
+ li r5, HID0_DCE|HID0_DLOCK
+ andc r3, r3, r5
+ ori r5, r3, HID0_DCFI
+ sync
+ mtspr HID0, r5 /* sets invalidate, clears enable and lock */
+ sync
+ mtspr HID0, r3 /* clears invalidate */
+ mtlr r4
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, HID0
+ rlwinm r3, r3, (31 - HID0_DCE_SHIFT + 1), 31, 31
+ blr
+
+ .globl flush_dcache
+flush_dcache:
+ lis r3, 0
+ lis r5, CONFIG_SYS_CACHELINE_SIZE
+1: cmp 0, 1, r3, r5
+ bge 2f
+ lwz r5, 0(r3)
+ lis r5, CONFIG_SYS_CACHELINE_SIZE
+ addi r3, r3, 0x4
+ b 1b
+2: blr
+
+/*-------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__bss_start)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE)
+ * + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+ la r8,-4(r4)
+ la r7,-4(r3)
+
+ /* copy */
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+
+ addi r0,r5,3
+ srwi. r0,r0,2
+ mtctr r0
+ la r8,-4(r4)
+ la r7,-4(r3)
+
+ /* and compare */
+20: lwzu r20,4(r8)
+ lwzu r21,4(r7)
+ xor. r22, r20, r21
+ bne 30f
+ bdnz 20b
+ b 4f
+
+ /* compare failed */
+30: li r3, 0
+ blr
+
+2: slwi r0,r0,2 /* re copy in reverse order ... y do we needed it? */
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+#ifndef MINIMAL_SPL
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+#endif
+
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+#if defined(CONFIG_HYMOD)
+ /*
+ * For HYMOD - the environment is the very last item in flash.
+ * The real .bss stops just before environment starts, so only
+ * clear up to that point.
+ *
+ * taken from mods for FADS board
+ */
+ lwz r4,GOT(environment)
+#else
+ lwz r4,GOT(__bss_end)
+#endif
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+#ifndef MINIMAL_SPL
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mfmsr r3 /* now that the vectors have */
+ lis r7, MSR_IP@h /* relocated into low memory */
+ ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
+ andc r3, r3, r7 /* (if it was on) */
+ SYNC /* Some chip revs need this... */
+ mtmsr r3
+ SYNC
+
+ mtlr r4 /* restore link register */
+ blr
+
+#endif /* !MINIMAL_SPL */
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+lock_ram_in_cache:
+ /* Allocate Initial RAM in data cache.
+ */
+ lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+ li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
+ (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+ mtctr r4
+1:
+ dcbz r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+
+ /* Lock the data cache */
+ mfspr r0, HID0
+ ori r0, r0, HID0_DLOCK
+ sync
+ mtspr HID0, r0
+ sync
+ blr
+
+#ifndef MINIMAL_SPL
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+ li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
+ (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+ mtctr r4
+1: icbi r0, r3
+ dcbi r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+ sync /* Wait for all icbi to complete on bus */
+ isync
+
+ /* Unlock the data cache and invalidate it */
+ mfspr r3, HID0
+ li r5, HID0_DLOCK|HID0_DCFI
+ andc r3, r3, r5 /* no invalidate, unlock */
+ ori r5, r3, HID0_DCFI /* invalidate, unlock */
+ sync
+ mtspr HID0, r5 /* invalidate, unlock */
+ sync
+ mtspr HID0, r3 /* no invalidate, unlock */
+ blr
+#endif /* !MINIMAL_SPL */
+#endif /* CONFIG_SYS_INIT_RAM_LOCK */
+
+#ifdef CONFIG_SYS_FLASHBOOT
+map_flash_by_law1:
+ /* When booting from ROM (Flash or EPROM), clear the */
+ /* Address Mask in OR0 so ROM appears everywhere */
+ /*----------------------------------------------------*/
+ lis r3, (CONFIG_SYS_IMMR)@h /* r3 <= CONFIG_SYS_IMMR */
+ lwz r4, OR0@l(r3)
+ li r5, 0x7fff /* r5 <= 0x00007FFFF */
+ and r4, r4, r5
+ stw r4, OR0@l(r3) /* OR0 <= OR0 & 0x00007FFFF */
+
+ /* As MPC8349E User's Manual presented, when RCW[BMS] is set to 0,
+ * system will boot from 0x0000_0100, and the LBLAWBAR0[BASE_ADDR]
+ * reset value is 0x00000; when RCW[BMS] is set to 1, system will boot
+ * from 0xFFF0_0100, and the LBLAWBAR0[BASE_ADDR] reset value is
+ * 0xFF800. From the hard resetting to here, the processor fetched and
+ * executed the instructions one by one. There is not absolutely
+ * jumping happened. Laterly, the u-boot code has to do an absolutely
+ * jumping to tell the CPU instruction fetching component what the
+ * u-boot TEXT base address is. Because the TEXT base resides in the
+ * boot ROM memory space, to garantee the code can run smoothly after
+ * that jumping, we must map in the entire boot ROM by Local Access
+ * Window. Sometimes, we desire an non-0x00000 or non-0xFF800 starting
+ * address for boot ROM, such as 0xFE000000. In this case, the default
+ * LBIU Local Access Widow 0 will not cover this memory space. So, we
+ * need another window to map in it.
+ */
+ lis r4, (CONFIG_SYS_FLASH_BASE)@h
+ ori r4, r4, (CONFIG_SYS_FLASH_BASE)@l
+ stw r4, LBLAWBAR1(r3) /* LBLAWBAR1 <= CONFIG_SYS_FLASH_BASE */
+
+ /* Store 0x80000012 + log2(CONFIG_SYS_FLASH_SIZE) into LBLAWAR1 */
+ lis r4, (0x80000012)@h
+ ori r4, r4, (0x80000012)@l
+ li r5, CONFIG_SYS_FLASH_SIZE
+1: srawi. r5, r5, 1 /* r5 = r5 >> 1 */
+ addi r4, r4, 1
+ bne 1b
+
+ stw r4, LBLAWAR1(r3) /* LBLAWAR1 <= 8MB Flash Size */
+ /* Wait for HW to catch up */
+ lwz r4, LBLAWAR1(r3)
+ twi 0,r4,0
+ isync
+ blr
+
+ /* Though all the LBIU Local Access Windows and LBC Banks will be
+ * initialized in the C code, we'd better configure boot ROM's
+ * window 0 and bank 0 correctly at here.
+ */
+remap_flash_by_law0:
+ /* Initialize the BR0 with the boot ROM starting address. */
+ lwz r4, BR0(r3)
+ li r5, 0x7FFF
+ and r4, r4, r5
+ lis r5, (CONFIG_SYS_FLASH_BASE & 0xFFFF8000)@h
+ ori r5, r5, (CONFIG_SYS_FLASH_BASE & 0xFFFF8000)@l
+ or r5, r5, r4
+ stw r5, BR0(r3) /* r5 <= (CONFIG_SYS_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
+
+ lwz r4, OR0(r3)
+ lis r5, ~((CONFIG_SYS_FLASH_SIZE << 4) - 1)
+ or r4, r4, r5
+ stw r4, OR0(r3)
+
+ lis r4, (CONFIG_SYS_FLASH_BASE)@h
+ ori r4, r4, (CONFIG_SYS_FLASH_BASE)@l
+ stw r4, LBLAWBAR0(r3) /* LBLAWBAR0 <= CONFIG_SYS_FLASH_BASE */
+
+ /* Store 0x80000012 + log2(CONFIG_SYS_FLASH_SIZE) into LBLAWAR0 */
+ lis r4, (0x80000012)@h
+ ori r4, r4, (0x80000012)@l
+ li r5, CONFIG_SYS_FLASH_SIZE
+1: srawi. r5, r5, 1 /* r5 = r5 >> 1 */
+ addi r4, r4, 1
+ bne 1b
+ stw r4, LBLAWAR0(r3) /* LBLAWAR0 <= Flash Size */
+
+
+ xor r4, r4, r4
+ stw r4, LBLAWBAR1(r3)
+ stw r4, LBLAWAR1(r3) /* Off LBIU LAW1 */
+ /* Wait for HW to catch up */
+ lwz r4, LBLAWAR1(r3)
+ twi 0,r4,0
+ isync
+ blr
+#endif /* CONFIG_SYS_FLASHBOOT */
diff --git a/arch/powerpc/cpu/mpc83xx/traps.c b/arch/powerpc/cpu/mpc83xx/traps.c
new file mode 100644
index 0000000..53a1062
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/traps.c
@@ -0,0 +1,257 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware
+ * exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+#include <asm/mpc8349_pci.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ puts ("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ putc ('\n');
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ putc ('\n');
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ putc ('\n');
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0) {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7) {
+ putc ('\n');
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+#ifdef CONFIG_PCI
+void dump_pci (void)
+{
+/*
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ printf ("PCI: err status %x err mask %x err ctrl %x\n",
+ le32_to_cpu (immap->im_pci.pci_esr),
+ le32_to_cpu (immap->im_pci.pci_emr),
+ le32_to_cpu (immap->im_pci.pci_ecr));
+ printf (" error address %x error data %x ctrl %x\n",
+ le32_to_cpu (immap->im_pci.pci_eacr),
+ le32_to_cpu (immap->im_pci.pci_edcr),
+ le32_to_cpu (immap->im_pci.pci_eccr));
+*/
+}
+#endif
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+#ifdef CONFIG_PCI
+#if 0
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+#ifdef DEBUG
+ dump_pci();
+#endif
+ /* clear the error in the error status register */
+ if(immap->im_pci.pci_esr & cpu_to_le32(PCI_ERROR_PCI_NO_RSP)) {
+ immap->im_pci.pci_esr = cpu_to_le32(PCI_ERROR_PCI_NO_RSP);
+ return;
+ }
+#endif
+#endif /* CONFIG_PCI */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ puts ("Machine check in kernel mode.\n"
+ "Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x000F0000) {
+ case (0x80000000>>12):
+ puts ("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13):
+ puts ("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14):
+ puts ("Data parity signal\n");
+ break;
+ case (0x80000000>>15):
+ puts ("Address parity signal\n");
+ break;
+ default:
+ puts ("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+#ifdef CONFIG_PCI
+ dump_pci();
+#endif
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc83xx/u-boot-spl.lds b/arch/powerpc/cpu/mpc83xx/u-boot-spl.lds
new file mode 100644
index 0000000..870b47d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/u-boot-spl.lds
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ . = 0xfff00000;
+ .text : {
+ *(.text*)
+ . = ALIGN(16);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ . = ALIGN(8);
+ .data : {
+ *(.data*)
+ *(.sdata*)
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+
+ . = ALIGN(8);
+ __bss_start = .;
+ .bss (NOLOAD) : {
+ *(.*bss)
+ }
+ __bss_end = .;
+}
+ENTRY(_start)
+ASSERT(__bss_end <= 0xfff01000, "NAND bootstrap too big");
diff --git a/arch/powerpc/cpu/mpc83xx/u-boot.lds b/arch/powerpc/cpu/mpc83xx/u-boot.lds
new file mode 100644
index 0000000..a9d8598
--- /dev/null
+++ b/arch/powerpc/cpu/mpc83xx/u-boot.lds
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright 2006-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .text :
+ {
+ arch/powerpc/cpu/mpc83xx/start.o (.text*)
+ *(.text*)
+ . = ALIGN(16);
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
+ENTRY(_start)
diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile
new file mode 100644
index 0000000..4669883
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/Makefile
@@ -0,0 +1,182 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao,X.Xiao@motorola.com
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+START = start.o resetvec.o
+
+ifdef MINIMAL
+
+COBJS-y += cpu_init_early.o tlb.o spl_minimal.o
+
+else
+
+SOBJS-$(CONFIG_MP) += release.o
+SOBJS = $(SOBJS-y)
+
+COBJS-$(CONFIG_CMD_ERRATA) += cmd_errata.o
+COBJS-$(CONFIG_CPM2) += commproc.o
+
+# supports ddr1
+COBJS-$(CONFIG_MPC8540) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8560) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8541) += ddr-gen1.o
+COBJS-$(CONFIG_MPC8555) += ddr-gen1.o
+
+# supports ddr1/2
+COBJS-$(CONFIG_MPC8548) += ddr-gen2.o
+COBJS-$(CONFIG_MPC8568) += ddr-gen2.o
+COBJS-$(CONFIG_MPC8544) += ddr-gen2.o
+
+# supports ddr1/2/3
+COBJS-$(CONFIG_MPC8572) += ddr-gen3.o
+COBJS-$(CONFIG_MPC8536) += ddr-gen3.o
+COBJS-$(CONFIG_MPC8569) += ddr-gen3.o
+COBJS-$(CONFIG_P1010) += ddr-gen3.o
+COBJS-$(CONFIG_P1011) += ddr-gen3.o
+COBJS-$(CONFIG_P1012) += ddr-gen3.o
+COBJS-$(CONFIG_P1013) += ddr-gen3.o
+COBJS-$(CONFIG_P1014) += ddr-gen3.o
+COBJS-$(CONFIG_P1020) += ddr-gen3.o
+COBJS-$(CONFIG_P1021) += ddr-gen3.o
+COBJS-$(CONFIG_P1022) += ddr-gen3.o
+COBJS-$(CONFIG_P1023) += ddr-gen3.o
+COBJS-$(CONFIG_P1024) += ddr-gen3.o
+COBJS-$(CONFIG_P1025) += ddr-gen3.o
+COBJS-$(CONFIG_P2010) += ddr-gen3.o
+COBJS-$(CONFIG_P2020) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_P2041) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_P3041) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_P4080) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_P5020) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_P5040) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_T4240) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_T4160) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_B4420) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_B4860) += ddr-gen3.o
+COBJS-$(CONFIG_BSC9131) += ddr-gen3.o
+COBJS-$(CONFIG_BSC9132) += ddr-gen3.o
+COBJS-$(CONFIG_PPC_T1040) += ddr-gen3.o
+
+COBJS-$(CONFIG_CPM2) += ether_fcc.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-$(CONFIG_FSL_CORENET) += liodn.o
+COBJS-$(CONFIG_MP) += mp.o
+COBJS-$(CONFIG_PCI) += pci.o
+COBJS-$(CONFIG_SYS_DPAA_QBMAN) += portals.o
+
+# various SoC specific assignments
+COBJS-$(CONFIG_PPC_P2041) += p2041_ids.o
+COBJS-$(CONFIG_PPC_P3041) += p3041_ids.o
+COBJS-$(CONFIG_PPC_P4080) += p4080_ids.o
+COBJS-$(CONFIG_PPC_P5020) += p5020_ids.o
+COBJS-$(CONFIG_PPC_P5040) += p5040_ids.o
+COBJS-$(CONFIG_PPC_T4240) += t4240_ids.o
+COBJS-$(CONFIG_PPC_T4160) += t4240_ids.o
+COBJS-$(CONFIG_PPC_B4420) += b4860_ids.o
+COBJS-$(CONFIG_PPC_B4860) += b4860_ids.o
+COBJS-$(CONFIG_PPC_T1040) += t1040_ids.o
+
+COBJS-$(CONFIG_QE) += qe_io.o
+COBJS-$(CONFIG_CPM2) += serial_scc.o
+COBJS-$(CONFIG_SYS_FSL_QORIQ_CHASSIS1) += fsl_corenet_serdes.o
+COBJS-$(CONFIG_SYS_FSL_QORIQ_CHASSIS2) += fsl_corenet2_serdes.o
+
+# SoC specific SERDES support
+COBJS-$(CONFIG_MPC8536) += mpc8536_serdes.o
+COBJS-$(CONFIG_MPC8544) += mpc8544_serdes.o
+COBJS-$(CONFIG_MPC8548) += mpc8548_serdes.o
+COBJS-$(CONFIG_MPC8568) += mpc8568_serdes.o
+COBJS-$(CONFIG_MPC8569) += mpc8569_serdes.o
+COBJS-$(CONFIG_MPC8572) += mpc8572_serdes.o
+COBJS-$(CONFIG_P1010) += p1010_serdes.o
+COBJS-$(CONFIG_P1011) += p1021_serdes.o
+COBJS-$(CONFIG_P1012) += p1021_serdes.o
+COBJS-$(CONFIG_P1013) += p1022_serdes.o
+COBJS-$(CONFIG_P1014) += p1010_serdes.o
+COBJS-$(CONFIG_P1017) += p1023_serdes.o
+COBJS-$(CONFIG_P1020) += p1021_serdes.o
+COBJS-$(CONFIG_P1021) += p1021_serdes.o
+COBJS-$(CONFIG_P1022) += p1022_serdes.o
+COBJS-$(CONFIG_P1023) += p1023_serdes.o
+COBJS-$(CONFIG_P1024) += p1021_serdes.o
+COBJS-$(CONFIG_P1025) += p1021_serdes.o
+COBJS-$(CONFIG_P2010) += p2020_serdes.o
+COBJS-$(CONFIG_P2020) += p2020_serdes.o
+COBJS-$(CONFIG_PPC_P2041) += p2041_serdes.o
+COBJS-$(CONFIG_PPC_P3041) += p3041_serdes.o
+COBJS-$(CONFIG_PPC_P4080) += p4080_serdes.o
+COBJS-$(CONFIG_PPC_P5020) += p5020_serdes.o
+COBJS-$(CONFIG_PPC_P5040) += p5040_serdes.o
+COBJS-$(CONFIG_PPC_T4240) += t4240_serdes.o
+COBJS-$(CONFIG_PPC_T4160) += t4240_serdes.o
+COBJS-$(CONFIG_PPC_B4420) += b4860_serdes.o
+COBJS-$(CONFIG_PPC_B4860) += b4860_serdes.o
+COBJS-$(CONFIG_BSC9132) += bsc9132_serdes.o
+COBJS-$(CONFIG_PPC_T1040) += t1040_serdes.o
+
+COBJS-y += cpu.o
+COBJS-y += cpu_init.o
+COBJS-y += cpu_init_early.o
+COBJS-y += interrupts.o
+COBJS-y += speed.o
+COBJS-y += tlb.o
+COBJS-y += traps.o
+
+# Stub implementations of cache management functions for USB
+COBJS-y += cache.o
+
+endif # not minimal
+
+COBJS = $(COBJS-y)
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc85xx/b4860_ids.c b/arch/powerpc/cpu/mpc85xx/b4860_ids.c
new file mode 100644
index 0000000..0f4e82e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/b4860_ids.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO(1, 27, 1, 0),
+ SET_QP_INFO(2, 28, 1, 0),
+ SET_QP_INFO(3, 29, 1, 1),
+ SET_QP_INFO(4, 30, 1, 1),
+ SET_QP_INFO(5, 31, 1, 2),
+ SET_QP_INFO(6, 32, 1, 2),
+ SET_QP_INFO(7, 33, 1, 3),
+ SET_QP_INFO(8, 34, 1, 3),
+ SET_QP_INFO(9, 35, 1, 0),
+ SET_QP_INFO(10, 36, 1, 0),
+ SET_QP_INFO(11, 37, 1, 1),
+ SET_QP_INFO(12, 38, 1, 1),
+ SET_QP_INFO(13, 39, 1, 2),
+ SET_QP_INFO(14, 40, 1, 2),
+ SET_QP_INFO(15, 41, 1, 3),
+ SET_QP_INFO(16, 42, 1, 3),
+ SET_QP_INFO(17, 43, 1, 0),
+ SET_QP_INFO(18, 44, 1, 0),
+ SET_QP_INFO(19, 45, 1, 1),
+ SET_QP_INFO(20, 46, 1, 1),
+ SET_QP_INFO(21, 47, 1, 2),
+ SET_QP_INFO(22, 48, 1, 2),
+ SET_QP_INFO(23, 49, 1, 3),
+ SET_QP_INFO(24, 50, 1, 3),
+ SET_QP_INFO(25, 51, 1, 0),
+};
+#endif
+
+#ifdef CONFIG_SYS_SRIO
+struct srio_liodn_id_table srio_liodn_tbl[] = {
+ SET_SRIO_LIODN_1(1, 307),
+ SET_SRIO_LIODN_1(2, 387),
+};
+int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(62),
+ SET_BMAN_LIODN(63),
+#endif
+
+ SET_SDHC_LIODN(1, 552),
+
+ SET_USB_LIODN(1, "fsl-usb2-mph", 553),
+
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 148),
+
+ SET_DMA_LIODN(1, 147),
+ SET_DMA_LIODN(2, 227),
+
+#ifndef CONFIG_PPC_B4420
+ SET_GUTS_LIODN("fsl,rapidio-delta", 199, rio1liodnr, 0),
+ SET_GUTS_LIODN(NULL, 200, rio2liodnr, 0),
+ SET_GUTS_LIODN(NULL, 201, rio1maintliodnr, 0),
+ SET_GUTS_LIODN(NULL, 202, rio2maintliodnr, 0),
+#endif
+
+ /* SET_NEXUS_LIODN(557), -- not yet implemented */
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 88),
+ SET_FMAN_RX_1G_LIODN(1, 1, 89),
+ SET_FMAN_RX_1G_LIODN(1, 2, 90),
+ SET_FMAN_RX_1G_LIODN(1, 3, 91),
+ SET_FMAN_RX_1G_LIODN(1, 4, 92),
+ SET_FMAN_RX_1G_LIODN(1, 5, 93),
+#ifndef CONFIG_PPC_B4420
+ SET_FMAN_RX_10G_LIODN(1, 0, 94),
+ SET_FMAN_RX_10G_LIODN(1, 1, 95),
+#endif
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ SET_SEC_JR_LIODN_ENTRY(0, 454, 458),
+ SET_SEC_JR_LIODN_ENTRY(1, 455, 459),
+ SET_SEC_JR_LIODN_ENTRY(2, 456, 460),
+ SET_SEC_JR_LIODN_ENTRY(3, 457, 461),
+ SET_SEC_RTIC_LIODN_ENTRY(a, 453),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 549),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 550),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 551),
+ SET_SEC_DECO_LIODN_ENTRY(0, 541, 610),
+ SET_SEC_DECO_LIODN_ENTRY(1, 542, 611),
+ SET_SEC_DECO_LIODN_ENTRY(2, 543, 612),
+ SET_SEC_DECO_LIODN_ENTRY(3, 544, 613),
+ SET_SEC_DECO_LIODN_ENTRY(4, 545, 614),
+ SET_SEC_DECO_LIODN_ENTRY(5, 546, 615),
+ SET_SEC_DECO_LIODN_ENTRY(6, 547, 616),
+ SET_SEC_DECO_LIODN_ENTRY(7, 548, 617),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+struct liodn_id_table rman_liodn_tbl[] = {
+ /* Set RMan block 0-3 liodn offset */
+ SET_RMAN_LIODN(0, 678),
+ SET_RMAN_LIODN(1, 679),
+ SET_RMAN_LIODN(2, 680),
+ SET_RMAN_LIODN(3, 681),
+};
+int rman_liodn_tbl_sz = ARRAY_SIZE(rman_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_bases[] = {
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(462, 558),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(973),
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ [FSL_HW_PORTAL_RMAN] = SET_LIODN_BASE_1(922),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/b4860_serdes.c b/arch/powerpc/cpu/mpc85xx/b4860_serdes.c
new file mode 100644
index 0000000..bd32342
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/b4860_serdes.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet2_serdes.h"
+
+struct serdes_config {
+ u8 protocol;
+ u8 lanes[SRDS_MAX_LANES];
+};
+
+#ifdef CONFIG_PPC_B4860
+static struct serdes_config serdes1_cfg_tbl[] = {
+ /* SerDes 1 */
+ {0x0D, {CPRI8, CPRI7, CPRI6, CPRI5,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x0E, {CPRI8, CPRI7, CPRI6, CPRI5,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x12, {CPRI8, CPRI7, CPRI6, CPRI5,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x2a, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ CPRI6, CPRI5, CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x2C, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ CPRI6, CPRI5, CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x2D, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ CPRI6, CPRI5, CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x2E, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ CPRI6, CPRI5, CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x30, {AURORA, AURORA,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x32, {AURORA, AURORA,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x33, {AURORA, AURORA,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x34, {AURORA, AURORA,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {0x3E, {CPRI8, CPRI7, CPRI6, CPRI5,
+ CPRI4, CPRI3, CPRI2, CPRI1}},
+ {}
+};
+static struct serdes_config serdes2_cfg_tbl[] = {
+ /* SerDes 2 */
+ {0x18, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ AURORA, AURORA, SRIO1, SRIO1}},
+ {0x1D, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ AURORA, AURORA, SRIO1, SRIO1}},
+ {0x2B, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SRIO2, SRIO2,
+ AURORA, AURORA, SRIO1, SRIO1}},
+ {0x30, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SRIO2, SRIO2,
+ AURORA, AURORA,
+ SRIO1, SRIO1}},
+ {0x49, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, AURORA,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {0x4A, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, AURORA,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {0x4C, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, AURORA,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {0x4E, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, AURORA,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {0x7A, {SRIO2, SRIO2, SRIO2, SRIO2,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {0x84, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SRIO2, SRIO2, AURORA, AURORA,
+ XFI_FM1_MAC9, XFI_FM1_MAC10}},
+ {0x85, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SRIO2, SRIO2, AURORA, AURORA,
+ XFI_FM1_MAC9, XFI_FM1_MAC10}},
+ {0x87, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SRIO2, SRIO2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ XFI_FM1_MAC9, XFI_FM1_MAC10}},
+ {0x8D, {SRIO2, SRIO2, SRIO2, SRIO2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ XFI_FM1_MAC9, XFI_FM1_MAC10}},
+ {0x93, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10}},
+ {0x9E, {PCIE1, PCIE1, PCIE1, PCIE1,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10}},
+ {0x9A, {PCIE1, PCIE1,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10}},
+ {0xB2, {PCIE1, PCIE1, PCIE1, PCIE1,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ XFI_FM1_MAC9, XFI_FM1_MAC10}},
+ {0xC3, {XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {0x98, {XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10}},
+ {}
+};
+#endif
+
+#ifdef CONFIG_PPC_B4420
+static struct serdes_config serdes1_cfg_tbl[] = {
+ {0x0D, {NONE, NONE, CPRI6, CPRI5,
+ CPRI4, CPRI3, NONE, NONE} },
+ {0x0E, {NONE, NONE, CPRI8, CPRI5,
+ CPRI4, CPRI3, NONE, NONE} },
+ {0x0F, {NONE, NONE, CPRI6, CPRI5,
+ CPRI4, CPRI3, NONE, NONE} },
+ {0x18, {NONE, NONE,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ NONE, NONE, NONE, NONE} },
+ {0x1B, {NONE, NONE,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ NONE, NONE, NONE, NONE} },
+ {0x1E, {NONE, NONE, AURORA, AURORA,
+ NONE, NONE, NONE, NONE} },
+ {0x21, {NONE, NONE, AURORA, AURORA,
+ NONE, NONE, NONE, NONE} },
+ {0x3E, {NONE, NONE, CPRI6, CPRI5,
+ CPRI4, CPRI3, NONE, NONE} },
+ {}
+};
+static struct serdes_config serdes2_cfg_tbl[] = {
+ {0x49, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, AURORA,
+ NONE, NONE, NONE, NONE} },
+ {0x4A, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, AURORA,
+ NONE, NONE, NONE, NONE} },
+ {0x6F, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ AURORA, AURORA, NONE, NONE, NONE, NONE} },
+ {0x70, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ AURORA, AURORA, NONE, NONE, NONE, NONE} },
+ {0x9A, {PCIE1, PCIE1,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ NONE, NONE, NONE, NONE} },
+ {0x9E, {PCIE1, PCIE1, PCIE1, PCIE1,
+ NONE, NONE, NONE, NONE} },
+ {}
+};
+#endif
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+ serdes1_cfg_tbl,
+ serdes2_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+ struct serdes_config *ptr;
+
+ if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ ptr = serdes_cfg_tbl[serdes];
+ while (ptr->protocol) {
+ if (ptr->protocol == cfg)
+ return ptr->lanes[lane];
+ ptr++;
+ }
+
+ return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+ int i;
+ struct serdes_config *ptr;
+
+ if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ ptr = serdes_cfg_tbl[serdes];
+ while (ptr->protocol) {
+ if (ptr->protocol == prtcl)
+ break;
+ ptr++;
+ }
+
+ if (!ptr->protocol)
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (ptr->lanes[i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/bsc9132_serdes.c b/arch/powerpc/cpu/mpc85xx/bsc9132_serdes.c
new file mode 100644
index 0000000..300a4db
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/bsc9132_serdes.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ * Author: Prabhakar Kushwaha <prabhakar@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+
+static u32 serdes1_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0] = {NONE, NONE, NONE, NONE},
+ [1] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [2] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [3] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [4] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [5] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [6] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [7] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [8] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [9] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [10] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [11] = {PCIE1, PCIE2, SGMII_TSEC1, SGMII_TSEC2},
+ [12] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [13] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [14] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [15] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [16] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [17] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [18] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [19] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [20] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [21] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [22] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [23] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [24] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [25] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [26] = {PCIE1, PCIE2, CPRI2, CPRI1},
+ [27] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [28] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [29] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [30] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [31] = {PCIE1, PCIE2, SGMII_TSEC1, CPRI1},
+ [32] = {PCIE1, PCIE2, SGMII_TSEC1, SGMII_TSEC2},
+ [33] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [34] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [35] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [36] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [37] = {PCIE1, SGMII_TSEC2, CPRI2, CPRI1},
+ [38] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [39] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [40] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [41] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [42] = {PCIE1, SGMII_TSEC2, SGMII_TSEC1, CPRI1},
+ [43] = {SGMII_TSEC1, SGMII_TSEC2, CPRI2, CPRI1},
+ [44] = {SGMII_TSEC1, SGMII_TSEC2, CPRI2, CPRI1},
+ [45] = {SGMII_TSEC1, SGMII_TSEC2, CPRI2, CPRI1},
+ [46] = {SGMII_TSEC1, SGMII_TSEC2, CPRI2, CPRI1},
+ [47] = {SGMII_TSEC1, SGMII_TSEC2, CPRI2, CPRI1},
+};
+
+int is_serdes_configured(enum srds_prtcl prtcl)
+{
+ return (1 << prtcl) & serdes1_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/cache.c b/arch/powerpc/cpu/mpc85xx/cache.c
new file mode 100644
index 0000000..2a08b65
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cache.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ *
+ * This file contains stub implementation of
+ * invalidate_dcache_range()
+ * flush_dcache_range()
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
new file mode 100644
index 0000000..a7ed877
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/compiler.h>
+#include <asm/processor.h>
+#include "fsl_corenet_serdes.h"
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004849
+/*
+ * This work-around is implemented in PBI, so just check to see if the
+ * work-around was actually applied. To do this, we check for specific data
+ * at specific addresses in DCSR.
+ *
+ * Array offsets[] contains a list of offsets within DCSR. According to the
+ * erratum document, the value at each offset should be 2.
+ */
+static void check_erratum_a4849(uint32_t svr)
+{
+ void __iomem *dcsr = (void *)CONFIG_SYS_DCSRBAR + 0xb0000;
+ unsigned int i;
+
+#if defined(CONFIG_PPC_P2041) || defined(CONFIG_PPC_P3041)
+ static const uint8_t offsets[] = {
+ 0x50, 0x54, 0x58, 0x90, 0x94, 0x98
+ };
+#endif
+#ifdef CONFIG_PPC_P4080
+ static const uint8_t offsets[] = {
+ 0x60, 0x64, 0x68, 0x6c, 0xa0, 0xa4, 0xa8, 0xac
+ };
+#endif
+ uint32_t x108; /* The value that should be at offset 0x108 */
+
+ for (i = 0; i < ARRAY_SIZE(offsets); i++) {
+ if (in_be32(dcsr + offsets[i]) != 2) {
+ printf("Work-around for Erratum A004849 is not enabled\n");
+ return;
+ }
+ }
+
+#if defined(CONFIG_PPC_P2041) || defined(CONFIG_PPC_P3041)
+ x108 = 0x12;
+#endif
+
+#ifdef CONFIG_PPC_P4080
+ /*
+ * For P4080, the erratum document says that the value at offset 0x108
+ * should be 0x12 on rev2, or 0x1c on rev3.
+ */
+ if (SVR_MAJ(svr) == 2)
+ x108 = 0x12;
+ if (SVR_MAJ(svr) == 3)
+ x108 = 0x1c;
+#endif
+
+ if (in_be32(dcsr + 0x108) != x108) {
+ printf("Work-around for Erratum A004849 is not enabled\n");
+ return;
+ }
+
+ /* Everything matches, so the erratum work-around was applied */
+
+ printf("Work-around for Erratum A004849 enabled\n");
+}
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004580
+/*
+ * This work-around is implemented in PBI, so just check to see if the
+ * work-around was actually applied. To do this, we check for specific data
+ * at specific addresses in the SerDes register block.
+ *
+ * The work-around says that for each SerDes lane, write BnTTLCRy0 =
+ * 0x1B00_0001, Register 2 = 0x0088_0000, and Register 3 = 0x4000_0000.
+
+ */
+static void check_erratum_a4580(uint32_t svr)
+{
+ const serdes_corenet_t __iomem *srds_regs =
+ (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
+ unsigned int lane;
+
+ for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+ if (serdes_lane_enabled(lane)) {
+ const struct serdes_lane __iomem *srds_lane =
+ &srds_regs->lane[serdes_get_lane_idx(lane)];
+
+ /*
+ * Verify that the values we were supposed to write in
+ * the PBI are actually there. Also, the lower 15
+ * bits of res4[3] should be the same as the upper 15
+ * bits of res4[1].
+ */
+ if ((in_be32(&srds_lane->ttlcr0) != 0x1b000001) ||
+ (in_be32(&srds_lane->res4[1]) != 0x880000) ||
+ (in_be32(&srds_lane->res4[3]) != 0x40000044)) {
+ printf("Work-around for Erratum A004580 is "
+ "not enabled\n");
+ return;
+ }
+ }
+ }
+
+ /* Everything matches, so the erratum work-around was applied */
+
+ printf("Work-around for Erratum A004580 enabled\n");
+}
+#endif
+
+static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+ extern int enable_cpu_a011_workaround;
+#endif
+ __maybe_unused u32 svr = get_svr();
+
+#if defined(CONFIG_FSL_SATA_V2) && defined(CONFIG_FSL_SATA_ERRATUM_A001)
+ if (IS_SVR_REV(svr, 1, 0)) {
+ switch (SVR_SOC_VER(svr)) {
+ case SVR_P1013:
+ case SVR_P1022:
+ puts("Work-around for Erratum SATA A001 enabled\n");
+ }
+ }
+#endif
+
+#if defined(CONFIG_SYS_P4080_ERRATUM_SERDES8)
+ puts("Work-around for Erratum SERDES8 enabled\n");
+#endif
+#if defined(CONFIG_SYS_P4080_ERRATUM_SERDES9)
+ puts("Work-around for Erratum SERDES9 enabled\n");
+#endif
+#if defined(CONFIG_SYS_P4080_ERRATUM_SERDES_A005)
+ puts("Work-around for Erratum SERDES-A005 enabled\n");
+#endif
+#if defined(CONFIG_SYS_P4080_ERRATUM_CPU22)
+ if (SVR_MAJ(svr) < 3)
+ puts("Work-around for Erratum CPU22 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+ /*
+ * NMG_CPU_A011 applies to P4080 rev 1.0, 2.0, fixed in 3.0
+ * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1
+ * The SVR has been checked by cpu_init_r().
+ */
+ if (enable_cpu_a011_workaround)
+ puts("Work-around for Erratum CPU-A011 enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_CPU_A003999)
+ puts("Work-around for Erratum CPU-A003999 enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_DDR_A003474)
+ puts("Work-around for Erratum DDR-A003473 enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_DDR_MSYNC_IN)
+ puts("Work-around for DDR MSYNC_IN Erratum enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_ESDHC111)
+ puts("Work-around for Erratum ESDHC111 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004468
+ puts("Work-around for Erratum A004468 enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_ESDHC135)
+ puts("Work-around for Erratum ESDHC135 enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_ESDHC13)
+ if (SVR_MAJ(svr) < 3)
+ puts("Work-around for Erratum ESDHC13 enabled\n");
+#endif
+#if defined(CONFIG_SYS_FSL_ERRATUM_ESDHC_A001)
+ puts("Work-around for Erratum ESDHC-A001 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPC_A002
+ puts("Work-around for Erratum CPC-A002 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPC_A003
+ puts("Work-around for Erratum CPC-A003 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+ puts("Work-around for Erratum ELBC-A001 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003
+ puts("Work-around for Erratum DDR-A003 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_115
+ puts("Work-around for Erratum DDR115 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+ puts("Work-around for Erratum DDR111 enabled\n");
+ puts("Work-around for Erratum DDR134 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_IFC_A002769
+ puts("Work-around for Erratum IFC-A002769 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_P1010_A003549
+ puts("Work-around for Erratum P1010-A003549 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_IFC_A003399
+ puts("Work-around for Erratum IFC A-003399 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_DDR120
+ if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
+ puts("Work-around for Erratum NMG DDR120 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_LBC103
+ puts("Work-around for Erratum NMG_LBC103 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
+ if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0))
+ puts("Work-around for Erratum NMG ETSEC129 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
+ puts("Work-around for Erratum A004510 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+ puts("Work-around for Erratum SRIO-A004034 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934
+ puts("Work-around for Erratum A004934 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A005871
+ if (IS_SVR_REV(svr, 1, 0))
+ puts("Work-around for Erratum A005871 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004849
+ /* This work-around is implemented in PBI, so just check for it */
+ check_erratum_a4849(svr);
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004580
+ /* This work-around is implemented in PBI, so just check for it */
+ check_erratum_a4580(svr);
+#endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
+ puts("Work-around for Erratum PCIe-A003 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_USB14
+ puts("Work-around for Erratum USB14 enabled\n");
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006593
+ puts("Work-around for Erratum A006593 enabled\n");
+#endif
+ return 0;
+}
+
+U_BOOT_CMD(
+ errata, 1, 0, do_errata,
+ "Report errata workarounds",
+ ""
+);
diff --git a/arch/powerpc/cpu/mpc85xx/commproc.c b/arch/powerpc/cpu/mpc85xx/commproc.c
new file mode 100644
index 0000000..37e7062
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/commproc.c
@@ -0,0 +1,186 @@
+/*
+ * Adapted for Motorola MPC8560 chips
+ * Xianghua Xiao <x.xiao@motorola.com>
+ *
+ * This file is based on "arch/powerpc/8260_io/commproc.c" - here is it's
+ * copyright notice:
+ *
+ * General Purpose functions for the global management of the
+ * 8220 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
+ * 2.3.99 Updates
+ * Copyright (c) 2003 Motorola,Inc.
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space. The allocator for that is here. When the communication
+ * process is reset, we reclaim the memory available. There is
+ * currently no deallocator for this memory.
+ */
+#include <common.h>
+#include <asm/cpm_85xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * because we have stack and init data in dual port ram
+ * we must reduce the size
+ */
+#undef CPM_DATAONLY_SIZE
+#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+
+void
+m8560_cpm_reset(void)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile ulong count;
+
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /* Reclaim the DP memory for our use.
+ */
+ gd->arch.dp_alloc_base = CPM_DATAONLY_BASE;
+ gd->arch.dp_alloc_top = gd->arch.dp_alloc_base + CPM_DATAONLY_SIZE;
+
+ /*
+ * Reset CPM
+ */
+ cpm->im_cpm_cp.cpcr = CPM_CR_RST;
+ count = 0;
+ do { /* Spin until command processed */
+ __asm__ __volatile__ ("eieio");
+ } while ((cpm->im_cpm_cp.cpcr & CPM_CR_FLG) && ++count < 1000000);
+}
+
+/* Allocate some memory from the dual ported ram.
+ * To help protocols with object alignment restrictions, we do that
+ * if they ask.
+ */
+uint
+m8560_cpm_dpalloc(uint size, uint align)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ uint retloc;
+ uint align_mask, off;
+ uint savebase;
+
+ align_mask = align - 1;
+ savebase = gd->arch.dp_alloc_base;
+
+ off = gd->arch.dp_alloc_base & align_mask;
+ if (off != 0)
+ gd->arch.dp_alloc_base += (align - off);
+
+ if ((off = size & align_mask) != 0)
+ size += align - off;
+
+ if ((gd->arch.dp_alloc_base + size) >= gd->arch.dp_alloc_top) {
+ gd->arch.dp_alloc_base = savebase;
+ panic("m8560_cpm_dpalloc: ran out of dual port ram!");
+ }
+
+ retloc = gd->arch.dp_alloc_base;
+ gd->arch.dp_alloc_base += size;
+
+ memset((void *)&(cpm->im_dprambase[retloc]), 0, size);
+
+ return(retloc);
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8560_cpm_hostalloc(uint size, uint align)
+{
+ /* the host might not even have RAM yet - just use dual port RAM */
+ return (m8560_cpm_dpalloc(size, align));
+}
+
+/* Set a baud rate generator. This needs lots of work. There are
+ * eight BRGs, which can be connected to the CPM channels or output
+ * as clocks. The BRGs are in two different block of internal
+ * memory mapped space.
+ * The baud rate clock is the system clock divided by something.
+ * It was set up long ago during the initial boot phase and is
+ * is given to us.
+ * Baud rate clocks are zero-based in the driver code (as that maps
+ * to port numbers). Documentation uses 1-based numbering.
+ */
+#define BRG_INT_CLK gd->arch.brg_clk
+#define BRG_UART_CLK ((BRG_INT_CLK + 15) / 16)
+
+/* This function is used by UARTS, or anything else that uses a 16x
+ * oversampled clock.
+ */
+void
+m8560_cpm_setbrg(uint brg, uint rate)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = (((((BRG_UART_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+}
+
+/* This function is used to set high speed synchronous baud rate
+ * clocks.
+ */
+void
+m8560_cpm_fastbrg(uint brg, uint rate, int div16)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile uint *bp;
+
+ /* This is good enough to get SMCs running.....
+ */
+ if (brg < 4) {
+ bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = (((((BRG_INT_CLK+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+ if (div16)
+ *bp |= CPM_BRG_DIV16;
+}
+
+/* This function is used to set baud rate generators using an external
+ * clock source and 16x oversampling.
+ */
+
+void
+m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile uint *bp;
+
+ if (brg < 4) {
+ bp = (uint *)&(cpm->im_cpm_brg1.brgc1);
+ }
+ else {
+ bp = (uint *)&(cpm->im_cpm_brg2.brgc5);
+ brg -= 4;
+ }
+ bp += brg;
+ *bp = ((((((extclk/16)+rate-1)/rate)-1)&0xfff)<<1)|CPM_BRG_EN;
+ if (pinsel == 0)
+ *bp |= CPM_BRG_EXTC_CLK3_9;
+ else
+ *bp |= CPM_BRG_EXTC_CLK5_15;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/config.mk b/arch/powerpc/cpu/mpc85xx/config.mk
new file mode 100644
index 0000000..f36d823
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/config.mk
@@ -0,0 +1,33 @@
+#
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao, X.Xiao@motorola.com
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -ffixed-r2 -Wa,-me500 -msoft-float -mno-string
+
+# -mspe=yes is needed to have -mno-spe accepted by a buggy GCC;
+# see "[PATCH,rs6000] make -mno-spe work as expected" on
+# http://gcc.gnu.org/ml/gcc-patches/2008-04/msg00311.html
+PF_CPPFLAGS_SPE := $(call cc-option,-mspe=yes) \
+ $(call cc-option,-mno-spe)
+PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_SPE)
diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c
new file mode 100644
index 0000000..fbee753
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cpu.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright 2004,2007-2011 Freescale Semiconductor, Inc.
+ * (C) Copyright 2002, 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <fsl_esdhc.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/fsl_ifc.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_lbc.h>
+#include <post.h>
+#include <asm/processor.h>
+#include <asm/fsl_ddr_sdram.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Default board reset function
+ */
+static void
+__board_reset(void)
+{
+ /* Do nothing */
+}
+void board_reset(void) __attribute__((weak, alias("__board_reset")));
+
+int checkcpu (void)
+{
+ sys_info_t sysinfo;
+ uint pvr, svr;
+ uint ver;
+ uint major, minor;
+ struct cpu_type *cpu;
+ char buf1[32], buf2[32];
+#if (defined(CONFIG_DDR_CLK_FREQ) || \
+ defined(CONFIG_FSL_CORENET)) && !defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2)
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#endif /* CONFIG_FSL_CORENET */
+
+ /*
+ * Cornet platforms use ddr sync bit in RCW to indicate sync vs async
+ * mode. Previous platform use ddr ratio to do the same. This
+ * information is only for display here.
+ */
+#ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ u32 ddr_sync = 0; /* only async mode is supported */
+#else
+ u32 ddr_sync = ((gur->rcwsr[5]) & FSL_CORENET_RCWSR5_DDR_SYNC)
+ >> FSL_CORENET_RCWSR5_DDR_SYNC_SHIFT;
+#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+#else /* CONFIG_FSL_CORENET */
+#ifdef CONFIG_DDR_CLK_FREQ
+ u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO)
+ >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+#else
+ u32 ddr_ratio = 0;
+#endif /* CONFIG_DDR_CLK_FREQ */
+#endif /* CONFIG_FSL_CORENET */
+
+ unsigned int i, core, nr_cores = cpu_numcores();
+ u32 mask = cpu_mask();
+
+ svr = get_svr();
+ major = SVR_MAJ(svr);
+ minor = SVR_MIN(svr);
+
+ if (cpu_numcores() > 1) {
+#ifndef CONFIG_MP
+ puts("Unicore software on multiprocessor system!!\n"
+ "To enable mutlticore build define CONFIG_MP\n");
+#endif
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
+ printf("CPU%d: ", pic->whoami);
+ } else {
+ puts("CPU: ");
+ }
+
+ cpu = gd->arch.cpu;
+
+ puts(cpu->name);
+ if (IS_E_PROCESSOR(svr))
+ puts("E");
+
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+
+ pvr = get_pvr();
+ ver = PVR_VER(pvr);
+ major = PVR_MAJ(pvr);
+ minor = PVR_MIN(pvr);
+
+ printf("Core: ");
+ switch(ver) {
+ case PVR_VER_E500_V1:
+ case PVR_VER_E500_V2:
+ puts("e500");
+ break;
+ case PVR_VER_E500MC:
+ puts("e500mc");
+ break;
+ case PVR_VER_E5500:
+ puts("e5500");
+ break;
+ case PVR_VER_E6500:
+ puts("e6500");
+ break;
+ default:
+ puts("Unknown");
+ break;
+ }
+
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
+
+ if (nr_cores > CONFIG_MAX_CPUS) {
+ panic("\nUnexpected number of cores: %d, max is %d\n",
+ nr_cores, CONFIG_MAX_CPUS);
+ }
+
+ get_sys_info(&sysinfo);
+
+ puts("Clock Configuration:");
+ for_each_cpu(i, core, nr_cores, mask) {
+ if (!(i & 3))
+ printf ("\n ");
+ printf("CPU%d:%-4s MHz, ", core,
+ strmhz(buf1, sysinfo.freqProcessor[core]));
+ }
+ printf("\n CCB:%-4s MHz,\n", strmhz(buf1, sysinfo.freqSystemBus));
+
+#ifdef CONFIG_FSL_CORENET
+ if (ddr_sync == 1) {
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Synchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ } else {
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Asynchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ }
+#else
+ switch (ddr_ratio) {
+ case 0x0:
+ printf(" DDR:%-4s MHz (%s MT/s data rate), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ break;
+ case 0x7:
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Synchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ break;
+ default:
+ printf(" DDR:%-4s MHz (%s MT/s data rate) "
+ "(Asynchronous), ",
+ strmhz(buf1, sysinfo.freqDDRBus/2),
+ strmhz(buf2, sysinfo.freqDDRBus));
+ break;
+ }
+#endif
+
+#if defined(CONFIG_FSL_LBC)
+ if (sysinfo.freqLocalBus > LCRR_CLKDIV) {
+ printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus));
+ } else {
+ printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n",
+ sysinfo.freqLocalBus);
+ }
+#endif
+
+#if defined(CONFIG_FSL_IFC)
+ printf("IFC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus));
+#endif
+
+#ifdef CONFIG_CPM2
+ printf("CPM: %s MHz\n", strmhz(buf1, sysinfo.freqSystemBus));
+#endif
+
+#ifdef CONFIG_QE
+ printf(" QE:%-4s MHz\n", strmhz(buf1, sysinfo.freqQE));
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ for (i = 0; i < CONFIG_SYS_NUM_FMAN; i++) {
+ printf(" FMAN%d: %s MHz\n", i + 1,
+ strmhz(buf1, sysinfo.freqFMan[i]));
+ }
+#endif
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ printf(" QMAN: %s MHz\n", strmhz(buf1, sysinfo.freqQMAN));
+#endif
+
+#ifdef CONFIG_SYS_DPAA_PME
+ printf(" PME: %s MHz\n", strmhz(buf1, sysinfo.freqPME));
+#endif
+
+ puts("L1: D-cache 32 kB enabled\n I-cache 32 kB enabled\n");
+
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+/* Everything after the first generation of PQ3 parts has RSTCR */
+#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
+ defined(CONFIG_MPC8555) || defined(CONFIG_MPC8560)
+ unsigned long val, msr;
+
+ /*
+ * Initiate hard reset in debug control register DBCR0
+ * Make sure MSR[DE] = 1. This only resets the core.
+ */
+ msr = mfmsr ();
+ msr |= MSR_DE;
+ mtmsr (msr);
+
+ val = mfspr(DBCR0);
+ val |= 0x70000000;
+ mtspr(DBCR0,val);
+#else
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ /* Attempt board-specific reset */
+ board_reset();
+
+ /* Next try asserting HRESET_REQ */
+ out_be32(&gur->rstcr, 0x2);
+ udelay(100);
+#endif
+
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+#ifndef CONFIG_SYS_FSL_TBCLK_DIV
+#define CONFIG_SYS_FSL_TBCLK_DIV 8
+#endif
+unsigned long get_tbclk (void)
+{
+ unsigned long tbclk_div = CONFIG_SYS_FSL_TBCLK_DIV;
+
+ return (gd->bus_clk + (tbclk_div >> 1)) / tbclk_div;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void
+reset_85xx_watchdog(void)
+{
+ /*
+ * Clear TSR(WIS) bit by writing 1
+ */
+ mtspr(SPRN_TSR, TSR_WIS);
+}
+
+void
+watchdog_reset(void)
+{
+ int re_enable = disable_interrupts();
+
+ reset_85xx_watchdog();
+ if (re_enable)
+ enable_interrupts();
+}
+#endif /* CONFIG_WATCHDOG */
+
+/*
+ * Initializes on-chip MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_FSL_ESDHC
+ return fsl_esdhc_mmc_init(bis);
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Print out the state of various machine registers.
+ * Currently prints out LAWs, BR0/OR0 for LBC, CSPR/CSOR/Timing
+ * parameters for IFC and TLBs
+ */
+void mpc85xx_reginfo(void)
+{
+ print_tlbcam();
+ print_laws();
+#if defined(CONFIG_FSL_LBC)
+ print_lbc_regs();
+#endif
+#ifdef CONFIG_FSL_IFC
+ print_ifc_regs();
+#endif
+
+}
+
+/* Common ddr init for non-corenet fsl 85xx platforms */
+#ifndef CONFIG_FSL_CORENET
+#if (defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)) && \
+ !defined(CONFIG_SYS_INIT_L2_ADDR)
+phys_size_t initdram(int board_type)
+{
+#if defined(CONFIG_SPD_EEPROM) || defined(CONFIG_DDR_SPD)
+ return fsl_ddr_sdram_size();
+#else
+ return (phys_size_t)CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
+#endif
+}
+#else /* CONFIG_SYS_RAMBOOT */
+phys_size_t initdram(int board_type)
+{
+ phys_size_t dram_size = 0;
+
+#if defined(CONFIG_SYS_FSL_ERRATUM_DDR_MSYNC_IN)
+ {
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ unsigned int x = 10;
+ unsigned int i;
+
+ /*
+ * Work around to stabilize DDR DLL
+ */
+ out_be32(&gur->ddrdllcr, 0x81000000);
+ asm("sync;isync;msync");
+ udelay(200);
+ while (in_be32(&gur->ddrdllcr) != 0x81000100) {
+ setbits_be32(&gur->devdisr, 0x00010000);
+ for (i = 0; i < x; i++)
+ ;
+ clrbits_be32(&gur->devdisr, 0x00010000);
+ x++;
+ }
+ }
+#endif
+
+#if defined(CONFIG_SPD_EEPROM) || \
+ defined(CONFIG_DDR_SPD) || \
+ defined(CONFIG_SYS_DDR_RAW_TIMING)
+ dram_size = fsl_ddr_sdram();
+#else
+ dram_size = fixed_sdram();
+#endif
+ dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+ dram_size *= 0x100000;
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+ /*
+ * Initialize and enable DDR ECC.
+ */
+ ddr_enable_ecc(dram_size);
+#endif
+
+#if defined(CONFIG_FSL_LBC)
+ /* Some boards also have sdram on the lbc */
+ lbc_sdram_init();
+#endif
+
+ debug("DDR: ");
+ return dram_size;
+}
+#endif /* CONFIG_SYS_RAMBOOT */
+#endif
+
+#if CONFIG_POST & CONFIG_SYS_POST_MEMORY
+
+/* Board-specific functions defined in each board's ddr.c */
+void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
+ unsigned int ctrl_num);
+void read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, unsigned long *epn,
+ phys_addr_t *rpn);
+unsigned int
+ setup_ddr_tlbs_phys(phys_addr_t p_addr, unsigned int memsize_in_meg);
+
+void clear_ddr_tlbs_phys(phys_addr_t p_addr, unsigned int memsize_in_meg);
+
+static void dump_spd_ddr_reg(void)
+{
+ int i, j, k, m;
+ u8 *p_8;
+ u32 *p_32;
+ ccsr_ddr_t *ddr[CONFIG_NUM_DDR_CONTROLLERS];
+ generic_spd_eeprom_t
+ spd[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR];
+
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
+ fsl_ddr_get_spd(spd[i], i);
+
+ puts("SPD data of all dimms (zero vaule is omitted)...\n");
+ puts("Byte (hex) ");
+ k = 1;
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++)
+ printf("Dimm%d ", k++);
+ }
+ puts("\n");
+ for (k = 0; k < sizeof(generic_spd_eeprom_t); k++) {
+ m = 0;
+ printf("%3d (0x%02x) ", k, k);
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ p_8 = (u8 *) &spd[i][j];
+ if (p_8[k]) {
+ printf("0x%02x ", p_8[k]);
+ m++;
+ } else
+ puts(" ");
+ }
+ }
+ if (m)
+ puts("\n");
+ else
+ puts("\r");
+ }
+
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ switch (i) {
+ case 0:
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+ break;
+#if defined(CONFIG_SYS_MPC8xxx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
+ case 1:
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_MPC8xxx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+ case 2:
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR3_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_MPC8xxx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+ case 3:
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR4_ADDR;
+ break;
+#endif
+ default:
+ printf("%s unexpected controller number = %u\n",
+ __func__, i);
+ return;
+ }
+ }
+ printf("DDR registers dump for all controllers "
+ "(zero vaule is omitted)...\n");
+ puts("Offset (hex) ");
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
+ printf(" Base + 0x%04x", (u32)ddr[i] & 0xFFFF);
+ puts("\n");
+ for (k = 0; k < sizeof(ccsr_ddr_t)/4; k++) {
+ m = 0;
+ printf("%6d (0x%04x)", k * 4, k * 4);
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ p_32 = (u32 *) ddr[i];
+ if (p_32[k]) {
+ printf(" 0x%08x", p_32[k]);
+ m++;
+ } else
+ puts(" ");
+ }
+ if (m)
+ puts("\n");
+ else
+ puts("\r");
+ }
+ puts("\n");
+}
+
+/* invalid the TLBs for DDR and setup new ones to cover p_addr */
+static int reset_tlb(phys_addr_t p_addr, u32 size, phys_addr_t *phys_offset)
+{
+ u32 vstart = CONFIG_SYS_DDR_SDRAM_BASE;
+ unsigned long epn;
+ u32 tsize, valid, ptr;
+ int ddr_esel;
+
+ clear_ddr_tlbs_phys(p_addr, size>>20);
+
+ /* Setup new tlb to cover the physical address */
+ setup_ddr_tlbs_phys(p_addr, size>>20);
+
+ ptr = vstart;
+ ddr_esel = find_tlb_idx((void *)ptr, 1);
+ if (ddr_esel != -1) {
+ read_tlbcam_entry(ddr_esel, &valid, &tsize, &epn, phys_offset);
+ } else {
+ printf("TLB error in function %s\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * slide the testing window up to test another area
+ * for 32_bit system, the maximum testable memory is limited to
+ * CONFIG_MAX_MEM_MAPPED
+ */
+int arch_memory_test_advance(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
+{
+ phys_addr_t test_cap, p_addr;
+ phys_size_t p_size = min(gd->ram_size, CONFIG_MAX_MEM_MAPPED);
+
+#if !defined(CONFIG_PHYS_64BIT) || \
+ !defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS) || \
+ (CONFIG_SYS_INIT_RAM_ADDR_PHYS < 0x100000000ull)
+ test_cap = p_size;
+#else
+ test_cap = gd->ram_size;
+#endif
+ p_addr = (*vstart) + (*size) + (*phys_offset);
+ if (p_addr < test_cap - 1) {
+ p_size = min(test_cap - p_addr, CONFIG_MAX_MEM_MAPPED);
+ if (reset_tlb(p_addr, p_size, phys_offset) == -1)
+ return -1;
+ *vstart = CONFIG_SYS_DDR_SDRAM_BASE;
+ *size = (u32) p_size;
+ printf("Testing 0x%08llx - 0x%08llx\n",
+ (u64)(*vstart) + (*phys_offset),
+ (u64)(*vstart) + (*phys_offset) + (*size) - 1);
+ } else
+ return 1;
+
+ return 0;
+}
+
+/* initialization for testing area */
+int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
+{
+ phys_size_t p_size = min(gd->ram_size, CONFIG_MAX_MEM_MAPPED);
+
+ *vstart = CONFIG_SYS_DDR_SDRAM_BASE;
+ *size = (u32) p_size; /* CONFIG_MAX_MEM_MAPPED < 4G */
+ *phys_offset = 0;
+
+#if !defined(CONFIG_PHYS_64BIT) || \
+ !defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS) || \
+ (CONFIG_SYS_INIT_RAM_ADDR_PHYS < 0x100000000ull)
+ if (gd->ram_size > CONFIG_MAX_MEM_MAPPED) {
+ puts("Cannot test more than ");
+ print_size(CONFIG_MAX_MEM_MAPPED,
+ " without proper 36BIT support.\n");
+ }
+#endif
+ printf("Testing 0x%08llx - 0x%08llx\n",
+ (u64)(*vstart) + (*phys_offset),
+ (u64)(*vstart) + (*phys_offset) + (*size) - 1);
+
+ return 0;
+}
+
+/* invalid TLBs for DDR and remap as normal after testing */
+int arch_memory_test_cleanup(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
+{
+ unsigned long epn;
+ u32 tsize, valid, ptr;
+ phys_addr_t rpn = 0;
+ int ddr_esel;
+
+ /* disable the TLBs for this testing */
+ ptr = *vstart;
+
+ while (ptr < (*vstart) + (*size)) {
+ ddr_esel = find_tlb_idx((void *)ptr, 1);
+ if (ddr_esel != -1) {
+ read_tlbcam_entry(ddr_esel, &valid, &tsize, &epn, &rpn);
+ disable_tlb(ddr_esel);
+ }
+ ptr += TSIZE_TO_BYTES(tsize);
+ }
+
+ puts("Remap DDR ");
+ setup_ddr_tlbs(gd->ram_size>>20);
+ puts("\n");
+
+ return 0;
+}
+
+void arch_memory_failure_handle(void)
+{
+ dump_spd_ddr_reg();
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
new file mode 100644
index 0000000..3c8f59c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -0,0 +1,744 @@
+/*
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Modified by Xianghua Xiao, X.Xiao@motorola.com
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/processor.h>
+#include <ioports.h>
+#include <sata.h>
+#include <fm_eth.h>
+#include <asm/io.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_serdes.h>
+#include <asm/fsl_srio.h>
+#include <hwconfig.h>
+#include <linux/compiler.h>
+#include "mp.h"
+#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND
+#include <nand.h>
+#include <errno.h>
+#endif
+
+#include "../../../../drivers/block/fsl_sata.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_QE
+extern qe_iop_conf_t qe_iop_conf_tab[];
+extern void qe_config_iopin(u8 port, u8 pin, int dir,
+ int open_drain, int assign);
+extern void qe_init(uint qe_base);
+extern void qe_reset(void);
+
+static void config_qe_ioports(void)
+{
+ u8 port, pin;
+ int dir, open_drain, assign;
+ int i;
+
+ for (i = 0; qe_iop_conf_tab[i].assign != QE_IOP_TAB_END; i++) {
+ port = qe_iop_conf_tab[i].port;
+ pin = qe_iop_conf_tab[i].pin;
+ dir = qe_iop_conf_tab[i].dir;
+ open_drain = qe_iop_conf_tab[i].open_drain;
+ assign = qe_iop_conf_tab[i].assign;
+ qe_config_iopin(port, pin, dir, open_drain, assign);
+ }
+}
+#endif
+
+#ifdef CONFIG_CPM2
+void config_8560_ioports (volatile ccsr_cpm_t * cpm)
+{
+ int portnum;
+
+ for (portnum = 0; portnum < 4; portnum++) {
+ uint pmsk = 0,
+ ppar = 0,
+ psor = 0,
+ pdir = 0,
+ podr = 0,
+ pdat = 0;
+ iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0];
+ iop_conf_t *eiopc = iopc + 32;
+ uint msk = 1;
+
+ /*
+ * NOTE:
+ * index 0 refers to pin 31,
+ * index 31 refers to pin 0
+ */
+ while (iopc < eiopc) {
+ if (iopc->conf) {
+ pmsk |= msk;
+ if (iopc->ppar)
+ ppar |= msk;
+ if (iopc->psor)
+ psor |= msk;
+ if (iopc->pdir)
+ pdir |= msk;
+ if (iopc->podr)
+ podr |= msk;
+ if (iopc->pdat)
+ pdat |= msk;
+ }
+
+ msk <<= 1;
+ iopc++;
+ }
+
+ if (pmsk != 0) {
+ volatile ioport_t *iop = ioport_addr (cpm, portnum);
+ uint tpmsk = ~pmsk;
+
+ /*
+ * the (somewhat confused) paragraph at the
+ * bottom of page 35-5 warns that there might
+ * be "unknown behaviour" when programming
+ * PSORx and PDIRx, if PPARx = 1, so I
+ * decided this meant I had to disable the
+ * dedicated function first, and enable it
+ * last.
+ */
+ iop->ppar &= tpmsk;
+ iop->psor = (iop->psor & tpmsk) | psor;
+ iop->podr = (iop->podr & tpmsk) | podr;
+ iop->pdat = (iop->pdat & tpmsk) | pdat;
+ iop->pdir = (iop->pdir & tpmsk) | pdir;
+ iop->ppar |= ppar;
+ }
+ }
+}
+#endif
+
+#ifdef CONFIG_SYS_FSL_CPC
+static void enable_cpc(void)
+{
+ int i;
+ u32 size = 0;
+
+ cpc_corenet_t *cpc = (cpc_corenet_t *)CONFIG_SYS_FSL_CPC_ADDR;
+
+ for (i = 0; i < CONFIG_SYS_NUM_CPC; i++, cpc++) {
+ u32 cpccfg0 = in_be32(&cpc->cpccfg0);
+ size += CPC_CFG0_SZ_K(cpccfg0);
+#ifdef CONFIG_RAMBOOT_PBL
+ if (in_be32(&cpc->cpcsrcr0) & CPC_SRCR0_SRAMEN) {
+ /* find and disable LAW of SRAM */
+ struct law_entry law = find_law(CONFIG_SYS_INIT_L3_ADDR);
+
+ if (law.index == -1) {
+ printf("\nFatal error happened\n");
+ return;
+ }
+ disable_law(law.index);
+
+ clrbits_be32(&cpc->cpchdbcr0, CPC_HDBCR0_CDQ_SPEC_DIS);
+ out_be32(&cpc->cpccsr0, 0);
+ out_be32(&cpc->cpcsrcr0, 0);
+ }
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPC_A002
+ setbits_be32(&cpc->cpchdbcr0, CPC_HDBCR0_TAG_ECC_SCRUB_DIS);
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPC_A003
+ setbits_be32(&cpc->cpchdbcr0, CPC_HDBCR0_DATA_ECC_SCRUB_DIS);
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A006593
+ setbits_be32(&cpc->cpchdbcr0, 1 << (31 - 21));
+#endif
+
+ out_be32(&cpc->cpccsr0, CPC_CSR0_CE | CPC_CSR0_PE);
+ /* Read back to sync write */
+ in_be32(&cpc->cpccsr0);
+
+ }
+
+ printf("Corenet Platform Cache: %d KB enabled\n", size);
+}
+
+static void invalidate_cpc(void)
+{
+ int i;
+ cpc_corenet_t *cpc = (cpc_corenet_t *)CONFIG_SYS_FSL_CPC_ADDR;
+
+ for (i = 0; i < CONFIG_SYS_NUM_CPC; i++, cpc++) {
+ /* skip CPC when it used as all SRAM */
+ if (in_be32(&cpc->cpcsrcr0) & CPC_SRCR0_SRAMEN)
+ continue;
+ /* Flash invalidate the CPC and clear all the locks */
+ out_be32(&cpc->cpccsr0, CPC_CSR0_FI | CPC_CSR0_LFC);
+ while (in_be32(&cpc->cpccsr0) & (CPC_CSR0_FI | CPC_CSR0_LFC))
+ ;
+ }
+}
+#else
+#define enable_cpc()
+#define invalidate_cpc()
+#endif /* CONFIG_SYS_FSL_CPC */
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map
+ * initialize a bunch of registers
+ */
+
+#ifdef CONFIG_FSL_CORENET
+static void corenet_tb_init(void)
+{
+ volatile ccsr_rcpm_t *rcpm =
+ (void *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR);
+ volatile ccsr_pic_t *pic =
+ (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
+ u32 whoami = in_be32(&pic->whoami);
+
+ /* Enable the timebase register for this core */
+ out_be32(&rcpm->ctbenrl, (1 << whoami));
+}
+#endif
+
+void cpu_init_f (void)
+{
+ extern void m8560_cpm_reset (void);
+#ifdef CONFIG_SYS_DCSRBAR_PHYS
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#endif
+#if defined(CONFIG_SECURE_BOOT)
+ struct law_entry law;
+#endif
+#ifdef CONFIG_MPC8548
+ ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
+ uint svr = get_svr();
+
+ /*
+ * CPU2 errata workaround: A core hang possible while executing
+ * a msync instruction and a snoopable transaction from an I/O
+ * master tagged to make quick forward progress is present.
+ * Fixed in silicon rev 2.1.
+ */
+ if ((SVR_MAJ(svr) == 1) || ((SVR_MAJ(svr) == 2 && SVR_MIN(svr) == 0x0)))
+ out_be32(&ecm->eebpcr, in_be32(&ecm->eebpcr) | (1 << 16));
+#endif
+
+ disable_tlb(14);
+ disable_tlb(15);
+
+#if defined(CONFIG_SECURE_BOOT)
+ /* Disable the LAW created for NOR flash by the PBI commands */
+ law = find_law(CONFIG_SYS_PBI_FLASH_BASE);
+ if (law.index != -1)
+ disable_law(law.index);
+#endif
+
+#ifdef CONFIG_CPM2
+ config_8560_ioports((ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR);
+#endif
+
+ init_early_memctl_regs();
+
+#if defined(CONFIG_CPM2)
+ m8560_cpm_reset();
+#endif
+#ifdef CONFIG_QE
+ /* Config QE ioports */
+ config_qe_ioports();
+#endif
+#if defined(CONFIG_FSL_DMA)
+ dma_init();
+#endif
+#ifdef CONFIG_FSL_CORENET
+ corenet_tb_init();
+#endif
+ init_used_tlb_cams();
+
+ /* Invalidate the CPC before DDR gets enabled */
+ invalidate_cpc();
+
+ #ifdef CONFIG_SYS_DCSRBAR_PHYS
+ /* set DCSRCR so that DCSR space is 1G */
+ setbits_be32(&gur->dcsrcr, FSL_CORENET_DCSR_SZ_1G);
+ in_be32(&gur->dcsrcr);
+#endif
+
+}
+
+/* Implement a dummy function for those platforms w/o SERDES */
+static void __fsl_serdes__init(void)
+{
+ return ;
+}
+__attribute__((weak, alias("__fsl_serdes__init"))) void fsl_serdes_init(void);
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+int enable_cluster_l2(void)
+{
+ int i = 0;
+ u32 cluster;
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ struct ccsr_cluster_l2 __iomem *l2cache;
+
+ cluster = in_be32(&gur->tp_cluster[i].lower);
+ if (cluster & TP_CLUSTER_EOC)
+ return 0;
+
+ /* The first cache has already been set up, so skip it */
+ i++;
+
+ /* Look through the remaining clusters, and set up their caches */
+ do {
+ int j, cluster_valid = 0;
+
+ l2cache = (void __iomem *)(CONFIG_SYS_FSL_CLUSTER_1_L2 + i * 0x40000);
+
+ cluster = in_be32(&gur->tp_cluster[i].lower);
+
+ /* check that at least one core/accel is enabled in cluster */
+ for (j = 0; j < 4; j++) {
+ u32 idx = (cluster >> (j*8)) & TP_CLUSTER_INIT_MASK;
+ u32 type = in_be32(&gur->tp_ityp[idx]);
+
+ if (type & TP_ITYP_AV)
+ cluster_valid = 1;
+ }
+
+ if (cluster_valid) {
+ /* set stash ID to (cluster) * 2 + 32 + 1 */
+ clrsetbits_be32(&l2cache->l2csr1, 0xff, 32 + i * 2 + 1);
+
+ printf("enable l2 for cluster %d %p\n", i, l2cache);
+
+ out_be32(&l2cache->l2csr0, L2CSR0_L2FI|L2CSR0_L2LFC);
+ while ((in_be32(&l2cache->l2csr0)
+ & (L2CSR0_L2FI|L2CSR0_L2LFC)) != 0)
+ ;
+ out_be32(&l2cache->l2csr0, L2CSR0_L2E|L2CSR0_L2PE|L2CSR0_L2REP_MODE);
+ }
+ i++;
+ } while (!(cluster & TP_CLUSTER_EOC));
+
+ return 0;
+}
+#endif
+
+/*
+ * Initialize L2 as cache.
+ *
+ * The newer 8548, etc, parts have twice as much cache, but
+ * use the same bit-encoding as the older 8555, etc, parts.
+ *
+ */
+int cpu_init_r(void)
+{
+ __maybe_unused u32 svr = get_svr();
+#ifdef CONFIG_SYS_LBC_LCRR
+ fsl_lbc_t *lbc = (void __iomem *)LBC_BASE_ADDR;
+#endif
+#ifdef CONFIG_L2_CACHE
+ ccsr_l2cache_t *l2cache = (void __iomem *)CONFIG_SYS_MPC85xx_L2_ADDR;
+#elif defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2)
+ struct ccsr_cluster_l2 * l2cache = (void __iomem *)CONFIG_SYS_FSL_CLUSTER_1_L2;
+#endif
+#if defined(CONFIG_PPC_SPINTABLE_COMPATIBLE) && defined(CONFIG_MP)
+ extern int spin_table_compat;
+ const char *spin;
+#endif
+
+#if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) || \
+ defined(CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011)
+ /*
+ * CPU22 and NMG_CPU_A011 share the same workaround.
+ * CPU22 applies to P4080 rev 1.0, 2.0, fixed in 3.0
+ * NMG_CPU_A011 applies to P4080 rev 1.0, 2.0, fixed in 3.0
+ * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1, both
+ * fixed in 2.0. NMG_CPU_A011 is activated by default and can
+ * be disabled by hwconfig with syntax:
+ *
+ * fsl_cpu_a011:disable
+ */
+ extern int enable_cpu_a011_workaround;
+#ifdef CONFIG_SYS_P4080_ERRATUM_CPU22
+ enable_cpu_a011_workaround = (SVR_MAJ(svr) < 3);
+#else
+ char buffer[HWCONFIG_BUFFER_SIZE];
+ char *buf = NULL;
+ int n, res;
+
+ n = getenv_f("hwconfig", buffer, sizeof(buffer));
+ if (n > 0)
+ buf = buffer;
+
+ res = hwconfig_arg_cmp_f("fsl_cpu_a011", "disable", buf);
+ if (res > 0)
+ enable_cpu_a011_workaround = 0;
+ else {
+ if (n >= HWCONFIG_BUFFER_SIZE) {
+ printf("fsl_cpu_a011 was not found. hwconfig variable "
+ "may be too long\n");
+ }
+ enable_cpu_a011_workaround =
+ (SVR_SOC_VER(svr) == SVR_P4080 && SVR_MAJ(svr) < 3) ||
+ (SVR_SOC_VER(svr) != SVR_P4080 && SVR_MAJ(svr) < 2);
+ }
+#endif
+ if (enable_cpu_a011_workaround) {
+ flush_dcache();
+ mtspr(L1CSR2, (mfspr(L1CSR2) | L1CSR2_DCWS));
+ sync();
+ }
+#endif
+
+#if defined(CONFIG_PPC_SPINTABLE_COMPATIBLE) && defined(CONFIG_MP)
+ spin = getenv("spin_table_compat");
+ if (spin && (*spin == 'n'))
+ spin_table_compat = 0;
+ else
+ spin_table_compat = 1;
+#endif
+
+ puts ("L2: ");
+
+#if defined(CONFIG_L2_CACHE)
+ volatile uint cache_ctl;
+ uint ver;
+ u32 l2siz_field;
+
+ ver = SVR_SOC_VER(svr);
+
+ asm("msync;isync");
+ cache_ctl = l2cache->l2ctl;
+
+#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L2_ADDR)
+ if (cache_ctl & MPC85xx_L2CTL_L2E) {
+ /* Clear L2 SRAM memory-mapped base address */
+ out_be32(&l2cache->l2srbar0, 0x0);
+ out_be32(&l2cache->l2srbar1, 0x0);
+
+ /* set MBECCDIS=0, SBECCDIS=0 */
+ clrbits_be32(&l2cache->l2errdis,
+ (MPC85xx_L2ERRDIS_MBECC |
+ MPC85xx_L2ERRDIS_SBECC));
+
+ /* set L2E=0, L2SRAM=0 */
+ clrbits_be32(&l2cache->l2ctl,
+ (MPC85xx_L2CTL_L2E |
+ MPC85xx_L2CTL_L2SRAM_ENTIRE));
+ }
+#endif
+
+ l2siz_field = (cache_ctl >> 28) & 0x3;
+
+ switch (l2siz_field) {
+ case 0x0:
+ printf(" unknown size (0x%08x)\n", cache_ctl);
+ return -1;
+ break;
+ case 0x1:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8555) {
+ puts("128 KB ");
+ /* set L2E=1, L2I=1, & L2BLKSZ=1 (128 Kbyte) */
+ cache_ctl = 0xc4000000;
+ } else {
+ puts("256 KB ");
+ cache_ctl = 0xc0000000; /* set L2E=1, L2I=1, & L2SRAM=0 */
+ }
+ break;
+ case 0x2:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8555) {
+ puts("256 KB ");
+ /* set L2E=1, L2I=1, & L2BLKSZ=2 (256 Kbyte) */
+ cache_ctl = 0xc8000000;
+ } else {
+ puts ("512 KB ");
+ /* set L2E=1, L2I=1, & L2SRAM=0 */
+ cache_ctl = 0xc0000000;
+ }
+ break;
+ case 0x3:
+ puts("1024 KB ");
+ /* set L2E=1, L2I=1, & L2SRAM=0 */
+ cache_ctl = 0xc0000000;
+ break;
+ }
+
+ if (l2cache->l2ctl & MPC85xx_L2CTL_L2E) {
+ puts("already enabled");
+#if defined(CONFIG_SYS_INIT_L2_ADDR) && defined(CONFIG_SYS_FLASH_BASE)
+ u32 l2srbar = l2cache->l2srbar0;
+ if (l2cache->l2ctl & MPC85xx_L2CTL_L2SRAM_ENTIRE
+ && l2srbar >= CONFIG_SYS_FLASH_BASE) {
+ l2srbar = CONFIG_SYS_INIT_L2_ADDR;
+ l2cache->l2srbar0 = l2srbar;
+ printf(", moving to 0x%08x", CONFIG_SYS_INIT_L2_ADDR);
+ }
+#endif /* CONFIG_SYS_INIT_L2_ADDR */
+ puts("\n");
+ } else {
+ asm("msync;isync");
+ l2cache->l2ctl = cache_ctl; /* invalidate & enable */
+ asm("msync;isync");
+ puts("enabled\n");
+ }
+#elif defined(CONFIG_BACKSIDE_L2_CACHE)
+ if (SVR_SOC_VER(svr) == SVR_P2040) {
+ puts("N/A\n");
+ goto skip_l2;
+ }
+
+ u32 l2cfg0 = mfspr(SPRN_L2CFG0);
+
+ /* invalidate the L2 cache */
+ mtspr(SPRN_L2CSR0, (L2CSR0_L2FI|L2CSR0_L2LFC));
+ while (mfspr(SPRN_L2CSR0) & (L2CSR0_L2FI|L2CSR0_L2LFC))
+ ;
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ /* set stash id to (coreID) * 2 + 32 + L2 (1) */
+ mtspr(SPRN_L2CSR1, (32 + 1));
+#endif
+
+ /* enable the cache */
+ mtspr(SPRN_L2CSR0, CONFIG_SYS_INIT_L2CSR0);
+
+ if (CONFIG_SYS_INIT_L2CSR0 & L2CSR0_L2E) {
+ while (!(mfspr(SPRN_L2CSR0) & L2CSR0_L2E))
+ ;
+ printf("%d KB enabled\n", (l2cfg0 & 0x3fff) * 64);
+ }
+
+skip_l2:
+#elif defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2)
+ if (l2cache->l2csr0 & L2CSR0_L2E)
+ printf("%d KB enabled\n", (l2cache->l2cfg0 & 0x3fff) * 64);
+
+ enable_cluster_l2();
+#else
+ puts("disabled\n");
+#endif
+
+ enable_cpc();
+
+ /* needs to be in ram since code uses global static vars */
+ fsl_serdes_init();
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A005871
+ if (IS_SVR_REV(svr, 1, 0)) {
+ int i;
+ __be32 *p = (void __iomem *)CONFIG_SYS_DCSRBAR + 0xb004c;
+
+ for (i = 0; i < 12; i++) {
+ p += i + (i > 5 ? 11 : 0);
+ out_be32(p, 0x2);
+ }
+ p = (void __iomem *)CONFIG_SYS_DCSRBAR + 0xb0108;
+ out_be32(p, 0x34);
+ }
+#endif
+
+#ifdef CONFIG_SYS_SRIO
+ srio_init();
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
+ char *s = getenv("bootmaster");
+ if (s) {
+ if (!strcmp(s, "SRIO1")) {
+ srio_boot_master(1);
+ srio_boot_master_release_slave(1);
+ }
+ if (!strcmp(s, "SRIO2")) {
+ srio_boot_master(2);
+ srio_boot_master_release_slave(2);
+ }
+ }
+#endif
+#endif
+
+#if defined(CONFIG_MP)
+ setup_mp();
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC13
+ {
+ if (SVR_MAJ(svr) < 3) {
+ void *p;
+ p = (void *)CONFIG_SYS_DCSRBAR + 0x20520;
+ setbits_be32(p, 1 << (31 - 14));
+ }
+ }
+#endif
+
+#ifdef CONFIG_SYS_LBC_LCRR
+ /*
+ * Modify the CLKDIV field of LCRR register to improve the writing
+ * speed for NOR flash.
+ */
+ clrsetbits_be32(&lbc->lcrr, LCRR_CLKDIV, CONFIG_SYS_LBC_LCRR);
+ __raw_readl(&lbc->lcrr);
+ isync();
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_LBC103
+ udelay(100);
+#endif
+#endif
+
+#ifdef CONFIG_SYS_FSL_USB1_PHY_ENABLE
+ {
+ ccsr_usb_phy_t *usb_phy1 =
+ (void *)CONFIG_SYS_MPC85xx_USB1_PHY_ADDR;
+ out_be32(&usb_phy1->usb_enable_override,
+ CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE);
+ }
+#endif
+#ifdef CONFIG_SYS_FSL_USB2_PHY_ENABLE
+ {
+ ccsr_usb_phy_t *usb_phy2 =
+ (void *)CONFIG_SYS_MPC85xx_USB2_PHY_ADDR;
+ out_be32(&usb_phy2->usb_enable_override,
+ CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE);
+ }
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_USB14
+ /* On P204x/P304x/P50x0 Rev1.0, USB transmit will result internal
+ * multi-bit ECC errors which has impact on performance, so software
+ * should disable all ECC reporting from USB1 and USB2.
+ */
+ if (IS_SVR_REV(get_svr(), 1, 0)) {
+ struct dcsr_dcfg_regs *dcfg = (struct dcsr_dcfg_regs *)
+ (CONFIG_SYS_DCSRBAR + CONFIG_SYS_DCSR_DCFG_OFFSET);
+ setbits_be32(&dcfg->ecccr1,
+ (DCSR_DCFG_ECC_DISABLE_USB1 |
+ DCSR_DCFG_ECC_DISABLE_USB2));
+ }
+#endif
+
+#if defined(CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE)
+ ccsr_usb_phy_t *usb_phy =
+ (void *)CONFIG_SYS_MPC85xx_USB1_PHY_ADDR;
+ setbits_be32(&usb_phy->pllprg[1],
+ CONFIG_SYS_FSL_USB_PLLPRG2_PHY2_CLK_EN |
+ CONFIG_SYS_FSL_USB_PLLPRG2_PHY1_CLK_EN |
+ CONFIG_SYS_FSL_USB_PLLPRG2_MFI |
+ CONFIG_SYS_FSL_USB_PLLPRG2_PLL_EN);
+ setbits_be32(&usb_phy->port1.ctrl,
+ CONFIG_SYS_FSL_USB_CTRL_PHY_EN);
+ setbits_be32(&usb_phy->port1.drvvbuscfg,
+ CONFIG_SYS_FSL_USB_DRVVBUS_CR_EN);
+ setbits_be32(&usb_phy->port1.pwrfltcfg,
+ CONFIG_SYS_FSL_USB_PWRFLT_CR_EN);
+ setbits_be32(&usb_phy->port2.ctrl,
+ CONFIG_SYS_FSL_USB_CTRL_PHY_EN);
+ setbits_be32(&usb_phy->port2.drvvbuscfg,
+ CONFIG_SYS_FSL_USB_DRVVBUS_CR_EN);
+ setbits_be32(&usb_phy->port2.pwrfltcfg,
+ CONFIG_SYS_FSL_USB_PWRFLT_CR_EN);
+#endif
+
+#ifdef CONFIG_FMAN_ENET
+ fman_enet_init();
+#endif
+
+#if defined(CONFIG_FSL_SATA_V2) && defined(CONFIG_FSL_SATA_ERRATUM_A001)
+ /*
+ * For P1022/1013 Rev1.0 silicon, after power on SATA host
+ * controller is configured in legacy mode instead of the
+ * expected enterprise mode. Software needs to clear bit[28]
+ * of HControl register to change to enterprise mode from
+ * legacy mode. We assume that the controller is offline.
+ */
+ if (IS_SVR_REV(svr, 1, 0) &&
+ ((SVR_SOC_VER(svr) == SVR_P1022) ||
+ (SVR_SOC_VER(svr) == SVR_P1013))) {
+ fsl_sata_reg_t *reg;
+
+ /* first SATA controller */
+ reg = (void *)CONFIG_SYS_MPC85xx_SATA1_ADDR;
+ clrbits_le32(&reg->hcontrol, HCONTROL_ENTERPRISE_EN);
+
+ /* second SATA controller */
+ reg = (void *)CONFIG_SYS_MPC85xx_SATA2_ADDR;
+ clrbits_le32(&reg->hcontrol, HCONTROL_ENTERPRISE_EN);
+ }
+#endif
+
+
+ return 0;
+}
+
+extern void setup_ivors(void);
+
+void arch_preboot_os(void)
+{
+ u32 msr;
+
+ /*
+ * We are changing interrupt offsets and are about to boot the OS so
+ * we need to make sure we disable all async interrupts. EE is already
+ * disabled by the time we get called.
+ */
+ msr = mfmsr();
+ msr &= ~(MSR_ME|MSR_CE);
+ mtmsr(msr);
+
+ setup_ivors();
+}
+
+#if defined(CONFIG_CMD_SATA) && defined(CONFIG_FSL_SATA)
+int sata_initialize(void)
+{
+ if (is_serdes_configured(SATA1) || is_serdes_configured(SATA2))
+ return __sata_initialize();
+
+ return 1;
+}
+#endif
+
+void cpu_secondary_init_r(void)
+{
+#ifdef CONFIG_QE
+ uint qe_base = CONFIG_SYS_IMMR + 0x00080000; /* QE immr base */
+#ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND
+ int ret;
+ size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
+
+ /* load QE firmware from NAND flash to DDR first */
+ ret = nand_read(&nand_info[0], (loff_t)CONFIG_SYS_QE_FMAN_FW_IN_NAND,
+ &fw_length, (u_char *)CONFIG_SYS_QE_FMAN_FW_ADDR);
+
+ if (ret && ret == -EUCLEAN) {
+ printf ("NAND read for QE firmware at offset %x failed %d\n",
+ CONFIG_SYS_QE_FMAN_FW_IN_NAND, ret);
+ }
+#endif
+ qe_init(qe_base);
+ qe_reset();
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init_early.c b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c
new file mode 100644
index 0000000..3b3c82f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init_early.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_A003399_NOR_WORKAROUND
+void setup_ifc(void)
+{
+ struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
+ u32 _mas0, _mas1, _mas2, _mas3, _mas7;
+ phys_addr_t flash_phys = CONFIG_SYS_FLASH_BASE_PHYS;
+
+ /*
+ * Adjust the TLB we were running out of to match the phys addr of the
+ * chip select we are adjusting and will return to.
+ */
+ flash_phys += (~CONFIG_SYS_AMASK0) + 1 - 4*1024*1024;
+
+ _mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(15);
+ _mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_IPROT |
+ MAS1_TSIZE(BOOKE_PAGESZ_4M);
+ _mas2 = FSL_BOOKE_MAS2(CONFIG_SYS_TEXT_BASE, MAS2_I|MAS2_G);
+ _mas3 = FSL_BOOKE_MAS3(flash_phys, 0, MAS3_SW|MAS3_SR|MAS3_SX);
+ _mas7 = FSL_BOOKE_MAS7(flash_phys);
+
+ mtspr(MAS0, _mas0);
+ mtspr(MAS1, _mas1);
+ mtspr(MAS2, _mas2);
+ mtspr(MAS3, _mas3);
+ mtspr(MAS7, _mas7);
+
+ asm volatile("isync;msync;tlbwe;isync");
+
+#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB)
+/*
+ * TLB entry for debuggging in AS1
+ * Create temporary TLB entry in AS0 to handle debug exception
+ * As on debug exception MSR is cleared i.e. Address space is changed
+ * to 0. A TLB entry (in AS0) is required to handle debug exception generated
+ * in AS1.
+ *
+ * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
+ * bacause flash's physical address is going to change as
+ * CONFIG_SYS_FLASH_BASE_PHYS.
+ */
+ _mas0 = MAS0_TLBSEL(1) |
+ MAS0_ESEL(CONFIG_SYS_PPC_E500_DEBUG_TLB);
+ _mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_IPROT |
+ MAS1_TSIZE(BOOKE_PAGESZ_4M);
+ _mas2 = FSL_BOOKE_MAS2(CONFIG_SYS_TEXT_BASE, MAS2_I|MAS2_G);
+ _mas3 = FSL_BOOKE_MAS3(flash_phys, 0, MAS3_SW|MAS3_SR|MAS3_SX);
+ _mas7 = FSL_BOOKE_MAS7(flash_phys);
+
+ mtspr(MAS0, _mas0);
+ mtspr(MAS1, _mas1);
+ mtspr(MAS2, _mas2);
+ mtspr(MAS3, _mas3);
+ mtspr(MAS7, _mas7);
+
+ asm volatile("isync;msync;tlbwe;isync");
+#endif
+
+ /* Change flash's physical address */
+ out_be32(&(ifc_regs->cspr_cs[0].cspr), CONFIG_SYS_CSPR0);
+ out_be32(&(ifc_regs->csor_cs[0].csor), CONFIG_SYS_CSOR0);
+ out_be32(&(ifc_regs->amask_cs[0].amask), CONFIG_SYS_AMASK0);
+
+ return ;
+}
+#endif
+
+/* We run cpu_init_early_f in AS = 1 */
+void cpu_init_early_f(void)
+{
+ u32 mas0, mas1, mas2, mas3, mas7;
+ int i;
+#ifdef CONFIG_SYS_FSL_ERRATUM_P1010_A003549
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#endif
+#ifdef CONFIG_A003399_NOR_WORKAROUND
+ ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+ u32 *dst, *src;
+ void (*setup_ifc_sram)(void);
+#endif
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /*
+ * Clear initial global data
+ * we don't use memset so we can share this code with NAND_SPL
+ */
+ for (i = 0; i < sizeof(gd_t); i++)
+ ((char *)gd)[i] = 0;
+
+ mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(13);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS | MAS1_TSIZE(BOOKE_PAGESZ_1M);
+ mas2 = FSL_BOOKE_MAS2(CONFIG_SYS_CCSRBAR, MAS2_I|MAS2_G);
+ mas3 = FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS, 0, MAS3_SW|MAS3_SR);
+ mas7 = FSL_BOOKE_MAS7(CONFIG_SYS_CCSRBAR_PHYS);
+
+ write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+/*
+ * Work Around for IFC Erratum A-003549. This issue is P1010
+ * specific. LCLK(a free running clk signal) is muxed with IFC_CS3 on P1010 SOC
+ * Hence specifically selecting CS3.
+ */
+#ifdef CONFIG_SYS_FSL_ERRATUM_P1010_A003549
+ setbits_be32(&gur->pmuxcr, MPC85xx_PMUXCR_LCLK_IFC_CS3);
+#endif
+
+ init_laws();
+
+/*
+ * Work Around for IFC Erratum A003399, issue will hit only when execution
+ * from NOR Flash
+ */
+#ifdef CONFIG_A003399_NOR_WORKAROUND
+#define SRAM_BASE_ADDR (0x00000000)
+ /* TLB for SRAM */
+ mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(9);
+ mas1 = MAS1_VALID | MAS1_TID(0) | MAS1_TS |
+ MAS1_TSIZE(BOOKE_PAGESZ_1M);
+ mas2 = FSL_BOOKE_MAS2(SRAM_BASE_ADDR, MAS2_I);
+ mas3 = FSL_BOOKE_MAS3(SRAM_BASE_ADDR, 0, MAS3_SX|MAS3_SW|MAS3_SR);
+ mas7 = FSL_BOOKE_MAS7(0);
+
+ write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ out_be32(&l2cache->l2srbar0, SRAM_BASE_ADDR);
+
+ out_be32(&l2cache->l2errdis,
+ (MPC85xx_L2ERRDIS_MBECC | MPC85xx_L2ERRDIS_SBECC));
+
+ out_be32(&l2cache->l2ctl,
+ (MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE));
+
+ /*
+ * Copy the code in setup_ifc to L2SRAM. Do a word copy
+ * because NOR Flash on P1010 does not support byte
+ * access (Erratum IFC-A002769)
+ */
+ setup_ifc_sram = (void *)SRAM_BASE_ADDR;
+ dst = (u32 *) SRAM_BASE_ADDR;
+ src = (u32 *) setup_ifc;
+ for (i = 0; i < 1024; i++)
+ *dst++ = *src++;
+
+ setup_ifc_sram();
+
+ /* CLEANUP */
+ clrbits_be32(&l2cache->l2ctl,
+ (MPC85xx_L2CTL_L2E |
+ MPC85xx_L2CTL_L2SRAM_ENTIRE));
+ out_be32(&l2cache->l2srbar0, 0x0);
+#endif
+
+ invalidate_tlb(1);
+
+#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && \
+ !(defined(CONFIG_SPL_INIT_MINIMAL) && defined(CONFIG_SPL_BUILD)) && \
+ !defined(CONFIG_NAND_SPL)
+ disable_tlb(CONFIG_SYS_PPC_E500_DEBUG_TLB);
+#endif
+
+ init_tlbs();
+}
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
new file mode 100644
index 0000000..8a86819
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ volatile ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+
+ if (ctrl_num != 0) {
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+ } else if (i == 1) {
+ out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+ } else if (i == 2) {
+ out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+ } else if (i == 3) {
+ out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs3_config, regs->cs[i].config);
+ }
+ }
+
+ out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+#if defined(CONFIG_MPC8555) || defined(CONFIG_MPC8541)
+ out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+#endif
+
+ /*
+ * 200 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ */
+ udelay(200);
+ asm volatile("sync;isync");
+
+ out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+ asm("sync;isync;msync");
+ udelay(500);
+}
+
+#if defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+/*
+ * Initialize all of memory for ECC, then enable errors.
+ */
+
+void
+ddr_enable_ecc(unsigned int dram_size)
+{
+ volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR);
+
+ dma_meminit(CONFIG_MEM_INIT_VALUE, dram_size);
+
+ /*
+ * Enable errors for ECC.
+ */
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+ ddr->err_disable = 0x00000000;
+ asm("sync;isync;msync");
+ debug("DMA DDR: err_disable = 0x%08x\n", ddr->err_disable);
+}
+
+#endif /* CONFIG_DDR_ECC && ! CONFIG_ECC_INIT_VIA_DDRCONTROLLER */
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
new file mode 100644
index 0000000..a705862
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+
+#if defined(CONFIG_SYS_FSL_ERRATUM_NMG_DDR120) && defined(CONFIG_MPC85xx)
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ uint svr;
+#endif
+
+ if (ctrl_num) {
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_DDR120
+ /*
+ * Set the DDR IO receiver to an acceptable bias point.
+ * Fixed in Rev 2.1.
+ */
+ svr = get_svr();
+ if ((SVR_MAJ(svr) == 1) || IS_SVR_REV(svr, 2, 0)) {
+ if ((regs->ddr_sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) ==
+ SDRAM_CFG_SDRAM_TYPE_DDR2)
+ out_be32(&gur->ddrioovcr, 0x90000000);
+ else
+ out_be32(&gur->ddrioovcr, 0xA8000000);
+ }
+#endif
+
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+ } else if (i == 1) {
+ out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+ } else if (i == 2) {
+ out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+ } else if (i == 3) {
+ out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs3_config, regs->cs[i].config);
+ }
+ }
+
+ out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+ out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+ out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+ out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+ out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+ out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+ out_be32(&ddr->init_addr, regs->ddr_init_addr);
+ out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+ /*
+ * 200 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ */
+ udelay(200);
+ asm volatile("sync;isync");
+
+ out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+ /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
+ while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
+ udelay(10000); /* throttle polling rate */
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
new file mode 100644
index 0000000..c5b4720
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/processor.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num)
+{
+ unsigned int i, bus_width;
+ volatile ccsr_ddr_t *ddr;
+ u32 temp_sdram_cfg;
+ u32 total_gb_size_per_controller;
+ int timeout;
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+ int timeout_save;
+ volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR;
+ unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t;
+ int csn = -1;
+#endif
+
+ switch (ctrl_num) {
+ case 0:
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+ break;
+#if defined(CONFIG_SYS_MPC8xxx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
+ case 1:
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_MPC8xxx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+ case 2:
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR3_ADDR;
+ break;
+#endif
+#if defined(CONFIG_SYS_MPC8xxx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+ case 3:
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR4_ADDR;
+ break;
+#endif
+ default:
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+ if (regs->ddr_eor)
+ out_be32(&ddr->eor, regs->ddr_eor);
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+ debug("Workaround for ERRATUM_DDR111_DDR134\n");
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ cs_sa = (regs->cs[i].bnds >> 16) & 0xfff;
+ cs_ea = regs->cs[i].bnds & 0xfff;
+ if ((cs_sa <= 0xff) && (cs_ea >= 0xff)) {
+ csn = i;
+ csn_bnds_backup = regs->cs[i].bnds;
+ csn_bnds_t = (unsigned int *) &regs->cs[i].bnds;
+ if (cs_ea > 0xeff)
+ *csn_bnds_t = regs->cs[i].bnds + 0x01000000;
+ else
+ *csn_bnds_t = regs->cs[i].bnds + 0x01000100;
+ debug("Found cs%d_bns (0x%08x) covering 0xff000000, "
+ "change it to 0x%x\n",
+ csn, csn_bnds_backup, regs->cs[i].bnds);
+ break;
+ }
+ }
+#endif
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs0_config, regs->cs[i].config);
+ out_be32(&ddr->cs0_config_2, regs->cs[i].config_2);
+
+ } else if (i == 1) {
+ out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs1_config, regs->cs[i].config);
+ out_be32(&ddr->cs1_config_2, regs->cs[i].config_2);
+
+ } else if (i == 2) {
+ out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs2_config, regs->cs[i].config);
+ out_be32(&ddr->cs2_config_2, regs->cs[i].config_2);
+
+ } else if (i == 3) {
+ out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs3_config, regs->cs[i].config);
+ out_be32(&ddr->cs3_config_2, regs->cs[i].config_2);
+ }
+ }
+
+ out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+ out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+ out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+ out_be32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
+ out_be32(&ddr->sdram_mode_4, regs->ddr_sdram_mode_4);
+ out_be32(&ddr->sdram_mode_5, regs->ddr_sdram_mode_5);
+ out_be32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6);
+ out_be32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7);
+ out_be32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8);
+ out_be32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+ out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+ out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+ out_be32(&ddr->init_addr, regs->ddr_init_addr);
+ out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+ out_be32(&ddr->timing_cfg_4, regs->timing_cfg_4);
+ out_be32(&ddr->timing_cfg_5, regs->timing_cfg_5);
+ out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
+ out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
+ if (regs->ddr_wrlvl_cntl_2)
+ out_be32(&ddr->ddr_wrlvl_cntl_2, regs->ddr_wrlvl_cntl_2);
+ if (regs->ddr_wrlvl_cntl_3)
+ out_be32(&ddr->ddr_wrlvl_cntl_3, regs->ddr_wrlvl_cntl_3);
+
+ out_be32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr);
+ out_be32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
+ out_be32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
+ out_be32(&ddr->ddr_cdr1, regs->ddr_cdr1);
+ out_be32(&ddr->ddr_cdr2, regs->ddr_cdr2);
+ out_be32(&ddr->err_disable, regs->err_disable);
+ out_be32(&ddr->err_int_en, regs->err_int_en);
+ for (i = 0; i < 32; i++) {
+ if (regs->debug[i]) {
+ debug("Write to debug_%d as %08x\n", i+1, regs->debug[i]);
+ out_be32(&ddr->debug[i], regs->debug[i]);
+ }
+ }
+#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934
+ out_be32(&ddr->debug[28], 0x30003000);
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003474
+ out_be32(&ddr->debug[12], 0x00000015);
+ out_be32(&ddr->debug[21], 0x24000000);
+#endif /* CONFIG_SYS_FSL_ERRATUM_DDR_A003474 */
+
+ /* Set, but do not enable the memory */
+ temp_sdram_cfg = regs->ddr_sdram_cfg;
+ temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN);
+ out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_A003
+ debug("Workaround for ERRATUM_DDR_A003\n");
+ if (regs->ddr_sdram_rcw_2 & 0x00f00000) {
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2 & 0xf07fffff);
+ out_be32(&ddr->debug[2], 0x00000400);
+ out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl & 0x7fffffff);
+ out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl & 0x7fffffff);
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2 & 0xffffffeb);
+ out_be32(&ddr->mtcr, 0);
+ out_be32(&ddr->debug[12], 0x00000015);
+ out_be32(&ddr->debug[21], 0x24000000);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval & 0xffff);
+ out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_BI | SDRAM_CFG_MEM_EN);
+
+ asm volatile("sync;isync");
+ while (!(in_be32(&ddr->debug[1]) & 0x2))
+ ;
+
+ switch (regs->ddr_sdram_rcw_2 & 0x00f00000) {
+ case 0x00000000:
+ out_be32(&ddr->sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x04000000 |
+ MD_CNTL_WRCW |
+ MD_CNTL_MD_VALUE(0x02));
+ break;
+ case 0x00100000:
+ out_be32(&ddr->sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x04000000 |
+ MD_CNTL_WRCW |
+ MD_CNTL_MD_VALUE(0x0a));
+ break;
+ case 0x00200000:
+ out_be32(&ddr->sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x04000000 |
+ MD_CNTL_WRCW |
+ MD_CNTL_MD_VALUE(0x12));
+ break;
+ case 0x00300000:
+ out_be32(&ddr->sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x04000000 |
+ MD_CNTL_WRCW |
+ MD_CNTL_MD_VALUE(0x1a));
+ break;
+ default:
+ out_be32(&ddr->sdram_md_cntl,
+ MD_CNTL_MD_EN |
+ MD_CNTL_CS_SEL_CS0_CS1 |
+ 0x04000000 |
+ MD_CNTL_WRCW |
+ MD_CNTL_MD_VALUE(0x02));
+ printf("Unsupported RC10\n");
+ break;
+ }
+
+ while (in_be32(&ddr->sdram_md_cntl) & 0x80000000)
+ ;
+ udelay(6);
+ out_be32(&ddr->sdram_cfg, temp_sdram_cfg);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->debug[2], 0x0);
+ out_be32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
+ out_be32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ out_be32(&ddr->debug[12], 0x0);
+ out_be32(&ddr->debug[21], 0x0);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+
+ }
+#endif
+ /*
+ * For 8572 DDR1 erratum - DDR controller may enter illegal state
+ * when operatiing in 32-bit bus mode with 4-beat bursts,
+ * This erratum does not affect DDR3 mode, only for DDR2 mode.
+ */
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR_115
+ debug("Workaround for ERRATUM_DDR_115\n");
+ if ((((in_be32(&ddr->sdram_cfg) >> 24) & 0x7) == SDRAM_TYPE_DDR2)
+ && in_be32(&ddr->sdram_cfg) & 0x80000) {
+ /* set DEBUG_1[31] */
+ setbits_be32(&ddr->debug[0], 1);
+ }
+#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+ debug("Workaround for ERRATUM_DDR111_DDR134\n");
+ /*
+ * This is the combined workaround for DDR111 and DDR134
+ * following the published errata for MPC8572
+ */
+
+ /* 1. Set EEBACR[3] */
+ setbits_be32(&ecm->eebacr, 0x10000000);
+ debug("Setting EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr));
+
+ /* 2. Set DINIT in SDRAM_CFG_2*/
+ setbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_D_INIT);
+ debug("Setting sdram_cfg_2[D_INIT] to 0x%08x\n",
+ in_be32(&ddr->sdram_cfg_2));
+
+ /* 3. Set DEBUG_3[21] */
+ setbits_be32(&ddr->debug[2], 0x400);
+ debug("Setting DEBUG_3[21] to 0x%08x\n", in_be32(&ddr->debug[2]));
+
+#endif /* part 1 of the workaound */
+
+ /*
+ * 500 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ * DDR2 need 200 us, and DDR3 need 500 us from spec,
+ * we choose the max, that is 500 us for all of case.
+ */
+ udelay(500);
+ asm volatile("sync;isync");
+
+ /* Let the controller go */
+ temp_sdram_cfg = in_be32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
+ out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
+ asm volatile("sync;isync");
+
+ total_gb_size_per_controller = 0;
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (!(regs->cs[i].config & 0x80000000))
+ continue;
+ total_gb_size_per_controller += 1 << (
+ ((regs->cs[i].config >> 14) & 0x3) + 2 +
+ ((regs->cs[i].config >> 8) & 0x7) + 12 +
+ ((regs->cs[i].config >> 0) & 0x7) + 8 +
+ 3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) -
+ 26); /* minus 26 (count of 64M) */
+ }
+ if (fsl_ddr_get_intl3r() & 0x80000000) /* 3-way interleaving */
+ total_gb_size_per_controller *= 3;
+ else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */
+ total_gb_size_per_controller <<= 1;
+ /*
+ * total memory / bus width = transactions needed
+ * transactions needed / data rate = seconds
+ * to add plenty of buffer, double the time
+ * For example, 2GB on 666MT/s 64-bit bus takes about 402ms
+ * Let's wait for 800ms
+ */
+ bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK)
+ >> SDRAM_CFG_DBW_SHIFT);
+ timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 /
+ (get_ddr_freq(0) >> 20)) << 1;
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+ timeout_save = timeout;
+#endif
+ total_gb_size_per_controller >>= 4; /* shift down to gb size */
+ debug("total %d GB\n", total_gb_size_per_controller);
+ debug("Need to wait up to %d * 10ms\n", timeout);
+
+ /* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done. */
+ while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) &&
+ (timeout >= 0)) {
+ udelay(10000); /* throttle polling rate */
+ timeout--;
+ }
+
+ if (timeout <= 0)
+ printf("Waiting for D_INIT timeout. Memory may not work.\n");
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+ /* continue this workaround */
+
+ /* 4. Clear DEBUG3[21] */
+ clrbits_be32(&ddr->debug[2], 0x400);
+ debug("Clearing D3[21] to 0x%08x\n", in_be32(&ddr->debug[2]));
+
+ /* DDR134 workaround starts */
+ /* A: Clear sdram_cfg_2[odt_cfg] */
+ clrbits_be32(&ddr->sdram_cfg_2, SDRAM_CFG2_ODT_CFG_MASK);
+ debug("Clearing SDRAM_CFG2[ODT_CFG] to 0x%08x\n",
+ in_be32(&ddr->sdram_cfg_2));
+
+ /* B: Set DEBUG1[15] */
+ setbits_be32(&ddr->debug[0], 0x10000);
+ debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0]));
+
+ /* C: Set timing_cfg_2[cpo] to 0b11111 */
+ setbits_be32(&ddr->timing_cfg_2, TIMING_CFG_2_CPO_MASK);
+ debug("Setting TMING_CFG_2[CPO] to 0x%08x\n",
+ in_be32(&ddr->timing_cfg_2));
+
+ /* D: Set D6 to 0x9f9f9f9f */
+ out_be32(&ddr->debug[5], 0x9f9f9f9f);
+ debug("Setting D6 to 0x%08x\n", in_be32(&ddr->debug[5]));
+
+ /* E: Set D7 to 0x9f9f9f9f */
+ out_be32(&ddr->debug[6], 0x9f9f9f9f);
+ debug("Setting D7 to 0x%08x\n", in_be32(&ddr->debug[6]));
+
+ /* F: Set D2[20] */
+ setbits_be32(&ddr->debug[1], 0x800);
+ debug("Setting D2[20] to 0x%08x\n", in_be32(&ddr->debug[1]));
+
+ /* G: Poll on D2[20] until cleared */
+ while (in_be32(&ddr->debug[1]) & 0x800)
+ udelay(10000); /* throttle polling rate */
+
+ /* H: Clear D1[15] */
+ clrbits_be32(&ddr->debug[0], 0x10000);
+ debug("Setting D1[15] to 0x%08x\n", in_be32(&ddr->debug[0]));
+
+ /* I: Set sdram_cfg_2[odt_cfg] */
+ setbits_be32(&ddr->sdram_cfg_2,
+ regs->ddr_sdram_cfg_2 & SDRAM_CFG2_ODT_CFG_MASK);
+ debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2));
+
+ /* Continuing with the DDR111 workaround */
+ /* 5. Set D2[21] */
+ setbits_be32(&ddr->debug[1], 0x400);
+ debug("Setting D2[21] to 0x%08x\n", in_be32(&ddr->debug[1]));
+
+ /* 6. Poll D2[21] until its cleared */
+ while (in_be32(&ddr->debug[1]) & 0x400)
+ udelay(10000); /* throttle polling rate */
+
+ /* 7. Wait for state machine 2nd run, roughly 400ms/GB */
+ debug("Wait for %d * 10ms\n", timeout_save);
+ udelay(timeout_save * 10000);
+
+ /* 8. Set sdram_cfg_2[dinit] if options requires */
+ setbits_be32(&ddr->sdram_cfg_2,
+ regs->ddr_sdram_cfg_2 & SDRAM_CFG2_D_INIT);
+ debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2));
+
+ /* 9. Poll until dinit is cleared */
+ timeout = timeout_save;
+ debug("Need to wait up to %d * 10ms\n", timeout);
+ while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) &&
+ (timeout >= 0)) {
+ udelay(10000); /* throttle polling rate */
+ timeout--;
+ }
+
+ if (timeout <= 0)
+ printf("Waiting for D_INIT timeout. Memory may not work.\n");
+
+ /* 10. Clear EEBACR[3] */
+ clrbits_be32(&ecm->eebacr, 10000000);
+ debug("Clearing EEBACR[3] to 0x%08x\n", in_be32(&ecm->eebacr));
+
+ if (csn != -1) {
+ csn_bnds_t = (unsigned int *) &regs->cs[csn].bnds;
+ *csn_bnds_t = csn_bnds_backup;
+ debug("Change cs%d_bnds back to 0x%08x\n",
+ csn, regs->cs[csn].bnds);
+ setbits_be32(&ddr->sdram_cfg, 0x2); /* MEM_HALT */
+ switch (csn) {
+ case 0:
+ out_be32(&ddr->cs0_bnds, regs->cs[csn].bnds);
+ break;
+ case 1:
+ out_be32(&ddr->cs1_bnds, regs->cs[csn].bnds);
+ break;
+ case 2:
+ out_be32(&ddr->cs2_bnds, regs->cs[csn].bnds);
+ break;
+ case 3:
+ out_be32(&ddr->cs3_bnds, regs->cs[csn].bnds);
+ break;
+ }
+ clrbits_be32(&ddr->sdram_cfg, 0x2);
+ }
+#endif /* CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134 */
+}
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
new file mode 100644
index 0000000..7d372aa
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -0,0 +1,468 @@
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Copyright (c) 2003 Motorola,Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8560 FCC Fast Ethernet
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * This code will not perform the IO port configuration. This should be
+ * done in the iop_conf_t structure specific for the board.
+ *
+ * TODO:
+ * add a PHY driver to do the negotiation
+ * reflect negotiation results in FPSMR
+ * look for ways to configure the board specific stuff elsewhere, eg.
+ * config_xxx.h or the board directory
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/cpm_85xx.h>
+#include <command.h>
+#include <config.h>
+#include <net.h>
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+#include <miiphy.h>
+#endif
+
+#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET)
+
+static struct ether_fcc_info_s
+{
+ int ether_index;
+ int proff_enet;
+ ulong cpm_cr_enet_sblock;
+ ulong cpm_cr_enet_page;
+ ulong cmxfcr_mask;
+ ulong cmxfcr_value;
+}
+ ether_fcc_info[] =
+{
+#ifdef CONFIG_ETHER_ON_FCC1
+{
+ 0,
+ PROFF_FCC1,
+ CPM_CR_FCC1_SBLOCK,
+ CPM_CR_FCC1_PAGE,
+ CONFIG_SYS_CMXFCR_MASK1,
+ CONFIG_SYS_CMXFCR_VALUE1
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC2
+{
+ 1,
+ PROFF_FCC2,
+ CPM_CR_FCC2_SBLOCK,
+ CPM_CR_FCC2_PAGE,
+ CONFIG_SYS_CMXFCR_MASK2,
+ CONFIG_SYS_CMXFCR_VALUE2
+},
+#endif
+
+#ifdef CONFIG_ETHER_ON_FCC3
+{
+ 2,
+ PROFF_FCC3,
+ CPM_CR_FCC3_SBLOCK,
+ CPM_CR_FCC3_PAGE,
+ CONFIG_SYS_CMXFCR_MASK3,
+ CONFIG_SYS_CMXFCR_VALUE3
+},
+#endif
+};
+
+/*---------------------------------------------------------------------*/
+
+/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */
+#define PKT_MAXDMA_SIZE 1520
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets. */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+
+/* Maximum input buffer size. Must be a multiple of 32. */
+#define PKT_MAXBLR_SIZE 1536
+
+#define TOUT_LOOP 1000000
+
+#define TX_BUF_CNT 2
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * FCC Ethernet Tx and Rx buffer descriptors.
+ * Provide for Double Buffering
+ * Note: PKTBUFSRX is defined in net.h
+ */
+
+typedef volatile struct rtxbd {
+ cbd_t rxbd[PKTBUFSRX];
+ cbd_t txbd[TX_BUF_CNT];
+} RTXBD;
+
+/* Good news: the FCC supports external BDs! */
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+#undef ET_DEBUG
+
+static int fec_send(struct eth_device *dev, void *packet, int length)
+{
+ int i = 0;
+ int result = 0;
+
+ if (length <= 0) {
+ printf("fec: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+ rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx.txbd[txIdx].cbd_datlen = length;
+ rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST | \
+ BD_ENET_TX_TC | BD_ENET_TX_PAD);
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx error\n");
+ goto out;
+ }
+ }
+
+#ifdef ET_DEBUG
+ printf("cycles: 0x%x txIdx=0x%04x status: 0x%04x\n", i, txIdx,rtx.txbd[txIdx].cbd_sc);
+ printf("packets at 0x%08x, length_in_bytes=0x%x\n",(uint)packet,length);
+ for(i=0;i<(length/16 + 1);i++) {
+ printf("%08x %08x %08x %08x\n",*((uint *)rtx.txbd[txIdx].cbd_bufaddr+i*4),\
+ *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 1),*((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 2), \
+ *((uint *)rtx.txbd[txIdx].cbd_bufaddr + i*4 + 3));
+ }
+#endif
+
+ /* return only status bits */
+ result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+ txIdx = (txIdx + 1) % TX_BUF_CNT;
+
+out:
+ return result;
+}
+
+static int fec_recv(struct eth_device* dev)
+{
+ int length;
+
+ for (;;)
+ {
+ if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+ length = rtx.rxbd[rxIdx].cbd_datlen;
+
+ if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
+ printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
+ }
+ else {
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ }
+
+
+ /* Give the buffer back to the FCC. */
+ rtx.rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ }
+ else {
+ rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+ }
+ return length;
+}
+
+
+static int fec_init(struct eth_device* dev, bd_t *bis)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ int i;
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
+ fcc_enet_t *pram_ptr;
+ unsigned long mem_addr;
+
+#if 0
+ mii_discover_phy();
+#endif
+
+ /* 28.9 - (1-2): ioports have been set up already */
+
+ /* 28.9 - (3): connect FCC's tx and rx clocks */
+ cpm->im_cpm_mux.cmxuar = 0; /* ATM */
+ cpm->im_cpm_mux.cmxfcr = (cpm->im_cpm_mux.cmxfcr & ~info->cmxfcr_mask) |
+ info->cmxfcr_value;
+
+ /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, set Mode Ethernet */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ } else if (info->ether_index == 2) {
+ cpm->im_cpm_fcc3.gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+ }
+
+ /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet,MII */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+ } else if (info->ether_index == 1){
+ cpm->im_cpm_fcc2.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+ } else if (info->ether_index == 2){
+ cpm->im_cpm_fcc3.fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
+ }
+
+ /* 28.9 - (6): FDSR: Ethernet Syn */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.fdsr = 0xD555;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.fdsr = 0xD555;
+ } else if (info->ether_index == 2) {
+ cpm->im_cpm_fcc3.fdsr = 0xD555;
+ }
+
+ /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
+ rxIdx = 0;
+ txIdx = 0;
+
+ /* Setup Receiver Buffer Descriptors */
+ for (i = 0; i < PKTBUFSRX; i++)
+ {
+ rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ rtx.rxbd[i].cbd_datlen = 0;
+ rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+ }
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /* Setup Ethernet Transmitter Buffer Descriptors */
+ for (i = 0; i < TX_BUF_CNT; i++)
+ {
+ rtx.txbd[i].cbd_sc = 0;
+ rtx.txbd[i].cbd_datlen = 0;
+ rtx.txbd[i].cbd_bufaddr = 0;
+ }
+ rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /* 28.9 - (7): initialize parameter ram */
+ pram_ptr = (fcc_enet_t *)&(cpm->im_dprambase[info->proff_enet]);
+
+ /* clear whole structure to make sure all reserved fields are zero */
+ memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
+
+ /*
+ * common Parameter RAM area
+ *
+ * Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ * CPM_FCC_SPECIAL_BASE: 0xB000 for MPC8540, MPC8560
+ * 0x9000 for MPC8541, MPC8555
+ */
+ mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
+ pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
+ pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
+ /*
+ * Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; /* 1536 */
+ /* localbus SDRAM should be preferred */
+ pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
+ CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+ pram_ptr->fen_genfcc.fcc_rbdstat = 0;
+ pram_ptr->fen_genfcc.fcc_rbdlen = 0;
+ pram_ptr->fen_genfcc.fcc_rdptr = 0;
+ /* localbus SDRAM should be preferred */
+ pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
+ CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
+ pram_ptr->fen_genfcc.fcc_tbdstat = 0;
+ pram_ptr->fen_genfcc.fcc_tbdlen = 0;
+ pram_ptr->fen_genfcc.fcc_tdptr = 0;
+
+ /* protocol-specific area */
+ pram_ptr->fen_statbuf = 0x0;
+ pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */
+ pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */
+ pram_ptr->fen_crcec = 0;
+ pram_ptr->fen_alec = 0;
+ pram_ptr->fen_disfc = 0;
+ pram_ptr->fen_retlim = 15; /* Retry limit threshold */
+ pram_ptr->fen_retcnt = 0;
+ pram_ptr->fen_pper = 0;
+ pram_ptr->fen_boffcnt = 0;
+ pram_ptr->fen_gaddrh = 0;
+ pram_ptr->fen_gaddrl = 0;
+ pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ /*
+ * Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ * So far we have only been given one Ethernet address. We make
+ * it unique by setting a few bits in the upper byte of the
+ * non-static part of the address.
+ */
+#define ea eth_get_dev()->enetaddr
+ pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
+ pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
+ pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+ pram_ptr->fen_ibdcount = 0;
+ pram_ptr->fen_ibdstart = 0;
+ pram_ptr->fen_ibdend = 0;
+ pram_ptr->fen_txlen = 0;
+ pram_ptr->fen_iaddrh = 0; /* disable hash */
+ pram_ptr->fen_iaddrl = 0;
+ pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register: 64 */
+ /* pad pointer. use tiptr since we don't need a specific padding char */
+ pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
+ pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length:1520 */
+ pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length:1520 */
+
+#if defined(ET_DEBUG)
+ printf("parm_ptr(0xff788500) = %p\n",pram_ptr);
+ printf("pram_ptr->fen_genfcc.fcc_rbase %08x\n",
+ pram_ptr->fen_genfcc.fcc_rbase);
+ printf("pram_ptr->fen_genfcc.fcc_tbase %08x\n",
+ pram_ptr->fen_genfcc.fcc_tbase);
+#endif
+
+ /* 28.9 - (8)(9): clear out events in FCCE */
+ /* 28.9 - (9): FCCM: mask all events */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.fcce = ~0x0;
+ cpm->im_cpm_fcc1.fccm = 0;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.fcce = ~0x0;
+ cpm->im_cpm_fcc2.fccm = 0;
+ } else if (info->ether_index == 2) {
+ cpm->im_cpm_fcc3.fcce = ~0x0;
+ cpm->im_cpm_fcc3.fccm = 0;
+ }
+
+ /* 28.9 - (10-12): we don't use ethernet interrupts */
+
+ /* 28.9 - (13)
+ *
+ * Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cp->cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
+ info->cpm_cr_enet_sblock,
+ 0x0c,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ do {
+ __asm__ __volatile__ ("eieio");
+ } while (cp->cpcr & CPM_CR_FLG);
+
+ /* 28.9 - (14): enable tx/rx in gfmr */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ } else if (info->ether_index == 1) {
+ cpm->im_cpm_fcc2.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ } else if (info->ether_index == 2) {
+ cpm->im_cpm_fcc3.gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+ }
+
+ return 1;
+}
+
+static void fec_halt(struct eth_device* dev)
+{
+ struct ether_fcc_info_s * info = dev->priv;
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+ /* write GFMR: disable tx/rx */
+ if(info->ether_index == 0) {
+ cpm->im_cpm_fcc1.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ } else if(info->ether_index == 1) {
+ cpm->im_cpm_fcc2.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ } else if(info->ether_index == 2) {
+ cpm->im_cpm_fcc3.gfmr &= ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+ }
+}
+
+int fec_initialize(bd_t *bis)
+{
+ struct eth_device* dev;
+ int i;
+
+ for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+ {
+ dev = (struct eth_device*) malloc(sizeof *dev);
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "FCC%d",
+ ether_fcc_info[i].ether_index + 1);
+ dev->priv = &ether_fcc_info[i];
+ dev->init = fec_init;
+ dev->halt = fec_halt;
+ dev->send = fec_send;
+ dev->recv = fec_recv;
+
+ eth_register(dev);
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
+ && defined(CONFIG_BITBANGMII)
+ miiphy_register(dev->name,
+ bb_miiphy_read, bb_miiphy_write);
+#endif
+ }
+
+ return 1;
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
new file mode 100644
index 0000000..bb95f3d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -0,0 +1,835 @@
+/*
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/processor.h>
+#include <linux/ctype.h>
+#include <asm/io.h>
+#include <asm/fsl_portals.h>
+#ifdef CONFIG_FSL_ESDHC
+#include <fsl_esdhc.h>
+#endif
+#include "../../../../drivers/qe/qe.h" /* For struct qe_firmware */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void ft_qe_setup(void *blob);
+extern void ft_fixup_num_cores(void *blob);
+extern void ft_srio_setup(void *blob);
+
+#ifdef CONFIG_MP
+#include "mp.h"
+
+void ft_fixup_cpu(void *blob, u64 memory_limit)
+{
+ int off;
+ phys_addr_t spin_tbl_addr = get_spin_phys_addr();
+ u32 bootpg = determine_mp_bootpg(NULL);
+ u32 id = get_my_id();
+ const char *enable_method;
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+
+ if (reg) {
+ u32 phys_cpu_id = thread_to_core(*reg);
+ u64 val = phys_cpu_id * SIZE_BOOT_ENTRY + spin_tbl_addr;
+ val = cpu_to_fdt64(val);
+ if (*reg == id) {
+ fdt_setprop_string(blob, off, "status",
+ "okay");
+ } else {
+ fdt_setprop_string(blob, off, "status",
+ "disabled");
+ }
+
+ if (hold_cores_in_reset(0)) {
+#ifdef CONFIG_FSL_CORENET
+ /* Cores held in reset, use BRR to release */
+ enable_method = "fsl,brr-holdoff";
+#else
+ /* Cores held in reset, use EEBPCR to release */
+ enable_method = "fsl,eebpcr-holdoff";
+#endif
+ } else {
+ /* Cores out of reset and in a spin-loop */
+ enable_method = "spin-table";
+
+ fdt_setprop(blob, off, "cpu-release-addr",
+ &val, sizeof(val));
+ }
+
+ fdt_setprop_string(blob, off, "enable-method",
+ enable_method);
+ } else {
+ printf ("cpu NULL\n");
+ }
+ off = fdt_node_offset_by_prop_value(blob, off,
+ "device_type", "cpu", 4);
+ }
+
+ /* Reserve the boot page so OSes dont use it */
+ if ((u64)bootpg < memory_limit) {
+ off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
+ if (off < 0)
+ printf("Failed to reserve memory for bootpg: %s\n",
+ fdt_strerror(off));
+ }
+
+#ifndef CONFIG_MPC8xxx_DISABLE_BPTR
+ /*
+ * Reserve the default boot page so OSes dont use it.
+ * The default boot page is always mapped to bootpg above using
+ * boot page translation.
+ */
+ if (0xfffff000ull < memory_limit) {
+ off = fdt_add_mem_rsv(blob, 0xfffff000ull, (u64)4096);
+ if (off < 0) {
+ printf("Failed to reserve memory for 0xfffff000: %s\n",
+ fdt_strerror(off));
+ }
+ }
+#endif
+
+ /* Reserve spin table page */
+ if (spin_tbl_addr < memory_limit) {
+ off = fdt_add_mem_rsv(blob,
+ (spin_tbl_addr & ~0xffful), 4096);
+ if (off < 0)
+ printf("Failed to reserve memory for spin table: %s\n",
+ fdt_strerror(off));
+ }
+}
+#endif
+
+#ifdef CONFIG_SYS_FSL_CPC
+static inline void ft_fixup_l3cache(void *blob, int off)
+{
+ u32 line_size, num_ways, size, num_sets;
+ cpc_corenet_t *cpc = (void *)CONFIG_SYS_FSL_CPC_ADDR;
+ u32 cfg0 = in_be32(&cpc->cpccfg0);
+
+ size = CPC_CFG0_SZ_K(cfg0) * 1024 * CONFIG_SYS_NUM_CPC;
+ num_ways = CPC_CFG0_NUM_WAYS(cfg0);
+ line_size = CPC_CFG0_LINE_SZ(cfg0);
+ num_sets = size / (line_size * num_ways);
+
+ fdt_setprop(blob, off, "cache-unified", NULL, 0);
+ fdt_setprop_cell(blob, off, "cache-block-size", line_size);
+ fdt_setprop_cell(blob, off, "cache-size", size);
+ fdt_setprop_cell(blob, off, "cache-sets", num_sets);
+ fdt_setprop_cell(blob, off, "cache-level", 3);
+#ifdef CONFIG_SYS_CACHE_STASHING
+ fdt_setprop_cell(blob, off, "cache-stash-id", 1);
+#endif
+}
+#else
+#define ft_fixup_l3cache(x, y)
+#endif
+
+#if defined(CONFIG_L2_CACHE)
+/* return size in kilobytes */
+static inline u32 l2cache_size(void)
+{
+ volatile ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+ volatile u32 l2siz_field = (l2cache->l2ctl >> 28) & 0x3;
+ u32 ver = SVR_SOC_VER(get_svr());
+
+ switch (l2siz_field) {
+ case 0x0:
+ break;
+ case 0x1:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8555)
+ return 128;
+ else
+ return 256;
+ break;
+ case 0x2:
+ if (ver == SVR_8540 || ver == SVR_8560 ||
+ ver == SVR_8541 || ver == SVR_8555)
+ return 256;
+ else
+ return 512;
+ break;
+ case 0x3:
+ return 1024;
+ break;
+ }
+
+ return 0;
+}
+
+static inline void ft_fixup_l2cache(void *blob)
+{
+ int len, off;
+ u32 *ph;
+ struct cpu_type *cpu = identify_cpu(SVR_SOC_VER(get_svr()));
+
+ const u32 line_size = 32;
+ const u32 num_ways = 8;
+ const u32 size = l2cache_size() * 1024;
+ const u32 num_sets = size / (line_size * num_ways);
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+ if (off < 0) {
+ debug("no cpu node fount\n");
+ return;
+ }
+
+ ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
+
+ if (ph == NULL) {
+ debug("no next-level-cache property\n");
+ return ;
+ }
+
+ off = fdt_node_offset_by_phandle(blob, *ph);
+ if (off < 0) {
+ printf("%s: %s\n", __func__, fdt_strerror(off));
+ return ;
+ }
+
+ if (cpu) {
+ char buf[40];
+
+ if (isdigit(cpu->name[0])) {
+ /* MPCxxxx, where xxxx == 4-digit number */
+ len = sprintf(buf, "fsl,mpc%s-l2-cache-controller",
+ cpu->name) + 1;
+ } else {
+ /* Pxxxx or Txxxx, where xxxx == 4-digit number */
+ len = sprintf(buf, "fsl,%c%s-l2-cache-controller",
+ tolower(cpu->name[0]), cpu->name + 1) + 1;
+ }
+
+ /*
+ * append "cache" after the NULL character that the previous
+ * sprintf wrote. This is how a device tree stores multiple
+ * strings in a property.
+ */
+ len += sprintf(buf + len, "cache") + 1;
+
+ fdt_setprop(blob, off, "compatible", buf, len);
+ }
+ fdt_setprop(blob, off, "cache-unified", NULL, 0);
+ fdt_setprop_cell(blob, off, "cache-block-size", line_size);
+ fdt_setprop_cell(blob, off, "cache-size", size);
+ fdt_setprop_cell(blob, off, "cache-sets", num_sets);
+ fdt_setprop_cell(blob, off, "cache-level", 2);
+
+ /* we dont bother w/L3 since no platform of this type has one */
+}
+#elif defined(CONFIG_BACKSIDE_L2_CACHE) || \
+ defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2)
+static inline void ft_fixup_l2cache(void *blob)
+{
+ int off, l2_off, l3_off = -1;
+ u32 *ph;
+#ifdef CONFIG_BACKSIDE_L2_CACHE
+ u32 l2cfg0 = mfspr(SPRN_L2CFG0);
+#else
+ struct ccsr_cluster_l2 *l2cache =
+ (struct ccsr_cluster_l2 __iomem *)(CONFIG_SYS_FSL_CLUSTER_1_L2);
+ u32 l2cfg0 = in_be32(&l2cache->l2cfg0);
+#endif
+ u32 size, line_size, num_ways, num_sets;
+ int has_l2 = 1;
+
+ /* P2040/P2040E has no L2, so dont set any L2 props */
+ if (SVR_SOC_VER(get_svr()) == SVR_P2040)
+ has_l2 = 0;
+
+ size = (l2cfg0 & 0x3fff) * 64 * 1024;
+ num_ways = ((l2cfg0 >> 14) & 0x1f) + 1;
+ line_size = (((l2cfg0 >> 23) & 0x3) + 1) * 32;
+ num_sets = size / (line_size * num_ways);
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+
+ while (off != -FDT_ERR_NOTFOUND) {
+ ph = (u32 *)fdt_getprop(blob, off, "next-level-cache", 0);
+
+ if (ph == NULL) {
+ debug("no next-level-cache property\n");
+ goto next;
+ }
+
+ l2_off = fdt_node_offset_by_phandle(blob, *ph);
+ if (l2_off < 0) {
+ printf("%s: %s\n", __func__, fdt_strerror(off));
+ goto next;
+ }
+
+ if (has_l2) {
+#ifdef CONFIG_SYS_CACHE_STASHING
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ /* Only initialize every eighth thread */
+ if (reg && !((*reg) % 8))
+#else
+ if (reg)
+#endif
+ fdt_setprop_cell(blob, l2_off, "cache-stash-id",
+ (*reg * 2) + 32 + 1);
+#endif
+
+ fdt_setprop(blob, l2_off, "cache-unified", NULL, 0);
+ fdt_setprop_cell(blob, l2_off, "cache-block-size",
+ line_size);
+ fdt_setprop_cell(blob, l2_off, "cache-size", size);
+ fdt_setprop_cell(blob, l2_off, "cache-sets", num_sets);
+ fdt_setprop_cell(blob, l2_off, "cache-level", 2);
+ fdt_setprop(blob, l2_off, "compatible", "cache", 6);
+ }
+
+ if (l3_off < 0) {
+ ph = (u32 *)fdt_getprop(blob, l2_off, "next-level-cache", 0);
+
+ if (ph == NULL) {
+ debug("no next-level-cache property\n");
+ goto next;
+ }
+ l3_off = *ph;
+ }
+next:
+ off = fdt_node_offset_by_prop_value(blob, off,
+ "device_type", "cpu", 4);
+ }
+ if (l3_off > 0) {
+ l3_off = fdt_node_offset_by_phandle(blob, l3_off);
+ if (l3_off < 0) {
+ printf("%s: %s\n", __func__, fdt_strerror(off));
+ return ;
+ }
+ ft_fixup_l3cache(blob, l3_off);
+ }
+}
+#else
+#define ft_fixup_l2cache(x)
+#endif
+
+static inline void ft_fixup_cache(void *blob)
+{
+ int off;
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 l1cfg0 = mfspr(SPRN_L1CFG0);
+ u32 l1cfg1 = mfspr(SPRN_L1CFG1);
+ u32 isize, iline_size, inum_sets, inum_ways;
+ u32 dsize, dline_size, dnum_sets, dnum_ways;
+
+ /* d-side config */
+ dsize = (l1cfg0 & 0x7ff) * 1024;
+ dnum_ways = ((l1cfg0 >> 11) & 0xff) + 1;
+ dline_size = (((l1cfg0 >> 23) & 0x3) + 1) * 32;
+ dnum_sets = dsize / (dline_size * dnum_ways);
+
+ fdt_setprop_cell(blob, off, "d-cache-block-size", dline_size);
+ fdt_setprop_cell(blob, off, "d-cache-size", dsize);
+ fdt_setprop_cell(blob, off, "d-cache-sets", dnum_sets);
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+ if (reg)
+ fdt_setprop_cell(blob, off, "cache-stash-id",
+ (*reg * 2) + 32 + 0);
+ }
+#endif
+
+ /* i-side config */
+ isize = (l1cfg1 & 0x7ff) * 1024;
+ inum_ways = ((l1cfg1 >> 11) & 0xff) + 1;
+ iline_size = (((l1cfg1 >> 23) & 0x3) + 1) * 32;
+ inum_sets = isize / (iline_size * inum_ways);
+
+ fdt_setprop_cell(blob, off, "i-cache-block-size", iline_size);
+ fdt_setprop_cell(blob, off, "i-cache-size", isize);
+ fdt_setprop_cell(blob, off, "i-cache-sets", inum_sets);
+
+ off = fdt_node_offset_by_prop_value(blob, off,
+ "device_type", "cpu", 4);
+ }
+
+ ft_fixup_l2cache(blob);
+}
+
+
+void fdt_add_enet_stashing(void *fdt)
+{
+ do_fixup_by_compat(fdt, "gianfar", "bd-stash", NULL, 0, 1);
+
+ do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-len", 96, 1);
+
+ do_fixup_by_compat_u32(fdt, "gianfar", "rx-stash-idx", 0, 1);
+ do_fixup_by_compat(fdt, "fsl,etsec2", "bd-stash", NULL, 0, 1);
+ do_fixup_by_compat_u32(fdt, "fsl,etsec2", "rx-stash-len", 96, 1);
+ do_fixup_by_compat_u32(fdt, "fsl,etsec2", "rx-stash-idx", 0, 1);
+}
+
+#if defined(CONFIG_SYS_DPAA_FMAN) || defined(CONFIG_SYS_DPAA_PME)
+#ifdef CONFIG_SYS_DPAA_FMAN
+static void ft_fixup_clks(void *blob, const char *compat, u32 offset,
+ unsigned long freq)
+{
+ phys_addr_t phys = offset + CONFIG_SYS_CCSRBAR_PHYS;
+ int off = fdt_node_offset_by_compat_reg(blob, compat, phys);
+
+ if (off >= 0) {
+ off = fdt_setprop_cell(blob, off, "clock-frequency", freq);
+ if (off > 0)
+ printf("WARNING enable to set clock-frequency "
+ "for %s: %s\n", compat, fdt_strerror(off));
+ }
+}
+#endif
+
+static void ft_fixup_dpaa_clks(void *blob)
+{
+ sys_info_t sysinfo;
+
+ get_sys_info(&sysinfo);
+#ifdef CONFIG_SYS_DPAA_FMAN
+ ft_fixup_clks(blob, "fsl,fman", CONFIG_SYS_FSL_FM1_OFFSET,
+ sysinfo.freqFMan[0]);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ ft_fixup_clks(blob, "fsl,fman", CONFIG_SYS_FSL_FM2_OFFSET,
+ sysinfo.freqFMan[1]);
+#endif
+#endif
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ do_fixup_by_compat_u32(blob, "fsl,qman",
+ "clock-frequency", sysinfo.freqQMAN, 1);
+#endif
+
+#ifdef CONFIG_SYS_DPAA_PME
+ do_fixup_by_compat_u32(blob, "fsl,pme",
+ "clock-frequency", sysinfo.freqPME, 1);
+#endif
+}
+#else
+#define ft_fixup_dpaa_clks(x)
+#endif
+
+#ifdef CONFIG_QE
+static void ft_fixup_qe_snum(void *blob)
+{
+ unsigned int svr;
+
+ svr = mfspr(SPRN_SVR);
+ if (SVR_SOC_VER(svr) == SVR_8569) {
+ if(IS_SVR_REV(svr, 1, 0))
+ do_fixup_by_compat_u32(blob, "fsl,qe",
+ "fsl,qe-num-snums", 46, 1);
+ else
+ do_fixup_by_compat_u32(blob, "fsl,qe",
+ "fsl,qe-num-snums", 76, 1);
+ }
+}
+#endif
+
+/**
+ * fdt_fixup_fman_firmware -- insert the Fman firmware into the device tree
+ *
+ * The binding for an Fman firmware node is documented in
+ * Documentation/powerpc/dts-bindings/fsl/dpaa/fman.txt. This node contains
+ * the actual Fman firmware binary data. The operating system is expected to
+ * be able to parse the binary data to determine any attributes it needs.
+ */
+#ifdef CONFIG_SYS_DPAA_FMAN
+void fdt_fixup_fman_firmware(void *blob)
+{
+ int rc, fmnode, fwnode = -1;
+ uint32_t phandle;
+ struct qe_firmware *fmanfw;
+ const struct qe_header *hdr;
+ unsigned int length;
+ uint32_t crc;
+ const char *p;
+
+ /* The first Fman we find will contain the actual firmware. */
+ fmnode = fdt_node_offset_by_compatible(blob, -1, "fsl,fman");
+ if (fmnode < 0)
+ /* Exit silently if there are no Fman devices */
+ return;
+
+ /* If we already have a firmware node, then also exit silently. */
+ if (fdt_node_offset_by_compatible(blob, -1, "fsl,fman-firmware") > 0)
+ return;
+
+ /* If the environment variable is not set, then exit silently */
+ p = getenv("fman_ucode");
+ if (!p)
+ return;
+
+ fmanfw = (struct qe_firmware *) simple_strtoul(p, NULL, 0);
+ if (!fmanfw)
+ return;
+
+ hdr = &fmanfw->header;
+ length = be32_to_cpu(hdr->length);
+
+ /* Verify the firmware. */
+ if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
+ (hdr->magic[2] != 'F')) {
+ printf("Data at %p is not an Fman firmware\n", fmanfw);
+ return;
+ }
+
+ if (length > CONFIG_SYS_QE_FMAN_FW_LENGTH) {
+ printf("Fman firmware at %p is too large (size=%u)\n",
+ fmanfw, length);
+ return;
+ }
+
+ length -= sizeof(u32); /* Subtract the size of the CRC */
+ crc = be32_to_cpu(*(u32 *)((void *)fmanfw + length));
+ if (crc != crc32_no_comp(0, (void *)fmanfw, length)) {
+ printf("Fman firmware at %p has invalid CRC\n", fmanfw);
+ return;
+ }
+
+ /* Increase the size of the fdt to make room for the node. */
+ rc = fdt_increase_size(blob, fmanfw->header.length);
+ if (rc < 0) {
+ printf("Unable to make room for Fman firmware: %s\n",
+ fdt_strerror(rc));
+ return;
+ }
+
+ /* Create the firmware node. */
+ fwnode = fdt_add_subnode(blob, fmnode, "fman-firmware");
+ if (fwnode < 0) {
+ char s[64];
+ fdt_get_path(blob, fmnode, s, sizeof(s));
+ printf("Could not add firmware node to %s: %s\n", s,
+ fdt_strerror(fwnode));
+ return;
+ }
+ rc = fdt_setprop_string(blob, fwnode, "compatible", "fsl,fman-firmware");
+ if (rc < 0) {
+ char s[64];
+ fdt_get_path(blob, fwnode, s, sizeof(s));
+ printf("Could not add compatible property to node %s: %s\n", s,
+ fdt_strerror(rc));
+ return;
+ }
+ phandle = fdt_create_phandle(blob, fwnode);
+ if (!phandle) {
+ char s[64];
+ fdt_get_path(blob, fwnode, s, sizeof(s));
+ printf("Could not add phandle property to node %s: %s\n", s,
+ fdt_strerror(rc));
+ return;
+ }
+ rc = fdt_setprop(blob, fwnode, "fsl,firmware", fmanfw, fmanfw->header.length);
+ if (rc < 0) {
+ char s[64];
+ fdt_get_path(blob, fwnode, s, sizeof(s));
+ printf("Could not add firmware property to node %s: %s\n", s,
+ fdt_strerror(rc));
+ return;
+ }
+
+ /* Find all other Fman nodes and point them to the firmware node. */
+ while ((fmnode = fdt_node_offset_by_compatible(blob, fmnode, "fsl,fman")) > 0) {
+ rc = fdt_setprop_cell(blob, fmnode, "fsl,firmware-phandle", phandle);
+ if (rc < 0) {
+ char s[64];
+ fdt_get_path(blob, fmnode, s, sizeof(s));
+ printf("Could not add pointer property to node %s: %s\n",
+ s, fdt_strerror(rc));
+ return;
+ }
+ }
+}
+#else
+#define fdt_fixup_fman_firmware(x)
+#endif
+
+#if defined(CONFIG_PPC_P4080)
+static void fdt_fixup_usb(void *fdt)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 rcwsr11 = in_be32(&gur->rcwsr[11]);
+ int off;
+
+ off = fdt_node_offset_by_compatible(fdt, -1, "fsl,mpc85xx-usb2-mph");
+ if ((rcwsr11 & FSL_CORENET_RCWSR11_EC1) !=
+ FSL_CORENET_RCWSR11_EC1_FM1_USB1)
+ fdt_status_disabled(fdt, off);
+
+ off = fdt_node_offset_by_compatible(fdt, -1, "fsl,mpc85xx-usb2-dr");
+ if ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) !=
+ FSL_CORENET_RCWSR11_EC2_USB2)
+ fdt_status_disabled(fdt, off);
+}
+#else
+#define fdt_fixup_usb(x)
+#endif
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ int off;
+ int val;
+ sys_info_t sysinfo;
+
+ /* delete crypto node if not on an E-processor */
+ if (!IS_E_PROCESSOR(get_svr()))
+ fdt_fixup_crypto_node(blob, 0);
+#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
+ else {
+ ccsr_sec_t __iomem *sec;
+
+ sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ fdt_fixup_crypto_node(blob, in_be32(&sec->secvid_ms));
+ }
+#endif
+
+ fdt_fixup_ethernet(blob);
+
+ fdt_add_enet_stashing(blob);
+
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", get_tbclk(), 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ get_sys_info(&sysinfo);
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+ val = cpu_to_fdt32(sysinfo.freqProcessor[*reg]);
+ fdt_setprop(blob, off, "clock-frequency", &val, 4);
+ off = fdt_node_offset_by_prop_value(blob, off, "device_type",
+ "cpu", 4);
+ }
+ do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,pq3-localbus",
+ "bus-frequency", gd->arch.lbc_clk, 1);
+ do_fixup_by_compat_u32(blob, "fsl,elbc",
+ "bus-frequency", gd->arch.lbc_clk, 1);
+#ifdef CONFIG_QE
+ ft_qe_setup(blob);
+ ft_fixup_qe_snum(blob);
+#endif
+
+ fdt_fixup_fman_firmware(blob);
+
+#ifdef CONFIG_SYS_NS16550
+ do_fixup_by_compat_u32(blob, "ns16550",
+ "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+#ifdef CONFIG_CPM2
+ do_fixup_by_compat_u32(blob, "fsl,cpm2-scc-uart",
+ "current-speed", bd->bi_baudrate, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,cpm2-brg",
+ "clock-frequency", bd->bi_brgfreq, 1);
+#endif
+
+#ifdef CONFIG_FSL_CORENET
+ do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-1.0",
+ "clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
+ do_fixup_by_compat_u32(blob, "fsl,qoriq-clockgen-2.0",
+ "clock-frequency", CONFIG_SYS_CLK_FREQ, 1);
+ do_fixup_by_compat_u32(blob, "fsl,mpic",
+ "clock-frequency", get_bus_freq(0)/2, 1);
+#else
+ do_fixup_by_compat_u32(blob, "fsl,mpic",
+ "clock-frequency", get_bus_freq(0), 1);
+#endif
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+#ifdef CONFIG_MP
+ ft_fixup_cpu(blob, (u64)bd->bi_memstart + (u64)bd->bi_memsize);
+ ft_fixup_num_cores(blob);
+#endif
+
+ ft_fixup_cache(blob);
+
+#if defined(CONFIG_FSL_ESDHC)
+ fdt_fixup_esdhc(blob, bd);
+#endif
+
+ ft_fixup_dpaa_clks(blob);
+
+#if defined(CONFIG_SYS_BMAN_MEM_PHYS)
+ fdt_portal(blob, "fsl,bman-portal", "bman-portals",
+ (u64)CONFIG_SYS_BMAN_MEM_PHYS,
+ CONFIG_SYS_BMAN_MEM_SIZE);
+ fdt_fixup_bportals(blob);
+#endif
+
+#if defined(CONFIG_SYS_QMAN_MEM_PHYS)
+ fdt_portal(blob, "fsl,qman-portal", "qman-portals",
+ (u64)CONFIG_SYS_QMAN_MEM_PHYS,
+ CONFIG_SYS_QMAN_MEM_SIZE);
+
+ fdt_fixup_qportals(blob);
+#endif
+
+#ifdef CONFIG_SYS_SRIO
+ ft_srio_setup(blob);
+#endif
+
+ /*
+ * system-clock = CCB clock/2
+ * Here gd->bus_clk = CCB clock
+ * We are using the system clock as 1588 Timer reference
+ * clock source select
+ */
+ do_fixup_by_compat_u32(blob, "fsl,gianfar-ptp-timer",
+ "timer-frequency", gd->bus_clk/2, 1);
+
+ /*
+ * clock-freq should change to clock-frequency and
+ * flexcan-v1.0 should change to p1010-flexcan respectively
+ * in the future.
+ */
+ do_fixup_by_compat_u32(blob, "fsl,flexcan-v1.0",
+ "clock_freq", gd->bus_clk/2, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,flexcan-v1.0",
+ "clock-frequency", gd->bus_clk/2, 1);
+
+ do_fixup_by_compat_u32(blob, "fsl,p1010-flexcan",
+ "clock-frequency", gd->bus_clk/2, 1);
+
+ fdt_fixup_usb(blob);
+}
+
+/*
+ * For some CCSR devices, we only have the virtual address, not the physical
+ * address. This is because we map CCSR as a whole, so we typically don't need
+ * a macro for the physical address of any device within CCSR. In this case,
+ * we calculate the physical address of that device using it's the difference
+ * between the virtual address of the device and the virtual address of the
+ * beginning of CCSR.
+ */
+#define CCSR_VIRT_TO_PHYS(x) \
+ (CONFIG_SYS_CCSRBAR_PHYS + ((x) - CONFIG_SYS_CCSRBAR))
+
+static void msg(const char *name, uint64_t uaddr, uint64_t daddr)
+{
+ printf("Warning: U-Boot configured %s at address %llx,\n"
+ "but the device tree has it at %llx\n", name, uaddr, daddr);
+}
+
+/*
+ * Verify the device tree
+ *
+ * This function compares several CONFIG_xxx macros that contain physical
+ * addresses with the corresponding nodes in the device tree, to see if
+ * the physical addresses are all correct. For example, if
+ * CONFIG_SYS_NS16550_COM1 is defined, then it contains the virtual address
+ * of the first UART. We convert this to a physical address and compare
+ * that with the physical address of the first ns16550-compatible node
+ * in the device tree. If they don't match, then we display a warning.
+ *
+ * Returns 1 on success, 0 on failure
+ */
+int ft_verify_fdt(void *fdt)
+{
+ uint64_t addr = 0;
+ int aliases;
+ int off;
+
+ /* First check the CCSR base address */
+ off = fdt_node_offset_by_prop_value(fdt, -1, "device_type", "soc", 4);
+ if (off > 0)
+ addr = fdt_get_base_address(fdt, off);
+
+ if (!addr) {
+ printf("Warning: could not determine base CCSR address in "
+ "device tree\n");
+ /* No point in checking anything else */
+ return 0;
+ }
+
+ if (addr != CONFIG_SYS_CCSRBAR_PHYS) {
+ msg("CCSR", CONFIG_SYS_CCSRBAR_PHYS, addr);
+ /* No point in checking anything else */
+ return 0;
+ }
+
+ /*
+ * Check some nodes via aliases. We assume that U-Boot and the device
+ * tree enumerate the devices equally. E.g. the first serial port in
+ * U-Boot is the same as "serial0" in the device tree.
+ */
+ aliases = fdt_path_offset(fdt, "/aliases");
+ if (aliases > 0) {
+#ifdef CONFIG_SYS_NS16550_COM1
+ if (!fdt_verify_alias_address(fdt, aliases, "serial0",
+ CCSR_VIRT_TO_PHYS(CONFIG_SYS_NS16550_COM1)))
+ return 0;
+#endif
+
+#ifdef CONFIG_SYS_NS16550_COM2
+ if (!fdt_verify_alias_address(fdt, aliases, "serial1",
+ CCSR_VIRT_TO_PHYS(CONFIG_SYS_NS16550_COM2)))
+ return 0;
+#endif
+ }
+
+ /*
+ * The localbus node is typically a root node, even though the lbc
+ * controller is part of CCSR. If we were to put the lbc node under
+ * the SOC node, then the 'ranges' property in the lbc node would
+ * translate through the 'ranges' property of the parent SOC node, and
+ * we don't want that. Since it's a separate node, it's possible for
+ * the 'reg' property to be wrong, so check it here. For now, we
+ * only check for "fsl,elbc" nodes.
+ */
+#ifdef CONFIG_SYS_LBC_ADDR
+ off = fdt_node_offset_by_compatible(fdt, -1, "fsl,elbc");
+ if (off > 0) {
+ const fdt32_t *reg = fdt_getprop(fdt, off, "reg", NULL);
+ if (reg) {
+ uint64_t uaddr = CCSR_VIRT_TO_PHYS(CONFIG_SYS_LBC_ADDR);
+
+ addr = fdt_translate_address(fdt, off, reg);
+ if (uaddr != addr) {
+ msg("the localbus", uaddr, addr);
+ return 0;
+ }
+ }
+ }
+#endif
+
+ return 1;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/fixed_ivor.S b/arch/powerpc/cpu/mpc85xx/fixed_ivor.S
new file mode 100644
index 0000000..320cae3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fixed_ivor.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * Kumar Gala <kumar.gala@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* This file is intended to be included by other asm code since
+ * we will want to execute this on both the primary core when
+ * it does a bootm and the secondary core's that get released
+ * out of the spin table */
+
+#define SET_IVOR(vector_number, vector_offset) \
+ li r3,vector_offset@l; \
+ mtspr SPRN_IVOR##vector_number,r3;
+
+#define SET_GIVOR(vector_number, vector_offset) \
+ li r3,vector_offset@l; \
+ mtspr SPRN_GIVOR##vector_number,r3;
+
+ SET_IVOR(0, 0x020) /* Critical Input */
+ SET_IVOR(1, 0x000) /* Machine Check */
+ SET_IVOR(2, 0x060) /* Data Storage */
+ SET_IVOR(3, 0x080) /* Instruction Storage */
+ SET_IVOR(4, 0x0a0) /* External Input */
+ SET_IVOR(5, 0x0c0) /* Alignment */
+ SET_IVOR(6, 0x0e0) /* Program */
+ SET_IVOR(7, 0x100) /* FP Unavailable */
+ SET_IVOR(8, 0x120) /* System Call */
+ SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */
+ SET_IVOR(10, 0x160) /* Decrementer */
+ SET_IVOR(11, 0x180) /* Fixed Interval Timer */
+ SET_IVOR(12, 0x1a0) /* Watchdog Timer */
+ SET_IVOR(13, 0x1c0) /* Data TLB Error */
+ SET_IVOR(14, 0x1e0) /* Instruction TLB Error */
+ SET_IVOR(15, 0x040) /* Debug */
+
+/* e500v1 & e500v2 only */
+#ifndef CONFIG_E500MC
+ SET_IVOR(32, 0x200) /* SPE Unavailable */
+ SET_IVOR(33, 0x220) /* Embedded FP Data */
+ SET_IVOR(34, 0x240) /* Embedded FP Round */
+#endif
+
+ SET_IVOR(35, 0x260) /* Performance monitor */
+
+/* e500mc only */
+#ifdef CONFIG_E500MC
+ SET_IVOR(36, 0x280) /* Processor doorbell */
+ SET_IVOR(37, 0x2a0) /* Processor doorbell critical */
+ SET_IVOR(38, 0x2c0) /* Guest Processor doorbell */
+ SET_IVOR(39, 0x2e0) /* Guest Processor critical & machine check */
+ SET_IVOR(40, 0x300) /* Hypervisor system call */
+ SET_IVOR(41, 0x320) /* Hypervisor Priviledge */
+
+ SET_GIVOR(2, 0x060) /* Guest Data Storage */
+ SET_GIVOR(3, 0x080) /* Guest Instruction Storage */
+ SET_GIVOR(4, 0x0a0) /* Guest External Input */
+ SET_GIVOR(8, 0x120) /* Guest System Call */
+ SET_GIVOR(13, 0x1c0) /* Guest Data TLB Error */
+ SET_GIVOR(14, 0x1e0) /* Guest Instruction TLB Error */
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.c
new file mode 100644
index 0000000..93eca76
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/immap_85xx.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/fsl_law.h>
+#include <asm/errno.h>
+#include "fsl_corenet2_serdes.h"
+
+static u64 serdes1_prtcl_map;
+static u64 serdes2_prtcl_map;
+#ifdef CONFIG_SYS_FSL_SRDS_3
+static u64 serdes3_prtcl_map;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_4
+static u64 serdes4_prtcl_map;
+#endif
+
+#ifdef DEBUG
+static const char *serdes_prtcl_str[] = {
+ [NONE] = "NA",
+ [PCIE1] = "PCIE1",
+ [PCIE2] = "PCIE2",
+ [PCIE3] = "PCIE3",
+ [PCIE4] = "PCIE4",
+ [SATA1] = "SATA1",
+ [SATA2] = "SATA2",
+ [SRIO1] = "SRIO1",
+ [SRIO2] = "SRIO2",
+ [SGMII_FM1_DTSEC1] = "SGMII_FM1_DTSEC1",
+ [SGMII_FM1_DTSEC2] = "SGMII_FM1_DTSEC2",
+ [SGMII_FM1_DTSEC3] = "SGMII_FM1_DTSEC3",
+ [SGMII_FM1_DTSEC4] = "SGMII_FM1_DTSEC4",
+ [SGMII_FM1_DTSEC5] = "SGMII_FM1_DTSEC5",
+ [SGMII_FM1_DTSEC6] = "SGMII_FM1_DTSEC6",
+ [SGMII_FM2_DTSEC1] = "SGMII_FM2_DTSEC1",
+ [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2",
+ [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3",
+ [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4",
+ [XAUI_FM1] = "XAUI_FM1",
+ [XAUI_FM2] = "XAUI_FM2",
+ [AURORA] = "DEBUG",
+ [CPRI1] = "CPRI1",
+ [CPRI2] = "CPRI2",
+ [CPRI3] = "CPRI3",
+ [CPRI4] = "CPRI4",
+ [CPRI5] = "CPRI5",
+ [CPRI6] = "CPRI6",
+ [CPRI7] = "CPRI7",
+ [CPRI8] = "CPRI8",
+ [XAUI_FM1_MAC9] = "XAUI_FM1_MAC9",
+ [XAUI_FM1_MAC10] = "XAUI_FM1_MAC10",
+ [XAUI_FM2_MAC9] = "XAUI_FM2_MAC9",
+ [XAUI_FM2_MAC10] = "XAUI_FM2_MAC10",
+ [HIGIG_FM1_MAC9] = "HiGig_FM1_MAC9",
+ [HIGIG_FM1_MAC10] = "HiGig_FM1_MAC10",
+ [HIGIG_FM2_MAC9] = "HiGig_FM2_MAC9",
+ [HIGIG_FM2_MAC10] = "HiGig_FM2_MAC10",
+ [QSGMII_FM1_A] = "QSGMII_FM1_A",
+ [QSGMII_FM1_B] = "QSGMII_FM1_B",
+ [QSGMII_FM2_A] = "QSGMII_FM2_A",
+ [QSGMII_FM2_B] = "QSGMII_FM2_B",
+ [XFI_FM1_MAC9] = "XFI_FM1_MAC9",
+ [XFI_FM1_MAC10] = "XFI_FM1_MAC10",
+ [XFI_FM2_MAC9] = "XFI_FM2_MAC9",
+ [XFI_FM2_MAC10] = "XFI_FM2_MAC10",
+ [INTERLAKEN] = "INTERLAKEN",
+};
+#endif
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ u64 ret = 0;
+
+ ret |= (1ULL << device) & serdes1_prtcl_map;
+ ret |= (1ULL << device) & serdes2_prtcl_map;
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ ret |= (1ULL << device) & serdes3_prtcl_map;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_4
+ ret |= (1ULL << device) & serdes4_prtcl_map;
+#endif
+
+ return !!ret;
+}
+
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
+{
+ const ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 cfg = in_be32(&gur->rcwsr[4]);
+ int i;
+
+ switch (sd) {
+ case FSL_SRDS_1:
+ cfg &= FSL_CORENET2_RCWSR4_SRDS1_PRTCL;
+ cfg >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
+ break;
+ case FSL_SRDS_2:
+ cfg &= FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
+ cfg >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
+ break;
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ case FSL_SRDS_3:
+ cfg &= FSL_CORENET2_RCWSR4_SRDS3_PRTCL;
+ cfg >>= FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT;
+ break;
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_4
+ case FSL_SRDS_4:
+ cfg &= FSL_CORENET2_RCWSR4_SRDS4_PRTCL;
+ cfg >>= FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT;
+ break;
+#endif
+ default:
+ printf("invalid SerDes%d\n", sd);
+ break;
+ }
+ /* Is serdes enabled at all? */
+ if (unlikely(cfg == 0))
+ return -ENODEV;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_get_prtcl(sd, cfg, i) == device)
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift)
+{
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u64 serdes_prtcl_map = 0;
+ u32 cfg;
+ int lane;
+
+ cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask;
+ /* Is serdes enabled at all? */
+ if (!cfg) {
+ printf("SERDES%d is not enabled\n", sd + 1);
+ return 0;
+ }
+
+ cfg >>= sd_prctl_shift;
+ printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
+ if (!is_serdes_prtcl_valid(sd, cfg))
+ printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
+
+ for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
+ serdes_prtcl_map |= (1ULL << lane_prtcl);
+ }
+
+ return serdes_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+
+ serdes1_prtcl_map = serdes_init(FSL_SRDS_1,
+ CONFIG_SYS_FSL_CORENET_SERDES_ADDR,
+ FSL_CORENET2_RCWSR4_SRDS1_PRTCL,
+ FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT);
+ serdes2_prtcl_map = serdes_init(FSL_SRDS_2,
+ CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_2 * 0x1000,
+ FSL_CORENET2_RCWSR4_SRDS2_PRTCL,
+ FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT);
+#ifdef CONFIG_SYS_FSL_SRDS_3
+ serdes3_prtcl_map = serdes_init(FSL_SRDS_3,
+ CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_3 * 0x1000,
+ FSL_CORENET2_RCWSR4_SRDS3_PRTCL,
+ FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT);
+#endif
+#ifdef CONFIG_SYS_FSL_SRDS_4
+ serdes4_prtcl_map = serdes_init(FSL_SRDS_4,
+ CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_4 * 0x1000,
+ FSL_CORENET2_RCWSR4_SRDS4_PRTCL,
+ FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT);
+#endif
+
+}
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.h b/arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.h
new file mode 100644
index 0000000..2258f41
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet2_serdes.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_CORENET2_SERDES_H
+#define __FSL_CORENET2_SERDES_H
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl);
+int serdes_lane_enabled(int lane);
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane);
+#endif /* __FSL_CORENET2_SERDES_H */
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
new file mode 100644
index 0000000..b621adf
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+#include <hwconfig.h>
+#endif
+#include <asm/fsl_serdes.h>
+#include <asm/immap_85xx.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/fsl_law.h>
+#include <asm/errno.h>
+#include "fsl_corenet_serdes.h"
+
+/*
+ * The work-arounds for erratum SERDES8 and SERDES-A001 are linked together.
+ * The code is already very complicated as it is, and separating the two
+ * completely would just make things worse. We try to keep them as separate
+ * as possible, but for now we require SERDES8 if SERDES_A001 is defined.
+ */
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
+#ifndef CONFIG_SYS_P4080_ERRATUM_SERDES8
+#error "CONFIG_SYS_P4080_ERRATUM_SERDES_A001 requires CONFIG_SYS_P4080_ERRATUM_SERDES8"
+#endif
+#endif
+
+static u32 serdes_prtcl_map;
+
+#ifdef DEBUG
+static const char *serdes_prtcl_str[] = {
+ [NONE] = "NA",
+ [PCIE1] = "PCIE1",
+ [PCIE2] = "PCIE2",
+ [PCIE3] = "PCIE3",
+ [PCIE4] = "PCIE4",
+ [SATA1] = "SATA1",
+ [SATA2] = "SATA2",
+ [SRIO1] = "SRIO1",
+ [SRIO2] = "SRIO2",
+ [SGMII_FM1_DTSEC1] = "SGMII_FM1_DTSEC1",
+ [SGMII_FM1_DTSEC2] = "SGMII_FM1_DTSEC2",
+ [SGMII_FM1_DTSEC3] = "SGMII_FM1_DTSEC3",
+ [SGMII_FM1_DTSEC4] = "SGMII_FM1_DTSEC4",
+ [SGMII_FM1_DTSEC5] = "SGMII_FM1_DTSEC5",
+ [SGMII_FM2_DTSEC1] = "SGMII_FM2_DTSEC1",
+ [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2",
+ [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3",
+ [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4",
+ [SGMII_FM2_DTSEC5] = "SGMII_FM2_DTSEC5",
+ [XAUI_FM1] = "XAUI_FM1",
+ [XAUI_FM2] = "XAUI_FM2",
+ [AURORA] = "DEBUG",
+};
+#endif
+
+static const struct {
+ int idx;
+ unsigned int lpd; /* RCW lane powerdown bit */
+ int bank;
+} lanes[SRDS_MAX_LANES] = {
+ { 0, 152, FSL_SRDS_BANK_1 },
+ { 1, 153, FSL_SRDS_BANK_1 },
+ { 2, 154, FSL_SRDS_BANK_1 },
+ { 3, 155, FSL_SRDS_BANK_1 },
+ { 4, 156, FSL_SRDS_BANK_1 },
+ { 5, 157, FSL_SRDS_BANK_1 },
+ { 6, 158, FSL_SRDS_BANK_1 },
+ { 7, 159, FSL_SRDS_BANK_1 },
+ { 8, 160, FSL_SRDS_BANK_1 },
+ { 9, 161, FSL_SRDS_BANK_1 },
+ { 16, 162, FSL_SRDS_BANK_2 },
+ { 17, 163, FSL_SRDS_BANK_2 },
+ { 18, 164, FSL_SRDS_BANK_2 },
+ { 19, 165, FSL_SRDS_BANK_2 },
+#ifdef CONFIG_PPC_P4080
+ { 20, 170, FSL_SRDS_BANK_3 },
+ { 21, 171, FSL_SRDS_BANK_3 },
+ { 22, 172, FSL_SRDS_BANK_3 },
+ { 23, 173, FSL_SRDS_BANK_3 },
+#else
+ { 20, 166, FSL_SRDS_BANK_3 },
+ { 21, 167, FSL_SRDS_BANK_3 },
+ { 22, 168, FSL_SRDS_BANK_3 },
+ { 23, 169, FSL_SRDS_BANK_3 },
+#endif
+#if SRDS_MAX_BANK > 3
+ { 24, 175, FSL_SRDS_BANK_4 },
+ { 25, 176, FSL_SRDS_BANK_4 },
+#endif
+};
+
+int serdes_get_lane_idx(int lane)
+{
+ return lanes[lane].idx;
+}
+
+int serdes_get_bank_by_lane(int lane)
+{
+ return lanes[lane].bank;
+}
+
+int serdes_lane_enabled(int lane)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ serdes_corenet_t *regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
+
+ int bank = lanes[lane].bank;
+ int word = lanes[lane].lpd / 32;
+ int bit = lanes[lane].lpd % 32;
+
+ if (in_be32(&regs->bank[bank].rstctl) & SRDS_RSTCTL_SDPD)
+ return 0;
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ /*
+ * For banks two and three, use the srds_lpd_b[] array instead of the
+ * RCW, because this array contains the real values of SRDS_LPD_B2 and
+ * SRDS_LPD_B3.
+ */
+ if (bank > 0)
+ return !(srds_lpd_b[bank] & (8 >> (lane - (6 + 4 * bank))));
+#endif
+
+ return !(in_be32(&gur->rcwsr[word]) & (0x80000000 >> bit));
+}
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ /* Is serdes enabled at all? */
+ if (!(in_be32(&gur->rcwsr[5]) & FSL_CORENET_RCWSR5_SRDS_EN))
+ return 0;
+
+ return (1 << device) & serdes_prtcl_map;
+}
+
+static int __serdes_get_first_lane(uint32_t prtcl, enum srds_prtcl device)
+{
+ int i;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_get_prtcl(prtcl, i) == device)
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+/*
+ * Returns the SERDES lane (0..SRDS_MAX_LANES-1) that routes to the given
+ * device. This depends on the current SERDES protocol, as defined in the RCW.
+ *
+ * Returns a negative error code if SERDES is disabled or the given device is
+ * not supported in the current SERDES protocol.
+ */
+int serdes_get_first_lane(enum srds_prtcl device)
+{
+ u32 prtcl;
+ const ccsr_gur_t *gur;
+
+ gur = (typeof(gur))CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+ /* Is serdes enabled at all? */
+ if (unlikely((in_be32(&gur->rcwsr[5]) & 0x2000) == 0))
+ return -ENODEV;
+
+ prtcl = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
+
+ return __serdes_get_first_lane(prtcl, device);
+}
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
+/*
+ * Returns the SERDES bank (1, 2, or 3) that a given device is on for a given
+ * SERDES protocol.
+ *
+ * Returns a negative error code if the given device is not supported for the
+ * given SERDES protocol.
+ */
+static int serdes_get_bank_by_device(uint32_t prtcl, enum srds_prtcl device)
+{
+ int lane;
+
+ lane = __serdes_get_first_lane(prtcl, device);
+ if (unlikely(lane < 0))
+ return lane;
+
+ return serdes_get_bank_by_lane(lane);
+}
+
+static uint32_t __serdes_get_lane_count(uint32_t prtcl, enum srds_prtcl device,
+ int first)
+{
+ int lane;
+
+ for (lane = first; lane < SRDS_MAX_LANES; lane++) {
+ if (serdes_get_prtcl(prtcl, lane) != device)
+ break;
+ }
+
+ return lane - first;
+}
+
+static void __serdes_reset_rx(serdes_corenet_t *regs,
+ uint32_t prtcl,
+ enum srds_prtcl device)
+{
+ int lane, idx, first, last;
+
+ lane = __serdes_get_first_lane(prtcl, device);
+ if (unlikely(lane < 0))
+ return;
+ first = serdes_get_lane_idx(lane);
+ last = first + __serdes_get_lane_count(prtcl, device, lane);
+
+ /*
+ * Set BnGCRy0[RRST] = 0 for each lane in the each bank that is
+ * selected as XAUI to place the lane into reset.
+ */
+ for (idx = first; idx < last; idx++)
+ clrbits_be32(&regs->lane[idx].gcr0, SRDS_GCR0_RRST);
+
+ /* Wait at least 250 ns */
+ udelay(1);
+
+ /*
+ * Set BnGCRy0[RRST] = 1 for each lane in the each bank that is
+ * selected as XAUI to bring the lane out of reset.
+ */
+ for (idx = first; idx < last; idx++)
+ setbits_be32(&regs->lane[idx].gcr0, SRDS_GCR0_RRST);
+}
+
+void serdes_reset_rx(enum srds_prtcl device)
+{
+ u32 prtcl;
+ const ccsr_gur_t *gur;
+ serdes_corenet_t *regs;
+
+ if (unlikely(device == NONE))
+ return;
+
+ gur = (typeof(gur))CONFIG_SYS_MPC85xx_GUTS_ADDR;
+
+ /* Is serdes enabled at all? */
+ if (unlikely((in_be32(&gur->rcwsr[5]) & 0x2000) == 0))
+ return;
+
+ regs = (typeof(regs))CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
+ prtcl = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
+
+ __serdes_reset_rx(regs, prtcl, device);
+}
+#endif
+
+#ifndef CONFIG_SYS_DCSRBAR_PHYS
+#define CONFIG_SYS_DCSRBAR_PHYS 0x80000000 /* Must be 1GB-aligned for rev1.0 */
+#define CONFIG_SYS_DCSRBAR 0x80000000
+#define __DCSR_NOT_DEFINED_BY_CONFIG
+#endif
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+/*
+ * Enable a SERDES bank that was disabled via the RCW
+ *
+ * We only call this function for SERDES8 and SERDES-A001 in cases we really
+ * want to enable the bank, whether we actually want to use the lanes or not,
+ * so make sure at least one lane is enabled. We're only enabling this one
+ * lane to satisfy errata requirements that the bank be enabled.
+ *
+ * We use a local variable instead of srds_lpd_b[] because we want drivers to
+ * think that the lanes actually are disabled.
+ */
+static void enable_bank(ccsr_gur_t *gur, int bank)
+{
+ u32 rcw5;
+ u32 temp_lpd_b = srds_lpd_b[bank];
+
+ /*
+ * If we're asked to disable all lanes, just pretend we're doing
+ * that.
+ */
+ if (temp_lpd_b == 0xF)
+ temp_lpd_b = 0xE;
+
+ /*
+ * Enable the lanes SRDS_LPD_Bn. The RCW bits are read-only in
+ * CCSR, and read/write in DSCR.
+ */
+ rcw5 = in_be32(gur->rcwsr + 5);
+ if (bank == FSL_SRDS_BANK_2) {
+ rcw5 &= ~FSL_CORENET_RCWSRn_SRDS_LPD_B2;
+ rcw5 |= temp_lpd_b << 26;
+ } else if (bank == FSL_SRDS_BANK_3) {
+ rcw5 &= ~FSL_CORENET_RCWSRn_SRDS_LPD_B3;
+ rcw5 |= temp_lpd_b << 18;
+ } else {
+ printf("SERDES: enable_bank: bad bank %d\n", bank + 1);
+ return;
+ }
+
+ /* See similar code in cpu/mpc85xx/cpu_init.c for an explanation
+ * of the DCSR mapping.
+ */
+ {
+#ifdef __DCSR_NOT_DEFINED_BY_CONFIG
+ struct law_entry law = find_law(CONFIG_SYS_DCSRBAR_PHYS);
+ int law_index;
+ if (law.index == -1)
+ law_index = set_next_law(CONFIG_SYS_DCSRBAR_PHYS,
+ LAW_SIZE_1M, LAW_TRGT_IF_DCSR);
+ else
+ set_law(law.index, CONFIG_SYS_DCSRBAR_PHYS, LAW_SIZE_1M,
+ LAW_TRGT_IF_DCSR);
+#endif
+ u32 *p = (void *)CONFIG_SYS_DCSRBAR + 0x20114;
+ out_be32(p, rcw5);
+#ifdef __DCSR_NOT_DEFINED_BY_CONFIG
+ if (law.index == -1)
+ disable_law(law_index);
+ else
+ set_law(law.index, law.addr, law.size, law.trgt_id);
+#endif
+ }
+}
+
+/*
+ * To avoid problems with clock jitter, rev 2 p4080 uses the pll from
+ * bank 3 to clock banks 2 and 3, as well as a limited selection of
+ * protocol configurations. This requires that banks 2 and 3's lanes be
+ * disabled in the RCW, and enabled with some fixup here to re-enable
+ * them, and to configure bank 2's clock parameters in bank 3's pll in
+ * cases where they differ.
+ */
+static void p4080_erratum_serdes8(serdes_corenet_t *regs, ccsr_gur_t *gur,
+ u32 devdisr, u32 devdisr2, int cfg)
+{
+ int srds_ratio_b2;
+ int rfck_sel;
+
+ /*
+ * The disabled lanes of bank 2 will cause the associated
+ * logic blocks to be disabled in DEVDISR. We reverse that here.
+ *
+ * Note that normally it is not permitted to clear DEVDISR bits
+ * once the device has been disabled, but the hardware people
+ * say that this special case is OK.
+ */
+ clrbits_be32(&gur->devdisr, devdisr);
+ clrbits_be32(&gur->devdisr2, devdisr2);
+
+ /*
+ * Some protocols require special handling. There are a few
+ * additional protocol configurations that can be used, which are
+ * not listed here. See app note 4065 for supported protocol
+ * configurations.
+ */
+ switch (cfg) {
+ case 0x19:
+ /*
+ * Bank 2 has PCIe which wants BWSEL -- tell bank 3's PLL.
+ * SGMII on bank 3 should still be usable.
+ */
+ setbits_be32(&regs->bank[FSL_SRDS_BANK_3].pllcr1,
+ SRDS_PLLCR1_PLL_BWSEL);
+ break;
+
+ case 0x0f:
+ case 0x10:
+ /*
+ * Banks 2 (XAUI) and 3 (SGMII) have different clocking
+ * requirements in these configurations. Bank 3 cannot
+ * be used and should have its lanes (but not the bank
+ * itself) disabled in the RCW. We set up bank 3's pll
+ * for bank 2's needs here.
+ */
+ srds_ratio_b2 = (in_be32(&gur->rcwsr[4]) >> 13) & 7;
+
+ /* Determine refclock from XAUI ratio */
+ switch (srds_ratio_b2) {
+ case 1: /* 20:1 */
+ rfck_sel = SRDS_PLLCR0_RFCK_SEL_156_25;
+ break;
+ case 2: /* 25:1 */
+ rfck_sel = SRDS_PLLCR0_RFCK_SEL_125;
+ break;
+ default:
+ printf("SERDES: bad SRDS_RATIO_B2 %d\n",
+ srds_ratio_b2);
+ return;
+ }
+
+ clrsetbits_be32(&regs->bank[FSL_SRDS_BANK_3].pllcr0,
+ SRDS_PLLCR0_RFCK_SEL_MASK, rfck_sel);
+
+ clrsetbits_be32(&regs->bank[FSL_SRDS_BANK_3].pllcr0,
+ SRDS_PLLCR0_FRATE_SEL_MASK,
+ SRDS_PLLCR0_FRATE_SEL_6_25);
+ break;
+ }
+
+ enable_bank(gur, FSL_SRDS_BANK_3);
+}
+#endif
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A005
+/*
+ * If PCIe is not selected as a protocol for any lanes driven by a given PLL,
+ * that PLL should have SRDSBnPLLCR1[PLLBW_SEL] = 0.
+ */
+static void p4080_erratum_serdes_a005(serdes_corenet_t *regs, unsigned int cfg)
+{
+ enum srds_prtcl device;
+
+ switch (cfg) {
+ case 0x13:
+ case 0x16:
+ /*
+ * If SRDS_PRTCL = 0x13 or 0x16, set SRDSB1PLLCR1[PLLBW_SEL]
+ * to 0.
+ */
+ clrbits_be32(&regs->bank[FSL_SRDS_BANK_1].pllcr1,
+ SRDS_PLLCR1_PLL_BWSEL);
+ break;
+ case 0x19:
+ /*
+ * If SRDS_PRTCL = 0x19, set SRDSB1PLLCR1[PLLBW_SEL] to 0 and
+ * SRDSB3PLLCR1[PLLBW_SEL] to 1.
+ */
+ clrbits_be32(&regs->bank[FSL_SRDS_BANK_1].pllcr1,
+ SRDS_PLLCR1_PLL_BWSEL);
+ setbits_be32(&regs->bank[FSL_SRDS_BANK_3].pllcr1,
+ SRDS_PLLCR1_PLL_BWSEL);
+ break;
+ }
+
+ /*
+ * Set SRDSBnPLLCR1[PLLBW_SEL] to 0 for each bank that selects XAUI
+ * before XAUI is initialized.
+ */
+ for (device = XAUI_FM1; device <= XAUI_FM2; device++) {
+ if (is_serdes_configured(device)) {
+ int bank = serdes_get_bank_by_device(cfg, device);
+
+ clrbits_be32(&regs->bank[bank].pllcr1,
+ SRDS_PLLCR1_PLL_BWSEL);
+ }
+ }
+}
+#endif
+
+/*
+ * Wait for the RSTDONE bit to get set, or a one-second timeout.
+ */
+static void wait_for_rstdone(unsigned int bank)
+{
+ serdes_corenet_t *srds_regs =
+ (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
+ unsigned long long end_tick;
+ u32 rstctl;
+
+ /* wait for reset complete or 1-second timeout */
+ end_tick = usec2ticks(1000000) + get_ticks();
+ do {
+ rstctl = in_be32(&srds_regs->bank[bank].rstctl);
+ if (rstctl & SRDS_RSTCTL_RSTDONE)
+ break;
+ } while (end_tick > get_ticks());
+
+ if (!(rstctl & SRDS_RSTCTL_RSTDONE))
+ printf("SERDES: timeout resetting bank %u\n", bank + 1);
+}
+
+
+static void __soc_serdes_init(void)
+{
+ /* Allow for SoC-specific initialization in <SOC>_serdes.c */
+};
+void soc_serdes_init(void) __attribute__((weak, alias("__soc_serdes_init")));
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ int cfg;
+ serdes_corenet_t *srds_regs;
+#ifdef CONFIG_PPC_P5040
+ serdes_corenet_t *srds2_regs;
+#endif
+ int lane, bank, idx;
+ int have_bank[SRDS_MAX_BANK] = {};
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ u32 serdes8_devdisr = 0;
+ u32 serdes8_devdisr2 = 0;
+ char srds_lpd_opt[16];
+ const char *srds_lpd_arg;
+ size_t arglen;
+#endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
+ int need_serdes_a001; /* true == need work-around for SERDES A001 */
+#endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ char buffer[HWCONFIG_BUFFER_SIZE];
+ char *buf = NULL;
+
+ /*
+ * Extract hwconfig from environment since we have not properly setup
+ * the environment but need it for ddr config params
+ */
+ if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
+ buf = buffer;
+#endif
+
+ /* Is serdes enabled at all? */
+ if (!(in_be32(&gur->rcwsr[5]) & FSL_CORENET_RCWSR5_SRDS_EN))
+ return;
+
+ srds_regs = (void *)(CONFIG_SYS_FSL_CORENET_SERDES_ADDR);
+ cfg = (in_be32(&gur->rcwsr[4]) & FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
+ debug("Using SERDES configuration 0x%x, lane settings:\n", cfg);
+
+ if (!is_serdes_prtcl_valid(cfg)) {
+ printf("SERDES[PRTCL] = 0x%x is not valid\n", cfg);
+ return;
+ }
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ /*
+ * Display a warning if banks two and three are not disabled in the RCW,
+ * since our work-around for SERDES8 depends on these banks being
+ * disabled at power-on.
+ */
+#define B2_B3 (FSL_CORENET_RCWSRn_SRDS_LPD_B2 | FSL_CORENET_RCWSRn_SRDS_LPD_B3)
+ if ((in_be32(&gur->rcwsr[5]) & B2_B3) != B2_B3) {
+ printf("Warning: SERDES8 requires banks two and "
+ "three to be disabled in the RCW\n");
+ }
+
+ /*
+ * Store the values of the fsl_srds_lpd_b2 and fsl_srds_lpd_b3
+ * hwconfig options into the srds_lpd_b[] array. See README.p4080ds
+ * for a description of these options.
+ */
+ for (bank = 1; bank < ARRAY_SIZE(srds_lpd_b); bank++) {
+ sprintf(srds_lpd_opt, "fsl_srds_lpd_b%u", bank + 1);
+ srds_lpd_arg =
+ hwconfig_subarg_f("serdes", srds_lpd_opt, &arglen, buf);
+ if (srds_lpd_arg)
+ srds_lpd_b[bank] =
+ simple_strtoul(srds_lpd_arg, NULL, 0) & 0xf;
+ }
+
+ if ((cfg == 0xf) || (cfg == 0x10)) {
+ /*
+ * For SERDES protocols 0xF and 0x10, force bank 3 to be
+ * disabled, because it is not supported.
+ */
+ srds_lpd_b[FSL_SRDS_BANK_3] = 0xF;
+ }
+#endif
+
+ /* Look for banks with all lanes disabled, and power down the bank. */
+ for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes_get_prtcl(cfg, lane);
+ if (serdes_lane_enabled(lane)) {
+ have_bank[serdes_get_bank_by_lane(lane)] = 1;
+ serdes_prtcl_map |= (1 << lane_prtcl);
+ }
+ }
+
+#ifdef CONFIG_PPC_P5040
+ /*
+ * Lanes on bank 4 on P5040 are commented-out, but for some SERDES
+ * protocols, these lanes are routed to SATA. We use serdes_prtcl_map
+ * to decide whether a protocol is supported on a given lane, so SATA
+ * will be identified as not supported, and therefore not initialized.
+ * So for protocols which use SATA on bank4, we add SATA support in
+ * serdes_prtcl_map.
+ */
+ switch (cfg) {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ serdes_prtcl_map |= 1 << SATA1 | 1 << SATA2;
+ break;
+ default:
+ srds2_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES2_ADDR;
+
+ /* We don't need bank 4, so power it down */
+ setbits_be32(&srds2_regs->bank[0].rstctl, SRDS_RSTCTL_SDPD);
+ }
+#endif
+
+ soc_serdes_init();
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ /*
+ * Bank two uses the clock from bank three, so if bank two is enabled,
+ * then bank three must also be enabled.
+ */
+ if (have_bank[FSL_SRDS_BANK_2])
+ have_bank[FSL_SRDS_BANK_3] = 1;
+#endif
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
+ /*
+ * The work-aroud for erratum SERDES-A001 is needed only if bank two
+ * is disabled and bank three is enabled. The converse is also true,
+ * but SERDES8 ensures that bank 3 is always enabled if bank 2 is
+ * enabled, so there's no point in complicating the code to handle
+ * that situation.
+ */
+ need_serdes_a001 =
+ !have_bank[FSL_SRDS_BANK_2] && have_bank[FSL_SRDS_BANK_3];
+#endif
+
+ /* Power down the banks we're not interested in */
+ for (bank = 0; bank < SRDS_MAX_BANK; bank++) {
+ if (!have_bank[bank]) {
+ printf("SERDES: bank %d disabled\n", bank + 1);
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
+ /*
+ * Erratum SERDES-A001 says bank two needs to be powered
+ * down after bank three is powered up, so don't power
+ * down bank two here.
+ */
+ if (!need_serdes_a001 || (bank != FSL_SRDS_BANK_2))
+ setbits_be32(&srds_regs->bank[bank].rstctl,
+ SRDS_RSTCTL_SDPD);
+#else
+ setbits_be32(&srds_regs->bank[bank].rstctl,
+ SRDS_RSTCTL_SDPD);
+#endif
+ }
+ }
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004699
+ /*
+ * To avoid the situation that resulted in the P4080 erratum
+ * SERDES-8, a given SerDes bank will use the PLLs from the previous
+ * bank if one of the PLL frequencies is a multiple of the other. For
+ * instance, if bank 3 is running at 2.5GHz and bank 2 is at 1.25GHz,
+ * then bank 3 will use bank 2's PLL. P5040 Erratum A-004699 says
+ * that, in this situation, lane synchronization is not initiated. So
+ * when we detect a bank with a "borrowed" PLL, we have to manually
+ * initiate lane synchronization.
+ */
+ for (bank = FSL_SRDS_BANK_2; bank <= FSL_SRDS_BANK_3; bank++) {
+ /* Determine the first lane for this bank */
+ unsigned int lane;
+
+ for (lane = 0; lane < SRDS_MAX_LANES; lane++)
+ if (lanes[lane].bank == bank)
+ break;
+ idx = lanes[lane].idx;
+
+ /*
+ * Check if the PLL for the bank is borrowed. The UOTHL
+ * bit of the first lane will tell us that.
+ */
+ if (in_be32(&srds_regs->lane[idx].gcr0) & SRDS_GCR0_UOTHL) {
+ /* Manually start lane synchronization */
+ setbits_be32(&srds_regs->bank[bank].pllcr0,
+ SRDS_PLLCR0_PVCOCNT_EN);
+ }
+ }
+#endif
+
+#if defined(CONFIG_SYS_P4080_ERRATUM_SERDES8) || defined (CONFIG_SYS_P4080_ERRATUM_SERDES9)
+ for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl;
+
+ idx = serdes_get_lane_idx(lane);
+ lane_prtcl = serdes_get_prtcl(cfg, lane);
+
+#ifdef DEBUG
+ switch (lane) {
+ case 0:
+ puts("Bank1: ");
+ break;
+ case 10:
+ puts("\nBank2: ");
+ break;
+ case 14:
+ puts("\nBank3: ");
+ break;
+ default:
+ break;
+ }
+
+ printf("%s ", serdes_prtcl_str[lane_prtcl]);
+#endif
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
+ /*
+ * Set BnTTLCRy0[FLT_SEL] = 011011 and set BnTTLCRy0[31] = 1
+ * for each of the SerDes lanes selected as SGMII, XAUI, SRIO,
+ * or AURORA before the device is initialized.
+ *
+ * Note that this part of the SERDES-9 work-around is
+ * redundant if the work-around for A-4580 has already been
+ * applied via PBI.
+ */
+ switch (lane_prtcl) {
+ case SGMII_FM1_DTSEC1:
+ case SGMII_FM1_DTSEC2:
+ case SGMII_FM1_DTSEC3:
+ case SGMII_FM1_DTSEC4:
+ case SGMII_FM2_DTSEC1:
+ case SGMII_FM2_DTSEC2:
+ case SGMII_FM2_DTSEC3:
+ case SGMII_FM2_DTSEC4:
+ case SGMII_FM2_DTSEC5:
+ case XAUI_FM1:
+ case XAUI_FM2:
+ case SRIO1:
+ case SRIO2:
+ case AURORA:
+ out_be32(&srds_regs->lane[idx].ttlcr0,
+ SRDS_TTLCR0_FLT_SEL_KFR_26 |
+ SRDS_TTLCR0_FLT_SEL_KPH_28 |
+ SRDS_TTLCR0_FLT_SEL_750PPM |
+ SRDS_TTLCR0_FREQOVD_EN);
+ break;
+ default:
+ break;
+ }
+#endif
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ switch (lane_prtcl) {
+ case PCIE1:
+ case PCIE2:
+ case PCIE3:
+ serdes8_devdisr |= FSL_CORENET_DEVDISR_PCIE1 >>
+ (lane_prtcl - PCIE1);
+ break;
+ case SRIO1:
+ case SRIO2:
+ serdes8_devdisr |= FSL_CORENET_DEVDISR_SRIO1 >>
+ (lane_prtcl - SRIO1);
+ break;
+ case SGMII_FM1_DTSEC1:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 |
+ FSL_CORENET_DEVDISR2_DTSEC1_1;
+ break;
+ case SGMII_FM1_DTSEC2:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 |
+ FSL_CORENET_DEVDISR2_DTSEC1_2;
+ break;
+ case SGMII_FM1_DTSEC3:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 |
+ FSL_CORENET_DEVDISR2_DTSEC1_3;
+ break;
+ case SGMII_FM1_DTSEC4:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 |
+ FSL_CORENET_DEVDISR2_DTSEC1_4;
+ break;
+ case SGMII_FM2_DTSEC1:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 |
+ FSL_CORENET_DEVDISR2_DTSEC2_1;
+ break;
+ case SGMII_FM2_DTSEC2:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 |
+ FSL_CORENET_DEVDISR2_DTSEC2_2;
+ break;
+ case SGMII_FM2_DTSEC3:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 |
+ FSL_CORENET_DEVDISR2_DTSEC2_3;
+ break;
+ case SGMII_FM2_DTSEC4:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 |
+ FSL_CORENET_DEVDISR2_DTSEC2_4;
+ break;
+ case SGMII_FM2_DTSEC5:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 |
+ FSL_CORENET_DEVDISR2_DTSEC2_5;
+ break;
+ case XAUI_FM1:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 |
+ FSL_CORENET_DEVDISR2_10GEC1;
+ break;
+ case XAUI_FM2:
+ serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 |
+ FSL_CORENET_DEVDISR2_10GEC2;
+ break;
+ case AURORA:
+ break;
+ default:
+ break;
+ }
+
+#endif
+ }
+#endif
+
+#ifdef DEBUG
+ puts("\n");
+#endif
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A005
+ p4080_erratum_serdes_a005(srds_regs, cfg);
+#endif
+
+ for (idx = 0; idx < SRDS_MAX_BANK; idx++) {
+ bank = idx;
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ /*
+ * Change bank init order to 0, 2, 1, so that the third bank's
+ * PLL is established before we start the second bank. The
+ * second bank uses the third bank's PLL.
+ */
+
+ if (idx == 1)
+ bank = FSL_SRDS_BANK_3;
+ else if (idx == 2)
+ bank = FSL_SRDS_BANK_2;
+#endif
+
+ /* Skip disabled banks */
+ if (!have_bank[bank])
+ continue;
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+ if (idx == 1) {
+ /*
+ * Re-enable devices on banks two and three that were
+ * disabled by the RCW, and then enable bank three. The
+ * devices need to be enabled before either bank is
+ * powered up.
+ */
+ p4080_erratum_serdes8(srds_regs, gur, serdes8_devdisr,
+ serdes8_devdisr2, cfg);
+ } else if (idx == 2) {
+ /* Enable bank two now that bank three is enabled. */
+ enable_bank(gur, FSL_SRDS_BANK_2);
+ }
+#endif
+
+ wait_for_rstdone(bank);
+ }
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
+ if (need_serdes_a001) {
+ /* Bank 3 has been enabled, so now we can disable bank 2 */
+ setbits_be32(&srds_regs->bank[FSL_SRDS_BANK_2].rstctl,
+ SRDS_RSTCTL_SDPD);
+ }
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.h b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.h
new file mode 100644
index 0000000..3c551e9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_CORENET_SERDES_H
+#define __FSL_CORENET_SERDES_H
+
+enum srds_bank {
+ FSL_SRDS_BANK_1 = 0,
+ FSL_SRDS_BANK_2 = 1,
+ FSL_SRDS_BANK_3 = 2,
+};
+
+int is_serdes_prtcl_valid(u32 prtcl);
+int serdes_get_lane_idx(int lane);
+int serdes_get_bank_by_lane(int lane);
+int serdes_lane_enabled(int lane);
+enum srds_prtcl serdes_get_prtcl(int cfg, int lane);
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+extern uint16_t srds_lpd_b[SRDS_MAX_BANK];
+#endif
+
+#endif /* __FSL_CORENET_SERDES_H */
diff --git a/arch/powerpc/cpu/mpc85xx/interrupts.c b/arch/powerpc/cpu/mpc85xx/interrupts.c
new file mode 100644
index 0000000..7ab7113
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/interrupts.c
@@ -0,0 +1,126 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 Motorola Inc. (MPC85xx port)
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#ifdef CONFIG_POST
+#include <post.h>
+#endif
+
+int interrupt_init_cpu(unsigned int *decrementer_count)
+{
+ ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC8xxx_PIC_ADDR;
+
+#ifdef CONFIG_POST
+ /*
+ * The POST word is stored in the PIC's TFRR register which gets
+ * cleared when the PIC is reset. Save it off so we can restore it
+ * later.
+ */
+ ulong post_word = post_word_load();
+#endif
+
+ out_be32(&pic->gcr, MPC85xx_PICGCR_RST);
+ while (in_be32(&pic->gcr) & MPC85xx_PICGCR_RST)
+ ;
+ out_be32(&pic->gcr, MPC85xx_PICGCR_M);
+ in_be32(&pic->gcr);
+
+ *decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+
+ /* PIE is same as DIE, dec interrupt enable */
+ mtspr(SPRN_TCR, TCR_PIE);
+
+#ifdef CONFIG_INTERRUPTS
+ pic->iivpr1 = 0x810001; /* 50220 enable ecm interrupts */
+ debug("iivpr1@%x = %x\n", (uint)&pic->iivpr1, pic->iivpr1);
+
+ pic->iivpr2 = 0x810002; /* 50240 enable ddr interrupts */
+ debug("iivpr2@%x = %x\n", (uint)&pic->iivpr2, pic->iivpr2);
+
+ pic->iivpr3 = 0x810003; /* 50260 enable lbc interrupts */
+ debug("iivpr3@%x = %x\n", (uint)&pic->iivpr3, pic->iivpr3);
+
+#ifdef CONFIG_PCI1
+ pic->iivpr8 = 0x810008; /* enable pci1 interrupts */
+ debug("iivpr8@%x = %x\n", (uint)&pic->iivpr8, pic->iivpr8);
+#endif
+#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2)
+ pic->iivpr9 = 0x810009; /* enable pci1 interrupts */
+ debug("iivpr9@%x = %x\n", (uint)&pic->iivpr9, pic->iivpr9);
+#endif
+#ifdef CONFIG_PCIE1
+ pic->iivpr10 = 0x81000a; /* enable pcie1 interrupts */
+ debug("iivpr10@%x = %x\n", (uint)&pic->iivpr10, pic->iivpr10);
+#endif
+#ifdef CONFIG_PCIE3
+ pic->iivpr11 = 0x81000b; /* enable pcie3 interrupts */
+ debug("iivpr11@%x = %x\n", (uint)&pic->iivpr11, pic->iivpr11);
+#endif
+
+ pic->ctpr=0; /* 40080 clear current task priority register */
+#endif
+
+#ifdef CONFIG_POST
+ post_word_store(post_word);
+#endif
+
+ return (0);
+}
+
+/* Install and free a interrupt handler. Not implemented yet. */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+ return;
+}
+
+void
+irq_free_handler(int vec)
+{
+ return;
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+ /* PIS is same as DIS, dec interrupt status */
+ mtspr(SPRN_TSR, TSR_PIS);
+}
+
+#if defined(CONFIG_CMD_IRQ)
+/* irqinfo - print information about PCI devices,not implemented. */
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ return 0;
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/liodn.c b/arch/powerpc/cpu/mpc85xx/liodn.c
new file mode 100644
index 0000000..2e53367
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/liodn.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+
+#include <asm/immap_85xx.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset)
+{
+ liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset;
+
+ if (liodn_bases[dpaa_dev].num_ids == 2)
+ liodns[1] = liodn_bases[dpaa_dev].id[1] + liodn_offset;
+
+ return liodn_bases[dpaa_dev].num_ids;
+}
+
+#ifdef CONFIG_SYS_SRIO
+static void set_srio_liodn(struct srio_liodn_id_table *tbl, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ unsigned long reg_off = tbl[i].reg_offset[0];
+ out_be32((u32 *)reg_off, tbl[i].id[0]);
+
+ if (tbl[i].num_ids == 2) {
+ reg_off = tbl[i].reg_offset[1];
+ out_be32((u32 *)reg_off, tbl[i].id[1]);
+ }
+ }
+}
+#endif
+
+static void set_liodn(struct liodn_id_table *tbl, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ u32 liodn;
+ if (tbl[i].num_ids == 2) {
+ liodn = (tbl[i].id[0] << 16) | tbl[i].id[1];
+ } else {
+ liodn = tbl[i].id[0];
+ }
+
+ out_be32((volatile u32 *)(tbl[i].reg_offset), liodn);
+ }
+}
+
+static void setup_sec_liodn_base(void)
+{
+ ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+ u32 base;
+
+ if (!IS_E_PROCESSOR(get_svr()))
+ return;
+
+ /* QILCR[QSLOM] */
+ out_be32(&sec->qilcr_ms, 0x3ff<<16);
+
+ base = (liodn_bases[FSL_HW_PORTAL_SEC].id[0] << 16) |
+ liodn_bases[FSL_HW_PORTAL_SEC].id[1];
+
+ out_be32(&sec->qilcr_ls, base);
+}
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+static void setup_fman_liodn_base(enum fsl_dpaa_dev dev,
+ struct liodn_id_table *tbl, int size)
+{
+ int i;
+ ccsr_fman_t *fm;
+ u32 base;
+
+ switch(dev) {
+ case FSL_HW_PORTAL_FMAN1:
+ fm = (void *)CONFIG_SYS_FSL_FM1_ADDR;
+ break;
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ case FSL_HW_PORTAL_FMAN2:
+ fm = (void *)CONFIG_SYS_FSL_FM2_ADDR;
+ break;
+#endif
+ default:
+ printf("Error: Invalid device type to %s\n", __FUNCTION__);
+ return ;
+ }
+
+ base = (liodn_bases[dev].id[0] << 16) | liodn_bases[dev].id[0];
+
+ /* setup all bases the same */
+ for (i = 0; i < 32; i++) {
+ out_be32(&fm->fm_dma.fmdmplr[i], base);
+ }
+
+ /* update tbl to ... */
+ for (i = 0; i < size; i++)
+ tbl[i].id[0] += liodn_bases[dev].id[0];
+}
+#endif
+
+static void setup_pme_liodn_base(void)
+{
+#ifdef CONFIG_SYS_DPAA_PME
+ ccsr_pme_t *pme = (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
+ u32 base = (liodn_bases[FSL_HW_PORTAL_PME].id[0] << 16) |
+ liodn_bases[FSL_HW_PORTAL_PME].id[1];
+
+ out_be32(&pme->liodnbr, base);
+#endif
+}
+
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+static void setup_raide_liodn_base(void)
+{
+ struct ccsr_raide *raide = (void *)CONFIG_SYS_FSL_RAID_ENGINE_ADDR;
+
+ /* setup raid engine liodn base for data/desc ; both set to 47 */
+ u32 base = (liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0] << 16) |
+ liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0];
+
+ out_be32(&raide->liodnbr, base);
+}
+#endif
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+static void set_rman_liodn(struct liodn_id_table *tbl, int size)
+{
+ int i;
+ struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
+
+ for (i = 0; i < size; i++) {
+ /* write the RMan block number */
+ out_be32(&rman->mmitar, i);
+ /* write the liodn offset corresponding to the block */
+ out_be32((u32 *)(tbl[i].reg_offset), tbl[i].id[0]);
+ }
+}
+
+static void setup_rman_liodn_base(struct liodn_id_table *tbl, int size)
+{
+ int i;
+ struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
+ u32 base = liodn_bases[FSL_HW_PORTAL_RMAN].id[0];
+
+ out_be32(&rman->mmliodnbr, base);
+
+ /* update liodn offset */
+ for (i = 0; i < size; i++)
+ tbl[i].id[0] += base;
+}
+#endif
+
+void set_liodns(void)
+{
+ /* setup general liodn offsets */
+ set_liodn(liodn_tbl, liodn_tbl_sz);
+
+#ifdef CONFIG_SYS_SRIO
+ /* setup SRIO port liodns */
+ set_srio_liodn(srio_liodn_tbl, srio_liodn_tbl_sz);
+#endif
+
+ /* setup SEC block liodn bases & offsets if we have one */
+ if (IS_E_PROCESSOR(get_svr())) {
+ set_liodn(sec_liodn_tbl, sec_liodn_tbl_sz);
+ setup_sec_liodn_base();
+ }
+
+ /* setup FMAN block(s) liodn bases & offsets if we have one */
+#ifdef CONFIG_SYS_DPAA_FMAN
+ set_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz);
+ setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl,
+ fman1_liodn_tbl_sz);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ set_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz);
+ setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl,
+ fman2_liodn_tbl_sz);
+#endif
+#endif
+ /* setup PME liodn base */
+ setup_pme_liodn_base();
+
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+ /* raid engine ccr addr code for liodn */
+ set_liodn(raide_liodn_tbl, raide_liodn_tbl_sz);
+ setup_raide_liodn_base();
+#endif
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+ /* setup RMan liodn offsets */
+ set_rman_liodn(rman_liodn_tbl, rman_liodn_tbl_sz);
+ /* setup RMan liodn base */
+ setup_rman_liodn_base(rman_liodn_tbl, rman_liodn_tbl_sz);
+#endif
+}
+
+#ifdef CONFIG_SYS_SRIO
+static void fdt_fixup_srio_liodn(void *blob, struct srio_liodn_id_table *tbl)
+{
+ int i, srio_off;
+
+ /* search for srio node, if doesn't exist just return - nothing todo */
+ srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio");
+ if (srio_off < 0)
+ return ;
+
+ for (i = 0; i < srio_liodn_tbl_sz; i++) {
+ int off, portid = tbl[i].portid;
+
+ off = fdt_node_offset_by_prop_value(blob, srio_off,
+ "cell-index", &portid, 4);
+ if (off >= 0) {
+ off = fdt_setprop(blob, off, "fsl,liodn",
+ &tbl[i].id[0],
+ sizeof(u32) * tbl[i].num_ids);
+ if (off > 0)
+ printf("WARNING unable to set fsl,liodn for "
+ "fsl,srio port %d: %s\n",
+ portid, fdt_strerror(off));
+ } else {
+ debug("WARNING: couldn't set fsl,liodn for srio: %s.\n",
+ fdt_strerror(off));
+ }
+ }
+}
+#endif
+
+#define CONFIG_SYS_MAX_PCI_EPS 8
+#define CONFIG_SYS_PCI_EP_LIODN_START 256
+
+static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat)
+{
+ int off, pci_idx = 0, pci_cnt = 0, i, rc;
+ const uint32_t *base_liodn;
+ uint32_t liodn_offs[CONFIG_SYS_MAX_PCI_EPS + 1] = { 0 };
+
+ /*
+ * Count the number of pci nodes.
+ * It's needed later when the interleaved liodn offsets are generated.
+ */
+ off = fdt_node_offset_by_compatible(fdt, -1, compat);
+ while (off != -FDT_ERR_NOTFOUND) {
+ pci_cnt++;
+ off = fdt_node_offset_by_compatible(fdt, off, compat);
+ }
+
+ for (off = fdt_node_offset_by_compatible(fdt, -1, compat);
+ off != -FDT_ERR_NOTFOUND;
+ off = fdt_node_offset_by_compatible(fdt, off, compat)) {
+ base_liodn = fdt_getprop(fdt, off, "fsl,liodn", &rc);
+ if (!base_liodn) {
+ char path[64];
+
+ if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
+ strcpy(path, "(unknown)");
+ printf("WARNING Could not get liodn of node %s: %s\n",
+ path, fdt_strerror(rc));
+ continue;
+ }
+ for (i = 0; i < CONFIG_SYS_MAX_PCI_EPS; i++)
+ liodn_offs[i + 1] = CONFIG_SYS_PCI_EP_LIODN_START +
+ i * pci_cnt + pci_idx - *base_liodn;
+ rc = fdt_setprop(fdt, off, "fsl,liodn-offset-list",
+ liodn_offs, sizeof(liodn_offs));
+ if (rc) {
+ char path[64];
+
+ if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
+ strcpy(path, "(unknown)");
+ printf("WARNING Unable to set fsl,liodn-offset-list for "
+ "node %s: %s\n", path, fdt_strerror(rc));
+ continue;
+ }
+ pci_idx++;
+ }
+}
+
+static void fdt_fixup_liodn_tbl(void *blob, struct liodn_id_table *tbl, int sz)
+{
+ int i;
+
+ for (i = 0; i < sz; i++) {
+ int off;
+
+ if (tbl[i].compat == NULL)
+ continue;
+
+ off = fdt_node_offset_by_compat_reg(blob,
+ tbl[i].compat, tbl[i].compat_offset);
+ if (off >= 0) {
+ off = fdt_setprop(blob, off, "fsl,liodn",
+ &tbl[i].id[0],
+ sizeof(u32) * tbl[i].num_ids);
+ if (off > 0)
+ printf("WARNING unable to set fsl,liodn for "
+ "%s: %s\n",
+ tbl[i].compat, fdt_strerror(off));
+ } else {
+ debug("WARNING: could not set fsl,liodn for %s: %s.\n",
+ tbl[i].compat, fdt_strerror(off));
+ }
+ }
+}
+
+void fdt_fixup_liodn(void *blob)
+{
+#ifdef CONFIG_SYS_SRIO
+ fdt_fixup_srio_liodn(blob, srio_liodn_tbl);
+#endif
+
+ fdt_fixup_liodn_tbl(blob, liodn_tbl, liodn_tbl_sz);
+#ifdef CONFIG_SYS_DPAA_FMAN
+ fdt_fixup_liodn_tbl(blob, fman1_liodn_tbl, fman1_liodn_tbl_sz);
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ fdt_fixup_liodn_tbl(blob, fman2_liodn_tbl, fman2_liodn_tbl_sz);
+#endif
+#endif
+ fdt_fixup_liodn_tbl(blob, sec_liodn_tbl, sec_liodn_tbl_sz);
+
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+ fdt_fixup_liodn_tbl(blob, raide_liodn_tbl, raide_liodn_tbl_sz);
+#endif
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+ fdt_fixup_liodn_tbl(blob, rman_liodn_tbl, rman_liodn_tbl_sz);
+#endif
+
+ fdt_fixup_pci_liodn_offsets(blob, "fsl,qoriq-pcie-v2.4");
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mp.c b/arch/powerpc/cpu/mpc85xx/mp.c
new file mode 100644
index 0000000..861c8e0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mp.c
@@ -0,0 +1,488 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <ioports.h>
+#include <lmb.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_ddr_sdram.h>
+#include "mp.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+u32 fsl_ddr_get_intl3r(void);
+
+extern u32 __spin_table[];
+
+u32 get_my_id()
+{
+ return mfspr(SPRN_PIR);
+}
+
+/*
+ * Determine if U-Boot should keep secondary cores in reset, or let them out
+ * of reset and hold them in a spinloop
+ */
+int hold_cores_in_reset(int verbose)
+{
+ /* Default to no, overriden by 'y', 'yes', 'Y', 'Yes', or '1' */
+ if (getenv_yesno("mp_holdoff") == 1) {
+ if (verbose) {
+ puts("Secondary cores are being held in reset.\n");
+ puts("See 'mp_holdoff' environment variable\n");
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int cpu_reset(int nr)
+{
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
+ out_be32(&pic->pir, 1 << nr);
+ /* the dummy read works around an errata on early 85xx MP PICs */
+ (void)in_be32(&pic->pir);
+ out_be32(&pic->pir, 0x0);
+
+ return 0;
+}
+
+int cpu_status(int nr)
+{
+ u32 *table, id = get_my_id();
+
+ if (hold_cores_in_reset(1))
+ return 0;
+
+ if (nr == id) {
+ table = (u32 *)&__spin_table;
+ printf("table base @ 0x%p\n", table);
+ } else if (is_core_disabled(nr)) {
+ puts("Disabled\n");
+ } else {
+ table = (u32 *)&__spin_table + nr * NUM_BOOT_ENTRY;
+ printf("Running on cpu %d\n", id);
+ printf("\n");
+ printf("table @ 0x%p\n", table);
+ printf(" addr - 0x%08x\n", table[BOOT_ENTRY_ADDR_LOWER]);
+ printf(" r3 - 0x%08x\n", table[BOOT_ENTRY_R3_LOWER]);
+ printf(" pir - 0x%08x\n", table[BOOT_ENTRY_PIR]);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_FSL_CORENET
+int cpu_disable(int nr)
+{
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ setbits_be32(&gur->coredisrl, 1 << nr);
+
+ return 0;
+}
+
+int is_core_disabled(int nr) {
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 coredisrl = in_be32(&gur->coredisrl);
+
+ return (coredisrl & (1 << nr));
+}
+#else
+int cpu_disable(int nr)
+{
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ switch (nr) {
+ case 0:
+ setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_CPU0);
+ break;
+ case 1:
+ setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_CPU1);
+ break;
+ default:
+ printf("Invalid cpu number for disable %d\n", nr);
+ return 1;
+ }
+
+ return 0;
+}
+
+int is_core_disabled(int nr) {
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 devdisr = in_be32(&gur->devdisr);
+
+ switch (nr) {
+ case 0:
+ return (devdisr & MPC85xx_DEVDISR_CPU0);
+ case 1:
+ return (devdisr & MPC85xx_DEVDISR_CPU1);
+ default:
+ printf("Invalid cpu number for disable %d\n", nr);
+ }
+
+ return 0;
+}
+#endif
+
+static u8 boot_entry_map[4] = {
+ 0,
+ BOOT_ENTRY_PIR,
+ BOOT_ENTRY_R3_LOWER,
+};
+
+int cpu_release(int nr, int argc, char * const argv[])
+{
+ u32 i, val, *table = (u32 *)&__spin_table + nr * NUM_BOOT_ENTRY;
+ u64 boot_addr;
+
+ if (hold_cores_in_reset(1))
+ return 0;
+
+ if (nr == get_my_id()) {
+ printf("Invalid to release the boot core.\n\n");
+ return 1;
+ }
+
+ if (argc != 4) {
+ printf("Invalid number of arguments to release.\n\n");
+ return 1;
+ }
+
+ boot_addr = simple_strtoull(argv[0], NULL, 16);
+
+ /* handle pir, r3 */
+ for (i = 1; i < 3; i++) {
+ if (argv[i][0] != '-') {
+ u8 entry = boot_entry_map[i];
+ val = simple_strtoul(argv[i], NULL, 16);
+ table[entry] = val;
+ }
+ }
+
+ table[BOOT_ENTRY_ADDR_UPPER] = (u32)(boot_addr >> 32);
+
+ /* ensure all table updates complete before final address write */
+ eieio();
+
+ table[BOOT_ENTRY_ADDR_LOWER] = (u32)(boot_addr & 0xffffffff);
+
+ return 0;
+}
+
+u32 determine_mp_bootpg(unsigned int *pagesize)
+{
+ u32 bootpg;
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004468
+ u32 svr = get_svr();
+ u32 granule_size, check;
+ struct law_entry e;
+#endif
+
+
+ /* use last 4K of mapped memory */
+ bootpg = ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ?
+ CONFIG_MAX_MEM_MAPPED : gd->ram_size) +
+ CONFIG_SYS_SDRAM_BASE - 4096;
+ if (pagesize)
+ *pagesize = 4096;
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004468
+/*
+ * Erratum A004468 has two parts. The 3-way interleaving applies to T4240,
+ * to be fixed in rev 2.0. The 2-way interleaving applies to many SoCs. But
+ * the way boot page chosen in u-boot avoids hitting this erratum. So only
+ * thw workaround for 3-way interleaving is needed.
+ *
+ * To make sure boot page translation works with 3-Way DDR interleaving
+ * enforce a check for the following constrains
+ * 8K granule size requires BRSIZE=8K and
+ * bootpg >> log2(BRSIZE) %3 == 1
+ * 4K and 1K granule size requires BRSIZE=4K and
+ * bootpg >> log2(BRSIZE) %3 == 0
+ */
+ if (SVR_SOC_VER(svr) == SVR_T4240 && SVR_MAJ(svr) < 2) {
+ e = find_law(bootpg);
+ switch (e.trgt_id) {
+ case LAW_TRGT_IF_DDR_INTLV_123:
+ granule_size = fsl_ddr_get_intl3r() & 0x1f;
+ if (granule_size == FSL_DDR_3WAY_8KB_INTERLEAVING) {
+ if (pagesize)
+ *pagesize = 8192;
+ bootpg &= 0xffffe000; /* align to 8KB */
+ check = bootpg >> 13;
+ while ((check % 3) != 1)
+ check--;
+ bootpg = check << 13;
+ debug("Boot page (8K) at 0x%08x\n", bootpg);
+ break;
+ } else {
+ bootpg &= 0xfffff000; /* align to 4KB */
+ check = bootpg >> 12;
+ while ((check % 3) != 0)
+ check--;
+ bootpg = check << 12;
+ debug("Boot page (4K) at 0x%08x\n", bootpg);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+#endif /* CONFIG_SYS_FSL_ERRATUM_A004468 */
+
+ return bootpg;
+}
+
+phys_addr_t get_spin_phys_addr(void)
+{
+ return virt_to_phys(&__spin_table);
+}
+
+#ifdef CONFIG_FSL_CORENET
+static void plat_mp_up(unsigned long bootpg, unsigned int pagesize)
+{
+ u32 cpu_up_mask, whoami, brsize = LAW_SIZE_4K;
+ u32 *table = (u32 *)&__spin_table;
+ volatile ccsr_gur_t *gur;
+ volatile ccsr_local_t *ccm;
+ volatile ccsr_rcpm_t *rcpm;
+ volatile ccsr_pic_t *pic;
+ int timeout = 10;
+ u32 mask = cpu_mask();
+ struct law_entry e;
+
+ gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ ccm = (void *)(CONFIG_SYS_FSL_CORENET_CCM_ADDR);
+ rcpm = (void *)(CONFIG_SYS_FSL_CORENET_RCPM_ADDR);
+ pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
+
+ whoami = in_be32(&pic->whoami);
+ cpu_up_mask = 1 << whoami;
+ out_be32(&ccm->bstrl, bootpg);
+
+ e = find_law(bootpg);
+ /* pagesize is only 4K or 8K */
+ if (pagesize == 8192)
+ brsize = LAW_SIZE_8K;
+ out_be32(&ccm->bstrar, LAW_EN | e.trgt_id << 20 | brsize);
+ debug("BRSIZE is 0x%x\n", brsize);
+
+ /* readback to sync write */
+ in_be32(&ccm->bstrar);
+
+ /* disable time base at the platform */
+ out_be32(&rcpm->ctbenrl, cpu_up_mask);
+
+ out_be32(&gur->brrl, mask);
+
+ /* wait for everyone */
+ while (timeout) {
+ unsigned int i, cpu, nr_cpus = cpu_numcores();
+
+ for_each_cpu(i, cpu, nr_cpus, mask) {
+ if (table[cpu * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+ cpu_up_mask |= (1 << cpu);
+ }
+
+ if ((cpu_up_mask & mask) == mask)
+ break;
+
+ udelay(100);
+ timeout--;
+ }
+
+ if (timeout == 0)
+ printf("CPU up timeout. CPU up mask is %x should be %x\n",
+ cpu_up_mask, mask);
+
+ /* enable time base at the platform */
+ out_be32(&rcpm->ctbenrl, 0);
+
+ /* readback to sync write */
+ in_be32(&rcpm->ctbenrl);
+
+ mtspr(SPRN_TBWU, 0);
+ mtspr(SPRN_TBWL, 0);
+
+ out_be32(&rcpm->ctbenrl, mask);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+ /*
+ * Disabling Boot Page Translation allows the memory region 0xfffff000
+ * to 0xffffffff to be used normally. Leaving Boot Page Translation
+ * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+ * unusable for normal operation but it does allow OSes to easily
+ * reset a processor core to put it back into U-Boot's spinloop.
+ */
+ clrbits_be32(&ccm->bstrar, LAW_EN);
+#endif
+}
+#else
+static void plat_mp_up(unsigned long bootpg, unsigned int pagesize)
+{
+ u32 up, cpu_up_mask, whoami;
+ u32 *table = (u32 *)&__spin_table;
+ volatile u32 bpcr;
+ volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
+ u32 devdisr;
+ int timeout = 10;
+
+ whoami = in_be32(&pic->whoami);
+ out_be32(&ecm->bptr, 0x80000000 | (bootpg >> 12));
+
+ /* disable time base at the platform */
+ devdisr = in_be32(&gur->devdisr);
+ if (whoami)
+ devdisr |= MPC85xx_DEVDISR_TB0;
+ else
+ devdisr |= MPC85xx_DEVDISR_TB1;
+ out_be32(&gur->devdisr, devdisr);
+
+ /* release the hounds */
+ up = ((1 << cpu_numcores()) - 1);
+ bpcr = in_be32(&ecm->eebpcr);
+ bpcr |= (up << 24);
+ out_be32(&ecm->eebpcr, bpcr);
+ asm("sync; isync; msync");
+
+ cpu_up_mask = 1 << whoami;
+ /* wait for everyone */
+ while (timeout) {
+ int i;
+ for (i = 0; i < cpu_numcores(); i++) {
+ if (table[i * NUM_BOOT_ENTRY + BOOT_ENTRY_ADDR_LOWER])
+ cpu_up_mask |= (1 << i);
+ };
+
+ if ((cpu_up_mask & up) == up)
+ break;
+
+ udelay(100);
+ timeout--;
+ }
+
+ if (timeout == 0)
+ printf("CPU up timeout. CPU up mask is %x should be %x\n",
+ cpu_up_mask, up);
+
+ /* enable time base at the platform */
+ if (whoami)
+ devdisr |= MPC85xx_DEVDISR_TB1;
+ else
+ devdisr |= MPC85xx_DEVDISR_TB0;
+ out_be32(&gur->devdisr, devdisr);
+
+ /* readback to sync write */
+ in_be32(&gur->devdisr);
+
+ mtspr(SPRN_TBWU, 0);
+ mtspr(SPRN_TBWL, 0);
+
+ devdisr &= ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1);
+ out_be32(&gur->devdisr, devdisr);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+ /*
+ * Disabling Boot Page Translation allows the memory region 0xfffff000
+ * to 0xffffffff to be used normally. Leaving Boot Page Translation
+ * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+ * unusable for normal operation but it does allow OSes to easily
+ * reset a processor core to put it back into U-Boot's spinloop.
+ */
+ clrbits_be32(&ecm->bptr, 0x80000000);
+#endif
+}
+#endif
+
+void cpu_mp_lmb_reserve(struct lmb *lmb)
+{
+ u32 bootpg = determine_mp_bootpg(NULL);
+
+ lmb_reserve(lmb, bootpg, 4096);
+}
+
+void setup_mp(void)
+{
+ extern u32 __secondary_start_page;
+ extern u32 __bootpg_addr, __spin_table_addr, __second_half_boot_page;
+
+ int i;
+ ulong fixup = (u32)&__secondary_start_page;
+ u32 bootpg, bootpg_map, pagesize;
+
+ bootpg = determine_mp_bootpg(&pagesize);
+
+ /*
+ * pagesize is only 4K or 8K
+ * we only use the last 4K of boot page
+ * bootpg_map saves the address for the boot page
+ * 8K is used for the workaround of 3-way DDR interleaving
+ */
+
+ bootpg_map = bootpg;
+
+ if (pagesize == 8192)
+ bootpg += 4096; /* use 2nd half */
+
+ /* Some OSes expect secondary cores to be held in reset */
+ if (hold_cores_in_reset(0))
+ return;
+
+ /*
+ * Store the bootpg's cache-able half address for use by secondary
+ * CPU cores to continue to boot
+ */
+ __bootpg_addr = (u32)virt_to_phys(&__second_half_boot_page);
+
+ /* Store spin table's physical address for use by secondary cores */
+ __spin_table_addr = (u32)get_spin_phys_addr();
+
+ /* flush bootpg it before copying invalidate any staled cacheline */
+ flush_cache(bootpg, 4096);
+
+ /* look for the tlb covering the reset page, there better be one */
+ i = find_tlb_idx((void *)CONFIG_BPTR_VIRT_ADDR, 1);
+
+ /* we found a match */
+ if (i != -1) {
+ /* map reset page to bootpg so we can copy code there */
+ disable_tlb(i);
+
+ set_tlb(1, CONFIG_BPTR_VIRT_ADDR, bootpg, /* tlb, epn, rpn */
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, /* perms, wimge */
+ 0, i, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */
+
+ memcpy((void *)CONFIG_BPTR_VIRT_ADDR, (void *)fixup, 4096);
+
+ plat_mp_up(bootpg_map, pagesize);
+ } else {
+ puts("WARNING: No reset page TLB. "
+ "Skipping secondary core setup\n");
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mp.h b/arch/powerpc/cpu/mpc85xx/mp.h
new file mode 100644
index 0000000..ad9950b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mp.h
@@ -0,0 +1,21 @@
+#ifndef __MPC85XX_MP_H_
+#define __MPC85XX_MP_H_
+
+#include <asm/mp.h>
+
+phys_addr_t get_spin_phys_addr(void);
+u32 get_my_id(void);
+int hold_cores_in_reset(int verbose);
+
+#define BOOT_ENTRY_ADDR_UPPER 0
+#define BOOT_ENTRY_ADDR_LOWER 1
+#define BOOT_ENTRY_R3_UPPER 2
+#define BOOT_ENTRY_R3_LOWER 3
+#define BOOT_ENTRY_RESV 4
+#define BOOT_ENTRY_PIR 5
+#define BOOT_ENTRY_R6_UPPER 6
+#define BOOT_ENTRY_R6_LOWER 7
+#define NUM_BOOT_ENTRY 16 /* pad to 64 bytes */
+#define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32))
+
+#endif
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
new file mode 100644
index 0000000..ec96e81
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mpc8536_serdes.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2008,2010 Freescale Semiconductor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+/* PORDEVSR register */
+#define GUTS_PORDEVSR_OFFS 0xc
+#define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000
+#define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27
+
+/* SerDes CR0 register */
+#define FSL_SRDSCR0_OFFS 0x0
+#define FSL_SRDSCR0_TXEQA_MASK 0x00007000
+#define FSL_SRDSCR0_TXEQA_SGMII 0x00004000
+#define FSL_SRDSCR0_TXEQA_SATA 0x00001000
+#define FSL_SRDSCR0_TXEQE_MASK 0x00000700
+#define FSL_SRDSCR0_TXEQE_SGMII 0x00000400
+#define FSL_SRDSCR0_TXEQE_SATA 0x00000100
+
+/* SerDes CR1 register */
+#define FSL_SRDSCR1_OFFS 0x4
+#define FSL_SRDSCR1_LANEA_MASK 0x80200000
+#define FSL_SRDSCR1_LANEA_OFF 0x80200000
+#define FSL_SRDSCR1_LANEE_MASK 0x08020000
+#define FSL_SRDSCR1_LANEE_OFF 0x08020000
+
+/* SerDes CR2 register */
+#define FSL_SRDSCR2_OFFS 0x8
+#define FSL_SRDSCR2_EICA_MASK 0x00001f00
+#define FSL_SRDSCR2_EICA_SGMII 0x00000400
+#define FSL_SRDSCR2_EICA_SATA 0x00001400
+#define FSL_SRDSCR2_EICE_MASK 0x0000001f
+#define FSL_SRDSCR2_EICE_SGMII 0x00000004
+#define FSL_SRDSCR2_EICE_SATA 0x00000014
+
+/* SerDes CR3 register */
+#define FSL_SRDSCR3_OFFS 0xc
+#define FSL_SRDSCR3_LANEA_MASK 0x3f000700
+#define FSL_SRDSCR3_LANEA_SGMII 0x00000000
+#define FSL_SRDSCR3_LANEA_SATA 0x15000500
+#define FSL_SRDSCR3_LANEE_MASK 0x003f0007
+#define FSL_SRDSCR3_LANEE_SGMII 0x00000000
+#define FSL_SRDSCR3_LANEE_SATA 0x00150005
+
+#define SRDS1_MAX_LANES 8
+#define SRDS2_MAX_LANES 2
+
+static u32 serdes1_prtcl_map, serdes2_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
+ [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
+};
+
+static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
+ [0x1] = {SATA1, SATA2},
+ [0x3] = {SATA1, NONE},
+ [0x4] = {SGMII_TSEC1, SGMII_TSEC3},
+ [0x6] = {SGMII_TSEC1, NONE},
+};
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ int ret = (1 << device) & serdes1_prtcl_map;
+
+ if (ret)
+ return ret;
+
+ return (1 << device) & serdes2_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR;
+ u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS);
+ u32 srds1_io_sel, srds2_io_sel;
+ u32 tmp;
+ int lane;
+
+ srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+
+ /* parse the SRDS2_IO_SEL of PORDEVSR */
+ srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL)
+ >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT;
+
+ debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel);
+ debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel);
+
+ switch (srds2_io_sel) {
+ case 1: /* Lane A - SATA1, Lane E - SATA2 */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SATA;
+ tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+ tmp |= FSL_SRDSCR0_TXEQE_SATA;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SATA;
+ tmp &= ~FSL_SRDSCR2_EICE_MASK;
+ tmp |= FSL_SRDSCR2_EICE_SATA;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SATA;
+ tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+ tmp |= FSL_SRDSCR3_LANEE_SATA;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 3: /* Lane A - SATA1, Lane E - disabled */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SATA;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ tmp |= FSL_SRDSCR1_LANEE_OFF;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SATA;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SATA;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+ tmp &= ~FSL_SRDSCR0_TXEQE_MASK;
+ tmp |= FSL_SRDSCR0_TXEQE_SGMII;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SGMII;
+ tmp &= ~FSL_SRDSCR2_EICE_MASK;
+ tmp |= FSL_SRDSCR2_EICE_SGMII;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SGMII;
+ tmp &= ~FSL_SRDSCR3_LANEE_MASK;
+ tmp |= FSL_SRDSCR3_LANEE_SGMII;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */
+ /* CR 0 */
+ tmp = in_be32(sd + FSL_SRDSCR0_OFFS);
+ tmp &= ~FSL_SRDSCR0_TXEQA_MASK;
+ tmp |= FSL_SRDSCR0_TXEQA_SGMII;
+ out_be32(sd + FSL_SRDSCR0_OFFS, tmp);
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ tmp |= FSL_SRDSCR1_LANEE_OFF;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ /* CR 2 */
+ tmp = in_be32(sd + FSL_SRDSCR2_OFFS);
+ tmp &= ~FSL_SRDSCR2_EICA_MASK;
+ tmp |= FSL_SRDSCR2_EICA_SGMII;
+ out_be32(sd + FSL_SRDSCR2_OFFS, tmp);
+ /* CR 3 */
+ tmp = in_be32(sd + FSL_SRDSCR3_OFFS);
+ tmp &= ~FSL_SRDSCR3_LANEA_MASK;
+ tmp |= FSL_SRDSCR3_LANEA_SGMII;
+ out_be32(sd + FSL_SRDSCR3_OFFS, tmp);
+ break;
+ case 7: /* Lane A - disabled, Lane E - disabled */
+ /* CR 1 */
+ tmp = in_be32(sd + FSL_SRDSCR1_OFFS);
+ tmp &= ~FSL_SRDSCR1_LANEA_MASK;
+ tmp |= FSL_SRDSCR1_LANEA_OFF;
+ tmp &= ~FSL_SRDSCR1_LANEE_MASK;
+ tmp |= FSL_SRDSCR1_LANEE_OFF;
+ out_be32(sd + FSL_SRDSCR1_OFFS, tmp);
+ break;
+ default:
+ break;
+ }
+
+ if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel);
+ return;
+ }
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) {
+ printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane];
+ serdes2_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c
new file mode 100644
index 0000000..3483366
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mpc8544_serdes.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 8
+#define SRDS2_MAX_LANES 4
+
+static u32 serdes1_prtcl_map, serdes2_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
+ [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
+ [0x4] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x6] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
+};
+
+static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
+ [0x1] = {NONE, NONE, SGMII_TSEC1, SGMII_TSEC3},
+ [0x3] = {NONE, NONE, SGMII_TSEC1, SGMII_TSEC3},
+ [0x5] = {NONE, NONE, SGMII_TSEC1, SGMII_TSEC3},
+ [0x6] = {PCIE3, NONE, NONE, NONE},
+ [0x7] = {PCIE3, NONE, SGMII_TSEC1, SGMII_TSEC3},
+};
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ int ret = (1 << device) & serdes1_prtcl_map;
+
+ if (ret)
+ return ret;
+
+ return (1 << device) & serdes2_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
+ serdes2_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (pordevsr & MPC85xx_PORDEVSR_SGMII1_DIS)
+ serdes2_prtcl_map &= ~(1 << SGMII_TSEC1);
+
+ if (pordevsr & MPC85xx_PORDEVSR_SGMII3_DIS)
+ serdes2_prtcl_map &= ~(1 << SGMII_TSEC3);
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c
new file mode 100644
index 0000000..c9eea15
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mpc8548_serdes.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 8
+
+static u32 serdes1_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x4] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x5] = {NONE, NONE, NONE, NONE, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x6] = {NONE, NONE, NONE, NONE, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
+};
+
+int is_serdes_configured(enum srds_prtcl prtcl)
+{
+ return (1 << prtcl) & serdes1_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds1_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL] = %x\n", srds1_cfg);
+
+ if (srds1_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL] = %d\n", srds1_cfg);
+ return ;
+ }
+
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c
new file mode 100644
index 0000000..49a0290
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mpc8568_serdes.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 8
+
+static u32 serdes1_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x4] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x5] = {NONE, NONE, NONE, NONE, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x6] = {NONE, NONE, NONE, NONE, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
+};
+
+int is_serdes_configured(enum srds_prtcl prtcl)
+{
+ return (1 << prtcl) & serdes1_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c
new file mode 100644
index 0000000..7af6aff
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mpc8569_serdes.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+
+static u32 serdes1_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x0] = {PCIE1, NONE, NONE, NONE},
+ [0x1] = {SRIO1, SRIO2, SGMII_TSEC1, SGMII_TSEC2},
+ [0x2] = {SRIO1, SRIO2, SGMII_TSEC1, SGMII_TSEC2},
+ [0x3] = {SRIO1, SRIO2, NONE, NONE},
+ [0x4] = {PCIE1, NONE, SGMII_TSEC1, SGMII_TSEC2},
+ [0x5] = {PCIE1, PCIE1, SGMII_TSEC1, SGMII_TSEC2},
+ [0x6] = {PCIE1, NONE, SRIO1, SRIO2},
+ [0x7] = {PCIE1, PCIE1, SRIO1, SRIO2},
+ [0x8] = {PCIE1, PCIE1, SRIO1, SRIO2},
+ [0x9] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xa] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xb] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xc] = {PCIE1, SRIO1, SGMII_TSEC1, SGMII_TSEC2},
+ [0xf] = {PCIE1, PCIE1, PCIE1, PCIE1},
+};
+
+int is_serdes_configured(enum srds_prtcl prtcl)
+{
+ return (1 << prtcl) & serdes1_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c b/arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c
new file mode 100644
index 0000000..fcccb52
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/mpc8572_serdes.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 8
+
+static u32 serdes1_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE},
+ [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x6] = {NONE, NONE, NONE, NONE, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3},
+ [0xb] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xc] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xd] = {NONE, NONE, NONE, NONE, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xe] = {NONE, NONE, NONE, NONE, SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xf] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1},
+};
+
+int is_serdes_configured(enum srds_prtcl prtcl)
+{
+ return (1 << prtcl) & serdes1_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (!(pordevsr & MPC85xx_PORDEVSR_SGMII1_DIS))
+ serdes1_prtcl_map |= (1 << SGMII_TSEC1);
+
+ if (!(pordevsr & MPC85xx_PORDEVSR_SGMII2_DIS))
+ serdes1_prtcl_map |= (1 << SGMII_TSEC2);
+
+ if (!(pordevsr & MPC85xx_PORDEVSR_SGMII3_DIS))
+ serdes1_prtcl_map |= (1 << SGMII_TSEC3);
+
+ if (!(pordevsr & MPC85xx_PORDEVSR_SGMII4_DIS))
+ serdes1_prtcl_map |= (1 << SGMII_TSEC4);
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p1010_serdes.c b/arch/powerpc/cpu/mpc85xx/p1010_serdes.c
new file mode 100644
index 0000000..1f7dba0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p1010_serdes.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ * Author: Prabhakar Kushwaha <prabhakar@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+#define SRDS2_MAX_LANES 2
+
+static u32 serdes1_prtcl_map, serdes2_prtcl_map;
+
+static const u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x00] = {NONE, NONE, NONE, NONE},
+ [0x01] = {PCIE1, PCIE2, SGMII_TSEC2, SGMII_TSEC3},
+ [0x02] = {PCIE1, SGMII_TSEC1, SGMII_TSEC2, SGMII_TSEC3},
+ [0x03] = {NONE, SGMII_TSEC1, SGMII_TSEC2, SGMII_TSEC3},
+};
+
+static const u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
+ [0x00] = {NONE, NONE},
+ [0x01] = {SATA1, SATA2},
+ [0x02] = {SATA1, SATA2},
+ [0x03] = {PCIE1, PCIE2},
+};
+
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ int ret = (1 << device) & serdes1_prtcl_map;
+
+ if (ret)
+ return ret;
+
+ return (1 << device) & serdes2_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
+ serdes2_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p1021_serdes.c b/arch/powerpc/cpu/mpc85xx/p1021_serdes.c
new file mode 100644
index 0000000..d6d2696
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p1021_serdes.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+typedef struct serdes_85xx {
+ u32 srdscr0; /* 0x00 - SRDS Control Register 0 */
+ u32 srdscr1; /* 0x04 - SRDS Control Register 1 */
+ u32 srdscr2; /* 0x08 - SRDS Control Register 2 */
+ u32 srdscr3; /* 0x0C - SRDS Control Register 3 */
+ u32 srdscr4; /* 0x10 - SRDS Control Register 4 */
+} serdes_85xx_t;
+#define FSL_SRDSCR3_EIC0(x) (((x) & 0x1f) << 8)
+#define FSL_SRDSCR3_EIC0_MASK FSL_SRDSCR3_EIC0(0x1f)
+#define FSL_SRDSCR3_EIC1(x) (((x) & 0x1f) << 0)
+#define FSL_SRDSCR3_EIC1_MASK FSL_SRDSCR3_EIC1(0x1f)
+#define FSL_SRDSCR4_EIC2(x) (((x) & 0x1f) << 8)
+#define FSL_SRDSCR4_EIC2_MASK FSL_SRDSCR4_EIC2(0x1f)
+#define FSL_SRDSCR4_EIC3(x) (((x) & 0x1f) << 0)
+#define FSL_SRDSCR4_EIC3_MASK FSL_SRDSCR4_EIC3(0x1f)
+#define EIC_PCIE 0x13
+#define EIC_SGMII 0x04
+
+#define SRDS1_MAX_LANES 4
+
+static u32 serdes1_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x0] = {PCIE1, NONE, NONE, NONE},
+ [0x6] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0xe] = {PCIE1, PCIE2, SGMII_TSEC2, SGMII_TSEC3},
+ [0xf] = {PCIE1, PCIE1, SGMII_TSEC2, SGMII_TSEC3},
+};
+
+int is_serdes_configured(enum srds_prtcl prtcl)
+{
+ return (1 << prtcl) & serdes1_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ serdes_85xx_t *serdes = (void *)CONFIG_SYS_MPC85xx_SERDES1_ADDR;
+
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+ u32 mask, val;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ /* Init SERDES Receiver electrical idle detection control for PCIe */
+
+ /* Lane 0 is always PCIe 1 */
+ mask = FSL_SRDSCR3_EIC0_MASK;
+ val = FSL_SRDSCR3_EIC0(EIC_PCIE);
+
+ /* Lane 1 */
+ if ((serdes1_cfg_tbl[srds_cfg][1] == PCIE1) ||
+ (serdes1_cfg_tbl[srds_cfg][1] == PCIE2)) {
+ mask |= FSL_SRDSCR3_EIC1_MASK;
+ val |= FSL_SRDSCR3_EIC1(EIC_PCIE);
+ }
+
+ /* Handle lanes 0 & 1 */
+ clrsetbits_be32(&serdes->srdscr3, mask, val);
+
+ /* Handle lanes 2 & 3 */
+ if (srds_cfg == 0x6) {
+ mask = FSL_SRDSCR4_EIC2_MASK | FSL_SRDSCR4_EIC3_MASK;
+ val = FSL_SRDSCR4_EIC2(EIC_PCIE) | FSL_SRDSCR4_EIC3(EIC_PCIE);
+ clrsetbits_be32(&serdes->srdscr4, mask, val);
+ }
+
+ /* 100 ms delay */
+ udelay(100000);
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p1022_serdes.c b/arch/powerpc/cpu/mpc85xx/p1022_serdes.c
new file mode 100644
index 0000000..ed49920
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p1022_serdes.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+#define SRDS2_MAX_LANES 2
+
+static u32 serdes1_prtcl_map, serdes2_prtcl_map;
+
+static const u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x00] = {NONE, NONE, NONE, NONE},
+ [0x01] = {NONE, NONE, NONE, NONE},
+ [0x02] = {NONE, NONE, NONE, NONE},
+ [0x03] = {NONE, NONE, NONE, NONE},
+ [0x04] = {NONE, NONE, NONE, NONE},
+ [0x06] = {PCIE1, PCIE3, SGMII_TSEC1, PCIE2},
+ [0x07] = {PCIE1, PCIE3, SGMII_TSEC1, PCIE2},
+ [0x09] = {PCIE1, NONE, NONE, NONE},
+ [0x0a] = {PCIE1, PCIE3, SGMII_TSEC1, SGMII_TSEC2},
+ [0x0b] = {PCIE1, PCIE3, SGMII_TSEC1, SGMII_TSEC2},
+ [0x0d] = {PCIE1, PCIE1, SGMII_TSEC1, SGMII_TSEC2},
+ [0x0e] = {PCIE1, PCIE1, SGMII_TSEC1, SGMII_TSEC2},
+ [0x0f] = {PCIE1, PCIE1, SGMII_TSEC1, SGMII_TSEC2},
+ [0x15] = {PCIE1, PCIE3, PCIE2, PCIE2},
+ [0x16] = {PCIE1, PCIE3, PCIE2, PCIE2},
+ [0x17] = {PCIE1, PCIE3, PCIE2, PCIE2},
+ [0x18] = {PCIE1, PCIE1, PCIE2, PCIE2},
+ [0x19] = {PCIE1, PCIE1, PCIE2, PCIE2},
+ [0x1a] = {PCIE1, PCIE1, PCIE2, PCIE2},
+ [0x1b] = {PCIE1, PCIE1, PCIE2, PCIE2},
+ [0x1c] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x1d] = {PCIE1, PCIE1, PCIE2, PCIE2},
+ [0x1e] = {PCIE1, PCIE1, PCIE2, PCIE2},
+ [0x1f] = {PCIE1, PCIE1, PCIE2, PCIE2},
+};
+
+static const u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
+ [0x00] = {PCIE3, PCIE3},
+ [0x01] = {PCIE2, PCIE3},
+ [0x02] = {SATA1, SATA2},
+ [0x03] = {SGMII_TSEC1, SGMII_TSEC2},
+ [0x04] = {NONE, NONE},
+ [0x06] = {SATA1, SATA2},
+ [0x07] = {NONE, NONE},
+ [0x09] = {PCIE3, PCIE2},
+ [0x0a] = {SATA1, SATA2},
+ [0x0b] = {NONE, NONE},
+ [0x0d] = {PCIE3, PCIE2},
+ [0x0e] = {SATA1, SATA2},
+ [0x0f] = {NONE, NONE},
+ [0x15] = {SGMII_TSEC1, SGMII_TSEC2},
+ [0x16] = {SATA1, SATA2},
+ [0x17] = {NONE, NONE},
+ [0x18] = {PCIE3, PCIE3},
+ [0x19] = {SGMII_TSEC1, SGMII_TSEC2},
+ [0x1a] = {SATA1, SATA2},
+ [0x1b] = {NONE, NONE},
+ [0x1c] = {PCIE3, PCIE3},
+ [0x1d] = {SGMII_TSEC1, SGMII_TSEC2},
+ [0x1e] = {SATA1, SATA2},
+ [0x1f] = {NONE, NONE},
+};
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ int ret = (1 << device) & serdes1_prtcl_map;
+
+ if (ret)
+ return ret;
+
+ return (1 << device) & serdes2_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
+ serdes2_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p1023_serdes.c b/arch/powerpc/cpu/mpc85xx/p1023_serdes.c
new file mode 100644
index 0000000..0b4ae90
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p1023_serdes.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+
+static u32 serdes1_prtcl_map;
+
+static const u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x00] = {PCIE1, PCIE2, NONE, NONE},
+ [0x01] = {PCIE1, PCIE2, PCIE3, NONE},
+ [0x02] = {PCIE1, PCIE2, PCIE3, SGMII_FM1_DTSEC2},
+ [0x03] = {PCIE1, PCIE2, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2},
+};
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ int ret = (1 << device) & serdes1_prtcl_map;
+ return ret;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p2020_serdes.c b/arch/powerpc/cpu/mpc85xx/p2020_serdes.c
new file mode 100644
index 0000000..01af333
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p2020_serdes.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+
+static u32 serdes1_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x0] = {PCIE1, NONE, NONE, NONE},
+ [0x2] = {PCIE1, PCIE2, PCIE3, PCIE3},
+ [0x4] = {PCIE1, PCIE1, PCIE3, PCIE3},
+ [0x6] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x7] = {SRIO2, SRIO1, NONE, NONE},
+ [0x8] = {SRIO2, SRIO2, SRIO2, SRIO2},
+ [0x9] = {SRIO2, SRIO2, SRIO2, SRIO2},
+ [0xa] = {SRIO2, SRIO2, SRIO2, SRIO2},
+ [0xb] = {SRIO2, SRIO1, SGMII_TSEC2, SGMII_TSEC3},
+ [0xc] = {SRIO2, SRIO1, SGMII_TSEC2, SGMII_TSEC3},
+ [0xd] = {PCIE1, SRIO1, SGMII_TSEC2, SGMII_TSEC3},
+ [0xe] = {PCIE1, PCIE2, SGMII_TSEC2, SGMII_TSEC3},
+ [0xf] = {PCIE1, PCIE1, SGMII_TSEC2, SGMII_TSEC3},
+};
+
+int is_serdes_configured(enum srds_prtcl prtcl)
+{
+ return (1 << prtcl) & serdes1_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >>
+ MPC85xx_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p2041_ids.c b/arch/powerpc/cpu/mpc85xx/p2041_ids.c
new file mode 100644
index 0000000..ef685fe
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p2041_ids.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO(1, 2, 1, 0),
+ SET_QP_INFO(3, 4, 2, 1),
+ SET_QP_INFO(5, 6, 3, 2),
+ SET_QP_INFO(7, 8, 4, 3),
+ SET_QP_INFO(9, 10, 5, 0),
+ SET_QP_INFO(11, 12, 6, 1),
+ SET_QP_INFO(13, 14, 7, 2),
+ SET_QP_INFO(15, 16, 8, 3),
+ SET_QP_INFO(17, 18, 9, 0), /* for now sdest to 0 */
+ SET_QP_INFO(19, 20, 10, 0), /* for now sdest to 0 */
+};
+#endif
+
+struct srio_liodn_id_table srio_liodn_tbl[] = {
+ SET_SRIO_LIODN_2(1, 199, 200),
+ SET_SRIO_LIODN_2(2, 201, 202),
+};
+int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl);
+
+struct liodn_id_table liodn_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(31),
+ SET_BMAN_LIODN(32),
+#endif
+
+ SET_SDHC_LIODN(1, 64),
+
+ SET_PME_LIODN(117),
+
+ SET_USB_LIODN(1, "fsl-usb2-mph", 125),
+ SET_USB_LIODN(2, "fsl-usb2-dr", 126),
+
+ SET_SATA_LIODN(1, 127),
+ SET_SATA_LIODN(2, 128),
+
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 193),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 2, 194),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 3, 195),
+
+ SET_DMA_LIODN(1, 197),
+ SET_DMA_LIODN(2, 198),
+
+ SET_GUTS_LIODN("fsl,rapidio-delta", 199, rio1liodnr, 0),
+ SET_GUTS_LIODN(NULL, 200, rio2liodnr, 0),
+ SET_GUTS_LIODN(NULL, 201, rio1maintliodnr, 0),
+ SET_GUTS_LIODN(NULL, 202, rio2maintliodnr, 0),
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 10),
+ SET_FMAN_RX_1G_LIODN(1, 1, 11),
+ SET_FMAN_RX_1G_LIODN(1, 2, 12),
+ SET_FMAN_RX_1G_LIODN(1, 3, 13),
+ SET_FMAN_RX_1G_LIODN(1, 4, 14),
+#if (CONFIG_SYS_NUM_FM1_10GEC == 1)
+ SET_FMAN_RX_10G_LIODN(1, 0, 15),
+#endif
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ SET_SEC_JR_LIODN_ENTRY(0, 129, 130),
+ SET_SEC_JR_LIODN_ENTRY(1, 131, 132),
+ SET_SEC_JR_LIODN_ENTRY(2, 133, 134),
+ SET_SEC_JR_LIODN_ENTRY(3, 135, 136),
+ SET_SEC_RTIC_LIODN_ENTRY(a, 154),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 155),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 156),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 157),
+ SET_SEC_DECO_LIODN_ENTRY(0, 97, 98),
+ SET_SEC_DECO_LIODN_ENTRY(1, 99, 100),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+struct liodn_id_table rman_liodn_tbl[] = {
+ /* Set RMan block 0-3 liodn offset */
+ SET_RMAN_LIODN(0, 6),
+ SET_RMAN_LIODN(1, 7),
+ SET_RMAN_LIODN(2, 8),
+ SET_RMAN_LIODN(3, 9),
+};
+int rman_liodn_tbl_sz = ARRAY_SIZE(rman_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_bases[] = {
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(64, 100),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(32),
+#endif
+#ifdef CONFIG_SYS_DPAA_PME
+ [FSL_HW_PORTAL_PME] = SET_LIODN_BASE_2(136, 172),
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ [FSL_HW_PORTAL_RMAN] = SET_LIODN_BASE_1(80),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/p2041_serdes.c b/arch/powerpc/cpu/mpc85xx/p2041_serdes.c
new file mode 100644
index 0000000..87335c9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p2041_serdes.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet_serdes.h"
+
+static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = {
+ [0x2] = {NONE, NONE, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, NONE, NONE, },
+ [0x5] = {NONE, NONE, PCIE1, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, NONE, NONE, },
+ [0x8] = {NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, PCIE2,
+ PCIE2, PCIE2, PCIE2, NONE, NONE, NONE, NONE, SATA1,
+ SATA2, NONE, NONE, NONE, NONE, },
+ [0x9] = {NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, PCIE2,
+ PCIE2, PCIE2, PCIE2, NONE, NONE, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, NONE, NONE, NONE, NONE, },
+ [0xa] = {NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, PCIE2,
+ PCIE2, PCIE2, PCIE2, NONE, NONE, PCIE3, PCIE3, PCIE3,
+ PCIE3, NONE, NONE, NONE, NONE, },
+ [0xf] = {NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SRIO2,
+ SRIO2, SRIO1, SRIO1, NONE, NONE, PCIE3, SGMII_FM1_DTSEC5,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, NONE, NONE, },
+ [0x14] = {NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, PCIE2,
+ PCIE2, SRIO1, SRIO1, NONE, NONE, AURORA,
+ SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE,
+ NONE, NONE, NONE, },
+ [0x16] = {NONE, NONE, PCIE1, PCIE3, PCIE2, PCIE2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, NONE, NONE, NONE, NONE, SATA1, SATA2, NONE,
+ NONE, NONE, NONE, },
+ [0x17] = {NONE, NONE, PCIE1, PCIE3, PCIE2, PCIE2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, NONE, NONE, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, NONE, NONE, NONE, NONE, },
+ [0x19] = {NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, PCIE2,
+ PCIE2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE,
+ NONE, NONE, SATA1, SATA2, NONE, NONE, NONE, NONE, },
+ [0x1a] = {NONE, NONE, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SRIO2,
+ SRIO2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE,
+ NONE, NONE, SATA1, SATA2, NONE, NONE, NONE, NONE, },
+ [0x1c] = {NONE, NONE, PCIE1, SGMII_FM1_DTSEC2, PCIE2, PCIE2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, AURORA,
+ SGMII_FM1_DTSEC5, NONE, NONE, NONE, NONE, NONE, NONE, },
+};
+
+enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
+{
+ enum srds_prtcl prtcl;
+ u32 svr = get_svr();
+ u32 ver = SVR_SOC_VER(svr);
+
+ if (!serdes_lane_enabled(lane))
+ return NONE;
+
+ prtcl = serdes_cfg_tbl[cfg][lane];
+
+ /* P2040[e] does not support XAUI */
+ if (ver == SVR_P2040 && prtcl == XAUI_FM1)
+ prtcl = NONE;
+
+ return prtcl;
+}
+
+int is_serdes_prtcl_valid(u32 prtcl)
+{
+ int i;
+ u32 svr = get_svr();
+ u32 ver = SVR_SOC_VER(svr);
+
+ if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ /* P2040[e] does not support XAUI */
+ if (ver == SVR_P2040 && prtcl == XAUI_FM1)
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_cfg_tbl[prtcl][i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p3041_ids.c b/arch/powerpc/cpu/mpc85xx/p3041_ids.c
new file mode 100644
index 0000000..cab03f8
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p3041_ids.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO(1, 2, 1, 0),
+ SET_QP_INFO(3, 4, 2, 1),
+ SET_QP_INFO(5, 6, 3, 2),
+ SET_QP_INFO(7, 8, 4, 3),
+ SET_QP_INFO(9, 10, 5, 0),
+ SET_QP_INFO(1, 12, 6, 1),
+ SET_QP_INFO(13, 14, 7, 2),
+ SET_QP_INFO(15, 16, 8, 3),
+ SET_QP_INFO(17, 18, 9, 0), /* for now sdest to 0 */
+ SET_QP_INFO(19, 20, 10, 0), /* for now sdest to 0 */
+};
+#endif
+
+struct srio_liodn_id_table srio_liodn_tbl[] = {
+ SET_SRIO_LIODN_2(1, 199, 200),
+ SET_SRIO_LIODN_2(2, 201, 202),
+};
+int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl);
+
+struct liodn_id_table liodn_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(31),
+ SET_BMAN_LIODN(32),
+#endif
+
+ SET_SDHC_LIODN(1, 64),
+
+ SET_PME_LIODN(117),
+
+ SET_USB_LIODN(1, "fsl-usb2-mph", 125),
+ SET_USB_LIODN(2, "fsl-usb2-dr", 126),
+
+ SET_SATA_LIODN(1, 127),
+ SET_SATA_LIODN(2, 128),
+
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 193),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 2, 194),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 3, 195),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 4, 196),
+
+ SET_DMA_LIODN(1, 197),
+ SET_DMA_LIODN(2, 198),
+
+ SET_GUTS_LIODN("fsl,rapidio-delta", 199, rio1liodnr, 0),
+ SET_GUTS_LIODN(NULL, 200, rio2liodnr, 0),
+ SET_GUTS_LIODN(NULL, 201, rio1maintliodnr, 0),
+ SET_GUTS_LIODN(NULL, 202, rio2maintliodnr, 0),
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 10),
+ SET_FMAN_RX_1G_LIODN(1, 1, 11),
+ SET_FMAN_RX_1G_LIODN(1, 2, 12),
+ SET_FMAN_RX_1G_LIODN(1, 3, 13),
+ SET_FMAN_RX_1G_LIODN(1, 4, 14),
+ SET_FMAN_RX_10G_LIODN(1, 0, 15),
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ SET_SEC_JR_LIODN_ENTRY(0, 129, 130),
+ SET_SEC_JR_LIODN_ENTRY(1, 131, 132),
+ SET_SEC_JR_LIODN_ENTRY(2, 133, 134),
+ SET_SEC_JR_LIODN_ENTRY(3, 135, 136),
+ SET_SEC_RTIC_LIODN_ENTRY(a, 154),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 155),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 156),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 157),
+ SET_SEC_DECO_LIODN_ENTRY(0, 97, 98),
+ SET_SEC_DECO_LIODN_ENTRY(1, 99, 100),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+struct liodn_id_table rman_liodn_tbl[] = {
+ /* Set RMan block 0-3 liodn offset */
+ SET_RMAN_LIODN(0, 6),
+ SET_RMAN_LIODN(1, 7),
+ SET_RMAN_LIODN(2, 8),
+ SET_RMAN_LIODN(3, 9),
+};
+int rman_liodn_tbl_sz = ARRAY_SIZE(rman_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_bases[] = {
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(64, 100),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(32),
+#endif
+#ifdef CONFIG_SYS_DPAA_PME
+ [FSL_HW_PORTAL_PME] = SET_LIODN_BASE_2(136, 172),
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ [FSL_HW_PORTAL_RMAN] = SET_LIODN_BASE_1(80),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/p3041_serdes.c b/arch/powerpc/cpu/mpc85xx/p3041_serdes.c
new file mode 100644
index 0000000..a36dcd5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p3041_serdes.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet_serdes.h"
+
+static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = {
+ [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ PCIE4, AURORA, PCIE3, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x4] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ PCIE2, AURORA, PCIE3, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, },
+ [0xb] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO2, SRIO2, SRIO1, SRIO1,
+ PCIE2, AURORA, PCIE3, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x10] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x11] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x13] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, },
+ [0x14] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, PCIE3, PCIE3, PCIE3, PCIE3,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, },
+ [0x15] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x16] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SRIO1, SRIO1, SRIO1,
+ SRIO1, },
+ [0x17] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x18] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x1b] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x1d] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE,
+ SATA1, SATA2, },
+ [0x20] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, },
+ [0x21] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, PCIE3, PCIE3, PCIE3, PCIE3,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, },
+ [0x22] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x23] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO2, SRIO2, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x24] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO2, SRIO2, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x28] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x29] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x2a] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, },
+ [0x2b] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x2f] = {PCIE1, PCIE1, PCIE3, PCIE3, SRIO2, SRIO2, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x31] = {PCIE1, PCIE1, PCIE3, PCIE3, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x33] = {PCIE1, PCIE1, PCIE3, PCIE3, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x34] = {PCIE1, PCIE1, PCIE1, PCIE1, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA,
+ AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE,
+ NONE, SATA1, SATA2, },
+ [0x35] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA, AURORA, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE, NONE, SATA1, SATA2, },
+ [0x36] = {PCIE1, PCIE1, PCIE3, PCIE3, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA,
+ AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE,
+ NONE, SATA1, SATA2, },
+ [0x37] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA, AURORA, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE, NONE, SATA1, SATA2, },
+};
+
+enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
+{
+ if (!serdes_lane_enabled(lane))
+ return NONE;
+
+ return serdes_cfg_tbl[cfg][lane];
+}
+
+int is_serdes_prtcl_valid(u32 prtcl) {
+ int i;
+
+ if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_cfg_tbl[prtcl][i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p4080_ids.c b/arch/powerpc/cpu/mpc85xx/p4080_ids.c
new file mode 100644
index 0000000..5c287fb
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p4080_ids.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO( 1, 2, 1, 0),
+ SET_QP_INFO( 3, 4, 2, 1),
+ SET_QP_INFO( 5, 6, 3, 2),
+ SET_QP_INFO( 7, 8, 4, 3),
+ SET_QP_INFO( 9, 10, 5, 4),
+ SET_QP_INFO(11, 12, 6, 5),
+ SET_QP_INFO(13, 14, 7, 6),
+ SET_QP_INFO(15, 16, 8, 7),
+ SET_QP_INFO(17, 18, 9, 0), /* for now sdest to 0 */
+ SET_QP_INFO(19, 20, 10, 0), /* for now sdest to 0 */
+};
+#endif
+
+struct srio_liodn_id_table srio_liodn_tbl[] = {
+ SET_SRIO_LIODN_1(1, 198),
+ SET_SRIO_LIODN_1(2, 199),
+};
+int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl);
+
+struct liodn_id_table liodn_tbl[] = {
+ SET_USB_LIODN(1, "fsl-usb2-mph", 127),
+ SET_USB_LIODN(2, "fsl-usb2-dr", 157),
+
+ SET_SDHC_LIODN(1, 156),
+
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 193),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 2, 194),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 3, 195),
+
+ SET_DMA_LIODN(1, 196),
+ SET_DMA_LIODN(2, 197),
+
+ SET_GUTS_LIODN("fsl,srio-rmu", 200, rmuliodnr, 0xd3000),
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(31),
+ SET_BMAN_LIODN(32),
+#endif
+ SET_PME_LIODN(128),
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 11),
+ SET_FMAN_RX_1G_LIODN(1, 1, 12),
+ SET_FMAN_RX_1G_LIODN(1, 2, 13),
+ SET_FMAN_RX_1G_LIODN(1, 3, 14),
+ SET_FMAN_RX_10G_LIODN(1, 0, 15),
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+struct liodn_id_table fman2_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(2, 0, 16),
+ SET_FMAN_RX_1G_LIODN(2, 1, 17),
+ SET_FMAN_RX_1G_LIODN(2, 2, 18),
+ SET_FMAN_RX_1G_LIODN(2, 3, 19),
+ SET_FMAN_RX_10G_LIODN(2, 0, 20),
+};
+int fman2_liodn_tbl_sz = ARRAY_SIZE(fman2_liodn_tbl);
+#endif
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ /*
+ * We assume currently that all JR are in the same partition
+ * and as such they need to represent the same LIODN due to
+ * a 4080 rev.2 h/w requirement that DECOs sharing from themselves
+ * or from another DECO have the two Non-SEQ LIODN values equal
+ */
+ SET_SEC_JR_LIODN_ENTRY(0, 146, 154), /* (0, 146, 154), */
+ SET_SEC_JR_LIODN_ENTRY(1, 146, 154), /* (1, 147, 155), */
+ SET_SEC_JR_LIODN_ENTRY(2, 146, 154), /* (2, 178, 186), */
+ SET_SEC_JR_LIODN_ENTRY(3, 146, 154), /* (3, 179, 187), */
+ SET_SEC_RTIC_LIODN_ENTRY(a, 144),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 145),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 176),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 177),
+ SET_SEC_DECO_LIODN_ENTRY(0, 129, 161),
+ SET_SEC_DECO_LIODN_ENTRY(1, 130, 162),
+ SET_SEC_DECO_LIODN_ENTRY(2, 131, 163),
+ SET_SEC_DECO_LIODN_ENTRY(3, 132, 164),
+ SET_SEC_DECO_LIODN_ENTRY(4, 133, 165),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+struct liodn_id_table liodn_bases[] = {
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(96, 106),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(32),
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ [FSL_HW_PORTAL_FMAN2] = SET_LIODN_BASE_1(64),
+#endif
+#endif
+#ifdef CONFIG_SYS_DPAA_PME
+ [FSL_HW_PORTAL_PME] = SET_LIODN_BASE_2(116, 133),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/p4080_serdes.c b/arch/powerpc/cpu/mpc85xx/p4080_serdes.c
new file mode 100644
index 0000000..94ec445
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p4080_serdes.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet_serdes.h"
+
+static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = {
+ [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0x8] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0xd] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, SGMII_FM2_DTSEC3,
+ SGMII_FM2_DTSEC4, AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM2, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0xe] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, SGMII_FM2_DTSEC3,
+ SGMII_FM2_DTSEC4, AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM2, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0xf] = {PCIE1, PCIE1, PCIE1, PCIE1, SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4, AURORA, AURORA, XAUI_FM2,
+ XAUI_FM2, XAUI_FM2, XAUI_FM2, NONE, NONE, NONE, NONE},
+ [0x10] = {PCIE1, PCIE1, PCIE3, PCIE3, SGMII_FM2_DTSEC1,
+ SGMII_FM2_DTSEC2, SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ NONE, NONE, NONE, NONE},
+ [0x13] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0x16] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4},
+ [0x19] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, PCIE3, PCIE3, PCIE3, PCIE3, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4},
+ [0x1d] = {PCIE1, PCIE1, PCIE3, PCIE3, NONE, SRIO2, NONE, SRIO1,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0x22] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+ [0x25] = {PCIE1, PCIE1, PCIE3, PCIE3, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1},
+};
+
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+uint16_t srds_lpd_b[SRDS_MAX_BANK];
+#endif
+
+enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
+{
+ if (!serdes_lane_enabled(lane))
+ return NONE;
+
+ return serdes_cfg_tbl[cfg][lane];
+}
+
+int is_serdes_prtcl_valid(u32 prtcl) {
+ int i;
+
+ if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_cfg_tbl[prtcl][i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p5020_ids.c b/arch/powerpc/cpu/mpc85xx/p5020_ids.c
new file mode 100644
index 0000000..ca05b9c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p5020_ids.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO(1, 2, 1, 0),
+ SET_QP_INFO(3, 4, 2, 1),
+ SET_QP_INFO(5, 6, 3, 0),
+ SET_QP_INFO(7, 8, 4, 1),
+ SET_QP_INFO(9, 10, 5, 0),
+ SET_QP_INFO(11, 12, 6, 1),
+ SET_QP_INFO(13, 14, 7, 0),
+ SET_QP_INFO(15, 16, 8, 1),
+ SET_QP_INFO(17, 18, 9, 0),
+ SET_QP_INFO(19, 20, 10, 1),
+};
+#endif
+
+struct srio_liodn_id_table srio_liodn_tbl[] = {
+ SET_SRIO_LIODN_2(1, 199, 200),
+ SET_SRIO_LIODN_2(2, 201, 202),
+};
+int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl);
+
+struct liodn_id_table liodn_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(31),
+ SET_BMAN_LIODN(32),
+#endif
+
+ SET_SDHC_LIODN(1, 64),
+
+ SET_PME_LIODN(117),
+
+ SET_USB_LIODN(1, "fsl-usb2-mph", 125),
+ SET_USB_LIODN(2, "fsl-usb2-dr", 126),
+
+ SET_SATA_LIODN(1, 127),
+ SET_SATA_LIODN(2, 128),
+
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 193),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 2, 194),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 3, 195),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 4, 196),
+
+ SET_DMA_LIODN(1, 197),
+ SET_DMA_LIODN(2, 198),
+
+ SET_GUTS_LIODN("fsl,rapidio-delta", 199, rio1liodnr, 0),
+ SET_GUTS_LIODN(NULL, 200, rio2liodnr, 0),
+ SET_GUTS_LIODN(NULL, 201, rio1maintliodnr, 0),
+ SET_GUTS_LIODN(NULL, 202, rio2maintliodnr, 0),
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 10),
+ SET_FMAN_RX_1G_LIODN(1, 1, 11),
+ SET_FMAN_RX_1G_LIODN(1, 2, 12),
+ SET_FMAN_RX_1G_LIODN(1, 3, 13),
+ SET_FMAN_RX_1G_LIODN(1, 4, 14),
+ SET_FMAN_RX_10G_LIODN(1, 0, 15),
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ SET_SEC_JR_LIODN_ENTRY(0, 129, 130),
+ SET_SEC_JR_LIODN_ENTRY(1, 131, 132),
+ SET_SEC_JR_LIODN_ENTRY(2, 133, 134),
+ SET_SEC_JR_LIODN_ENTRY(3, 135, 136),
+ SET_SEC_RTIC_LIODN_ENTRY(a, 154),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 155),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 156),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 157),
+ SET_SEC_DECO_LIODN_ENTRY(0, 97, 98),
+ SET_SEC_DECO_LIODN_ENTRY(1, 99, 100),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+struct liodn_id_table raide_liodn_tbl[] = {
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(0, 0, 60),
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(0, 1, 61),
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(1, 0, 62),
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(1, 1, 63),
+};
+int raide_liodn_tbl_sz = ARRAY_SIZE(raide_liodn_tbl);
+#endif
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+struct liodn_id_table rman_liodn_tbl[] = {
+ /* Set RMan block 0-3 liodn offset */
+ SET_RMAN_LIODN(0, 6),
+ SET_RMAN_LIODN(1, 7),
+ SET_RMAN_LIODN(2, 8),
+ SET_RMAN_LIODN(3, 9),
+};
+int rman_liodn_tbl_sz = ARRAY_SIZE(rman_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_bases[] = {
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(64, 100),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(32),
+#endif
+#ifdef CONFIG_SYS_DPAA_PME
+ [FSL_HW_PORTAL_PME] = SET_LIODN_BASE_2(136, 172),
+#endif
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+ [FSL_HW_PORTAL_RAID_ENGINE] = SET_LIODN_BASE_1(47),
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ [FSL_HW_PORTAL_RMAN] = SET_LIODN_BASE_1(80),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/p5020_serdes.c b/arch/powerpc/cpu/mpc85xx/p5020_serdes.c
new file mode 100644
index 0000000..a36dcd5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p5020_serdes.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet_serdes.h"
+
+static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = {
+ [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ PCIE4, AURORA, PCIE3, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x4] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ PCIE2, AURORA, PCIE3, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, },
+ [0xb] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO2, SRIO2, SRIO1, SRIO1,
+ PCIE2, AURORA, PCIE3, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x10] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x11] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x13] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, },
+ [0x14] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, PCIE3, PCIE3, PCIE3, PCIE3,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, },
+ [0x15] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x16] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SRIO1, SRIO1, SRIO1,
+ SRIO1, },
+ [0x17] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x18] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x1b] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x1d] = {SRIO2, SRIO2, SRIO2, SRIO2, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, PCIE3, PCIE3, PCIE3, PCIE3, NONE, NONE,
+ SATA1, SATA2, },
+ [0x20] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, },
+ [0x21] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, PCIE3, PCIE3, PCIE3, PCIE3,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, },
+ [0x22] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x23] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO2, SRIO2, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x24] = {PCIE1, PCIE1, PCIE1, PCIE1, SRIO2, SRIO2, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x28] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2, },
+ [0x29] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x2a] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, },
+ [0x2b] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x2f] = {PCIE1, PCIE1, PCIE3, PCIE3, SRIO2, SRIO2, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x31] = {PCIE1, PCIE1, PCIE3, PCIE3, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5, NONE,
+ NONE, NONE, },
+ [0x33] = {PCIE1, PCIE1, PCIE3, PCIE3, SRIO1, SRIO1, SRIO1, SRIO1,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, },
+ [0x34] = {PCIE1, PCIE1, PCIE1, PCIE1, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA,
+ AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE,
+ NONE, SATA1, SATA2, },
+ [0x35] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA, AURORA, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE, NONE, SATA1, SATA2, },
+ [0x36] = {PCIE1, PCIE1, PCIE3, PCIE3, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA,
+ AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE,
+ NONE, SATA1, SATA2, },
+ [0x37] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA, AURORA, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE, NONE, SATA1, SATA2, },
+};
+
+enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
+{
+ if (!serdes_lane_enabled(lane))
+ return NONE;
+
+ return serdes_cfg_tbl[cfg][lane];
+}
+
+int is_serdes_prtcl_valid(u32 prtcl) {
+ int i;
+
+ if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_cfg_tbl[prtcl][i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/p5040_ids.c b/arch/powerpc/cpu/mpc85xx/p5040_ids.c
new file mode 100644
index 0000000..878ee3e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p5040_ids.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO(1, 2, 1, 0),
+ SET_QP_INFO(3, 4, 2, 1),
+ SET_QP_INFO(5, 6, 3, 2),
+ SET_QP_INFO(7, 8, 4, 3),
+ SET_QP_INFO(9, 10, 5, 0),
+ SET_QP_INFO(11, 12, 6, 1),
+ SET_QP_INFO(13, 14, 7, 2),
+ SET_QP_INFO(15, 16, 8, 3),
+ SET_QP_INFO(17, 18, 9, 0), /* for now, set sdest to 0 */
+ SET_QP_INFO(19, 20, 10, 0), /* for now, set sdest to 0 */
+};
+#endif
+
+struct liodn_id_table liodn_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(31),
+ SET_BMAN_LIODN(32),
+#endif
+
+ SET_SDHC_LIODN(1, 64),
+
+ SET_USB_LIODN(1, "fsl-usb2-mph", 93),
+ SET_USB_LIODN(2, "fsl-usb2-dr", 94),
+
+ SET_SATA_LIODN(1, 95),
+ SET_SATA_LIODN(2, 96),
+
+ SET_PCI_LIODN_BASE(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 195),
+ SET_PCI_LIODN_BASE(CONFIG_SYS_FSL_PCIE_COMPAT, 2, 196),
+ SET_PCI_LIODN_BASE(CONFIG_SYS_FSL_PCIE_COMPAT, 3, 197),
+
+ SET_DMA_LIODN(1, 193),
+ SET_DMA_LIODN(2, 194),
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 6),
+ SET_FMAN_RX_1G_LIODN(1, 1, 7),
+ SET_FMAN_RX_1G_LIODN(1, 2, 8),
+ SET_FMAN_RX_1G_LIODN(1, 3, 9),
+ SET_FMAN_RX_1G_LIODN(1, 4, 10),
+ SET_FMAN_RX_10G_LIODN(1, 0, 11),
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+struct liodn_id_table fman2_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(2, 0, 12),
+ SET_FMAN_RX_1G_LIODN(2, 1, 13),
+ SET_FMAN_RX_1G_LIODN(2, 2, 14),
+ SET_FMAN_RX_1G_LIODN(2, 3, 15),
+ SET_FMAN_RX_1G_LIODN(2, 4, 16),
+ SET_FMAN_RX_10G_LIODN(2, 0, 17),
+};
+int fman2_liodn_tbl_sz = ARRAY_SIZE(fman2_liodn_tbl);
+#endif
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ SET_SEC_JR_LIODN_ENTRY(0, 129, 130),
+ SET_SEC_JR_LIODN_ENTRY(1, 131, 132),
+ SET_SEC_JR_LIODN_ENTRY(2, 133, 134),
+ SET_SEC_JR_LIODN_ENTRY(3, 135, 136),
+ SET_SEC_RTIC_LIODN_ENTRY(a, 89),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 90),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 91),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 92),
+ SET_SEC_DECO_LIODN_ENTRY(0, 139, 140),
+ SET_SEC_DECO_LIODN_ENTRY(1, 141, 142),
+ SET_SEC_DECO_LIODN_ENTRY(2, 143, 144),
+ SET_SEC_DECO_LIODN_ENTRY(3, 145, 146),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+struct liodn_id_table raide_liodn_tbl[] = {
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(0, 0, 60),
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(0, 1, 61),
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(1, 0, 62),
+ SET_RAID_ENGINE_JQ_LIODN_ENTRY(1, 1, 63),
+};
+int raide_liodn_tbl_sz = ARRAY_SIZE(raide_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_bases[] = {
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(64, 101),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(32),
+#endif
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ [FSL_HW_PORTAL_FMAN2] = SET_LIODN_BASE_1(160),
+#endif
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+ [FSL_HW_PORTAL_RAID_ENGINE] = SET_LIODN_BASE_1(49),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/p5040_serdes.c b/arch/powerpc/cpu/mpc85xx/p5040_serdes.c
new file mode 100644
index 0000000..d646e85
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/p5040_serdes.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet_serdes.h"
+
+/*
+ * Note: For P5040, the fourth SerDes bank (with two lanes) is on SerDes2, but
+ * U-boot only supports one SerDes controller. Therefore, we ignore bank 4 in
+ * this table. This works because most of the SerDes code is for errata
+ * work-arounds, and there are no P5040 errata that effect bank 4.
+ */
+
+static u8 serdes_cfg_tbl[][SRDS_MAX_LANES] = {
+ [0x00] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2, /* SATA1, SATA2, */ },
+ [0x01] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ SGMII_FM1_DTSEC3, SGMII_FM2_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM2, /* SATA1, SATA2 */ },
+ [0x02] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM2, XAUI_FM2,
+ XAUI_FM2, XAUI_FM2, /* SATA1, SATA2 */ },
+ [0x03] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, SGMII_FM2_DTSEC1,
+ SGMII_FM2_DTSEC2, SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ /* SATA1, SATA2 */ },
+ [0x04] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE3, SGMII_FM2_DTSEC1,
+ SGMII_FM2_DTSEC2, SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ /* SATA1, SATA2 */ },
+ [0x05] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE3, SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4, SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM2, XAUI_FM2,
+ XAUI_FM2, XAUI_FM2, /* SATA1, SATA2 */ },
+ [0x06] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4,
+ XAUI_FM2, XAUI_FM2, XAUI_FM2, XAUI_FM2, /* SATA1, SATA2 */ },
+ [0x07] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1,
+ SGMII_FM1_DTSEC3, SGMII_FM2_DTSEC4, XAUI_FM1, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, XAUI_FM2, XAUI_FM2, XAUI_FM2,
+ XAUI_FM2, /* SATA1, SATA2 */ },
+ [0x11] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, NONE, NONE, SATA1, SATA2,
+ /* NONE, NONE */ },
+ [0x15] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1,
+ NONE, NONE, SATA1, SATA2, /* NONE, NONE */ },
+ [0x2a] = {PCIE1, PCIE1, PCIE3, PCIE3, PCIE2, PCIE2, PCIE2, PCIE2,
+ AURORA, AURORA, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, XAUI_FM2, XAUI_FM2,
+ XAUI_FM2, XAUI_FM2, /* NONE, NONE */ },
+ [0x34] = {PCIE1, PCIE1, PCIE1, PCIE1, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA,
+ AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE,
+ NONE, SATA1, SATA2, /* NONE, NONE */ },
+ [0x35] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA, AURORA, XAUI_FM1,
+ XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE, NONE, SATA1, SATA2,
+ /* NONE, NONE */ },
+ [0x36] = {PCIE1, PCIE1, PCIE3, PCIE3, SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4, AURORA,
+ AURORA, XAUI_FM1, XAUI_FM1, XAUI_FM1, XAUI_FM1, NONE,
+ NONE, SATA1, SATA2, /* NONE, NONE */ },
+};
+
+enum srds_prtcl serdes_get_prtcl(int cfg, int lane)
+{
+ if (!serdes_lane_enabled(lane))
+ return NONE;
+
+ return serdes_cfg_tbl[cfg][lane];
+}
+
+int is_serdes_prtcl_valid(u32 prtcl)
+{
+ int i;
+
+ if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_cfg_tbl[prtcl][i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/pci.c b/arch/powerpc/cpu/mpc85xx/pci.c
new file mode 100644
index 0000000..75d2716
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/pci.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * PCI Configuration space access support for MPC85xx PCI Bridge
+ */
+#include <common.h>
+#include <asm/cpm_85xx.h>
+#include <pci.h>
+
+#if !defined(CONFIG_FSL_PCI_INIT)
+
+#ifndef CONFIG_SYS_PCI1_MEM_BUS
+#define CONFIG_SYS_PCI1_MEM_BUS CONFIG_SYS_PCI1_MEM_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI1_IO_BUS
+#define CONFIG_SYS_PCI1_IO_BUS CONFIG_SYS_PCI1_IO_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI2_MEM_BUS
+#define CONFIG_SYS_PCI2_MEM_BUS CONFIG_SYS_PCI2_MEM_BASE
+#endif
+
+#ifndef CONFIG_SYS_PCI2_IO_BUS
+#define CONFIG_SYS_PCI2_IO_BUS CONFIG_SYS_PCI2_IO_BASE
+#endif
+
+static struct pci_controller *pci_hose;
+
+void
+pci_mpc85xx_init(struct pci_controller *board_hose)
+{
+ u16 reg16;
+ u32 dev;
+
+ volatile ccsr_pcix_t *pcix = (void *)(CONFIG_SYS_MPC85xx_PCIX_ADDR);
+#ifdef CONFIG_MPC85XX_PCI2
+ volatile ccsr_pcix_t *pcix2 = (void *)(CONFIG_SYS_MPC85xx_PCIX2_ADDR);
+#endif
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ struct pci_controller * hose;
+
+ pci_hose = board_hose;
+
+ hose = &pci_hose[0];
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ pci_setup_indirect(hose,
+ (CONFIG_SYS_IMMR+0x8000),
+ (CONFIG_SYS_IMMR+0x8004));
+
+ /*
+ * Hose scan.
+ */
+ dev = PCI_BDF(hose->first_busno, 0, 0);
+ pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+ if (!(gur->pordevsr & MPC85xx_PORDEVSR_PCI1)) {
+ /* PCI-X init */
+ if (CONFIG_SYS_CLK_FREQ < 66000000)
+ printf("PCI-X will only work at 66 MHz\n");
+
+ reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ
+ | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E;
+ pci_hose_write_config_word(hose, dev, PCIX_COMMAND, reg16);
+ }
+
+ pcix->potar1 = (CONFIG_SYS_PCI1_MEM_BUS >> 12) & 0x000fffff;
+ pcix->potear1 = 0x00000000;
+ pcix->powbar1 = (CONFIG_SYS_PCI1_MEM_PHYS >> 12) & 0x000fffff;
+ pcix->powbear1 = 0x00000000;
+ pcix->powar1 = (POWAR_EN | POWAR_MEM_READ |
+ POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI1_MEM_SIZE) - 1));
+
+ pcix->potar2 = (CONFIG_SYS_PCI1_IO_BUS >> 12) & 0x000fffff;
+ pcix->potear2 = 0x00000000;
+ pcix->powbar2 = (CONFIG_SYS_PCI1_IO_PHYS >> 12) & 0x000fffff;
+ pcix->powbear2 = 0x00000000;
+ pcix->powar2 = (POWAR_EN | POWAR_IO_READ |
+ POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI1_IO_SIZE) - 1));
+
+ pcix->pitar1 = 0x00000000;
+ pcix->piwbar1 = 0x00000000;
+ pcix->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+ pcix->powar3 = 0;
+ pcix->powar4 = 0;
+ pcix->piwar2 = 0;
+ pcix->piwar3 = 0;
+
+ pci_set_region(hose->regions + 0,
+ CONFIG_SYS_PCI1_MEM_BUS,
+ CONFIG_SYS_PCI1_MEM_PHYS,
+ CONFIG_SYS_PCI1_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ pci_set_region(hose->regions + 1,
+ CONFIG_SYS_PCI1_IO_BUS,
+ CONFIG_SYS_PCI1_IO_PHYS,
+ CONFIG_SYS_PCI1_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 2;
+
+ pci_register_hose(hose);
+
+#if defined(CONFIG_MPC8555CDS) || defined(CONFIG_MPC8541CDS)
+ /*
+ * This is a SW workaround for an apparent HW problem
+ * in the PCI controller on the MPC85555/41 CDS boards.
+ * The first config cycle must be to a valid, known
+ * device on the PCI bus in order to trick the PCI
+ * controller state machine into a known valid state.
+ * Without this, the first config cycle has the chance
+ * of hanging the controller permanently, just leaving
+ * it in a semi-working state, or leaving it working.
+ *
+ * Pick on the Tundra, Device 17, to get it right.
+ */
+ {
+ u8 header_type;
+
+ pci_hose_read_config_byte(hose,
+ PCI_BDF(0,BRIDGE_ID,0),
+ PCI_HEADER_TYPE,
+ &header_type);
+ }
+#endif
+
+ hose->last_busno = pci_hose_scan(hose);
+
+#ifdef CONFIG_MPC85XX_PCI2
+ hose = &pci_hose[1];
+
+ hose->first_busno = pci_hose[0].last_busno + 1;
+ hose->last_busno = 0xff;
+
+ pci_setup_indirect(hose,
+ (CONFIG_SYS_IMMR+0x9000),
+ (CONFIG_SYS_IMMR+0x9004));
+
+ dev = PCI_BDF(hose->first_busno, 0, 0);
+ pci_hose_read_config_word (hose, dev, PCI_COMMAND, &reg16);
+ reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
+
+ /*
+ * Clear non-reserved bits in status register.
+ */
+ pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
+
+ pcix2->potar1 = (CONFIG_SYS_PCI2_MEM_BUS >> 12) & 0x000fffff;
+ pcix2->potear1 = 0x00000000;
+ pcix2->powbar1 = (CONFIG_SYS_PCI2_MEM_PHYS >> 12) & 0x000fffff;
+ pcix2->powbear1 = 0x00000000;
+ pcix2->powar1 = (POWAR_EN | POWAR_MEM_READ |
+ POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI2_MEM_SIZE) - 1));
+
+ pcix2->potar2 = (CONFIG_SYS_PCI2_IO_BUS >> 12) & 0x000fffff;
+ pcix2->potear2 = 0x00000000;
+ pcix2->powbar2 = (CONFIG_SYS_PCI2_IO_PHYS >> 12) & 0x000fffff;
+ pcix2->powbear2 = 0x00000000;
+ pcix2->powar2 = (POWAR_EN | POWAR_IO_READ |
+ POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI2_IO_SIZE) - 1));
+
+ pcix2->pitar1 = 0x00000000;
+ pcix2->piwbar1 = 0x00000000;
+ pcix2->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G);
+
+ pcix2->powar3 = 0;
+ pcix2->powar4 = 0;
+ pcix2->piwar2 = 0;
+ pcix2->piwar3 = 0;
+
+ pci_set_region(hose->regions + 0,
+ CONFIG_SYS_PCI2_MEM_BUS,
+ CONFIG_SYS_PCI2_MEM_PHYS,
+ CONFIG_SYS_PCI2_MEM_SIZE,
+ PCI_REGION_MEM);
+
+ pci_set_region(hose->regions + 1,
+ CONFIG_SYS_PCI2_IO_BUS,
+ CONFIG_SYS_PCI2_IO_PHYS,
+ CONFIG_SYS_PCI2_IO_SIZE,
+ PCI_REGION_IO);
+
+ hose->region_count = 2;
+
+ /*
+ * Hose scan.
+ */
+ pci_register_hose(hose);
+
+ hose->last_busno = pci_hose_scan(hose);
+#endif
+}
+#endif /* !CONFIG_FSL_PCI_INIT */
diff --git a/arch/powerpc/cpu/mpc85xx/portals.c b/arch/powerpc/cpu/mpc85xx/portals.c
new file mode 100644
index 0000000..672edde
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/portals.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+void setup_portals(void)
+{
+ ccsr_qman_t *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
+#ifdef CONFIG_FSL_CORENET
+ int i;
+
+ for (i = 0; i < CONFIG_SYS_QMAN_NUM_PORTALS; i++) {
+ u8 sdest = qp_info[i].sdest;
+ u16 fliodn = qp_info[i].fliodn;
+ u16 dliodn = qp_info[i].dliodn;
+ u16 liodn_off = qp_info[i].liodn_offset;
+
+ out_be32(&qman->qcsp[i].qcsp_lio_cfg, (liodn_off << 16) |
+ dliodn);
+ /* set frame liodn */
+ out_be32(&qman->qcsp[i].qcsp_io_cfg, (sdest << 16) | fliodn);
+ }
+#endif
+
+ /* Set the Qman initiator BAR to match the LAW (for DQRR stashing) */
+#ifdef CONFIG_PHYS_64BIT
+ out_be32(&qman->qcsp_bare, (u32)(CONFIG_SYS_QMAN_MEM_PHYS >> 32));
+#endif
+ out_be32(&qman->qcsp_bar, (u32)CONFIG_SYS_QMAN_MEM_PHYS);
+}
+
+/* Update portal containter to match LAW setup of portal in phy map */
+void fdt_portal(void *blob, const char *compat, const char *container,
+ u64 addr, u32 size)
+{
+ int off;
+
+ off = fdt_node_offset_by_compatible(blob, -1, compat);
+ if (off < 0)
+ return ;
+
+ off = fdt_parent_offset(blob, off);
+ /* if non-zero assume we have a container */
+ if (off > 0) {
+ char buf[60];
+ const char *p, *name;
+ u32 *range;
+ int len;
+
+ /* fixup ranges */
+ range = fdt_getprop_w(blob, off, "ranges", &len);
+ if (range == NULL) {
+ printf("ERROR: container for %s has no ranges", compat);
+ return ;
+ }
+
+ range[0] = 0;
+ if (len == 16) {
+ range[1] = addr >> 32;
+ range[2] = addr & 0xffffffff;
+ range[3] = size;
+ } else {
+ range[1] = addr & 0xffffffff;
+ range[2] = size;
+ }
+ fdt_setprop_inplace(blob, off, "ranges", range, len);
+
+ /* fixup the name */
+ name = fdt_get_name(blob, off, &len);
+ p = memchr(name, '@', len);
+
+ if (p)
+ len = p - name;
+
+ /* if we are given a container name check it
+ * against what we found, if it doesnt match exit out */
+ if (container && (memcmp(container, name, len))) {
+ printf("WARNING: container names didn't match %s %s\n",
+ container, name);
+ return ;
+ }
+
+ memcpy(&buf, name, len);
+ len += sprintf(&buf[len], "@%llx", addr);
+ fdt_set_name(blob, off, buf);
+ return ;
+ }
+
+ printf("ERROR: %s isn't in a container. Not supported\n", compat);
+}
+
+static int fdt_qportal(void *blob, int off, int id, char *name,
+ enum fsl_dpaa_dev dev, int create)
+{
+ int childoff, dev_off, ret = 0;
+ uint32_t dev_handle;
+#ifdef CONFIG_FSL_CORENET
+ int num;
+ u32 liodns[2];
+#endif
+
+ childoff = fdt_subnode_offset(blob, off, name);
+ if (create) {
+ char handle[64], *p;
+
+ strncpy(handle, name, sizeof(handle));
+ p = strchr(handle, '@');
+ if (!strncmp(name, "fman", 4)) {
+ *p = *(p + 1);
+ p++;
+ }
+ *p = '\0';
+
+ dev_off = fdt_path_offset(blob, handle);
+ /* skip this node if alias is not found */
+ if (dev_off == -FDT_ERR_BADPATH)
+ return 0;
+ if (dev_off < 0)
+ return dev_off;
+
+ if (childoff <= 0)
+ childoff = fdt_add_subnode(blob, off, name);
+
+ /* need to update the dev_off after adding a subnode */
+ dev_off = fdt_path_offset(blob, handle);
+ if (dev_off < 0)
+ return dev_off;
+
+ if (childoff > 0) {
+ dev_handle = fdt_get_phandle(blob, dev_off);
+ if (dev_handle <= 0) {
+ dev_handle = fdt_alloc_phandle(blob);
+ ret = fdt_set_phandle(blob, dev_off,
+ dev_handle);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = fdt_setprop(blob, childoff, "dev-handle",
+ &dev_handle, sizeof(dev_handle));
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_FSL_CORENET
+ num = get_dpaa_liodn(dev, &liodns[0], id);
+ ret = fdt_setprop(blob, childoff, "fsl,liodn",
+ &liodns[0], sizeof(u32) * num);
+ if (!strncmp(name, "pme", 3)) {
+ u32 pme_rev1, pme_rev2;
+ ccsr_pme_t *pme_regs =
+ (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
+
+ pme_rev1 = in_be32(&pme_regs->pm_ip_rev_1);
+ pme_rev2 = in_be32(&pme_regs->pm_ip_rev_2);
+ ret = fdt_setprop(blob, childoff,
+ "fsl,pme-rev1", &pme_rev1, sizeof(u32));
+ if (ret < 0)
+ return ret;
+ ret = fdt_setprop(blob, childoff,
+ "fsl,pme-rev2", &pme_rev2, sizeof(u32));
+ }
+#endif
+ } else {
+ return childoff;
+ }
+ } else {
+ if (childoff > 0)
+ ret = fdt_del_node(blob, childoff);
+ }
+
+ return ret;
+}
+
+void fdt_fixup_qportals(void *blob)
+{
+ int off, err;
+ unsigned int maj, min;
+ unsigned int ip_cfg;
+ ccsr_qman_t *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
+ u32 rev_1 = in_be32(&qman->ip_rev_1);
+ u32 rev_2 = in_be32(&qman->ip_rev_2);
+ char compat[64];
+ int compat_len;
+
+ maj = (rev_1 >> 8) & 0xff;
+ min = rev_1 & 0xff;
+ ip_cfg = rev_2 & 0xff;
+
+ compat_len = sprintf(compat, "fsl,qman-portal-%u.%u.%u",
+ maj, min, ip_cfg) + 1;
+ compat_len += sprintf(compat + compat_len, "fsl,qman-portal") + 1;
+
+ off = fdt_node_offset_by_compatible(blob, -1, "fsl,qman-portal");
+ while (off != -FDT_ERR_NOTFOUND) {
+#ifdef CONFIG_FSL_CORENET
+ u32 liodns[2];
+#endif
+ const int *ci = fdt_getprop(blob, off, "cell-index", NULL);
+ int i = *ci;
+#ifdef CONFIG_SYS_DPAA_FMAN
+ int j;
+#endif
+
+ err = fdt_setprop(blob, off, "compatible", compat, compat_len);
+ if (err < 0)
+ goto err;
+
+#ifdef CONFIG_FSL_CORENET
+ liodns[0] = qp_info[i].dliodn;
+ liodns[1] = qp_info[i].fliodn;
+
+ err = fdt_setprop(blob, off, "fsl,liodn",
+ &liodns, sizeof(u32) * 2);
+ if (err < 0)
+ goto err;
+#endif
+
+ i++;
+
+ err = fdt_qportal(blob, off, i, "crypto@0", FSL_HW_PORTAL_SEC,
+ IS_E_PROCESSOR(get_svr()));
+ if (err < 0)
+ goto err;
+
+#ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SYS_DPAA_PME
+ err = fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 1);
+ if (err < 0)
+ goto err;
+#else
+ fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 0);
+#endif
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ for (j = 0; j < CONFIG_SYS_NUM_FMAN; j++) {
+ char name[] = "fman@0";
+
+ name[sizeof(name) - 2] = '0' + j;
+ err = fdt_qportal(blob, off, i, name,
+ FSL_HW_PORTAL_FMAN1 + j, 1);
+ if (err < 0)
+ goto err;
+ }
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ err = fdt_qportal(blob, off, i, "rman@0",
+ FSL_HW_PORTAL_RMAN, 1);
+ if (err < 0)
+ goto err;
+#endif
+
+err:
+ if (err < 0) {
+ printf("ERROR: unable to create props for %s: %s\n",
+ fdt_get_name(blob, off, NULL), fdt_strerror(err));
+ return;
+ }
+
+ off = fdt_node_offset_by_compatible(blob, off, "fsl,qman-portal");
+ }
+}
+
+void fdt_fixup_bportals(void *blob)
+{
+ int off, err;
+ unsigned int maj, min;
+ unsigned int ip_cfg;
+ ccsr_bman_t *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR;
+ u32 rev_1 = in_be32(&bman->ip_rev_1);
+ u32 rev_2 = in_be32(&bman->ip_rev_2);
+ char compat[64];
+ int compat_len;
+
+ maj = (rev_1 >> 8) & 0xff;
+ min = rev_1 & 0xff;
+
+ ip_cfg = rev_2 & 0xff;
+
+ compat_len = sprintf(compat, "fsl,bman-portal-%u.%u.%u",
+ maj, min, ip_cfg) + 1;
+ compat_len += sprintf(compat + compat_len, "fsl,bman-portal") + 1;
+
+ off = fdt_node_offset_by_compatible(blob, -1, "fsl,bman-portal");
+ while (off != -FDT_ERR_NOTFOUND) {
+ err = fdt_setprop(blob, off, "compatible", compat, compat_len);
+ if (err < 0) {
+ printf("ERROR: unable to create props for %s: %s\n",
+ fdt_get_name(blob, off, NULL),
+ fdt_strerror(err));
+ return;
+ }
+
+ off = fdt_node_offset_by_compatible(blob, off, "fsl,bman-portal");
+ }
+
+}
diff --git a/arch/powerpc/cpu/mpc85xx/qe_io.c b/arch/powerpc/cpu/mpc85xx/qe_io.c
new file mode 100644
index 0000000..72a29b7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/qe_io.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Freescale Semiconductor, Inc.
+ *
+ * Dave Liu <daveliu@freescale.com>
+ * based on source code of Shlomi Gridish
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "common.h"
+#include "asm/errno.h"
+#include "asm/io.h"
+#include "asm/immap_85xx.h"
+
+#if defined(CONFIG_QE)
+#define NUM_OF_PINS 32
+void qe_config_iopin(u8 port, u8 pin, int dir, int open_drain, int assign)
+{
+ u32 pin_2bit_mask;
+ u32 pin_2bit_dir;
+ u32 pin_2bit_assign;
+ u32 pin_1bit_mask;
+ u32 tmp_val;
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ volatile par_io_t *par_io = (volatile par_io_t *)
+ &(gur->qe_par_io);
+
+ /* Caculate pin location and 2bit mask and dir */
+ pin_2bit_mask = (u32)(0x3 << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+ pin_2bit_dir = (u32)(dir << (NUM_OF_PINS-(pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Setup the direction */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ? \
+ in_be32(&par_io[port].cpdir2) :
+ in_be32(&par_io[port].cpdir1);
+
+ if (pin > (NUM_OF_PINS/2) -1) {
+ out_be32(&par_io[port].cpdir2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cpdir2, pin_2bit_dir | tmp_val);
+ } else {
+ out_be32(&par_io[port].cpdir1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cpdir1, pin_2bit_dir | tmp_val);
+ }
+
+ /* Calculate pin location for 1bit mask */
+ pin_1bit_mask = (u32)(1 << (NUM_OF_PINS - (pin+1)));
+
+ /* Setup the open drain */
+ tmp_val = in_be32(&par_io[port].cpodr);
+ if (open_drain)
+ out_be32(&par_io[port].cpodr, pin_1bit_mask | tmp_val);
+ else
+ out_be32(&par_io[port].cpodr, ~pin_1bit_mask & tmp_val);
+
+ /* Setup the assignment */
+ tmp_val = (pin > (NUM_OF_PINS/2) - 1) ?
+ in_be32(&par_io[port].cppar2):
+ in_be32(&par_io[port].cppar1);
+ pin_2bit_assign = (u32)(assign
+ << (NUM_OF_PINS - (pin%(NUM_OF_PINS/2)+1)*2));
+
+ /* Clear and set 2 bits mask */
+ if (pin > (NUM_OF_PINS/2) - 1) {
+ out_be32(&par_io[port].cppar2, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cppar2, pin_2bit_assign | tmp_val);
+ } else {
+ out_be32(&par_io[port].cppar1, ~pin_2bit_mask & tmp_val);
+ out_be32(&par_io[port].cppar1, pin_2bit_assign | tmp_val);
+ }
+}
+
+#endif /* CONFIG_QE */
diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S
new file mode 100644
index 0000000..a4a21b0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/release.S
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Kumar Gala <kumar.gala@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc85xx.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/* To boot secondary cpus, we need a place for them to start up.
+ * Normally, they start at 0xfffffffc, but that's usually the
+ * firmware, and we don't want to have to run the firmware again.
+ * Instead, the primary cpu will set the BPTR to point here to
+ * this page. We then set up the core, and head to
+ * start_secondary. Note that this means that the code below
+ * must never exceed 1023 instructions (the branch at the end
+ * would then be the 1024th).
+ */
+ .globl __secondary_start_page
+ .align 12
+__secondary_start_page:
+/* First do some preliminary setup */
+ lis r3, HID0_EMCP@h /* enable machine check */
+#ifndef CONFIG_E500MC
+ ori r3,r3,HID0_TBEN@l /* enable Timebase */
+#endif
+#ifdef CONFIG_PHYS_64BIT
+ ori r3,r3,HID0_ENMAS7@l /* enable MAS7 updates */
+#endif
+ mtspr SPRN_HID0,r3
+
+#ifndef CONFIG_E500MC
+ li r3,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
+ mfspr r0,PVR
+ andi. r0,r0,0xff
+ cmpwi r0,0x50@l /* if we are rev 5.0 or greater set MBDD */
+ blt 1f
+ /* Set MBDD bit also */
+ ori r3, r3, HID1_MBDD@l
+1:
+ mtspr SPRN_HID1,r3
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+ mfspr r3,SPRN_HDBCR1
+ oris r3,r3,0x0100
+ mtspr SPRN_HDBCR1,r3
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
+ mfspr r3,SPRN_SVR
+ rlwinm r3,r3,0,0xff
+ li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
+ cmpw r3,r4
+ beq 1f
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
+ li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
+ cmpw r3,r4
+ beq 1f
+#endif
+
+ /* Not a supported revision affected by erratum */
+ b 2f
+
+1: /* Erratum says set bits 55:60 to 001001 */
+ msync
+ isync
+ mfspr r3,SPRN_HDBCR0
+ li r4,0x48
+ rlwimi r3,r4,0,0x1f8
+ mtspr SPRN_HDBCR0,r3
+ isync
+2:
+#endif
+
+ /* Enable branch prediction */
+ lis r3,BUCSR_ENABLE@h
+ ori r3,r3,BUCSR_ENABLE@l
+ mtspr SPRN_BUCSR,r3
+
+ /* Ensure TB is 0 */
+ li r3,0
+ mttbl r3
+ mttbu r3
+
+ /* Enable/invalidate the I-Cache */
+ lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ mtspr SPRN_L1CSR1,r2
+1:
+ mfspr r3,SPRN_L1CSR1
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ mtspr SPRN_L1CSR1,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR1
+ andi. r1,r3,L1CSR1_ICE@l
+ beq 2b
+
+ /* Enable/invalidate the D-Cache */
+ lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+ ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+ mtspr SPRN_L1CSR0,r2
+1:
+ mfspr r3,SPRN_L1CSR0
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+ ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+ mtspr SPRN_L1CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR0
+ andi. r1,r3,L1CSR0_DCE@l
+ beq 2b
+
+#define toreset(x) (x - __secondary_start_page + 0xfffff000)
+
+ /* get our PIR to figure out our table entry */
+ lis r3,toreset(__spin_table_addr)@h
+ ori r3,r3,toreset(__spin_table_addr)@l
+ lwz r3,0(r3)
+
+ mfspr r0,SPRN_PIR
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+/*
+ * PIR definition for Chassis 2
+ * 0-17 Reserved (logic 0s)
+ * 18-19 CHIP_ID, 2'b00 - SoC 1
+ * all others - reserved
+ * 20-24 CLUSTER_ID 5'b00000 - CCM 1
+ * all others - reserved
+ * 25-26 CORE_CLUSTER_ID 2'b00 - cluster 1
+ * 2'b01 - cluster 2
+ * 2'b10 - cluster 3
+ * 2'b11 - cluster 4
+ * 27-28 CORE_ID 2'b00 - core 0
+ * 2'b01 - core 1
+ * 2'b10 - core 2
+ * 2'b11 - core 3
+ * 29-31 THREAD_ID 3'b000 - thread 0
+ * 3'b001 - thread 1
+ *
+ * Power-on PIR increments threads by 0x01, cores within a cluster by 0x08
+ * and clusters by 0x20.
+ *
+ * We renumber PIR so that all threads in the system are consecutive.
+ */
+
+ rlwinm r8,r0,29,0x03 /* r8 = core within cluster */
+ srwi r10,r0,5 /* r10 = cluster */
+
+ mulli r5,r10,CONFIG_SYS_FSL_CORES_PER_CLUSTER
+ add r5,r5,r8 /* for spin table index */
+ mulli r4,r5,CONFIG_SYS_FSL_THREADS_PER_CORE /* for PIR */
+#elif defined(CONFIG_E500MC)
+ rlwinm r4,r0,27,27,31
+ mr r5,r4
+#else
+ mr r4,r0
+ mr r5,r4
+#endif
+
+ /*
+ * r10 has the base address for the entry.
+ * we cannot access it yet before setting up a new TLB
+ */
+ slwi r8,r5,6 /* spin table is padded to 64 byte */
+ add r10,r3,r8
+
+ mtspr SPRN_PIR,r4 /* write to PIR register */
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ /* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
+ slwi r8,r4,1
+ addi r8,r8,32
+ mtspr L1CSR2,r8
+#endif
+
+#if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) || \
+ defined(CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011)
+ /*
+ * CPU22 applies to P4080 rev 1.0, 2.0, fixed in 3.0
+ * NMG_CPU_A011 applies to P4080 rev 1.0, 2.0, fixed in 3.0
+ * also appleis to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1
+ */
+ mfspr r3,SPRN_SVR
+ rlwinm r6,r3,24,~0x800 /* clear E bit */
+
+ lis r5,SVR_P4080@h
+ ori r5,r5,SVR_P4080@l
+ cmpw r6,r5
+ bne 1f
+
+ rlwinm r3,r3,0,0xf0
+ li r5,0x30
+ cmpw r3,r5
+ bge 2f
+1:
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+ lis r3,toreset(enable_cpu_a011_workaround)@ha
+ lwz r3,toreset(enable_cpu_a011_workaround)@l(r3)
+ cmpwi r3,0
+ beq 2f
+#endif
+ mfspr r3,L1CSR2
+ oris r3,r3,(L1CSR2_DCWS)@h
+ mtspr L1CSR2,r3
+2:
+#endif
+
+#ifdef CONFIG_BACKSIDE_L2_CACHE
+ /* skip L2 setup on P2040/P2040E as they have no L2 */
+ mfspr r3,SPRN_SVR
+ rlwinm r6,r3,24,~0x800 /* clear E bit of SVR */
+
+ lis r3,SVR_P2040@h
+ ori r3,r3,SVR_P2040@l
+ cmpw r6,r3
+ beq 3f
+
+ /* Enable/invalidate the L2 cache */
+ msync
+ lis r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@h
+ ori r2,r2,(L2CSR0_L2FI|L2CSR0_L2LFC)@l
+ mtspr SPRN_L2CSR0,r2
+1:
+ mfspr r3,SPRN_L2CSR0
+ and. r1,r3,r2
+ bne 1b
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ /* set stash id to (coreID) * 2 + 32 + L2 (1) */
+ addi r3,r8,1
+ mtspr SPRN_L2CSR1,r3
+#endif
+
+ lis r3,CONFIG_SYS_INIT_L2CSR0@h
+ ori r3,r3,CONFIG_SYS_INIT_L2CSR0@l
+ mtspr SPRN_L2CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L2CSR0
+ andis. r1,r3,L2CSR0_L2E@h
+ beq 2b
+#endif
+3:
+ /* setup mapping for the spin table, WIMGE=0b00100 */
+ lis r13,toreset(__spin_table_addr)@h
+ ori r13,r13,toreset(__spin_table_addr)@l
+ lwz r13,0(r13)
+ /* mask by 4K */
+ rlwinm r13,r13,0,0,19
+
+ lis r11,(MAS0_TLBSEL(1)|MAS0_ESEL(1))@h
+ mtspr SPRN_MAS0,r11
+ lis r11,(MAS1_VALID|MAS1_IPROT)@h
+ ori r11,r11,(MAS1_TS|MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
+ mtspr SPRN_MAS1,r11
+ oris r11,r13,(MAS2_M|MAS2_G)@h
+ ori r11,r13,(MAS2_M|MAS2_G)@l
+ mtspr SPRN_MAS2,r11
+ oris r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@h
+ ori r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@l
+ mtspr SPRN_MAS3,r11
+ li r11,0
+ mtspr SPRN_MAS7,r11
+ tlbwe
+
+ /*
+ * __bootpg_addr has the address of __second_half_boot_page
+ * jump there in AS=1 space with cache enabled
+ */
+ lis r13,toreset(__bootpg_addr)@h
+ ori r13,r13,toreset(__bootpg_addr)@l
+ lwz r11,0(r13)
+ mtspr SPRN_SRR0,r11
+ mfmsr r13
+ ori r12,r13,MSR_IS|MSR_DS@l
+ mtspr SPRN_SRR1,r12
+ rfi
+
+ /*
+ * Allocate some space for the SDRAM address of the bootpg.
+ * This variable has to be in the boot page so that it can
+ * be accessed by secondary cores when they come out of reset.
+ */
+ .align L1_CACHE_SHIFT
+ .globl __bootpg_addr
+__bootpg_addr:
+ .long 0
+
+ .global __spin_table_addr
+__spin_table_addr:
+ .long 0
+
+ /*
+ * This variable is set by cpu_init_r() after parsing hwconfig
+ * to enable workaround for erratum NMG_CPU_A011.
+ */
+ .align L1_CACHE_SHIFT
+ .global enable_cpu_a011_workaround
+enable_cpu_a011_workaround:
+ .long 1
+
+ /* Fill in the empty space. The actual reset vector is
+ * the last word of the page */
+__secondary_start_code_end:
+ .space 4092 - (__secondary_start_code_end - __secondary_start_page)
+__secondary_reset_vector:
+ b __secondary_start_page
+
+
+/* this is a separated page for the spin table and cacheable boot code */
+ .align L1_CACHE_SHIFT
+ .global __second_half_boot_page
+__second_half_boot_page:
+#ifdef CONFIG_PPC_SPINTABLE_COMPATIBLE
+ lis r3,(spin_table_compat - __second_half_boot_page)@h
+ ori r3,r3,(spin_table_compat - __second_half_boot_page)@l
+ add r3,r3,r11 /* r11 has the address of __second_half_boot_page */
+ lwz r14,0(r3)
+#endif
+
+#define ENTRY_ADDR_UPPER 0
+#define ENTRY_ADDR_LOWER 4
+#define ENTRY_R3_UPPER 8
+#define ENTRY_R3_LOWER 12
+#define ENTRY_RESV 16
+#define ENTRY_PIR 20
+#define ENTRY_SIZE 64
+ /*
+ * setup the entry
+ * r10 has the base address of the spin table.
+ * spin table is defined as
+ * struct {
+ * uint64_t entry_addr;
+ * uint64_t r3;
+ * uint32_t rsvd1;
+ * uint32_t pir;
+ * };
+ * we pad this struct to 64 bytes so each entry is in its own cacheline
+ */
+ li r3,0
+ li r8,1
+ mfspr r4,SPRN_PIR
+ stw r3,ENTRY_ADDR_UPPER(r10)
+ stw r3,ENTRY_R3_UPPER(r10)
+ stw r4,ENTRY_R3_LOWER(r10)
+ stw r3,ENTRY_RESV(r10)
+ stw r4,ENTRY_PIR(r10)
+ msync
+ stw r8,ENTRY_ADDR_LOWER(r10)
+
+ /* spin waiting for addr */
+3:
+/*
+ * To comply with ePAPR 1.1, the spin table has been moved to cache-enabled
+ * memory. Old OS may not work with this change. A patch is waiting to be
+ * accepted for Linux kernel. Other OS needs similar fix to spin table.
+ * For OSes with old spin table code, we can enable this temporary fix by
+ * setting environmental variable "spin_table_compat". For new OSes, set
+ * "spin_table_compat=no". After Linux is fixed, we can remove this macro
+ * and related code. For now, it is enabled by default.
+ */
+#ifdef CONFIG_PPC_SPINTABLE_COMPATIBLE
+ cmpwi r14,0
+ beq 4f
+ dcbf 0, r10
+ sync
+4:
+#endif
+ lwz r4,ENTRY_ADDR_LOWER(r10)
+ andi. r11,r4,1
+ bne 3b
+ isync
+
+ /* setup IVORs to match fixed offsets */
+#include "fixed_ivor.S"
+
+ /* get the upper bits of the addr */
+ lwz r11,ENTRY_ADDR_UPPER(r10)
+
+ /* setup branch addr */
+ mtspr SPRN_SRR0,r4
+
+ /* mark the entry as released */
+ li r8,3
+ stw r8,ENTRY_ADDR_LOWER(r10)
+
+ /* mask by ~64M to setup our tlb we will jump to */
+ rlwinm r12,r4,0,0,5
+
+ /*
+ * setup r3, r4, r5, r6, r7, r8, r9
+ * r3 contains the value to put in the r3 register at secondary cpu
+ * entry. The high 32-bits are ignored on 32-bit chip implementations.
+ * 64-bit chip implementations however shall load all 64-bits
+ */
+#ifdef CONFIG_SYS_PPC64
+ ld r3,ENTRY_R3_UPPER(r10)
+#else
+ lwz r3,ENTRY_R3_LOWER(r10)
+#endif
+ li r4,0
+ li r5,0
+ li r6,0
+ lis r7,(64*1024*1024)@h
+ li r8,0
+ li r9,0
+
+ /* load up the pir */
+ lwz r0,ENTRY_PIR(r10)
+ mtspr SPRN_PIR,r0
+ mfspr r0,SPRN_PIR
+ stw r0,ENTRY_PIR(r10)
+
+ mtspr IVPR,r12
+/*
+ * Coming here, we know the cpu has one TLB mapping in TLB1[0]
+ * which maps 0xfffff000-0xffffffff one-to-one. We set up a
+ * second mapping that maps addr 1:1 for 64M, and then we jump to
+ * addr
+ */
+ lis r10,(MAS0_TLBSEL(1)|MAS0_ESEL(0))@h
+ mtspr SPRN_MAS0,r10
+ lis r10,(MAS1_VALID|MAS1_IPROT)@h
+ ori r10,r10,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l
+ mtspr SPRN_MAS1,r10
+ /* WIMGE = 0b00000 for now */
+ mtspr SPRN_MAS2,r12
+ ori r12,r12,(MAS3_SX|MAS3_SW|MAS3_SR)
+ mtspr SPRN_MAS3,r12
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ mtspr SPRN_MAS7,r11
+#endif
+ tlbwe
+
+/* Now we have another mapping for this page, so we jump to that
+ * mapping
+ */
+ mtspr SPRN_SRR1,r13
+ rfi
+
+
+ .align 6
+ .globl __spin_table
+__spin_table:
+ .space CONFIG_MAX_CPUS*ENTRY_SIZE
+
+#ifdef CONFIG_PPC_SPINTABLE_COMPATIBLE
+ .align L1_CACHE_SHIFT
+ .global spin_table_compat
+spin_table_compat:
+ .long 1
+
+#endif
+
+__spin_table_end:
+ .space 4096 - (__spin_table_end - __spin_table)
diff --git a/arch/powerpc/cpu/mpc85xx/resetvec.S b/arch/powerpc/cpu/mpc85xx/resetvec.S
new file mode 100644
index 0000000..29555d4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/resetvec.S
@@ -0,0 +1,2 @@
+ .section .resetvec,"ax"
+ b _start_e500
diff --git a/arch/powerpc/cpu/mpc85xx/serial_scc.c b/arch/powerpc/cpu/mpc85xx/serial_scc.c
new file mode 100644
index 0000000..6345362
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/serial_scc.c
@@ -0,0 +1,278 @@
+/*
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ * Modified based on 8260 for 8560.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SCC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <asm/cpm_85xx.h>
+#include <serial.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SCC)
+
+#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
+
+#define SCC_INDEX 0
+#define PROFF_SCC PROFF_SCC1
+#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
+ CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
+
+#define SCC_INDEX 1
+#define PROFF_SCC PROFF_SCC2
+#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
+ CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
+
+#define SCC_INDEX 2
+#define PROFF_SCC PROFF_SCC3
+#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
+ CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
+
+#define SCC_INDEX 3
+#define PROFF_SCC PROFF_SCC4
+#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
+ CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+static int mpc85xx_serial_init(void)
+{
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ volatile ccsr_cpm_scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
+ uint dpaddr;
+
+ /* initialize pointers to SCC */
+
+ sp = (ccsr_cpm_scc_t *) &(cpm->im_cpm_scc[SCC_INDEX]);
+ up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+
+ /* Disable transmitter/receiver.
+ */
+ sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* put the SCC channel into NMSI (non multiplexd serial interface)
+ * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+ */
+ cpm->im_cpm_mux.cmxscr = \
+ (cpm->im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+ serial_setbrg ();
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&(cpm->im_dprambase[dpaddr]);
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+ up->scc_genscc.scc_rfcr = CPMFCR_EB;
+ up->scc_genscc.scc_tfcr = CPMFCR_EB;
+ up->scc_genscc.scc_mrblr = 1;
+ up->scc_maxidl = 0;
+ up->scc_brkcr = 1;
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+ up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->sccm = 0;
+ sp->scce = 0xffff;
+
+ /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+ */
+ sp->gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
+ sp->gsmrl = \
+ SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+ /* Set CTS no flow control, 1 stop bit, 8 bit character length,
+ * normal async UART mode, no parity
+ */
+ sp->psmr = SCU_PSMR_CL;
+
+ /* execute the "Init Rx and Tx params" CP command.
+ */
+
+ while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+ return (0);
+}
+
+static void mpc85xx_serial_setbrg(void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+ m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
+ CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+ m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
+#endif
+}
+
+static void mpc85xx_serial_putc(const char c)
+{
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf;
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+ tbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_tbase]);
+
+ /* Wait for last character to go.
+ */
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ /* Load the character into the transmit buffer.
+ */
+ *(volatile char *)tbdf->cbd_bufaddr = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+static int mpc85xx_serial_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ unsigned char c;
+
+ up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
+
+ /* Wait for character to show up.
+ */
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* Grab the char and clear the buffer again.
+ */
+ c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return (c);
+}
+
+static int mpc85xx_serial_tstc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+
+ up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
+
+ return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+static struct serial_device mpc85xx_serial_drv = {
+ .name = "mpc85xx_serial",
+ .start = mpc85xx_serial_init,
+ .stop = NULL,
+ .setbrg = mpc85xx_serial_setbrg,
+ .putc = mpc85xx_serial_putc,
+ .puts = default_serial_puts,
+ .getc = mpc85xx_serial_getc,
+ .tstc = mpc85xx_serial_tstc,
+};
+
+void mpc85xx_serial_initialize(void)
+{
+ serial_register(&mpc85xx_serial_drv);
+}
+
+__weak struct serial_device *default_serial_console(void)
+{
+ return &mpc85xx_serial_drv;
+}
+#endif /* CONFIG_CONS_ON_SCC */
diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c
new file mode 100644
index 0000000..a4d6e9c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/speed.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2004, 2007-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao, (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <ppc_asm.tmpl>
+#include <linux/compiler.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* --------------------------------------------------------------- */
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+ volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+#ifdef CONFIG_FSL_IFC
+ struct fsl_ifc *ifc_regs = (void *)CONFIG_SYS_IFC_ADDR;
+ u32 ccr;
+#endif
+#ifdef CONFIG_FSL_CORENET
+ volatile ccsr_clk_t *clk = (void *)(CONFIG_SYS_FSL_CORENET_CLK_ADDR);
+ unsigned int cpu;
+
+ const u8 core_cplx_PLL[16] = {
+ [ 0] = 0, /* CC1 PPL / 1 */
+ [ 1] = 0, /* CC1 PPL / 2 */
+ [ 2] = 0, /* CC1 PPL / 4 */
+ [ 4] = 1, /* CC2 PPL / 1 */
+ [ 5] = 1, /* CC2 PPL / 2 */
+ [ 6] = 1, /* CC2 PPL / 4 */
+ [ 8] = 2, /* CC3 PPL / 1 */
+ [ 9] = 2, /* CC3 PPL / 2 */
+ [10] = 2, /* CC3 PPL / 4 */
+ [12] = 3, /* CC4 PPL / 1 */
+ [13] = 3, /* CC4 PPL / 2 */
+ [14] = 3, /* CC4 PPL / 4 */
+ };
+
+ const u8 core_cplx_PLL_div[16] = {
+ [ 0] = 1, /* CC1 PPL / 1 */
+ [ 1] = 2, /* CC1 PPL / 2 */
+ [ 2] = 4, /* CC1 PPL / 4 */
+ [ 4] = 1, /* CC2 PPL / 1 */
+ [ 5] = 2, /* CC2 PPL / 2 */
+ [ 6] = 4, /* CC2 PPL / 4 */
+ [ 8] = 1, /* CC3 PPL / 1 */
+ [ 9] = 2, /* CC3 PPL / 2 */
+ [10] = 4, /* CC3 PPL / 4 */
+ [12] = 1, /* CC4 PPL / 1 */
+ [13] = 2, /* CC4 PPL / 2 */
+ [14] = 4, /* CC4 PPL / 4 */
+ };
+ uint i, freqCC_PLL[6], rcw_tmp;
+ uint ratio[6];
+ unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
+ uint mem_pll_rat;
+
+ sysInfo->freqSystemBus = sysclk;
+#ifdef CONFIG_DDR_CLK_FREQ
+ sysInfo->freqDDRBus = CONFIG_DDR_CLK_FREQ;
+#else
+ sysInfo->freqDDRBus = sysclk;
+#endif
+
+ sysInfo->freqSystemBus *= (in_be32(&gur->rcwsr[0]) >> 25) & 0x1f;
+ mem_pll_rat = (in_be32(&gur->rcwsr[0]) >>
+ FSL_CORENET_RCWSR0_MEM_PLL_RAT_SHIFT)
+ & FSL_CORENET_RCWSR0_MEM_PLL_RAT_MASK;
+ if (mem_pll_rat > 2)
+ sysInfo->freqDDRBus *= mem_pll_rat;
+ else
+ sysInfo->freqDDRBus = sysInfo->freqSystemBus * mem_pll_rat;
+
+ ratio[0] = (in_be32(&clk->pllc1gsr) >> 1) & 0x3f;
+ ratio[1] = (in_be32(&clk->pllc2gsr) >> 1) & 0x3f;
+ ratio[2] = (in_be32(&clk->pllc3gsr) >> 1) & 0x3f;
+ ratio[3] = (in_be32(&clk->pllc4gsr) >> 1) & 0x3f;
+ ratio[4] = (in_be32(&clk->pllc5gsr) >> 1) & 0x3f;
+ ratio[5] = (in_be32(&clk->pllc6gsr) >> 1) & 0x3f;
+ for (i = 0; i < 6; i++) {
+ if (ratio[i] > 4)
+ freqCC_PLL[i] = sysclk * ratio[i];
+ else
+ freqCC_PLL[i] = sysInfo->freqSystemBus * ratio[i];
+ }
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ /*
+ * Each cluster has up to 4 cores, sharing the same PLL selection.
+ * The cluster assignment is fixed per SoC. PLL1, PLL2, PLL3 are
+ * cluster group A, feeding cores on cluster 1 and cluster 2.
+ * PLL4, PLL5, PLL6 are cluster group B, feeding cores on cluster 3
+ * and cluster 4 if existing.
+ */
+ for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
+ int cluster = fsl_qoriq_core_to_cluster(cpu);
+ u32 c_pll_sel = (in_be32(&clk->clkcsr[cluster].clkcncsr) >> 27)
+ & 0xf;
+ u32 cplx_pll = core_cplx_PLL[c_pll_sel];
+ if (cplx_pll > 3)
+ printf("Unsupported architecture configuration"
+ " in function %s\n", __func__);
+ cplx_pll += (cluster / 2) * 3;
+ sysInfo->freqProcessor[cpu] =
+ freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel];
+ }
+#ifdef CONFIG_PPC_B4860
+#define FM1_CLK_SEL 0xe0000000
+#define FM1_CLK_SHIFT 29
+#else
+#define PME_CLK_SEL 0xe0000000
+#define PME_CLK_SHIFT 29
+#define FM1_CLK_SEL 0x1c000000
+#define FM1_CLK_SHIFT 26
+#endif
+ rcw_tmp = in_be32(&gur->rcwsr[7]);
+
+#ifdef CONFIG_SYS_DPAA_PME
+ switch ((rcw_tmp & PME_CLK_SEL) >> PME_CLK_SHIFT) {
+ case 1:
+ sysInfo->freqPME = freqCC_PLL[0];
+ break;
+ case 2:
+ sysInfo->freqPME = freqCC_PLL[0] / 2;
+ break;
+ case 3:
+ sysInfo->freqPME = freqCC_PLL[0] / 3;
+ break;
+ case 4:
+ sysInfo->freqPME = freqCC_PLL[0] / 4;
+ break;
+ case 6:
+ sysInfo->freqPME = freqCC_PLL[1] / 2;
+ break;
+ case 7:
+ sysInfo->freqPME = freqCC_PLL[1] / 3;
+ break;
+ default:
+ printf("Error: Unknown PME clock select!\n");
+ case 0:
+ sysInfo->freqPME = sysInfo->freqSystemBus / 2;
+ break;
+
+ }
+#endif
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ sysInfo->freqQMAN = sysInfo->freqSystemBus / 2;
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ switch ((rcw_tmp & FM1_CLK_SEL) >> FM1_CLK_SHIFT) {
+ case 1:
+ sysInfo->freqFMan[0] = freqCC_PLL[3];
+ break;
+ case 2:
+ sysInfo->freqFMan[0] = freqCC_PLL[3] / 2;
+ break;
+ case 3:
+ sysInfo->freqFMan[0] = freqCC_PLL[3] / 3;
+ break;
+ case 4:
+ sysInfo->freqFMan[0] = freqCC_PLL[3] / 4;
+ break;
+ case 5:
+ sysInfo->freqFMan[0] = sysInfo->freqSystemBus;
+ break;
+ case 6:
+ sysInfo->freqFMan[0] = freqCC_PLL[4] / 2;
+ break;
+ case 7:
+ sysInfo->freqFMan[0] = freqCC_PLL[4] / 3;
+ break;
+ default:
+ printf("Error: Unknown FMan1 clock select!\n");
+ case 0:
+ sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2;
+ break;
+ }
+#if (CONFIG_SYS_NUM_FMAN) == 2
+#define FM2_CLK_SEL 0x00000038
+#define FM2_CLK_SHIFT 3
+ rcw_tmp = in_be32(&gur->rcwsr[15]);
+ switch ((rcw_tmp & FM2_CLK_SEL) >> FM2_CLK_SHIFT) {
+ case 1:
+ sysInfo->freqFMan[1] = freqCC_PLL[4];
+ break;
+ case 2:
+ sysInfo->freqFMan[1] = freqCC_PLL[4] / 2;
+ break;
+ case 3:
+ sysInfo->freqFMan[1] = freqCC_PLL[4] / 3;
+ break;
+ case 4:
+ sysInfo->freqFMan[1] = freqCC_PLL[4] / 4;
+ break;
+ case 6:
+ sysInfo->freqFMan[1] = freqCC_PLL[3] / 2;
+ break;
+ case 7:
+ sysInfo->freqFMan[1] = freqCC_PLL[3] / 3;
+ break;
+ default:
+ printf("Error: Unknown FMan2 clock select!\n");
+ case 0:
+ sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2;
+ break;
+ }
+#endif /* CONFIG_SYS_NUM_FMAN == 2 */
+#endif /* CONFIG_SYS_DPAA_FMAN */
+
+#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+ for_each_cpu(i, cpu, cpu_numcores(), cpu_mask()) {
+ u32 c_pll_sel = (in_be32(&clk->clkcsr[cpu].clkcncsr) >> 27)
+ & 0xf;
+ u32 cplx_pll = core_cplx_PLL[c_pll_sel];
+
+ sysInfo->freqProcessor[cpu] =
+ freqCC_PLL[cplx_pll] / core_cplx_PLL_div[c_pll_sel];
+ }
+#define PME_CLK_SEL 0x80000000
+#define FM1_CLK_SEL 0x40000000
+#define FM2_CLK_SEL 0x20000000
+#define HWA_ASYNC_DIV 0x04000000
+#if (CONFIG_SYS_FSL_NUM_CC_PLLS == 2)
+#define HWA_CC_PLL 1
+#elif (CONFIG_SYS_FSL_NUM_CC_PLLS == 3)
+#define HWA_CC_PLL 2
+#elif (CONFIG_SYS_FSL_NUM_CC_PLLS == 4)
+#define HWA_CC_PLL 2
+#else
+#error CONFIG_SYS_FSL_NUM_CC_PLLS not set or unknown case
+#endif
+ rcw_tmp = in_be32(&gur->rcwsr[7]);
+
+#ifdef CONFIG_SYS_DPAA_PME
+ if (rcw_tmp & PME_CLK_SEL) {
+ if (rcw_tmp & HWA_ASYNC_DIV)
+ sysInfo->freqPME = freqCC_PLL[HWA_CC_PLL] / 4;
+ else
+ sysInfo->freqPME = freqCC_PLL[HWA_CC_PLL] / 2;
+ } else {
+ sysInfo->freqPME = sysInfo->freqSystemBus / 2;
+ }
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ if (rcw_tmp & FM1_CLK_SEL) {
+ if (rcw_tmp & HWA_ASYNC_DIV)
+ sysInfo->freqFMan[0] = freqCC_PLL[HWA_CC_PLL] / 4;
+ else
+ sysInfo->freqFMan[0] = freqCC_PLL[HWA_CC_PLL] / 2;
+ } else {
+ sysInfo->freqFMan[0] = sysInfo->freqSystemBus / 2;
+ }
+#if (CONFIG_SYS_NUM_FMAN) == 2
+ if (rcw_tmp & FM2_CLK_SEL) {
+ if (rcw_tmp & HWA_ASYNC_DIV)
+ sysInfo->freqFMan[1] = freqCC_PLL[HWA_CC_PLL] / 4;
+ else
+ sysInfo->freqFMan[1] = freqCC_PLL[HWA_CC_PLL] / 2;
+ } else {
+ sysInfo->freqFMan[1] = sysInfo->freqSystemBus / 2;
+ }
+#endif
+#endif
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ sysInfo->freqQMAN = sysInfo->freqSystemBus / 2;
+#endif
+
+#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+#else /* CONFIG_FSL_CORENET */
+ uint plat_ratio, e500_ratio, half_freqSystemBus;
+ int i;
+#ifdef CONFIG_QE
+ __maybe_unused u32 qe_ratio;
+#endif
+
+ plat_ratio = (gur->porpllsr) & 0x0000003e;
+ plat_ratio >>= 1;
+ sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
+
+ /* Divide before multiply to avoid integer
+ * overflow for processor speeds above 2GHz */
+ half_freqSystemBus = sysInfo->freqSystemBus/2;
+ for (i = 0; i < cpu_numcores(); i++) {
+ e500_ratio = ((gur->porpllsr) >> (i * 8 + 16)) & 0x3f;
+ sysInfo->freqProcessor[i] = e500_ratio * half_freqSystemBus;
+ }
+
+ /* Note: freqDDRBus is the MCLK frequency, not the data rate. */
+ sysInfo->freqDDRBus = sysInfo->freqSystemBus;
+
+#ifdef CONFIG_DDR_CLK_FREQ
+ {
+ u32 ddr_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_DDR_RATIO)
+ >> MPC85xx_PORPLLSR_DDR_RATIO_SHIFT;
+ if (ddr_ratio != 0x7)
+ sysInfo->freqDDRBus = ddr_ratio * CONFIG_DDR_CLK_FREQ;
+ }
+#endif
+
+#ifdef CONFIG_QE
+#if defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
+ sysInfo->freqQE = sysInfo->freqSystemBus;
+#else
+ qe_ratio = ((gur->porpllsr) & MPC85xx_PORPLLSR_QE_RATIO)
+ >> MPC85xx_PORPLLSR_QE_RATIO_SHIFT;
+ sysInfo->freqQE = qe_ratio * CONFIG_SYS_CLK_FREQ;
+#endif
+#endif
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+ sysInfo->freqFMan[0] = sysInfo->freqSystemBus;
+#endif
+
+#endif /* CONFIG_FSL_CORENET */
+
+#if defined(CONFIG_FSL_LBC)
+ uint lcrr_div;
+#if defined(CONFIG_SYS_LBC_LCRR)
+ /* We will program LCRR to this value later */
+ lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV;
+#else
+ lcrr_div = in_be32(&(LBC_BASE_ADDR)->lcrr) & LCRR_CLKDIV;
+#endif
+ if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) {
+#if defined(CONFIG_FSL_CORENET)
+ /* If this is corenet based SoC, bit-representation
+ * for four times the clock divider values.
+ */
+ lcrr_div *= 4;
+#elif !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && \
+ !defined(CONFIG_MPC8555) && !defined(CONFIG_MPC8560)
+ /*
+ * Yes, the entire PQ38 family use the same
+ * bit-representation for twice the clock divider values.
+ */
+ lcrr_div *= 2;
+#endif
+ sysInfo->freqLocalBus = sysInfo->freqSystemBus / lcrr_div;
+ } else {
+ /* In case anyone cares what the unknown value is */
+ sysInfo->freqLocalBus = lcrr_div;
+ }
+#endif
+
+#if defined(CONFIG_FSL_IFC)
+ ccr = in_be32(&ifc_regs->ifc_ccr);
+ ccr = ((ccr & IFC_CCR_CLK_DIV_MASK) >> IFC_CCR_CLK_DIV_SHIFT) + 1;
+
+ sysInfo->freqLocalBus = sysInfo->freqSystemBus / ccr;
+#endif
+}
+
+
+int get_clocks (void)
+{
+ sys_info_t sys_info;
+#ifdef CONFIG_MPC8544
+ volatile ccsr_gur_t *gur = (void *) CONFIG_SYS_MPC85xx_GUTS_ADDR;
+#endif
+#if defined(CONFIG_CPM2)
+ volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
+ uint sccr, dfbrg;
+
+ /* set VCO = 4 * BRG */
+ cpm->im_cpm_intctl.sccr &= 0xfffffffc;
+ sccr = cpm->im_cpm_intctl.sccr;
+ dfbrg = (sccr & SCCR_DFBRG_MSK) >> SCCR_DFBRG_SHIFT;
+#endif
+ get_sys_info (&sys_info);
+ gd->cpu_clk = sys_info.freqProcessor[0];
+ gd->bus_clk = sys_info.freqSystemBus;
+ gd->mem_clk = sys_info.freqDDRBus;
+ gd->arch.lbc_clk = sys_info.freqLocalBus;
+
+#ifdef CONFIG_QE
+ gd->arch.qe_clk = sys_info.freqQE;
+ gd->arch.brg_clk = gd->arch.qe_clk / 2;
+#endif
+ /*
+ * The base clock for I2C depends on the actual SOC. Unfortunately,
+ * there is no pattern that can be used to determine the frequency, so
+ * the only choice is to look up the actual SOC number and use the value
+ * for that SOC. This information is taken from application note
+ * AN2919.
+ */
+#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
+ defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555)
+ gd->arch.i2c1_clk = sys_info.freqSystemBus;
+#elif defined(CONFIG_MPC8544)
+ /*
+ * On the 8544, the I2C clock is the same as the SEC clock. This can be
+ * either CCB/2 or CCB/3, depending on the value of cfg_sec_freq. See
+ * 4.4.3.3 of the 8544 RM. Note that this might actually work for all
+ * 85xx, but only the 8544 has cfg_sec_freq, so it's unknown if the
+ * PORDEVSR2_SEC_CFG bit is 0 on all 85xx boards that are not an 8544.
+ */
+ if (gur->pordevsr2 & MPC85xx_PORDEVSR2_SEC_CFG)
+ gd->arch.i2c1_clk = sys_info.freqSystemBus / 3;
+ else
+ gd->arch.i2c1_clk = sys_info.freqSystemBus / 2;
+#else
+ /* Most 85xx SOCs use CCB/2, so this is the default behavior. */
+ gd->arch.i2c1_clk = sys_info.freqSystemBus / 2;
+#endif
+ gd->arch.i2c2_clk = gd->arch.i2c1_clk;
+
+#if defined(CONFIG_FSL_ESDHC)
+#if defined(CONFIG_MPC8569) || defined(CONFIG_P1010) ||\
+ defined(CONFIG_P1014)
+ gd->arch.sdhc_clk = gd->bus_clk;
+#else
+ gd->arch.sdhc_clk = gd->bus_clk / 2;
+#endif
+#endif /* defined(CONFIG_FSL_ESDHC) */
+
+#if defined(CONFIG_CPM2)
+ gd->arch.vco_out = 2*sys_info.freqSystemBus;
+ gd->arch.cpm_clk = gd->arch.vco_out / 2;
+ gd->arch.scc_clk = gd->arch.vco_out / 4;
+ gd->arch.brg_clk = gd->arch.vco_out / (1 << (2 * (dfbrg + 1)));
+#endif
+
+ if(gd->cpu_clk != 0) return (0);
+ else return (1);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return system bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+ return gd->bus_clk;
+}
+
+/********************************************
+ * get_ddr_freq
+ * return ddr bus freq in Hz
+ *********************************************/
+ulong get_ddr_freq (ulong dummy)
+{
+ return gd->mem_clk;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/spl_minimal.c b/arch/powerpc/cpu/mpc85xx/spl_minimal.c
new file mode 100644
index 0000000..c6b9cd0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/spl_minimal.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/global_data.h>
+#include <asm/fsl_ifc.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void cpu_init_f(void)
+{
+#ifdef CONFIG_SYS_INIT_L2_ADDR
+ ccsr_l2cache_t *l2cache = (void *)CONFIG_SYS_MPC85xx_L2_ADDR;
+
+ out_be32(&l2cache->l2srbar0, CONFIG_SYS_INIT_L2_ADDR);
+
+ /* set MBECCDIS=1, SBECCDIS=1 */
+ out_be32(&l2cache->l2errdis,
+ (MPC85xx_L2ERRDIS_MBECC | MPC85xx_L2ERRDIS_SBECC));
+
+ /* set L2E=1 & L2SRAM=001 */
+ out_be32(&l2cache->l2ctl,
+ (MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2SRAM_ENTIRE));
+#endif
+}
+
+#ifndef CONFIG_SYS_FSL_TBCLK_DIV
+#define CONFIG_SYS_FSL_TBCLK_DIV 8
+#endif
+
+void udelay(unsigned long usec)
+{
+ u32 ticks_per_usec = gd->bus_clk / (CONFIG_SYS_FSL_TBCLK_DIV * 1000000);
+ u32 ticks = ticks_per_usec * usec;
+ u32 s = mfspr(SPRN_TBRL);
+
+ while ((mfspr(SPRN_TBRL) - s) < ticks);
+}
diff --git a/arch/powerpc/cpu/mpc85xx/start.S b/arch/powerpc/cpu/mpc85xx/start.S
new file mode 100644
index 0000000..2657982
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -0,0 +1,1979 @@
+/*
+ * Copyright 2004, 2007-2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2003 Motorola,Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot Startup Code for Motorola 85xx PowerPC based Embedded Boards
+ *
+ * The processor starts at 0xfffffffc and the code is first executed in the
+ * last 4K page(0xfffff000-0xffffffff) in flash/rom.
+ *
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc85xx.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
+
+#if defined(CONFIG_NAND_SPL) || \
+ (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_INIT_MINIMAL))
+#define MINIMAL_SPL
+#endif
+
+#if !defined(CONFIG_SPL) && !defined(CONFIG_SYS_RAMBOOT) && !defined(CONFIG_SECURE_BOOT)
+#define NOR_BOOT
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+#ifndef MINIMAL_SPL
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+#endif
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * e500 Startup -- after reset only the last 4KB of the effective
+ * address space is mapped in the MMU L2 TLB1 Entry0. The .bootpg
+ * section is located at THIS LAST page and basically does three
+ * things: clear some registers, set up exception tables and
+ * add more TLB entries for 'larger spaces'(e.g. the boot rom) to
+ * continue the boot procedure.
+
+ * Once the boot rom is mapped by TLB entries we can proceed
+ * with normal startup.
+ *
+ */
+
+ .section .bootpg,"ax"
+ .globl _start_e500
+
+_start_e500:
+/* Enable debug exception */
+ li r1,MSR_DE
+ mtmsr r1
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
+ mfspr r3,SPRN_SVR
+ rlwinm r3,r3,0,0xff
+ li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV
+ cmpw r3,r4
+ beq 1f
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
+ li r4,CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2
+ cmpw r3,r4
+ beq 1f
+#endif
+
+ /* Not a supported revision affected by erratum */
+ li r27,0
+ b 2f
+
+1: li r27,1 /* Remember for later that we have the erratum */
+ /* Erratum says set bits 55:60 to 001001 */
+ msync
+ isync
+ mfspr r3,SPRN_HDBCR0
+ li r4,0x48
+ rlwimi r3,r4,0,0x1f8
+ mtspr SPRN_HDBCR0,r3
+ isync
+2:
+#endif
+
+#if defined(CONFIG_SECURE_BOOT) && defined(CONFIG_E500MC)
+ /* ISBC uses L2 as stack.
+ * Disable L2 cache here so that u-boot can enable it later
+ * as part of it's normal flow
+ */
+
+ /* Check if L2 is enabled */
+ mfspr r3, SPRN_L2CSR0
+ lis r2, L2CSR0_L2E@h
+ ori r2, r2, L2CSR0_L2E@l
+ and. r4, r3, r2
+ beq l2_disabled
+
+ mfspr r3, SPRN_L2CSR0
+ /* Flush L2 cache */
+ lis r2,(L2CSR0_L2FL)@h
+ ori r2, r2, (L2CSR0_L2FL)@l
+ or r3, r2, r3
+ sync
+ isync
+ mtspr SPRN_L2CSR0,r3
+ isync
+1:
+ mfspr r3, SPRN_L2CSR0
+ and. r1, r3, r2
+ bne 1b
+
+ mfspr r3, SPRN_L2CSR0
+ lis r2, L2CSR0_L2E@h
+ ori r2, r2, L2CSR0_L2E@l
+ andc r4, r3, r2
+ sync
+ isync
+ mtspr SPRN_L2CSR0,r4
+ isync
+
+l2_disabled:
+#endif
+
+/* clear registers/arrays not reset by hardware */
+
+ /* L1 */
+ li r0,2
+ mtspr L1CSR0,r0 /* invalidate d-cache */
+ mtspr L1CSR1,r0 /* invalidate i-cache */
+
+ mfspr r1,DBSR
+ mtspr DBSR,r1 /* Clear all valid bits */
+
+
+ .macro create_tlb1_entry esel ts tsize epn wimg rpn perm phy_high scratch
+ lis \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@l
+ mtspr MAS0, \scratch
+ lis \scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS1(1, 1, 0, \ts, \tsize)@l
+ mtspr MAS1, \scratch
+ lis \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
+ mtspr MAS2, \scratch
+ lis \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
+ mtspr MAS3, \scratch
+ lis \scratch, \phy_high@h
+ ori \scratch, \scratch, \phy_high@l
+ mtspr MAS7, \scratch
+ isync
+ msync
+ tlbwe
+ isync
+ .endm
+
+ .macro create_tlb0_entry esel ts tsize epn wimg rpn perm phy_high scratch
+ lis \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@l
+ mtspr MAS0, \scratch
+ lis \scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS1(1, 0, 0, \ts, \tsize)@l
+ mtspr MAS1, \scratch
+ lis \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
+ mtspr MAS2, \scratch
+ lis \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS3(\rpn, 0, \perm)@l
+ mtspr MAS3, \scratch
+ lis \scratch, \phy_high@h
+ ori \scratch, \scratch, \phy_high@l
+ mtspr MAS7, \scratch
+ isync
+ msync
+ tlbwe
+ isync
+ .endm
+
+ .macro delete_tlb1_entry esel scratch
+ lis \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS0(1, \esel, 0)@l
+ mtspr MAS0, \scratch
+ li \scratch, 0
+ mtspr MAS1, \scratch
+ isync
+ msync
+ tlbwe
+ isync
+ .endm
+
+ .macro delete_tlb0_entry esel epn wimg scratch
+ lis \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS0(0, \esel, 0)@l
+ mtspr MAS0, \scratch
+ li \scratch, 0
+ mtspr MAS1, \scratch
+ lis \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@h
+ ori \scratch, \scratch, FSL_BOOKE_MAS2(\epn, \wimg)@l
+ mtspr MAS2, \scratch
+ isync
+ msync
+ tlbwe
+ isync
+ .endm
+
+/* Interrupt vectors do not fit in minimal SPL. */
+#if !defined(MINIMAL_SPL)
+ /* Setup interrupt vectors */
+ lis r1,CONFIG_SYS_MONITOR_BASE@h
+ mtspr IVPR,r1
+
+ lis r3,(CONFIG_SYS_MONITOR_BASE & 0xffff)@h
+ ori r3,r3,(CONFIG_SYS_MONITOR_BASE & 0xffff)@l
+
+ addi r4,r3,CriticalInput - _start + _START_OFFSET
+ mtspr IVOR0,r4 /* 0: Critical input */
+ addi r4,r3,MachineCheck - _start + _START_OFFSET
+ mtspr IVOR1,r4 /* 1: Machine check */
+ addi r4,r3,DataStorage - _start + _START_OFFSET
+ mtspr IVOR2,r4 /* 2: Data storage */
+ addi r4,r3,InstStorage - _start + _START_OFFSET
+ mtspr IVOR3,r4 /* 3: Instruction storage */
+ addi r4,r3,ExtInterrupt - _start + _START_OFFSET
+ mtspr IVOR4,r4 /* 4: External interrupt */
+ addi r4,r3,Alignment - _start + _START_OFFSET
+ mtspr IVOR5,r4 /* 5: Alignment */
+ addi r4,r3,ProgramCheck - _start + _START_OFFSET
+ mtspr IVOR6,r4 /* 6: Program check */
+ addi r4,r3,FPUnavailable - _start + _START_OFFSET
+ mtspr IVOR7,r4 /* 7: floating point unavailable */
+ addi r4,r3,SystemCall - _start + _START_OFFSET
+ mtspr IVOR8,r4 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ addi r4,r3,Decrementer - _start + _START_OFFSET
+ mtspr IVOR10,r4 /* 10: Decrementer */
+ addi r4,r3,IntervalTimer - _start + _START_OFFSET
+ mtspr IVOR11,r4 /* 11: Interval timer */
+ addi r4,r3,WatchdogTimer - _start + _START_OFFSET
+ mtspr IVOR12,r4 /* 12: Watchdog timer */
+ addi r4,r3,DataTLBError - _start + _START_OFFSET
+ mtspr IVOR13,r4 /* 13: Data TLB error */
+ addi r4,r3,InstructionTLBError - _start + _START_OFFSET
+ mtspr IVOR14,r4 /* 14: Instruction TLB error */
+ addi r4,r3,DebugBreakpoint - _start + _START_OFFSET
+ mtspr IVOR15,r4 /* 15: Debug */
+#endif
+
+ /* Clear and set up some registers. */
+ li r0,0x0000
+ lis r1,0xffff
+ mtspr DEC,r0 /* prevent dec exceptions */
+ mttbl r0 /* prevent fit & wdt exceptions */
+ mttbu r0
+ mtspr TSR,r1 /* clear all timer exception status */
+ mtspr TCR,r0 /* disable all */
+ mtspr ESR,r0 /* clear exception syndrome register */
+ mtspr MCSR,r0 /* machine check syndrome register */
+ mtxer r0 /* clear integer exception register */
+
+#ifdef CONFIG_SYS_BOOK3E_HV
+ mtspr MAS8,r0 /* make sure MAS8 is clear */
+#endif
+
+ /* Enable Time Base and Select Time Base Clock */
+ lis r0,HID0_EMCP@h /* Enable machine check */
+#if defined(CONFIG_ENABLE_36BIT_PHYS)
+ ori r0,r0,HID0_ENMAS7@l /* Enable MAS7 */
+#endif
+#ifndef CONFIG_E500MC
+ ori r0,r0,HID0_TBEN@l /* Enable Timebase */
+#endif
+ mtspr HID0,r0
+
+#ifndef CONFIG_E500MC
+ li r0,(HID1_ASTME|HID1_ABE)@l /* Addr streaming & broadcast */
+ mfspr r3,PVR
+ andi. r3,r3, 0xff
+ cmpwi r3,0x50@l /* if we are rev 5.0 or greater set MBDD */
+ blt 1f
+ /* Set MBDD bit also */
+ ori r0, r0, HID1_MBDD@l
+1:
+ mtspr HID1,r0
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+ mfspr r3,SPRN_HDBCR1
+ oris r3,r3,0x0100
+ mtspr SPRN_HDBCR1,r3
+#endif
+
+ /* Enable Branch Prediction */
+#if defined(CONFIG_BTB)
+ lis r0,BUCSR_ENABLE@h
+ ori r0,r0,BUCSR_ENABLE@l
+ mtspr SPRN_BUCSR,r0
+#endif
+
+#if defined(CONFIG_SYS_INIT_DBCR)
+ lis r1,0xffff
+ ori r1,r1,0xffff
+ mtspr DBSR,r1 /* Clear all status bits */
+ lis r0,CONFIG_SYS_INIT_DBCR@h /* DBCR0[IDM] must be set */
+ ori r0,r0,CONFIG_SYS_INIT_DBCR@l
+ mtspr DBCR0,r0
+#endif
+
+#ifdef CONFIG_MPC8569
+#define CONFIG_SYS_LBC_ADDR (CONFIG_SYS_CCSRBAR_DEFAULT + 0x5000)
+#define CONFIG_SYS_LBCR_ADDR (CONFIG_SYS_LBC_ADDR + 0xd0)
+
+ /* MPC8569 Rev.0 silcon needs to set bit 13 of LBCR to allow elBC to
+ * use address space which is more than 12bits, and it must be done in
+ * the 4K boot page. So we set this bit here.
+ */
+
+ /* create a temp mapping TLB0[0] for LBCR */
+ create_tlb0_entry 0, \
+ 0, BOOKE_PAGESZ_4K, \
+ CONFIG_SYS_LBC_ADDR, MAS2_I|MAS2_G, \
+ CONFIG_SYS_LBC_ADDR, MAS3_SW|MAS3_SR, \
+ 0, r6
+
+ /* Set LBCR register */
+ lis r4,CONFIG_SYS_LBCR_ADDR@h
+ ori r4,r4,CONFIG_SYS_LBCR_ADDR@l
+
+ lis r5,CONFIG_SYS_LBC_LBCR@h
+ ori r5,r5,CONFIG_SYS_LBC_LBCR@l
+ stw r5,0(r4)
+ isync
+
+ /* invalidate this temp TLB */
+ lis r4,CONFIG_SYS_LBC_ADDR@h
+ ori r4,r4,CONFIG_SYS_LBC_ADDR@l
+ tlbivax 0,r4
+ isync
+
+#endif /* CONFIG_MPC8569 */
+
+/*
+ * Search for the TLB that covers the code we're executing, and shrink it
+ * so that it covers only this 4K page. That will ensure that any other
+ * TLB we create won't interfere with it. We assume that the TLB exists,
+ * which is why we don't check the Valid bit of MAS1. We also assume
+ * it is in TLB1.
+ *
+ * This is necessary, for example, when booting from the on-chip ROM,
+ * which (oddly) creates a single 4GB TLB that covers CCSR and DDR.
+ */
+ bl nexti /* Find our address */
+nexti: mflr r1 /* R1 = our PC */
+ li r2, 0
+ mtspr MAS6, r2 /* Assume the current PID and AS are 0 */
+ isync
+ msync
+ tlbsx 0, r1 /* This must succeed */
+
+ mfspr r14, MAS0 /* Save ESEL for later */
+ rlwinm r14, r14, 16, 0xfff
+
+ /* Set the size of the TLB to 4KB */
+ mfspr r3, MAS1
+ li r2, 0xF80
+ andc r3, r3, r2 /* Clear the TSIZE bits */
+ ori r3, r3, MAS1_TSIZE(BOOKE_PAGESZ_4K)@l
+ oris r3, r3, MAS1_IPROT@h
+ mtspr MAS1, r3
+
+ /*
+ * Set the base address of the TLB to our PC. We assume that
+ * virtual == physical. We also assume that MAS2_EPN == MAS3_RPN.
+ */
+ lis r3, MAS2_EPN@h
+ ori r3, r3, MAS2_EPN@l /* R3 = MAS2_EPN */
+
+ and r1, r1, r3 /* Our PC, rounded down to the nearest page */
+
+ mfspr r2, MAS2
+ andc r2, r2, r3
+ or r2, r2, r1
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
+ cmpwi r27,0
+ beq 1f
+ andi. r15, r2, MAS2_I|MAS2_G /* save the old I/G for later */
+ rlwinm r2, r2, 0, ~MAS2_I
+ ori r2, r2, MAS2_G
+1:
+#endif
+ mtspr MAS2, r2 /* Set the EPN to our PC base address */
+
+ mfspr r2, MAS3
+ andc r2, r2, r3
+ or r2, r2, r1
+ mtspr MAS3, r2 /* Set the RPN to our PC base address */
+
+ isync
+ msync
+ tlbwe
+
+/*
+ * Clear out any other TLB entries that may exist, to avoid conflicts.
+ * Our TLB entry is in r14.
+ */
+ li r0, TLBIVAX_ALL | TLBIVAX_TLB0
+ tlbivax 0, r0
+ tlbsync
+
+ mfspr r4, SPRN_TLB1CFG
+ rlwinm r4, r4, 0, TLBnCFG_NENTRY_MASK
+
+ li r3, 0
+ mtspr MAS1, r3
+1: cmpw r3, r14
+ rlwinm r5, r3, 16, MAS0_ESEL_MSK
+ addi r3, r3, 1
+ beq 2f /* skip the entry we're executing from */
+
+ oris r5, r5, MAS0_TLBSEL(1)@h
+ mtspr MAS0, r5
+
+ isync
+ tlbwe
+ isync
+ msync
+
+2: cmpw r3, r4
+ blt 1b
+
+#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(MINIMAL_SPL)
+/*
+ * TLB entry for debuggging in AS1
+ * Create temporary TLB entry in AS0 to handle debug exception
+ * As on debug exception MSR is cleared i.e. Address space is changed
+ * to 0. A TLB entry (in AS0) is required to handle debug exception generated
+ * in AS1.
+ */
+
+#ifdef NOR_BOOT
+/*
+ * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
+ * bacause flash's virtual address maps to 0xff800000 - 0xffffffff.
+ * and this window is outside of 4K boot window.
+ */
+ create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
+ 0, BOOKE_PAGESZ_4M, \
+ CONFIG_SYS_MONITOR_BASE & 0xffc00000, MAS2_I|MAS2_G, \
+ 0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+
+#elif !defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SECURE_BOOT)
+ create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
+ 0, BOOKE_PAGESZ_1M, \
+ CONFIG_SYS_MONITOR_BASE, MAS2_I|MAS2_G, \
+ CONFIG_SYS_PBI_FLASH_WINDOW, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+#else
+/*
+ * TLB entry is created for IVPR + IVOR15 to map on valid OP code address
+ * because "nexti" will resize TLB to 4K
+ */
+ create_tlb1_entry CONFIG_SYS_PPC_E500_DEBUG_TLB, \
+ 0, BOOKE_PAGESZ_256K, \
+ CONFIG_SYS_MONITOR_BASE & 0xfffc0000, MAS2_I, \
+ CONFIG_SYS_MONITOR_BASE & 0xfffc0000, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+#endif
+#endif
+
+/*
+ * Relocate CCSR, if necessary. We relocate CCSR if (obviously) the default
+ * location is not where we want it. This typically happens on a 36-bit
+ * system, where we want to move CCSR to near the top of 36-bit address space.
+ *
+ * To move CCSR, we create two temporary TLBs, one for the old location, and
+ * another for the new location. On CoreNet systems, we also need to create
+ * a special, temporary LAW.
+ *
+ * As a general rule, TLB0 is used for short-term TLBs, and TLB1 is used for
+ * long-term TLBs, so we use TLB0 here.
+ */
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS)
+
+#if !defined(CONFIG_SYS_CCSRBAR_PHYS_HIGH) || !defined(CONFIG_SYS_CCSRBAR_PHYS_LOW)
+#error "CONFIG_SYS_CCSRBAR_PHYS_HIGH and CONFIG_SYS_CCSRBAR_PHYS_LOW) must be defined."
+#endif
+
+create_ccsr_new_tlb:
+ /*
+ * Create a TLB for the new location of CCSR. Register R8 is reserved
+ * for the virtual address of this TLB (CONFIG_SYS_CCSRBAR).
+ */
+ lis r8, CONFIG_SYS_CCSRBAR@h
+ ori r8, r8, CONFIG_SYS_CCSRBAR@l
+ lis r9, (CONFIG_SYS_CCSRBAR + 0x1000)@h
+ ori r9, r9, (CONFIG_SYS_CCSRBAR + 0x1000)@l
+ create_tlb0_entry 0, \
+ 0, BOOKE_PAGESZ_4K, \
+ CONFIG_SYS_CCSRBAR, MAS2_I|MAS2_G, \
+ CONFIG_SYS_CCSRBAR_PHYS_LOW, MAS3_SW|MAS3_SR, \
+ CONFIG_SYS_CCSRBAR_PHYS_HIGH, r3
+ /*
+ * Create a TLB for the current location of CCSR. Register R9 is reserved
+ * for the virtual address of this TLB (CONFIG_SYS_CCSRBAR + 0x1000).
+ */
+create_ccsr_old_tlb:
+ create_tlb0_entry 1, \
+ 0, BOOKE_PAGESZ_4K, \
+ CONFIG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G, \
+ CONFIG_SYS_CCSRBAR_DEFAULT, MAS3_SW|MAS3_SR, \
+ 0, r3 /* The default CCSR address is always a 32-bit number */
+
+
+ /*
+ * We have a TLB for what we think is the current (old) CCSR. Let's
+ * verify that, otherwise we won't be able to move it.
+ * CONFIG_SYS_CCSRBAR_DEFAULT is always a 32-bit number, so we only
+ * need to compare the lower 32 bits of CCSRBAR on CoreNet systems.
+ */
+verify_old_ccsr:
+ lis r0, CONFIG_SYS_CCSRBAR_DEFAULT@h
+ ori r0, r0, CONFIG_SYS_CCSRBAR_DEFAULT@l
+#ifdef CONFIG_FSL_CORENET
+ lwz r1, 4(r9) /* CCSRBARL */
+#else
+ lwz r1, 0(r9) /* CCSRBAR, shifted right by 12 */
+ slwi r1, r1, 12
+#endif
+
+ cmpl 0, r0, r1
+
+ /*
+ * If the value we read from CCSRBARL is not what we expect, then
+ * enter an infinite loop. This will at least allow a debugger to
+ * halt execution and examine TLBs, etc. There's no point in going
+ * on.
+ */
+infinite_debug_loop:
+ bne infinite_debug_loop
+
+#ifdef CONFIG_FSL_CORENET
+
+#define CCSR_LAWBARH0 (CONFIG_SYS_CCSRBAR + 0x1000)
+#define LAW_EN 0x80000000
+#define LAW_SIZE_4K 0xb
+#define CCSRBAR_LAWAR (LAW_EN | (0x1e << 20) | LAW_SIZE_4K)
+#define CCSRAR_C 0x80000000 /* Commit */
+
+create_temp_law:
+ /*
+ * On CoreNet systems, we create the temporary LAW using a special LAW
+ * target ID of 0x1e. LAWBARH is at offset 0xc00 in CCSR.
+ */
+ lis r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h
+ ori r0, r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
+ lis r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
+ ori r1, r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
+ lis r2, CCSRBAR_LAWAR@h
+ ori r2, r2, CCSRBAR_LAWAR@l
+
+ stw r0, 0xc00(r9) /* LAWBARH0 */
+ stw r1, 0xc04(r9) /* LAWBARL0 */
+ sync
+ stw r2, 0xc08(r9) /* LAWAR0 */
+
+ /*
+ * Read back from LAWAR to ensure the update is complete. e500mc
+ * cores also require an isync.
+ */
+ lwz r0, 0xc08(r9) /* LAWAR0 */
+ isync
+
+ /*
+ * Read the current CCSRBARH and CCSRBARL using load word instructions.
+ * Follow this with an isync instruction. This forces any outstanding
+ * accesses to configuration space to completion.
+ */
+read_old_ccsrbar:
+ lwz r0, 0(r9) /* CCSRBARH */
+ lwz r0, 4(r9) /* CCSRBARL */
+ isync
+
+ /*
+ * Write the new values for CCSRBARH and CCSRBARL to their old
+ * locations. The CCSRBARH has a shadow register. When the CCSRBARH
+ * has a new value written it loads a CCSRBARH shadow register. When
+ * the CCSRBARL is written, the CCSRBARH shadow register contents
+ * along with the CCSRBARL value are loaded into the CCSRBARH and
+ * CCSRBARL registers, respectively. Follow this with a sync
+ * instruction.
+ */
+write_new_ccsrbar:
+ lis r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h
+ ori r0, r0, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
+ lis r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
+ ori r1, r1, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
+ lis r2, CCSRAR_C@h
+ ori r2, r2, CCSRAR_C@l
+
+ stw r0, 0(r9) /* Write to CCSRBARH */
+ sync /* Make sure we write to CCSRBARH first */
+ stw r1, 4(r9) /* Write to CCSRBARL */
+ sync
+
+ /*
+ * Write a 1 to the commit bit (C) of CCSRAR at the old location.
+ * Follow this with a sync instruction.
+ */
+ stw r2, 8(r9)
+ sync
+
+ /* Delete the temporary LAW */
+delete_temp_law:
+ li r1, 0
+ stw r1, 0xc08(r8)
+ sync
+ stw r1, 0xc00(r8)
+ stw r1, 0xc04(r8)
+ sync
+
+#else /* #ifdef CONFIG_FSL_CORENET */
+
+write_new_ccsrbar:
+ /*
+ * Read the current value of CCSRBAR using a load word instruction
+ * followed by an isync. This forces all accesses to configuration
+ * space to complete.
+ */
+ sync
+ lwz r0, 0(r9)
+ isync
+
+/* CONFIG_SYS_CCSRBAR_PHYS right shifted by 12 */
+#define CCSRBAR_PHYS_RS12 ((CONFIG_SYS_CCSRBAR_PHYS_HIGH << 20) | \
+ (CONFIG_SYS_CCSRBAR_PHYS_LOW >> 12))
+
+ /* Write the new value to CCSRBAR. */
+ lis r0, CCSRBAR_PHYS_RS12@h
+ ori r0, r0, CCSRBAR_PHYS_RS12@l
+ stw r0, 0(r9)
+ sync
+
+ /*
+ * The manual says to perform a load of an address that does not
+ * access configuration space or the on-chip SRAM using an existing TLB,
+ * but that doesn't appear to be necessary. We will do the isync,
+ * though.
+ */
+ isync
+
+ /*
+ * Read the contents of CCSRBAR from its new location, followed by
+ * another isync.
+ */
+ lwz r0, 0(r8)
+ isync
+
+#endif /* #ifdef CONFIG_FSL_CORENET */
+
+ /* Delete the temporary TLBs */
+delete_temp_tlbs:
+ delete_tlb0_entry 0, CONFIG_SYS_CCSRBAR, MAS2_I|MAS2_G, r3
+ delete_tlb0_entry 1, CONFIG_SYS_CCSRBAR + 0x1000, MAS2_I|MAS2_G, r3
+
+#endif /* #if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR_PHYS) */
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+create_ccsr_l2_tlb:
+ /*
+ * Create a TLB for the MMR location of CCSR
+ * to access L2CSR0 register
+ */
+ create_tlb0_entry 0, \
+ 0, BOOKE_PAGESZ_4K, \
+ CONFIG_SYS_CCSRBAR + 0xC20000, MAS2_I|MAS2_G, \
+ CONFIG_SYS_CCSRBAR_PHYS_LOW + 0xC20000, MAS3_SW|MAS3_SR, \
+ CONFIG_SYS_CCSRBAR_PHYS_HIGH, r3
+
+enable_l2_cluster_l2:
+ /* enable L2 cache */
+ lis r3, (CONFIG_SYS_CCSRBAR + 0xC20000)@h
+ ori r3, r3, (CONFIG_SYS_CCSRBAR + 0xC20000)@l
+ li r4, 33 /* stash id */
+ stw r4, 4(r3)
+ lis r4, (L2CSR0_L2FI|L2CSR0_L2LFC)@h
+ ori r4, r4, (L2CSR0_L2FI|L2CSR0_L2LFC)@l
+ sync
+ stw r4, 0(r3) /* invalidate L2 */
+1: sync
+ lwz r0, 0(r3)
+ twi 0, r0, 0
+ isync
+ and. r1, r0, r4
+ bne 1b
+ lis r4, (L2CSR0_L2E|L2CSR0_L2PE)@h
+ ori r4, r4, (L2CSR0_L2REP_MODE)@l
+ sync
+ stw r4, 0(r3) /* enable L2 */
+delete_ccsr_l2_tlb:
+ delete_tlb0_entry 0, CONFIG_SYS_CCSRBAR + 0xC20000, MAS2_I|MAS2_G, r3
+#endif
+
+ /*
+ * Enable the L1. On e6500, this has to be done
+ * after the L2 is up.
+ */
+
+#ifdef CONFIG_SYS_CACHE_STASHING
+ /* set stash id to (coreID) * 2 + 32 + L1 CT (0) */
+ li r2,(32 + 0)
+ mtspr L1CSR2,r2
+#endif
+
+ /* Enable/invalidate the I-Cache */
+ lis r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r2,r2,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ mtspr SPRN_L1CSR1,r2
+1:
+ mfspr r3,SPRN_L1CSR1
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ mtspr SPRN_L1CSR1,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR1
+ andi. r1,r3,L1CSR1_ICE@l
+ beq 2b
+
+ /* Enable/invalidate the D-Cache */
+ lis r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@h
+ ori r2,r2,(L1CSR0_DCFI|L1CSR0_DCLFR)@l
+ mtspr SPRN_L1CSR0,r2
+1:
+ mfspr r3,SPRN_L1CSR0
+ and. r1,r3,r2
+ bne 1b
+
+ lis r3,(L1CSR0_CPE|L1CSR0_DCE)@h
+ ori r3,r3,(L1CSR0_CPE|L1CSR0_DCE)@l
+ mtspr SPRN_L1CSR0,r3
+ isync
+2:
+ mfspr r3,SPRN_L1CSR0
+ andi. r1,r3,L1CSR0_DCE@l
+ beq 2b
+#ifdef CONFIG_SYS_FSL_ERRATUM_A004510
+#define DCSR_LAWBARH0 (CONFIG_SYS_CCSRBAR + 0x1000)
+#define LAW_SIZE_1M 0x13
+#define DCSRBAR_LAWAR (LAW_EN | (0x1d << 20) | LAW_SIZE_1M)
+
+ cmpwi r27,0
+ beq 9f
+
+ /*
+ * Create a TLB entry for CCSR
+ *
+ * We're executing out of TLB1 entry in r14, and that's the only
+ * TLB entry that exists. To allocate some TLB entries for our
+ * own use, flip a bit high enough that we won't flip it again
+ * via incrementing.
+ */
+
+ xori r8, r14, 32
+ lis r0, MAS0_TLBSEL(1)@h
+ rlwimi r0, r8, 16, MAS0_ESEL_MSK
+ lis r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@h
+ ori r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_16M)@l
+ lis r7, CONFIG_SYS_CCSRBAR@h
+ ori r7, r7, CONFIG_SYS_CCSRBAR@l
+ ori r2, r7, MAS2_I|MAS2_G
+ lis r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@h
+ ori r3, r3, FSL_BOOKE_MAS3(CONFIG_SYS_CCSRBAR_PHYS_LOW, 0, (MAS3_SW|MAS3_SR))@l
+ lis r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@h
+ ori r4, r4, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
+ mtspr MAS0, r0
+ mtspr MAS1, r1
+ mtspr MAS2, r2
+ mtspr MAS3, r3
+ mtspr MAS7, r4
+ isync
+ tlbwe
+ isync
+ msync
+
+ /* Map DCSR temporarily to physical address zero */
+ li r0, 0
+ lis r3, DCSRBAR_LAWAR@h
+ ori r3, r3, DCSRBAR_LAWAR@l
+
+ stw r0, 0xc00(r7) /* LAWBARH0 */
+ stw r0, 0xc04(r7) /* LAWBARL0 */
+ sync
+ stw r3, 0xc08(r7) /* LAWAR0 */
+
+ /* Read back from LAWAR to ensure the update is complete. */
+ lwz r3, 0xc08(r7) /* LAWAR0 */
+ isync
+
+ /* Create a TLB entry for DCSR at zero */
+
+ addi r9, r8, 1
+ lis r0, MAS0_TLBSEL(1)@h
+ rlwimi r0, r9, 16, MAS0_ESEL_MSK
+ lis r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@h
+ ori r1, r1, FSL_BOOKE_MAS1(1, 1, 0, 0, BOOKE_PAGESZ_1M)@l
+ li r6, 0 /* DCSR effective address */
+ ori r2, r6, MAS2_I|MAS2_G
+ li r3, MAS3_SW|MAS3_SR
+ li r4, 0
+ mtspr MAS0, r0
+ mtspr MAS1, r1
+ mtspr MAS2, r2
+ mtspr MAS3, r3
+ mtspr MAS7, r4
+ isync
+ tlbwe
+ isync
+ msync
+
+ /* enable the timebase */
+#define CTBENR 0xe2084
+ li r3, 1
+ addis r4, r7, CTBENR@ha
+ stw r3, CTBENR@l(r4)
+ lwz r3, CTBENR@l(r4)
+ twi 0,r3,0
+ isync
+
+ .macro erratum_set_ccsr offset value
+ addis r3, r7, \offset@ha
+ lis r4, \value@h
+ addi r3, r3, \offset@l
+ ori r4, r4, \value@l
+ bl erratum_set_value
+ .endm
+
+ .macro erratum_set_dcsr offset value
+ addis r3, r6, \offset@ha
+ lis r4, \value@h
+ addi r3, r3, \offset@l
+ ori r4, r4, \value@l
+ bl erratum_set_value
+ .endm
+
+ erratum_set_dcsr 0xb0e08 0xe0201800
+ erratum_set_dcsr 0xb0e18 0xe0201800
+ erratum_set_dcsr 0xb0e38 0xe0400000
+ erratum_set_dcsr 0xb0008 0x00900000
+ erratum_set_dcsr 0xb0e40 0xe00a0000
+ erratum_set_ccsr 0x18600 CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY
+ erratum_set_ccsr 0x10f00 0x415e5000
+ erratum_set_ccsr 0x11f00 0x415e5000
+
+ /* Make temp mapping uncacheable again, if it was initially */
+ bl 2f
+2: mflr r3
+ tlbsx 0, r3
+ mfspr r4, MAS2
+ rlwimi r4, r15, 0, MAS2_I
+ rlwimi r4, r15, 0, MAS2_G
+ mtspr MAS2, r4
+ isync
+ tlbwe
+ isync
+ msync
+
+ /* Clear the cache */
+ lis r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@h
+ ori r3,r3,(L1CSR1_ICFI|L1CSR1_ICLFR)@l
+ sync
+ isync
+ mtspr SPRN_L1CSR1,r3
+ isync
+2: sync
+ mfspr r4,SPRN_L1CSR1
+ and. r4,r4,r3
+ bne 2b
+
+ lis r3,(L1CSR1_CPE|L1CSR1_ICE)@h
+ ori r3,r3,(L1CSR1_CPE|L1CSR1_ICE)@l
+ sync
+ isync
+ mtspr SPRN_L1CSR1,r3
+ isync
+2: sync
+ mfspr r4,SPRN_L1CSR1
+ and. r4,r4,r3
+ beq 2b
+
+ /* Remove temporary mappings */
+ lis r0, MAS0_TLBSEL(1)@h
+ rlwimi r0, r9, 16, MAS0_ESEL_MSK
+ li r3, 0
+ mtspr MAS0, r0
+ mtspr MAS1, r3
+ isync
+ tlbwe
+ isync
+ msync
+
+ li r3, 0
+ stw r3, 0xc08(r7) /* LAWAR0 */
+ lwz r3, 0xc08(r7)
+ isync
+
+ lis r0, MAS0_TLBSEL(1)@h
+ rlwimi r0, r8, 16, MAS0_ESEL_MSK
+ li r3, 0
+ mtspr MAS0, r0
+ mtspr MAS1, r3
+ isync
+ tlbwe
+ isync
+ msync
+
+ b 9f
+
+ /* r3 = addr, r4 = value, clobbers r5, r11, r12 */
+erratum_set_value:
+ /* Lock two cache lines into I-Cache */
+ sync
+ mfspr r11, SPRN_L1CSR1
+ rlwinm r11, r11, 0, ~L1CSR1_ICUL
+ sync
+ isync
+ mtspr SPRN_L1CSR1, r11
+ isync
+
+ mflr r12
+ bl 5f
+5: mflr r5
+ addi r5, r5, 2f - 5b
+ icbtls 0, 0, r5
+ addi r5, r5, 64
+
+ sync
+ mfspr r11, SPRN_L1CSR1
+3: andi. r11, r11, L1CSR1_ICUL
+ bne 3b
+
+ icbtls 0, 0, r5
+ addi r5, r5, 64
+
+ sync
+ mfspr r11, SPRN_L1CSR1
+3: andi. r11, r11, L1CSR1_ICUL
+ bne 3b
+
+ b 2f
+ .align 6
+ /* Inside a locked cacheline, wait a while, write, then wait a while */
+2: sync
+
+ mfspr r5, SPRN_TBRL
+ addis r11, r5, 0x10000@h /* wait 65536 timebase ticks */
+4: mfspr r5, SPRN_TBRL
+ subf. r5, r5, r11
+ bgt 4b
+
+ stw r4, 0(r3)
+
+ mfspr r5, SPRN_TBRL
+ addis r11, r5, 0x10000@h /* wait 65536 timebase ticks */
+4: mfspr r5, SPRN_TBRL
+ subf. r5, r5, r11
+ bgt 4b
+
+ sync
+
+ /*
+ * Fill out the rest of this cache line and the next with nops,
+ * to ensure that nothing outside the locked area will be
+ * fetched due to a branch.
+ */
+ .rept 19
+ nop
+ .endr
+
+ sync
+ mfspr r11, SPRN_L1CSR1
+ rlwinm r11, r11, 0, ~L1CSR1_ICUL
+ sync
+ isync
+ mtspr SPRN_L1CSR1, r11
+ isync
+
+ mtlr r12
+ blr
+
+9:
+#endif
+
+create_init_ram_area:
+ lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h
+ ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
+
+#ifdef NOR_BOOT
+ /* create a temp mapping in AS=1 to the 4M boot window */
+ create_tlb1_entry 15, \
+ 1, BOOKE_PAGESZ_4M, \
+ CONFIG_SYS_MONITOR_BASE & 0xffc00000, MAS2_I|MAS2_G, \
+ 0xffc00000, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+
+#elif !defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SECURE_BOOT)
+ /* create a temp mapping in AS = 1 for Flash mapping
+ * created by PBL for ISBC code
+ */
+ create_tlb1_entry 15, \
+ 1, BOOKE_PAGESZ_1M, \
+ CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
+ CONFIG_SYS_PBI_FLASH_WINDOW & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+#else
+ /*
+ * create a temp mapping in AS=1 to the 1M CONFIG_SYS_MONITOR_BASE space, the main
+ * image has been relocated to CONFIG_SYS_MONITOR_BASE on the second stage.
+ */
+ create_tlb1_entry 15, \
+ 1, BOOKE_PAGESZ_1M, \
+ CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
+ CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+#endif
+
+ /* create a temp mapping in AS=1 to the stack */
+#if defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS_LOW) && \
+ defined(CONFIG_SYS_INIT_RAM_ADDR_PHYS_HIGH)
+ create_tlb1_entry 14, \
+ 1, BOOKE_PAGESZ_16K, \
+ CONFIG_SYS_INIT_RAM_ADDR, 0, \
+ CONFIG_SYS_INIT_RAM_ADDR_PHYS_LOW, MAS3_SX|MAS3_SW|MAS3_SR, \
+ CONFIG_SYS_INIT_RAM_ADDR_PHYS_HIGH, r6
+
+#else
+ create_tlb1_entry 14, \
+ 1, BOOKE_PAGESZ_16K, \
+ CONFIG_SYS_INIT_RAM_ADDR, 0, \
+ CONFIG_SYS_INIT_RAM_ADDR, MAS3_SX|MAS3_SW|MAS3_SR, \
+ 0, r6
+#endif
+
+ lis r6,MSR_IS|MSR_DS|MSR_DE@h
+ ori r6,r6,MSR_IS|MSR_DS|MSR_DE@l
+ lis r7,switch_as@h
+ ori r7,r7,switch_as@l
+
+ mtspr SPRN_SRR0,r7
+ mtspr SPRN_SRR1,r6
+ rfi
+
+switch_as:
+/* L1 DCache is used for initial RAM */
+
+ /* Allocate Initial RAM in data cache.
+ */
+ lis r3,CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+ mfspr r2, L1CFG0
+ andi. r2, r2, 0x1ff
+ /* cache size * 1024 / (2 * L1 line size) */
+ slwi r2, r2, (10 - 1 - L1_CACHE_SHIFT)
+ mtctr r2
+ li r0,0
+1:
+ dcbz r0,r3
+ dcbtls 0,r0,r3
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 1b
+
+ /* Jump out the last 4K page and continue to 'normal' start */
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
+ /* We assume that we're already running at the address we're linked at */
+ b _start_cont
+#else
+ /* Calculate absolute address in FLASH and jump there */
+ /*--------------------------------------------------------------*/
+ lis r3,CONFIG_SYS_MONITOR_BASE@h
+ ori r3,r3,CONFIG_SYS_MONITOR_BASE@l
+ addi r3,r3,_start_cont - _start + _START_OFFSET
+ mtlr r3
+ blr
+#endif
+
+ .text
+ .globl _start
+_start:
+ .long 0x27051956 /* U-BOOT Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ .align 4
+ .globl _start_cont
+_start_cont:
+ /* Setup the stack in initial RAM,could be L2-as-SRAM or L1 dcache*/
+ lis r3,(CONFIG_SYS_INIT_RAM_ADDR)@h
+ ori r3,r3,((CONFIG_SYS_INIT_SP_OFFSET-16)&~0xf)@l /* Align to 16 */
+ li r0,0
+ stw r0,0(r3) /* Terminate Back Chain */
+ stw r0,+4(r3) /* NULL return address. */
+ mr r1,r3 /* Transfer to SP(r1) */
+
+ GET_GOT
+ bl cpu_init_early_f
+
+ /* switch back to AS = 0 */
+ lis r3,(MSR_CE|MSR_ME|MSR_DE)@h
+ ori r3,r3,(MSR_CE|MSR_ME|MSR_DE)@l
+ mtmsr r3
+ isync
+
+ bl cpu_init_f
+ bl board_init_f
+ isync
+
+ /* NOTREACHED - board_init_f() does not return */
+
+#ifndef MINIMAL_SPL
+ . = EXC_OFF_SYS_RESET
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+ CRIT_EXCEPTION(0x0100, CriticalInput, CritcalInputException)
+
+/* Machine check */
+ MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x0300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x0400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x0500, ExtInterrupt, ExtIntException)
+
+/* Alignment exception. */
+ . = 0x0600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x0700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* No FPU on MPC85xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x0800, FPUnavailable, UnknownException)
+
+ . = 0x0900
+/*
+ * r0 - SYSCALL number
+ * r3-... arguments
+ */
+SystemCall:
+ addis r11,r0,0 /* get functions table addr */
+ ori r11,r11,0 /* Note: this code is patched in trap_init */
+ addis r12,r0,0 /* get number of functions */
+ ori r12,r12,0
+
+ cmplw 0,r0,r12
+ bge 1f
+
+ rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
+ add r11,r11,r0
+ lwz r11,0(r11)
+
+ li r20,0xd00-4 /* Get stack pointer */
+ lwz r12,0(r20)
+ subi r12,r12,12 /* Adjust stack pointer */
+ li r0,0xc00+_end_back-SystemCall
+ cmplw 0,r0,r12 /* Check stack overflow */
+ bgt 1f
+ stw r12,0(r20)
+
+ mflr r0
+ stw r0,0(r12)
+ mfspr r0,SRR0
+ stw r0,4(r12)
+ mfspr r0,SRR1
+ stw r0,8(r12)
+
+ li r12,0xc00+_back-SystemCall
+ mtlr r12
+ mtspr SRR0,r11
+
+1: SYNC
+ rfi
+_back:
+
+ mfmsr r11 /* Disable interrupts */
+ li r12,0
+ ori r12,r12,MSR_EE
+ andc r11,r11,r12
+ SYNC /* Some chip revs need this... */
+ mtmsr r11
+ SYNC
+
+ li r12,0xd00-4 /* restore regs */
+ lwz r12,0(r12)
+
+ lwz r11,0(r12)
+ mtlr r11
+ lwz r11,4(r12)
+ mtspr SRR0,r11
+ lwz r11,8(r12)
+ mtspr SRR1,r11
+
+ addi r12,r12,12 /* Adjust stack pointer */
+ li r20,0xd00-4
+ stw r12,0(r20)
+
+ SYNC
+ rfi
+_end_back:
+
+ STD_EXCEPTION(0x0a00, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0x0b00, IntervalTimer, UnknownException)
+ STD_EXCEPTION(0x0c00, WatchdogTimer, UnknownException)
+
+ STD_EXCEPTION(0x0d00, DataTLBError, UnknownException)
+ STD_EXCEPTION(0x0e00, InstructionTLBError, UnknownException)
+
+ CRIT_EXCEPTION(0x0f00, DebugBreakpoint, DebugException )
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = . + (0x100 - ( . & 0xff )) /* align for debug */
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+crit_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SPRN_CSRR0,r2
+ mtspr SPRN_CSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfci
+
+mck_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SPRN_MCSRR0,r2
+ mtspr SPRN_MCSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfmci
+
+/* Cache functions.
+*/
+.globl flush_icache
+flush_icache:
+.globl invalidate_icache
+invalidate_icache:
+ mfspr r0,L1CSR1
+ ori r0,r0,L1CSR1_ICFI
+ msync
+ isync
+ mtspr L1CSR1,r0
+ isync
+ blr /* entire I cache */
+
+.globl invalidate_dcache
+invalidate_dcache:
+ mfspr r0,L1CSR0
+ ori r0,r0,L1CSR0_DCFI
+ msync
+ isync
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl icache_enable
+icache_enable:
+ mflr r8
+ bl invalidate_icache
+ mtlr r8
+ isync
+ mfspr r4,L1CSR1
+ ori r4,r4,0x0001
+ oris r4,r4,0x0001
+ mtspr L1CSR1,r4
+ isync
+ blr
+
+ .globl icache_disable
+icache_disable:
+ mfspr r0,L1CSR1
+ lis r3,0
+ ori r3,r3,L1CSR1_ICE
+ andc r0,r0,r3
+ mtspr L1CSR1,r0
+ isync
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3,L1CSR1
+ andi. r3,r3,L1CSR1_ICE
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mflr r8
+ bl invalidate_dcache
+ mtlr r8
+ isync
+ mfspr r0,L1CSR0
+ ori r0,r0,0x0001
+ oris r0,r0,0x0001
+ msync
+ isync
+ mtspr L1CSR0,r0
+ isync
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mfspr r3,L1CSR0
+ lis r4,0
+ ori r4,r4,L1CSR0_DCE
+ andc r3,r3,r4
+ mtspr L1CSR0,r3
+ isync
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3,L1CSR0
+ andi. r3,r3,L1CSR0_DCE
+ blr
+
+ .globl get_pir
+get_pir:
+ mfspr r3,PIR
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3,PVR
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3,SVR
+ blr
+
+ .globl wr_tcr
+wr_tcr:
+ mtspr TCR,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0x0000(r3)
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0x0000(r3)
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,r0,r3
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0x0000(r3)
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,r0,r3
+ sync
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in16 */
+/* Description: Input 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in16r */
+/* Description: Input 16 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0x0000(3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in32r */
+/* Description: Input 32 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,r0,r3
+ blr
+#endif /* !MINIMAL_SPL */
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void write_tlb(mas0, mas1, mas2, mas3, mas7)
+ */
+ .globl write_tlb
+write_tlb:
+ mtspr MAS0,r3
+ mtspr MAS1,r4
+ mtspr MAS2,r5
+ mtspr MAS3,r6
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ mtspr MAS7,r7
+#endif
+ li r3,0
+#ifdef CONFIG_SYS_BOOK3E_HV
+ mtspr MAS8,r3
+#endif
+ isync
+ tlbwe
+ msync
+ isync
+ blr
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1,r3 /* Set new stack pointer */
+ mr r9,r4 /* Save copy of Init Data pointer */
+ mr r10,r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3,r5 /* Destination Address */
+ lis r4,CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4,r4,CONFIG_SYS_MONITOR_BASE@l
+ lwz r5,GOT(__init_end)
+ sub r5,r5,r4
+ li r6,CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15,r10,r4
+
+ /* First our own GOT */
+ add r12,r12,r15
+ /* the the one used by the C code */
+ add r30,r30,r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0,r10,in_ram - _start + _START_OFFSET
+
+ /*
+ * As IVPR is going to point RAM address,
+ * Make sure IVOR15 has valid opcode to support debugger
+ */
+ mtspr IVOR15,r0
+
+ /*
+ * Re-point the IVPR at RAM
+ */
+ mtspr IVPR,r10
+
+ mtlr r0
+ blr /* NEVER RETURNS! */
+ .globl in_ram
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0,r3,r4
+ beq 6f
+
+ li r0,0
+5:
+ stw r0,0(r3)
+ addi r3,r3,4
+ cmplw 0,r3,r4
+ blt 5b
+6:
+
+ mr r3,r9 /* Init Data pointer */
+ mr r4,r10 /* Destination Address */
+ bl board_init_r
+
+#ifndef MINIMAL_SPL
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7,GOT(_start_of_vectors)
+ lwz r8,GOT(_end_of_vectors)
+
+ li r9,0x100 /* reset vector always at 0x100 */
+
+ cmplw 0,r7,r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0,0(r7)
+ stw r0,0(r9)
+ addi r7,r7,4
+ addi r9,r9,4
+ cmplw 0,r7,r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7,.L_CriticalInput - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_MachineCheck - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_DataStorage - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_InstStorage - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_ExtInterrupt - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Alignment - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_ProgramCheck - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_FPUnavailable - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_Decrementer - _start + _START_OFFSET
+ bl trap_reloc
+ li r7,.L_IntervalTimer - _start + _START_OFFSET
+ li r8,_end_of_vectors - _start + _START_OFFSET
+2:
+ bl trap_reloc
+ addi r7,r7,0x100 /* next exception vector */
+ cmplw 0,r7,r8
+ blt 2b
+
+ /* Update IVORs as per relocated vector table address */
+ li r7,0x0100
+ mtspr IVOR0,r7 /* 0: Critical input */
+ li r7,0x0200
+ mtspr IVOR1,r7 /* 1: Machine check */
+ li r7,0x0300
+ mtspr IVOR2,r7 /* 2: Data storage */
+ li r7,0x0400
+ mtspr IVOR3,r7 /* 3: Instruction storage */
+ li r7,0x0500
+ mtspr IVOR4,r7 /* 4: External interrupt */
+ li r7,0x0600
+ mtspr IVOR5,r7 /* 5: Alignment */
+ li r7,0x0700
+ mtspr IVOR6,r7 /* 6: Program check */
+ li r7,0x0800
+ mtspr IVOR7,r7 /* 7: floating point unavailable */
+ li r7,0x0900
+ mtspr IVOR8,r7 /* 8: System call */
+ /* 9: Auxiliary processor unavailable(unsupported) */
+ li r7,0x0a00
+ mtspr IVOR10,r7 /* 10: Decrementer */
+ li r7,0x0b00
+ mtspr IVOR11,r7 /* 11: Interval timer */
+ li r7,0x0c00
+ mtspr IVOR12,r7 /* 12: Watchdog timer */
+ li r7,0x0d00
+ mtspr IVOR13,r7 /* 13: Data TLB error */
+ li r7,0x0e00
+ mtspr IVOR14,r7 /* 14: Instruction TLB error */
+ li r7,0x0f00
+ mtspr IVOR15,r7 /* 15: Debug */
+
+ lis r7,0x0
+ mtspr IVPR,r7
+
+ mtlr r4 /* restore link register */
+ blr
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@h
+ ori r3,r3,(CONFIG_SYS_INIT_RAM_ADDR & ~(CONFIG_SYS_CACHELINE_SIZE-1))@l
+ mfspr r4,L1CFG0
+ andi. r4,r4,0x1ff
+ slwi r4,r4,(10 - 1 - L1_CACHE_SHIFT)
+ mtctr r4
+1: dcbi r0,r3
+ dcblc r0,r3
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 1b
+ sync
+
+ /* Invalidate the TLB entries for the cache */
+ lis r3,CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ addi r3,r3,0x1000
+ tlbivax 0,r3
+ isync
+ blr
+
+.globl flush_dcache
+flush_dcache:
+ mfspr r3,SPRN_L1CFG0
+
+ rlwinm r5,r3,9,3 /* Extract cache block size */
+ twlgti r5,1 /* Only 32 and 64 byte cache blocks
+ * are currently defined.
+ */
+ li r4,32
+ subfic r6,r5,2 /* r6 = log2(1KiB / cache block size) -
+ * log2(number of ways)
+ */
+ slw r5,r4,r5 /* r5 = cache block size */
+
+ rlwinm r7,r3,0,0xff /* Extract number of KiB in the cache */
+ mulli r7,r7,13 /* An 8-way cache will require 13
+ * loads per set.
+ */
+ slw r7,r7,r6
+
+ /* save off HID0 and set DCFA */
+ mfspr r8,SPRN_HID0
+ ori r9,r8,HID0_DCFA@l
+ mtspr SPRN_HID0,r9
+ isync
+
+ lis r4,0
+ mtctr r7
+
+1: lwz r3,0(r4) /* Load... */
+ add r4,r4,r5
+ bdnz 1b
+
+ msync
+ lis r4,0
+ mtctr r7
+
+1: dcbf 0,r4 /* ...and flush. */
+ add r4,r4,r5
+ bdnz 1b
+
+ /* restore HID0 */
+ mtspr SPRN_HID0,r8
+ isync
+
+ blr
+
+.globl setup_ivors
+setup_ivors:
+
+#include "fixed_ivor.S"
+ blr
+#endif /* !MINIMAL_SPL */
diff --git a/arch/powerpc/cpu/mpc85xx/t1040_ids.c b/arch/powerpc/cpu/mpc85xx/t1040_ids.c
new file mode 100644
index 0000000..ed61599
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/t1040_ids.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO(1, 27, 1, 0),
+ SET_QP_INFO(2, 28, 1, 0),
+ SET_QP_INFO(3, 29, 1, 1),
+ SET_QP_INFO(4, 30, 1, 1),
+ SET_QP_INFO(5, 31, 1, 2),
+ SET_QP_INFO(6, 32, 1, 2),
+ SET_QP_INFO(7, 33, 1, 3),
+ SET_QP_INFO(8, 34, 1, 3),
+ SET_QP_INFO(9, 35, 1, 0),
+ SET_QP_INFO(10, 36, 1, 0),
+ SET_QP_INFO(11, 37, 1, 1),
+ SET_QP_INFO(12, 38, 1, 1),
+ SET_QP_INFO(13, 39, 1, 2),
+ SET_QP_INFO(14, 40, 1, 2),
+ SET_QP_INFO(15, 41, 1, 3),
+ SET_QP_INFO(16, 42, 1, 3),
+ SET_QP_INFO(17, 43, 1, 0),
+ SET_QP_INFO(18, 44, 1, 0),
+ SET_QP_INFO(19, 45, 1, 1),
+ SET_QP_INFO(20, 46, 1, 1),
+ SET_QP_INFO(21, 47, 1, 2),
+ SET_QP_INFO(22, 48, 1, 2),
+ SET_QP_INFO(23, 49, 1, 3),
+ SET_QP_INFO(24, 50, 1, 3),
+ SET_QP_INFO(25, 51, 1, 0),
+};
+#endif
+
+struct srio_liodn_id_table srio_liodn_tbl[] = {
+ SET_SRIO_LIODN_1(1, 307),
+ SET_SRIO_LIODN_1(2, 387),
+};
+int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl);
+
+struct liodn_id_table liodn_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(62),
+ SET_BMAN_LIODN(63),
+#endif
+
+ SET_SDHC_LIODN(1, 552),
+
+ SET_USB_LIODN(1, "fsl-usb2-mph", 553),
+
+ SET_PCI_LIODN("fsl,qoriq-pcie-v2.2", 1, 148),
+
+ SET_DMA_LIODN(1, 147),
+ SET_DMA_LIODN(2, 227),
+
+ SET_GUTS_LIODN("fsl,rapidio-delta", 199, rio1liodnr, 0),
+ SET_GUTS_LIODN(NULL, 200, rio2liodnr, 0),
+ SET_GUTS_LIODN(NULL, 201, rio1maintliodnr, 0),
+ SET_GUTS_LIODN(NULL, 202, rio2maintliodnr, 0),
+
+ /* SET_NEXUS_LIODN(557), -- not yet implemented */
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 88),
+ SET_FMAN_RX_1G_LIODN(1, 1, 89),
+ SET_FMAN_RX_1G_LIODN(1, 2, 90),
+ SET_FMAN_RX_1G_LIODN(1, 3, 91),
+ SET_FMAN_RX_1G_LIODN(1, 4, 92),
+ SET_FMAN_RX_1G_LIODN(1, 5, 93),
+ SET_FMAN_RX_10G_LIODN(1, 0, 94),
+ SET_FMAN_RX_10G_LIODN(1, 1, 95),
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ SET_SEC_JR_LIODN_ENTRY(0, 454, 458),
+ SET_SEC_JR_LIODN_ENTRY(1, 455, 459),
+ SET_SEC_JR_LIODN_ENTRY(2, 456, 460),
+ SET_SEC_JR_LIODN_ENTRY(3, 457, 461),
+ SET_SEC_RTIC_LIODN_ENTRY(a, 453),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 549),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 550),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 551),
+ SET_SEC_DECO_LIODN_ENTRY(0, 541, 610),
+ SET_SEC_DECO_LIODN_ENTRY(1, 542, 611),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+struct liodn_id_table rman_liodn_tbl[] = {
+ /* Set RMan block 0-3 liodn offset */
+ SET_RMAN_LIODN(0, 678),
+ SET_RMAN_LIODN(1, 679),
+ SET_RMAN_LIODN(2, 680),
+ SET_RMAN_LIODN(3, 681),
+};
+int rman_liodn_tbl_sz = ARRAY_SIZE(rman_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_bases[] = {
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(462, 558),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(973),
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ [FSL_HW_PORTAL_RMAN] = SET_LIODN_BASE_1(922),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/t1040_serdes.c b/arch/powerpc/cpu/mpc85xx/t1040_serdes.c
new file mode 100644
index 0000000..19add9f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/t1040_serdes.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet2_serdes.h"
+
+static u8 serdes_cfg_tbl[MAX_SERDES][0xC4][SRDS_MAX_LANES] = {
+ { /* SerDes 1 */
+ [0x69] = {PCIE1, SGMII_FM1_DTSEC3, QSGMII_SW1_A, QSGMII_SW1_B,
+ PCIE2, PCIE3, SGMII_FM1_DTSEC4, SATA1},
+ [0x66] = {PCIE1, SGMII_FM1_DTSEC3, QSGMII_SW1_A, QSGMII_SW1_B,
+ PCIE2, PCIE3, PCIE4, SATA1},
+ [0x67] = {PCIE1, SGMII_FM1_DTSEC3, QSGMII_SW1_A, QSGMII_SW1_B,
+ PCIE2, PCIE3, PCIE4, SGMII_FM1_DTSEC5},
+ [0x60] = {PCIE1, SGMII_FM1_DTSEC3, QSGMII_SW1_A, QSGMII_SW1_B,
+ PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x8D] = {PCIE1, SGMII_SW1_DTSEC3, SGMII_SW1_DTSEC1, SGMII_SW1_DTSEC2,
+ PCIE2, SGMII_SW1_DTSEC6, SGMII_SW1_DTSEC4, SGMII_SW1_DTSEC5},
+ [0x89] = {PCIE1, SGMII_SW1_DTSEC3, SGMII_SW1_DTSEC1, SGMII_SW1_DTSEC2,
+ PCIE2, PCIE3, SGMII_SW1_DTSEC4, SATA1},
+ [0x86] = {PCIE1, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ PCIE2, PCIE3, PCIE4, SATA1},
+ [0x87] = {PCIE1, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ PCIE2, PCIE3, PCIE4, SGMII_FM1_DTSEC5},
+ [0xA7] = {PCIE1, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ PCIE2, PCIE3, PCIE4, SGMII_FM1_DTSEC5},
+ [0xAA] = {PCIE1, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ PCIE2, PCIE3, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5},
+ [0x40] = {PCIE1, PCIE1, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x06] = {PCIE1, PCIE1, PCIE1, PCIE1,
+ PCIE2, PCIE3, PCIE4, SATA1},
+ [0x08] = {PCIE1, PCIE1, PCIE1, PCIE1,
+ PCIE2, PCIE3, SATA2, SATA1},
+ [0x8F] = {PCIE1, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ AURORA, NONE, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5},
+ [0x85] = {PCIE1, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ PCIE2, PCIE2, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5},
+ [0xA5] = {PCIE1, SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ PCIE2, PCIE2, SGMII_FM1_DTSEC4, SGMII_FM1_DTSEC5},
+ [0x00] = {PCIE1, PCIE1, PCIE1, PCIE1,
+ PCIE2, PCIE2, PCIE2, PCIE2},
+ },
+ {
+ },
+ {
+ },
+ {
+ },
+};
+
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+ return serdes_cfg_tbl[serdes][cfg][lane];
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+ int i;
+
+ if (prtcl >= ARRAY_SIZE(serdes_cfg_tbl[serdes]))
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (serdes_cfg_tbl[serdes][prtcl][i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/t4240_ids.c b/arch/powerpc/cpu/mpc85xx/t4240_ids.c
new file mode 100644
index 0000000..a8f16b1
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/t4240_ids.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_portals.h>
+#include <asm/fsl_liodn.h>
+
+#ifdef CONFIG_SYS_DPAA_QBMAN
+struct qportal_info qp_info[CONFIG_SYS_QMAN_NUM_PORTALS] = {
+ /* dqrr liodn, frame data liodn, liodn off, sdest */
+ SET_QP_INFO(1, 27, 1, 0),
+ SET_QP_INFO(2, 28, 1, 0),
+ SET_QP_INFO(3, 29, 1, 1),
+ SET_QP_INFO(4, 30, 1, 1),
+ SET_QP_INFO(5, 31, 1, 2),
+ SET_QP_INFO(6, 32, 1, 2),
+ SET_QP_INFO(7, 33, 1, 3),
+ SET_QP_INFO(8, 34, 1, 3),
+ SET_QP_INFO(9, 35, 1, 4),
+ SET_QP_INFO(10, 36, 1, 4),
+ SET_QP_INFO(11, 37, 1, 5),
+ SET_QP_INFO(12, 38, 1, 5),
+ SET_QP_INFO(13, 39, 1, 6),
+ SET_QP_INFO(14, 40, 1, 6),
+ SET_QP_INFO(15, 41, 1, 7),
+ SET_QP_INFO(16, 42, 1, 7),
+ SET_QP_INFO(17, 43, 1, 8),
+ SET_QP_INFO(18, 44, 1, 8),
+ SET_QP_INFO(19, 45, 1, 9),
+ SET_QP_INFO(20, 46, 1, 9),
+ SET_QP_INFO(21, 47, 1, 10),
+ SET_QP_INFO(22, 48, 1, 10),
+ SET_QP_INFO(23, 49, 1, 11),
+ SET_QP_INFO(24, 50, 1, 11),
+ SET_QP_INFO(65, 89, 1, 0),
+ SET_QP_INFO(66, 90, 1, 0),
+ SET_QP_INFO(67, 91, 1, 1),
+ SET_QP_INFO(68, 92, 1, 1),
+ SET_QP_INFO(69, 93, 1, 2),
+ SET_QP_INFO(70, 94, 1, 2),
+ SET_QP_INFO(71, 95, 1, 3),
+ SET_QP_INFO(72, 96, 1, 3),
+ SET_QP_INFO(73, 97, 1, 4),
+ SET_QP_INFO(74, 98, 1, 4),
+ SET_QP_INFO(75, 99, 1, 5),
+ SET_QP_INFO(76, 100, 1, 5),
+ SET_QP_INFO(77, 101, 1, 6),
+ SET_QP_INFO(78, 102, 1, 6),
+ SET_QP_INFO(79, 103, 1, 7),
+ SET_QP_INFO(80, 104, 1, 7),
+ SET_QP_INFO(81, 105, 1, 8),
+ SET_QP_INFO(82, 106, 1, 8),
+ SET_QP_INFO(83, 107, 1, 9),
+ SET_QP_INFO(84, 108, 1, 9),
+ SET_QP_INFO(85, 109, 1, 10),
+ SET_QP_INFO(86, 110, 1, 10),
+ SET_QP_INFO(87, 111, 1, 11),
+ SET_QP_INFO(88, 112, 1, 11),
+ SET_QP_INFO(25, 51, 1, 0),
+ SET_QP_INFO(26, 52, 1, 0),
+};
+#endif
+
+struct srio_liodn_id_table srio_liodn_tbl[] = {
+ SET_SRIO_LIODN_1(1, 307),
+ SET_SRIO_LIODN_1(2, 387),
+};
+int srio_liodn_tbl_sz = ARRAY_SIZE(srio_liodn_tbl);
+
+struct liodn_id_table liodn_tbl[] = {
+#ifdef CONFIG_SYS_DPAA_QBMAN
+ SET_QMAN_LIODN(62),
+ SET_BMAN_LIODN(63),
+#endif
+
+ SET_SDHC_LIODN(1, 552),
+
+ SET_PME_LIODN(117),
+
+ SET_USB_LIODN(1, "fsl-usb2-mph", 553),
+ SET_USB_LIODN(2, "fsl-usb2-dr", 554),
+
+ SET_SATA_LIODN(1, 555),
+ SET_SATA_LIODN(2, 556),
+
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 1, 148),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 2, 228),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 3, 308),
+ SET_PCI_LIODN(CONFIG_SYS_FSL_PCIE_COMPAT, 4, 388),
+
+ SET_DMA_LIODN(1, 147),
+ SET_DMA_LIODN(2, 227),
+
+ SET_GUTS_LIODN("fsl,rapidio-delta", 199, rio1liodnr, 0),
+ SET_GUTS_LIODN(NULL, 200, rio2liodnr, 0),
+ SET_GUTS_LIODN(NULL, 201, rio1maintliodnr, 0),
+ SET_GUTS_LIODN(NULL, 202, rio2maintliodnr, 0),
+
+#ifdef CONFIG_SYS_PMAN
+ SET_PMAN_LIODN(1, 513),
+ SET_PMAN_LIODN(2, 514),
+ SET_PMAN_LIODN(3, 515),
+#endif
+
+ /* SET_NEXUS_LIODN(557), -- not yet implemented */
+};
+int liodn_tbl_sz = ARRAY_SIZE(liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_FMAN
+struct liodn_id_table fman1_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(1, 0, 88),
+ SET_FMAN_RX_1G_LIODN(1, 1, 89),
+ SET_FMAN_RX_1G_LIODN(1, 2, 90),
+ SET_FMAN_RX_1G_LIODN(1, 3, 91),
+ SET_FMAN_RX_1G_LIODN(1, 4, 92),
+ SET_FMAN_RX_1G_LIODN(1, 5, 93),
+ SET_FMAN_RX_10G_LIODN(1, 0, 94),
+ SET_FMAN_RX_10G_LIODN(1, 1, 95),
+};
+int fman1_liodn_tbl_sz = ARRAY_SIZE(fman1_liodn_tbl);
+#if (CONFIG_SYS_NUM_FMAN == 2)
+struct liodn_id_table fman2_liodn_tbl[] = {
+ SET_FMAN_RX_1G_LIODN(2, 0, 88),
+ SET_FMAN_RX_1G_LIODN(2, 1, 89),
+ SET_FMAN_RX_1G_LIODN(2, 2, 90),
+ SET_FMAN_RX_1G_LIODN(2, 3, 91),
+ SET_FMAN_RX_1G_LIODN(2, 4, 92),
+ SET_FMAN_RX_1G_LIODN(2, 5, 93),
+ SET_FMAN_RX_10G_LIODN(2, 0, 94),
+ SET_FMAN_RX_10G_LIODN(2, 1, 95),
+};
+int fman2_liodn_tbl_sz = ARRAY_SIZE(fman2_liodn_tbl);
+#endif
+#endif
+
+struct liodn_id_table sec_liodn_tbl[] = {
+ SET_SEC_JR_LIODN_ENTRY(0, 454, 458),
+ SET_SEC_JR_LIODN_ENTRY(1, 455, 459),
+ SET_SEC_JR_LIODN_ENTRY(2, 456, 460),
+ SET_SEC_JR_LIODN_ENTRY(3, 457, 461),
+ SET_SEC_RTIC_LIODN_ENTRY(a, 453),
+ SET_SEC_RTIC_LIODN_ENTRY(b, 549),
+ SET_SEC_RTIC_LIODN_ENTRY(c, 550),
+ SET_SEC_RTIC_LIODN_ENTRY(d, 551),
+ SET_SEC_DECO_LIODN_ENTRY(0, 541, 610),
+ SET_SEC_DECO_LIODN_ENTRY(1, 542, 611),
+ SET_SEC_DECO_LIODN_ENTRY(2, 543, 612),
+ SET_SEC_DECO_LIODN_ENTRY(3, 544, 613),
+ SET_SEC_DECO_LIODN_ENTRY(4, 545, 614),
+ SET_SEC_DECO_LIODN_ENTRY(5, 546, 615),
+ SET_SEC_DECO_LIODN_ENTRY(6, 547, 616),
+ SET_SEC_DECO_LIODN_ENTRY(7, 548, 617),
+};
+int sec_liodn_tbl_sz = ARRAY_SIZE(sec_liodn_tbl);
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+struct liodn_id_table rman_liodn_tbl[] = {
+ /* Set RMan block 0-3 liodn offset */
+ SET_RMAN_LIODN(0, 678),
+ SET_RMAN_LIODN(1, 679),
+ SET_RMAN_LIODN(2, 680),
+ SET_RMAN_LIODN(3, 681),
+};
+int rman_liodn_tbl_sz = ARRAY_SIZE(rman_liodn_tbl);
+#endif
+
+struct liodn_id_table liodn_bases[] = {
+#ifdef CONFIG_SYS_DPAA_DCE
+ [FSL_HW_PORTAL_DCE] = SET_LIODN_BASE_2(618, 694),
+#endif
+ [FSL_HW_PORTAL_SEC] = SET_LIODN_BASE_2(462, 558),
+#ifdef CONFIG_SYS_DPAA_FMAN
+ [FSL_HW_PORTAL_FMAN1] = SET_LIODN_BASE_1(973),
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ [FSL_HW_PORTAL_FMAN2] = SET_LIODN_BASE_1(1069),
+#endif
+#endif
+#ifdef CONFIG_SYS_DPAA_PME
+ [FSL_HW_PORTAL_PME] = SET_LIODN_BASE_2(770, 846),
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ [FSL_HW_PORTAL_RMAN] = SET_LIODN_BASE_1(922),
+#endif
+};
diff --git a/arch/powerpc/cpu/mpc85xx/t4240_serdes.c b/arch/powerpc/cpu/mpc85xx/t4240_serdes.c
new file mode 100644
index 0000000..c001780
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/t4240_serdes.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_serdes.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include "fsl_corenet2_serdes.h"
+
+struct serdes_config {
+ u32 protocol;
+ u8 lanes[SRDS_MAX_LANES];
+};
+
+#ifdef CONFIG_PPC_T4240
+static const struct serdes_config serdes1_cfg_tbl[] = {
+ /* SerDes 1 */
+ {1, {XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10}},
+ {2, {HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10}},
+ {4, {HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10}},
+ {28, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC9,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4}},
+ {36, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC9,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4}},
+ {38, {NONE, NONE, QSGMII_FM1_B, NONE,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {40, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {46, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {48, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {}
+};
+static const struct serdes_config serdes2_cfg_tbl[] = {
+ /* SerDes 2 */
+ {1, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC10, XAUI_FM2_MAC10,
+ XAUI_FM2_MAC10, XAUI_FM2_MAC10}},
+ {2, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC10, HIGIG_FM2_MAC10,
+ HIGIG_FM2_MAC10, HIGIG_FM2_MAC10}},
+ {4, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC10, HIGIG_FM2_MAC10,
+ HIGIG_FM2_MAC10, HIGIG_FM2_MAC10}},
+ {7, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {13, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {14, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {16, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {22, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {23, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {25, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {26, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {28, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {36, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {38, {NONE, NONE, QSGMII_FM2_B, NONE,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {40, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {46, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {48, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {50, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {52, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {54, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ NONE, NONE, QSGMII_FM1_A, NONE}},
+ {56, {XFI_FM1_MAC9, XFI_FM1_MAC10,
+ XFI_FM2_MAC10, XFI_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {57, {XFI_FM1_MAC9, XFI_FM1_MAC10,
+ XFI_FM2_MAC10, XFI_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4}},
+ {}
+};
+static const struct serdes_config serdes3_cfg_tbl[] = {
+ /* SerDes 3 */
+ {2, {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1}},
+ {4, {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2}},
+ {6, {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1}},
+ {8, {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, NONE, NONE, NONE}},
+ {9, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN}},
+ {10, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN}},
+ {12, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ PCIE2, PCIE2, PCIE2, PCIE2}},
+ {14, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ PCIE2, PCIE2, PCIE2, PCIE2}},
+ {16, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {17, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {19, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {20, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ SRIO1, SRIO1, SRIO1, SRIO1}},
+ {}
+};
+static const struct serdes_config serdes4_cfg_tbl[] = {
+ /* SerDes 4 */
+ {2, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3, PCIE3}},
+ {4, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4}},
+ {6, {PCIE3, PCIE3, PCIE3, PCIE3, SRIO2, SRIO2, SRIO2, SRIO2}},
+ {8, {PCIE3, PCIE3, PCIE3, PCIE3, SRIO2, SRIO2, SRIO2, SRIO2}},
+ {10, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, SATA1, SATA2} },
+ {12, {PCIE3, PCIE3, PCIE3, PCIE3, AURORA, AURORA, SATA1, SATA2} },
+ {14, {PCIE3, PCIE3, PCIE3, PCIE3, AURORA, AURORA, SRIO2, SRIO2}},
+ {16, {PCIE3, PCIE3, PCIE3, PCIE3, AURORA, AURORA, SRIO2, SRIO2}},
+ {18, {PCIE3, PCIE3, PCIE3, PCIE3, AURORA, AURORA, AURORA, AURORA}},
+ {}
+};
+#elif defined(CONFIG_PPC_T4160)
+static const struct serdes_config serdes1_cfg_tbl[] = {
+ /* SerDes 1 */
+ {1, {XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ XAUI_FM1_MAC9, XAUI_FM1_MAC9,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10,
+ XAUI_FM1_MAC10, XAUI_FM1_MAC10} },
+ {2, {HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10} },
+ {4, {HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC9, HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10,
+ HIGIG_FM1_MAC10, HIGIG_FM1_MAC10} },
+ {28, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC9,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4} },
+ {36, {SGMII_FM1_DTSEC5, SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC10, SGMII_FM1_DTSEC9,
+ SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3, SGMII_FM1_DTSEC4} },
+ {38, {NONE, NONE, QSGMII_FM1_B, NONE,
+ NONE, NONE, QSGMII_FM1_A, NONE} },
+ {}
+};
+static const struct serdes_config serdes2_cfg_tbl[] = {
+ /* SerDes 2 */
+ {7, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {13, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {16, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {22, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {25, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {26, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ NONE, NONE} },
+ {28, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {36, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {38, {NONE, NONE, QSGMII_FM2_B, NONE,
+ NONE, QSGMII_FM1_A, NONE, NONE} },
+ {40, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ NONE, QSGMII_FM1_A, NONE, NONE} },
+ {46, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ NONE, QSGMII_FM1_A, NONE, NONE} },
+ {48, {SGMII_FM2_DTSEC5, SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC10, SGMII_FM2_DTSEC9,
+ NONE, QSGMII_FM1_A, NONE, NONE} },
+ {50, {XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ XAUI_FM2_MAC9, XAUI_FM2_MAC9,
+ NONE, NONE, NONE, NONE} },
+ {52, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ NONE, NONE, NONE, NONE} },
+ {54, {HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC9, HIGIG_FM2_MAC9,
+ NONE, NONE, NONE, NONE} },
+ {56, {NONE, XFI_FM1_MAC10,
+ XFI_FM2_MAC10, NONE,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4} },
+ {57, {NONE, XFI_FM1_MAC10,
+ XFI_FM2_MAC10, NONE,
+ SGMII_FM2_DTSEC1, SGMII_FM2_DTSEC2,
+ NONE, NONE} },
+ {}
+};
+static const struct serdes_config serdes3_cfg_tbl[] = {
+ /* SerDes 3 */
+ {2, {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1} },
+ {4, {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2} },
+ {6, {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, SRIO1, SRIO1, SRIO1} },
+ {8, {PCIE1, PCIE1, PCIE1, PCIE1, SRIO1, NONE, NONE, NONE} },
+ {9, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN} },
+ {10, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN} },
+ {12, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ PCIE2, PCIE2, PCIE2, PCIE2} },
+ {14, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ PCIE2, PCIE2, PCIE2, PCIE2} },
+ {16, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ SRIO1, SRIO1, SRIO1, SRIO1} },
+ {17, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ SRIO1, SRIO1, SRIO1, SRIO1} },
+ {19, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ SRIO1, SRIO1, SRIO1, SRIO1} },
+ {20, {INTERLAKEN, INTERLAKEN, INTERLAKEN, INTERLAKEN,
+ NONE, NONE, NONE, NONE} },
+ {}
+};
+static const struct serdes_config serdes4_cfg_tbl[] = {
+ /* SerDes 4 */
+ {4, {PCIE3, PCIE3, PCIE3, PCIE3, PCIE4, PCIE4, PCIE4, PCIE4} },
+ {6, {SRIO2, SRIO2, SRIO2, SRIO2, SRIO2, SRIO2, SRIO2, SRIO2} },
+ {8, {SRIO2, SRIO2, SRIO2, SRIO2, SRIO2, SRIO2, SRIO2, SRIO2} },
+ {10, {PCIE3, PCIE3, PCIE3, PCIE3, SATA1, SATA1, SATA2, SATA2} },
+ {12, {AURORA, AURORA, AURORA, AURORA, SATA1, SATA1, SATA2, SATA2} },
+ {14, {AURORA, AURORA, AURORA, AURORA, SRIO2, SRIO2, SRIO2, SRIO2} },
+ {16, {AURORA, AURORA, AURORA, AURORA, SRIO2, SRIO2, SRIO2, SRIO2} },
+ {18, {AURORA, AURORA, AURORA, AURORA, AURORA, AURORA, AURORA, AURORA} },
+ {}
+}
+;
+#else
+#error "Need to define SerDes protocol"
+#endif
+static const struct serdes_config *serdes_cfg_tbl[] = {
+ serdes1_cfg_tbl,
+ serdes2_cfg_tbl,
+ serdes3_cfg_tbl,
+ serdes4_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+ const struct serdes_config *ptr;
+
+ if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ ptr = serdes_cfg_tbl[serdes];
+ while (ptr->protocol) {
+ if (ptr->protocol == cfg)
+ return ptr->lanes[lane];
+ ptr++;
+ }
+ return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+ int i;
+ const struct serdes_config *ptr;
+
+ if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+ return 0;
+
+ ptr = serdes_cfg_tbl[serdes];
+ while (ptr->protocol) {
+ if (ptr->protocol == prtcl)
+ break;
+ ptr++;
+ }
+
+ if (!ptr->protocol)
+ return 0;
+
+ for (i = 0; i < SRDS_MAX_LANES; i++) {
+ if (ptr->lanes[i] != NONE)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/tlb.c b/arch/powerpc/cpu/mpc85xx/tlb.c
new file mode 100644
index 0000000..0dff37f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/tlb.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#ifdef CONFIG_ADDR_MAP
+#include <addr_map.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void invalidate_tlb(u8 tlb)
+{
+ if (tlb == 0)
+ mtspr(MMUCSR0, 0x4);
+ if (tlb == 1)
+ mtspr(MMUCSR0, 0x2);
+}
+
+void init_tlbs(void)
+{
+ int i;
+
+ for (i = 0; i < num_tlb_entries; i++) {
+ write_tlb(tlb_table[i].mas0,
+ tlb_table[i].mas1,
+ tlb_table[i].mas2,
+ tlb_table[i].mas3,
+ tlb_table[i].mas7);
+ }
+
+ return ;
+}
+
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
+void read_tlbcam_entry(int idx, u32 *valid, u32 *tsize, unsigned long *epn,
+ phys_addr_t *rpn)
+{
+ u32 _mas1;
+
+ mtspr(MAS0, FSL_BOOKE_MAS0(1, idx, 0));
+ asm volatile("tlbre;isync");
+ _mas1 = mfspr(MAS1);
+
+ *valid = (_mas1 & MAS1_VALID);
+ *tsize = (_mas1 >> 7) & 0x1f;
+ *epn = mfspr(MAS2) & MAS2_EPN;
+ *rpn = mfspr(MAS3) & MAS3_RPN;
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ *rpn |= ((u64)mfspr(MAS7)) << 32;
+#endif
+}
+
+void print_tlbcam(void)
+{
+ int i;
+ unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+ /* walk all the entries */
+ printf("TLBCAM entries\n");
+ for (i = 0; i < num_cam; i++) {
+ unsigned long epn;
+ u32 tsize, valid;
+ phys_addr_t rpn;
+
+ read_tlbcam_entry(i, &valid, &tsize, &epn, &rpn);
+ printf("entry %02d: V: %d EPN 0x%08x RPN 0x%08llx size:",
+ i, (valid == 0) ? 0 : 1, (unsigned int)epn,
+ (unsigned long long)rpn);
+ print_size(TSIZE_TO_BYTES(tsize), "\n");
+ }
+}
+
+static inline void use_tlb_cam(u8 idx)
+{
+ int i = idx / 32;
+ int bit = idx % 32;
+
+ gd->arch.used_tlb_cams[i] |= (1 << bit);
+}
+
+static inline void free_tlb_cam(u8 idx)
+{
+ int i = idx / 32;
+ int bit = idx % 32;
+
+ gd->arch.used_tlb_cams[i] &= ~(1 << bit);
+}
+
+void init_used_tlb_cams(void)
+{
+ int i;
+ unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+ for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++)
+ gd->arch.used_tlb_cams[i] = 0;
+
+ /* walk all the entries */
+ for (i = 0; i < num_cam; i++) {
+ mtspr(MAS0, FSL_BOOKE_MAS0(1, i, 0));
+ asm volatile("tlbre;isync");
+ if (mfspr(MAS1) & MAS1_VALID)
+ use_tlb_cam(i);
+ }
+}
+
+int find_free_tlbcam(void)
+{
+ int i;
+ u32 idx;
+
+ for (i = 0; i < ((CONFIG_SYS_NUM_TLBCAMS+31)/32); i++) {
+ idx = ffz(gd->arch.used_tlb_cams[i]);
+
+ if (idx != 32)
+ break;
+ }
+
+ idx += i * 32;
+
+ if (idx >= CONFIG_SYS_NUM_TLBCAMS)
+ return -1;
+
+ return idx;
+}
+
+void set_tlb(u8 tlb, u32 epn, u64 rpn,
+ u8 perms, u8 wimge,
+ u8 ts, u8 esel, u8 tsize, u8 iprot)
+{
+ u32 _mas0, _mas1, _mas2, _mas3, _mas7;
+
+ if (tlb == 1)
+ use_tlb_cam(esel);
+
+ if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1 &&
+ tsize & 1) {
+ printf("%s: bad tsize %d on entry %d at 0x%08x\n",
+ __func__, tsize, tlb, epn);
+ return;
+ }
+
+ _mas0 = FSL_BOOKE_MAS0(tlb, esel, 0);
+ _mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize);
+ _mas2 = FSL_BOOKE_MAS2(epn, wimge);
+ _mas3 = FSL_BOOKE_MAS3(rpn, 0, perms);
+ _mas7 = FSL_BOOKE_MAS7(rpn);
+
+ write_tlb(_mas0, _mas1, _mas2, _mas3, _mas7);
+
+#ifdef CONFIG_ADDR_MAP
+ if ((tlb == 1) && (gd->flags & GD_FLG_RELOC))
+ addrmap_set_entry(epn, rpn, TSIZE_TO_BYTES(tsize), esel);
+#endif
+}
+
+void disable_tlb(u8 esel)
+{
+ u32 _mas0, _mas1, _mas2, _mas3;
+
+ free_tlb_cam(esel);
+
+ _mas0 = FSL_BOOKE_MAS0(1, esel, 0);
+ _mas1 = 0;
+ _mas2 = 0;
+ _mas3 = 0;
+
+ mtspr(MAS0, _mas0);
+ mtspr(MAS1, _mas1);
+ mtspr(MAS2, _mas2);
+ mtspr(MAS3, _mas3);
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+ mtspr(MAS7, 0);
+#endif
+ asm volatile("isync;msync;tlbwe;isync");
+
+#ifdef CONFIG_ADDR_MAP
+ if (gd->flags & GD_FLG_RELOC)
+ addrmap_set_entry(0, 0, 0, esel);
+#endif
+}
+
+static void tlbsx (const volatile unsigned *addr)
+{
+ __asm__ __volatile__ ("tlbsx 0,%0" : : "r" (addr), "m" (*addr));
+}
+
+/* return -1 if we didn't find anything */
+int find_tlb_idx(void *addr, u8 tlbsel)
+{
+ u32 _mas0, _mas1;
+
+ /* zero out Search PID, AS */
+ mtspr(MAS6, 0);
+
+ tlbsx(addr);
+
+ _mas0 = mfspr(MAS0);
+ _mas1 = mfspr(MAS1);
+
+ /* we found something, and its in the TLB we expect */
+ if ((MAS1_VALID & _mas1) &&
+ (MAS0_TLBSEL(tlbsel) == (_mas0 & MAS0_TLBSEL_MSK))) {
+ return ((_mas0 & MAS0_ESEL_MSK) >> 16);
+ }
+
+ return -1;
+}
+
+#ifdef CONFIG_ADDR_MAP
+void init_addr_map(void)
+{
+ int i;
+ unsigned int num_cam = mfspr(SPRN_TLB1CFG) & 0xfff;
+
+ /* walk all the entries */
+ for (i = 0; i < num_cam; i++) {
+ unsigned long epn;
+ u32 tsize, valid;
+ phys_addr_t rpn;
+
+ read_tlbcam_entry(i, &valid, &tsize, &epn, &rpn);
+ if (valid & MAS1_VALID)
+ addrmap_set_entry(epn, rpn, TSIZE_TO_BYTES(tsize), i);
+ }
+
+ return ;
+}
+#endif
+
+unsigned int
+setup_ddr_tlbs_phys(phys_addr_t p_addr, unsigned int memsize_in_meg)
+{
+ int i;
+ unsigned int tlb_size;
+ unsigned int wimge = MAS2_M;
+ unsigned int ram_tlb_address = (unsigned int)CONFIG_SYS_DDR_SDRAM_BASE;
+ unsigned int max_cam, tsize_mask;
+ u64 size, memsize = (u64)memsize_in_meg << 20;
+
+#ifdef CONFIG_SYS_PPC_DDR_WIMGE
+ wimge = CONFIG_SYS_PPC_DDR_WIMGE;
+#endif
+ size = min(memsize, CONFIG_MAX_MEM_MAPPED);
+ if ((mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1) {
+ /* Convert (4^max) kB to (2^max) bytes */
+ max_cam = ((mfspr(SPRN_TLB1CFG) >> 16) & 0xf) * 2 + 10;
+ tsize_mask = ~1U;
+ } else {
+ /* Convert (2^max) kB to (2^max) bytes */
+ max_cam = __ilog2(mfspr(SPRN_TLB1PS)) + 10;
+ tsize_mask = ~0U;
+ }
+
+ for (i = 0; size && i < 8; i++) {
+ int ram_tlb_index = find_free_tlbcam();
+ u32 camsize = __ilog2_u64(size) & tsize_mask;
+ u32 align = __ilog2(ram_tlb_address) & tsize_mask;
+
+ if (ram_tlb_index == -1)
+ break;
+
+ if (align == -2) align = max_cam;
+ if (camsize > align)
+ camsize = align;
+
+ if (camsize > max_cam)
+ camsize = max_cam;
+
+ tlb_size = camsize - 10;
+
+ set_tlb(1, ram_tlb_address, p_addr,
+ MAS3_SX|MAS3_SW|MAS3_SR, wimge,
+ 0, ram_tlb_index, tlb_size, 1);
+
+ size -= 1ULL << camsize;
+ memsize -= 1ULL << camsize;
+ ram_tlb_address += 1UL << camsize;
+ p_addr += 1UL << camsize;
+ }
+
+ if (memsize)
+ print_size(memsize, " left unmapped\n");
+ return memsize_in_meg;
+}
+
+unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg)
+{
+ return
+ setup_ddr_tlbs_phys(CONFIG_SYS_DDR_SDRAM_BASE, memsize_in_meg);
+}
+
+/* Invalidate the DDR TLBs for the requested size */
+void clear_ddr_tlbs_phys(phys_addr_t p_addr, unsigned int memsize_in_meg)
+{
+ u32 vstart = CONFIG_SYS_DDR_SDRAM_BASE;
+ unsigned long epn;
+ u32 tsize, valid, ptr;
+ phys_addr_t rpn = 0;
+ int ddr_esel;
+ u64 memsize = (u64)memsize_in_meg << 20;
+
+ ptr = vstart;
+
+ while (ptr < (vstart + memsize)) {
+ ddr_esel = find_tlb_idx((void *)ptr, 1);
+ if (ddr_esel != -1) {
+ read_tlbcam_entry(ddr_esel, &valid, &tsize, &epn, &rpn);
+ disable_tlb(ddr_esel);
+ }
+ ptr += TSIZE_TO_BYTES(tsize);
+ }
+}
+
+void clear_ddr_tlbs(unsigned int memsize_in_meg)
+{
+ clear_ddr_tlbs_phys(CONFIG_SYS_DDR_SDRAM_BASE, memsize_in_meg);
+}
+
+
+#endif /* not SPL */
diff --git a/arch/powerpc/cpu/mpc85xx/traps.c b/arch/powerpc/cpu/mpc85xx/traps.c
new file mode 100644
index 0000000..476ae93
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/traps.c
@@ -0,0 +1,313 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright 2007 Freescale Semiconductor.
+ * Copyright (C) 2003 Motorola
+ * Modified by Xianghua Xiao(x.xiao@motorola.com)
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of addressable memory. This may be less than the actual
+ * amount of memory on the system if we're unable to keep all
+ * the memory mapped in.
+ */
+extern ulong get_effective_memsize(void);
+#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
+
+static __inline__ void set_tsr(unsigned long val)
+{
+ asm volatile("mtspr 0x150, %0" : : "r" (val));
+}
+
+static __inline__ unsigned long get_esr(void)
+{
+ unsigned long val;
+ asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
+ return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void CritcalInputException(struct pt_regs *regs)
+{
+ panic("Critical Input Exception");
+}
+
+int machinecheck_count = 0;
+int machinecheck_error = 0;
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+ unsigned int mcsr, mcsrr0, mcsrr1, mcar;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+ mcsrr0 = mfspr(SPRN_MCSRR0);
+ mcsrr1 = mfspr(SPRN_MCSRR1);
+ mcsr = mfspr(SPRN_MCSR);
+ mcar = mfspr(SPRN_MCAR);
+
+ machinecheck_count++;
+ machinecheck_error=1;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from mcsr): ");
+ printf("mcsr = 0x%08x\n", mcsr);
+ if (mcsr & 0x80000000)
+ printf("Machine check input pin\n");
+ if (mcsr & 0x40000000)
+ printf("Instruction cache parity error\n");
+ if (mcsr & 0x20000000)
+ printf("Data cache push parity error\n");
+ if (mcsr & 0x10000000)
+ printf("Data cache parity error\n");
+ if (mcsr & 0x00000080)
+ printf("Bus instruction address error\n");
+ if (mcsr & 0x00000040)
+ printf("Bus Read address error\n");
+ if (mcsr & 0x00000020)
+ printf("Bus Write address error\n");
+ if (mcsr & 0x00000010)
+ printf("Bus Instruction data bus error\n");
+ if (mcsr & 0x00000008)
+ printf("Bus Read data bus error\n");
+ if (mcsr & 0x00000004)
+ printf("Bus Write bus error\n");
+ if (mcsr & 0x00000002)
+ printf("Bus Instruction parity error\n");
+ if (mcsr & 0x00000001)
+ printf("Bus Read parity error\n");
+
+ show_regs(regs);
+ printf("MCSR=0x%08x \tMCSRR0=0x%08x \nMCSRR1=0x%08x \tMCAR=0x%08x\n",
+ mcsr, mcsrr0, mcsrr1, mcar);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ if (machinecheck_count > 10) {
+ panic("machine check count too high\n");
+ }
+
+ if (machinecheck_count > 1) {
+ regs->nip += 4; /* skip offending instruction */
+ printf("Skipping current instr, Returning to 0x%08lx\n",
+ regs->nip);
+ } else {
+ printf("Returning back to 0x%08lx\n",regs->nip);
+ }
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ long esr_val;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+
+ esr_val = get_esr();
+ if( esr_val & ESR_PIL )
+ printf( "** Illegal Instruction **\n" );
+ else if( esr_val & ESR_PPR )
+ printf( "** Privileged Instruction **\n" );
+ else if( esr_val & ESR_PTR )
+ printf( "** Trap Instruction **\n" );
+
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void PITException(struct pt_regs *regs)
+{
+ /*
+ * Reset PIT interrupt
+ */
+ set_tsr(0x0c000000);
+
+ /*
+ * Call timer_interrupt routine in interrupts.c
+ */
+ timer_interrupt(NULL);
+}
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+void ExtIntException(struct pt_regs *regs)
+{
+ volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR);
+
+ uint vect;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("External Interrupt Exception at PC: %lx, SR: %lx, vector=%lx",
+ regs->nip, regs->msr, regs->trap);
+ vect = pic->iack0;
+ printf(" irq IACK0@%05x=%d\n",(int)&pic->iack0,vect);
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+}
+
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe(uint *addr)
+{
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds
new file mode 100644
index 0000000..65106f5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand.lds
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .text :
+ {
+ *(.text*)
+ } :text
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ } :text
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ .bootpg ADDR(.text) - 0x1000 :
+ {
+ KEEP(arch/powerpc/cpu/mpc85xx/start.o (.bootpg))
+ } :text = 0xffff
+
+ . = ADDR(.text) + 0x80000;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss*)
+ *(.bss*)
+ *(COMMON)
+ } :bss
+
+ . = ALIGN(4);
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds
new file mode 100644
index 0000000..80cd980
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-nand_spl.lds
@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de
+ *
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "config.h" /* CONFIG_BOARDDIR */
+
+OUTPUT_ARCH(powerpc)
+SECTIONS
+{
+ . = 0xfff00000;
+ .text : {
+ *(.text*)
+ }
+ _etext = .;
+
+ .reloc : {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ . = ALIGN(8);
+ .data : {
+ *(.rodata*)
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = ALIGN(8);
+ __init_begin = .;
+ __init_end = .;
+#if defined(CONFIG_FSL_IFC) /* Restrict bootpg at 4K boundry for IFC */
+ .bootpg ADDR(.text) + 0x1000 :
+ {
+ start.o (.bootpg)
+ }
+#define RESET_VECTOR_OFFSET 0x1ffc /* IFC has 8K sram */
+#elif defined(CONFIG_FSL_ELBC)
+#define RESET_VECTOR_OFFSET 0xffc /* LBC has 4k sram */
+#else
+#error unknown NAND controller
+#endif
+ .resetvec ADDR(.text) + RESET_VECTOR_OFFSET : {
+ KEEP(*(.resetvec))
+ } = 0xffff
+
+ __bss_start = .;
+ .bss : {
+ *(.sbss*)
+ *(.bss*)
+ }
+ __bss_end = .;
+}
+ASSERT(__init_end <= (0xfff00000 + RESET_VECTOR_OFFSET), "NAND bootstrap too big");
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
new file mode 100644
index 0000000..20284ed
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
@@ -0,0 +1,103 @@
+/*
+ * (C) Copyright 2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de
+ *
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "config.h" /* CONFIG_BOARDDIR */
+
+OUTPUT_ARCH(powerpc)
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+#endif
+SECTIONS
+{
+ . = CONFIG_SPL_TEXT_BASE;
+ .text : {
+ *(.text*)
+ }
+ _etext = .;
+
+ .reloc : {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ . = ALIGN(8);
+ .data : {
+ *(.rodata*)
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+
+ . = ALIGN(8);
+ __init_begin = .;
+ __init_end = .;
+/* FIXME for non-NAND SPL */
+#if defined(CONFIG_FSL_IFC) /* Restrict bootpg at 4K boundry for IFC */
+ .bootpg ADDR(.text) + 0x1000 :
+ {
+ arch/powerpc/cpu/mpc85xx/start.o (.bootpg)
+ }
+#define RESET_VECTOR_OFFSET 0x1ffc /* IFC has 8K sram */
+#elif defined(CONFIG_FSL_ELBC)
+#define RESET_VECTOR_OFFSET 0xffc /* LBC has 4k sram */
+#else
+#error unknown NAND controller
+#endif
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+ .bootpg ADDR(.text) - 0x1000 :
+ {
+ KEEP(*(.bootpg))
+ } :text = 0xffff
+#else
+ .resetvec ADDR(.text) + RESET_VECTOR_OFFSET : {
+ KEEP(*(.resetvec))
+ } = 0xffff
+#endif
+
+ /*
+ * Make sure that the bss segment isn't linked at 0x0, otherwise its
+ * address won't be updated during relocation fixups.
+ */
+ . |= 0x10;
+
+ . = ALIGN(4);
+ __bss_start = .;
+ .bss : {
+ *(.sbss*)
+ *(.bss*)
+ }
+ . = ALIGN(4);
+ __bss_end = .;
+}
diff --git a/arch/powerpc/cpu/mpc85xx/u-boot.lds b/arch/powerpc/cpu/mpc85xx/u-boot.lds
new file mode 100644
index 0000000..2643563
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot.lds
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2007-2009, 2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "config.h" /* CONFIG_BOARDDIR */
+
+#ifdef CONFIG_RESET_VECTOR_ADDRESS
+#define RESET_VECTOR_ADDRESS CONFIG_RESET_VECTOR_ADDRESS
+#else
+#define RESET_VECTOR_ADDRESS 0xfffffffc
+#endif
+
+OUTPUT_ARCH(powerpc)
+
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .text :
+ {
+ *(.text*)
+ } :text
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ } :text
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+#ifdef CONFIG_SYS_MPC85XX_NO_RESETVEC
+ .bootpg ADDR(.text) - 0x1000 :
+ {
+ KEEP(arch/powerpc/cpu/mpc85xx/start.o (.bootpg))
+ } :text = 0xffff
+ . = ADDR(.text) + 0x80000;
+#else
+ .bootpg RESET_VECTOR_ADDRESS - 0xffc :
+ {
+ arch/powerpc/cpu/mpc85xx/start.o (.bootpg)
+ } :text = 0xffff
+
+ .resetvec RESET_VECTOR_ADDRESS :
+ {
+ KEEP(*(.resetvec))
+ } :text = 0xffff
+
+ . = RESET_VECTOR_ADDRESS + 0x4;
+
+ /*
+ * Make sure that the bss segment isn't linked at 0x0, otherwise its
+ * address won't be updated during relocation fixups. Note that
+ * this is a temporary fix. Code to dynamically the fixup the bss
+ * location will be added in the future. When the bss relocation
+ * fixup code is present this workaround should be removed.
+ */
+#if (RESET_VECTOR_ADDRESS == 0xfffffffc)
+ . |= 0x10;
+#endif
+#endif
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.sbss*)
+ *(.bss*)
+ *(COMMON)
+ } :bss
+
+ . = ALIGN(4);
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc86xx/Makefile b/arch/powerpc/cpu/mpc86xx/Makefile
new file mode 100644
index 0000000..b4ef286
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/Makefile
@@ -0,0 +1,65 @@
+#
+# Copyright 2007 Freescale Semiconductor, Inc.
+# (C) Copyright 2002,2003 Motorola Inc.
+# Xianghua Xiao,X.Xiao@motorola.com
+#
+# (C) Copyright 2004 Freescale Semiconductor. (MC86xx Port)
+# Jeff Brown
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+SSTART = start.o
+CSTART = traps.o
+
+SOBJS-y += cache.o
+SOBJS-$(CONFIG_MP) += release.o
+
+COBJS-y += cpu.o
+COBJS-y += cpu_init.o
+# 8610 & 8641 are identical w/regards to DDR
+COBJS-$(CONFIG_MPC8610) += ddr-8641.o
+COBJS-$(CONFIG_MPC8641) += ddr-8641.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-y += interrupts.o
+COBJS-$(CONFIG_MP) += mp.o
+COBJS-$(CONFIG_MPC8610) += mpc8610_serdes.o
+COBJS-$(CONFIG_MPC8641) += mpc8641_serdes.o
+COBJS-y += speed.o
+
+SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+START := $(addprefix $(obj),$(SSTART) $(CSTART))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc86xx/cache.S b/arch/powerpc/cpu/mpc86xx/cache.S
new file mode 100644
index 0000000..0bb058b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/cache.S
@@ -0,0 +1,378 @@
+#include <config.h>
+#include <mpc86xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#ifndef CACHE_LINE_SIZE
+# define CACHE_LINE_SIZE L1_CACHE_BYTES
+#endif
+
+#if CACHE_LINE_SIZE == 128
+#define LG_CACHE_LINE_SIZE 7
+#elif CACHE_LINE_SIZE == 32
+#define LG_CACHE_LINE_SIZE 5
+#elif CACHE_LINE_SIZE == 16
+#define LG_CACHE_LINE_SIZE 4
+#elif CACHE_LINE_SIZE == 8
+#define LG_CACHE_LINE_SIZE 3
+#else
+# error "Invalid cache line size!"
+#endif
+
+/*
+ * Most of this code is taken from 74xx_7xx/cache.S
+ * and then cleaned up a bit
+ */
+
+/*
+ * Invalidate L1 instruction cache.
+ */
+_GLOBAL(invalidate_l1_instruction_cache)
+ /* use invalidate-all bit in HID0 */
+ mfspr r3,HID0
+ ori r3,r3,HID0_ICFI
+ mtspr HID0,r3
+ isync
+ blr
+
+/*
+ * Invalidate L1 data cache.
+ */
+_GLOBAL(invalidate_l1_data_cache)
+ mfspr r3,HID0
+ ori r3,r3,HID0_DCFI
+ mtspr HID0,r3
+ isync
+ blr
+
+/*
+ * Flush data cache.
+ */
+_GLOBAL(flush_dcache)
+ lis r3,0
+ lis r5,CACHE_LINE_SIZE
+flush:
+ cmp 0,1,r3,r5
+ bge done
+ lwz r5,0(r3)
+ lis r5,CACHE_LINE_SIZE
+ addi r3,r3,0x4
+ b flush
+done:
+ blr
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ * This is a no-op on the 601.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ *
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(clean_dcache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5 /* align r3 down to cache line */
+ subf r4,r3,r4 /* r4 = offset of stop from start of cache line */
+ add r4,r4,r5 /* r4 += cache_line_size-1 */
+ srwi. r4,r4,LG_CACHE_LINE_SIZE /* r4 = number of cache lines to flush */
+ beqlr /* if r4 == 0 return */
+ mtctr r4 /* ctr = r4 */
+
+ sync
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+ sync
+1: dcbf 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbf's to get to ram */
+ blr
+
+/*
+ * Like above, but invalidate the D-cache. This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ *
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_dcache_range)
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+
+ sync
+1: dcbi 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbi's to get to ram */
+ blr
+
+/*
+ * Flush a particular page from the data cache to RAM.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ *
+ * void __flush_page_to_ram(void *page)
+ */
+_GLOBAL(__flush_page_to_ram)
+ rlwinm r3,r3,0,0,19 /* Get page base address */
+ li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+0: dcbst 0,r3 /* Write line to ram */
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 0b
+ sync
+ mtctr r4
+1: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ isync
+ blr
+
+/*
+ * Flush a particular page from the instruction cache.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ *
+ * void __flush_icache_page(void *page)
+ */
+_GLOBAL(__flush_icache_page)
+ li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+1: icbi 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ isync
+ blr
+
+/*
+ * Clear a page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced). This only works on cacheable memory.
+ */
+_GLOBAL(clear_page)
+ li r0,4096/CACHE_LINE_SIZE
+ mtctr r0
+1: dcbz 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ blr
+
+/*
+ * Enable L1 Instruction cache
+ */
+_GLOBAL(icache_enable)
+ mfspr r3, HID0
+ li r5, HID0_ICFI|HID0_ILOCK
+ andc r3, r3, r5
+ ori r3, r3, HID0_ICE
+ ori r5, r3, HID0_ICFI
+ mtspr HID0, r5
+ mtspr HID0, r3
+ isync
+ blr
+
+/*
+ * Disable L1 Instruction cache
+ */
+_GLOBAL(icache_disable)
+ mflr r4
+ bl invalidate_l1_instruction_cache /* uses r3 */
+ sync
+ mtlr r4
+ mfspr r3, HID0
+ li r5, 0
+ ori r5, r5, HID0_ICE
+ andc r3, r3, r5
+ mtspr HID0, r3
+ isync
+ blr
+
+/*
+ * Is instruction cache enabled?
+ */
+_GLOBAL(icache_status)
+ mfspr r3, HID0
+ andi. r3, r3, HID0_ICE
+ blr
+
+
+_GLOBAL(l1dcache_enable)
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ ori r3, r3, HID0_DCE
+ ori r5, r3, HID0_DCFI
+ mtspr HID0, r5 /* enable + invalidate */
+ mtspr HID0, r3 /* enable */
+ sync
+ blr
+
+/*
+ * Enable data cache(s) - L1 and optionally L2
+ * Calls l2cache_enable. LR saved in r5
+ */
+_GLOBAL(dcache_enable)
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ ori r3, r3, HID0_DCE
+ ori r5, r3, HID0_DCFI
+ mtspr HID0, r5 /* enable + invalidate */
+ mtspr HID0, r3 /* enable */
+ sync
+#ifdef CONFIG_SYS_L2
+ mflr r5
+ bl l2cache_enable /* uses r3 and r4 */
+ sync
+ mtlr r5
+#endif
+ blr
+
+
+/*
+ * Disable data cache(s) - L1 and optionally L2
+ * Calls flush_dcache and l2cache_disable_no_flush.
+ * LR saved in r4
+ */
+_GLOBAL(dcache_disable)
+ mflr r4 /* save link register */
+ bl flush_dcache /* uses r3 and r5 */
+ sync
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ li r5, HID0_DCE|HID0_DCFI
+ andc r3, r3, r5 /* no enable, no invalidate */
+ mtspr HID0, r3
+ sync
+#ifdef CONFIG_SYS_L2
+ bl l2cache_disable_no_flush /* uses r3 */
+#endif
+ mtlr r4 /* restore link register */
+ blr
+
+/*
+ * Is data cache enabled?
+ */
+_GLOBAL(dcache_status)
+ mfspr r3, HID0
+ andi. r3, r3, HID0_DCE
+ blr
+
+/*
+ * Invalidate L2 cache using L2I, assume L2 is enabled
+ */
+_GLOBAL(l2cache_invalidate)
+ mfspr r3, l2cr
+ rlwinm. r3, r3, 0, 0, 0
+ beq 1f
+
+ mfspr r3, l2cr
+ rlwinm r3, r3, 0, 1, 31
+
+#ifdef CONFIG_ALTIVEC
+ dssall
+#endif
+ sync
+ mtspr l2cr, r3
+ sync
+1: mfspr r3, l2cr
+ oris r3, r3, L2CR_L2I@h
+ mtspr l2cr, r3
+
+invl2:
+ mfspr r3, l2cr
+ andis. r3, r3, L2CR_L2I@h
+ bne invl2
+ blr
+
+/*
+ * Enable L2 cache
+ * Calls l2cache_invalidate. LR is saved in r4
+ */
+_GLOBAL(l2cache_enable)
+ mflr r4 /* save link register */
+ bl l2cache_invalidate /* uses r3 */
+ sync
+ lis r3, L2_ENABLE@h
+ ori r3, r3, L2_ENABLE@l
+ mtspr l2cr, r3
+ isync
+ mtlr r4 /* restore link register */
+ blr
+
+/*
+ * Disable L2 cache
+ * Calls flush_dcache. LR is saved in r4
+ */
+_GLOBAL(l2cache_disable)
+ mflr r4 /* save link register */
+ bl flush_dcache /* uses r3 and r5 */
+ sync
+ mtlr r4 /* restore link register */
+l2cache_disable_no_flush: /* provide way to disable L2 w/o flushing */
+ lis r3, L2_INIT@h
+ ori r3, r3, L2_INIT@l
+ mtspr l2cr, r3
+ isync
+ blr
diff --git a/arch/powerpc/cpu/mpc86xx/config.mk b/arch/powerpc/cpu/mpc86xx/config.mk
new file mode 100644
index 0000000..92ff7bf
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/config.mk
@@ -0,0 +1,27 @@
+#
+# (C) Copyright 2004 Freescale Semiconductor.
+# Jeff Brown
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -ffixed-r2 -mstring
+PLATFORM_CPPFLAGS += -maltivec -mabi=altivec -msoft-float
diff --git a/arch/powerpc/cpu/mpc86xx/cpu.c b/arch/powerpc/cpu/mpc86xx/cpu.c
new file mode 100644
index 0000000..5ed3eb2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/cpu.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2006,2009-2010 Freescale Semiconductor, Inc.
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <mpc86xx.h>
+#include <asm/fsl_law.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Default board reset function
+ */
+static void
+__board_reset(void)
+{
+ /* Do nothing */
+}
+void board_reset(void) __attribute__((weak, alias("__board_reset")));
+
+
+int
+checkcpu(void)
+{
+ sys_info_t sysinfo;
+ uint pvr, svr;
+ uint major, minor;
+ char buf1[32], buf2[32];
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile ccsr_gur_t *gur = &immap->im_gur;
+ struct cpu_type *cpu;
+ uint msscr0 = mfspr(MSSCR0);
+
+ svr = get_svr();
+ major = SVR_MAJ(svr);
+ minor = SVR_MIN(svr);
+
+ if (cpu_numcores() > 1) {
+#ifndef CONFIG_MP
+ puts("Unicore software on multiprocessor system!!\n"
+ "To enable mutlticore build define CONFIG_MP\n");
+#endif
+ }
+ puts("CPU: ");
+
+ cpu = gd->arch.cpu;
+
+ puts(cpu->name);
+
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr);
+ puts("Core: ");
+
+ pvr = get_pvr();
+ major = PVR_E600_MAJ(pvr);
+ minor = PVR_E600_MIN(pvr);
+
+ printf("e600 Core %d", (msscr0 & 0x20) ? 1 : 0);
+ if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE)
+ puts("\n Core1Translation Enabled");
+ debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr);
+
+ printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr);
+
+ get_sys_info(&sysinfo);
+
+ puts("Clock Configuration:\n");
+ printf(" CPU:%-4s MHz, ", strmhz(buf1, sysinfo.freqProcessor));
+ printf("MPX:%-4s MHz\n", strmhz(buf1, sysinfo.freqSystemBus));
+ printf(" DDR:%-4s MHz (%s MT/s data rate), ",
+ strmhz(buf1, sysinfo.freqSystemBus / 2),
+ strmhz(buf2, sysinfo.freqSystemBus));
+
+ if (sysinfo.freqLocalBus > LCRR_CLKDIV) {
+ printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus));
+ } else {
+ printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n",
+ sysinfo.freqLocalBus);
+ }
+
+ puts("L1: D-cache 32 KB enabled\n");
+ puts(" I-cache 32 KB enabled\n");
+
+ puts("L2: ");
+ if (get_l2cr() & 0x80000000) {
+#if defined(CONFIG_MPC8610)
+ puts("256");
+#elif defined(CONFIG_MPC8641)
+ puts("512");
+#endif
+ puts(" KB enabled\n");
+ } else {
+ puts("Disabled\n");
+ }
+
+ return 0;
+}
+
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile ccsr_gur_t *gur = &immap->im_gur;
+
+ /* Attempt board-specific reset */
+ board_reset();
+
+ /* Next try asserting HRESET_REQ */
+ out_be32(&gur->rstcr, MPC86xx_RSTCR_HRST_REQ);
+
+ while (1)
+ ;
+
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long
+get_tbclk(void)
+{
+ sys_info_t sys_info;
+
+ get_sys_info(&sys_info);
+ return (sys_info.freqSystemBus + 3L) / 4L;
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void
+watchdog_reset(void)
+{
+#if defined(CONFIG_MPC8610)
+ /*
+ * This actually feed the hard enabled watchdog.
+ */
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile ccsr_wdt_t *wdt = &immap->im_wdt;
+ volatile ccsr_gur_t *gur = &immap->im_gur;
+ u32 tmp = gur->pordevsr;
+
+ if (tmp & 0x4000) {
+ wdt->swsrr = 0x556c;
+ wdt->swsrr = 0xaa39;
+ }
+#endif
+}
+#endif /* CONFIG_WATCHDOG */
+
+/*
+ * Print out the state of various machine registers.
+ * Currently prints out LAWs, BR0/OR0, and BATs
+ */
+void mpc86xx_reginfo(void)
+{
+ print_bats();
+ print_laws();
+ print_lbc_regs();
+}
+
+/*
+ * Set the DDR BATs to reflect the actual size of DDR.
+ *
+ * dram_size is the actual size of DDR, in bytes
+ *
+ * Note: we assume that CONFIG_MAX_MEM_MAPPED is 2G or smaller as we only
+ * are using a single BAT to cover DDR.
+ *
+ * If this is not true, (e.g. CONFIG_MAX_MEM_MAPPED is 2GB but HID0_XBSEN
+ * is not defined) then we might have a situation where U-Boot will attempt
+ * to relocated itself outside of the region mapped by DBAT0.
+ * This will cause a machine check.
+ *
+ * Currently we are limited to power of two sized DDR since we only use a
+ * single bat. If a non-power of two size is used that is less than
+ * CONFIG_MAX_MEM_MAPPED u-boot will crash.
+ *
+ */
+void setup_ddr_bat(phys_addr_t dram_size)
+{
+ unsigned long batu, bl;
+
+ bl = TO_BATU_BL(min(dram_size, CONFIG_MAX_MEM_MAPPED));
+
+ if (BATU_SIZE(bl) != dram_size) {
+ u64 sz = (u64)dram_size - BATU_SIZE(bl);
+ print_size(sz, " left unmapped\n");
+ }
+
+ batu = bl | BATU_VS | BATU_VP;
+ write_bat(DBAT0, batu, CONFIG_SYS_DBAT0L);
+ write_bat(IBAT0, batu, CONFIG_SYS_IBAT0L);
+}
diff --git a/arch/powerpc/cpu/mpc86xx/cpu_init.c b/arch/powerpc/cpu/mpc86xx/cpu_init.c
new file mode 100644
index 0000000..0375df2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/cpu_init.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2004,2009-2011 Freescale Semiconductor, Inc.
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cpu_init.c - low level cpu init
+ */
+
+#include <config.h>
+#include <common.h>
+#include <mpc86xx.h>
+#include <asm/mmu.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_serdes.h>
+#include <asm/mp.h>
+
+extern void srio_init(void);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Breathe some life into the CPU...
+ *
+ * Set up the memory map
+ * initialize a bunch of registers
+ */
+
+void cpu_init_f(void)
+{
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+
+ /* Clear initial global data */
+ memset ((void *) gd, 0, sizeof (gd_t));
+
+#ifdef CONFIG_FSL_LAW
+ init_laws();
+#endif
+
+ setup_bats();
+
+ init_early_memctl_regs();
+
+#if defined(CONFIG_FSL_DMA)
+ dma_init();
+#endif
+
+ /* enable the timebase bit in HID0 */
+ set_hid0(get_hid0() | 0x4000000);
+
+ /* enable EMCP, SYNCBE | ABE bits in HID1 */
+ set_hid1(get_hid1() | 0x80000C00);
+}
+
+/*
+ * initialize higher level parts of CPU like timers
+ */
+int cpu_init_r(void)
+{
+ /* needs to be in ram since code uses global static vars */
+ fsl_serdes_init();
+
+#ifdef CONFIG_SYS_SRIO
+ srio_init();
+#endif
+
+#if defined(CONFIG_MP)
+ setup_mp();
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_ADDR_MAP
+/* Initialize address mapping array */
+void init_addr_map(void)
+{
+ int i;
+ ppc_bat_t bat = DBAT0;
+ phys_size_t size;
+ unsigned long upper, lower;
+
+ for (i = 0; i < CONFIG_SYS_NUM_ADDR_MAP; i++, bat++) {
+ if (read_bat(bat, &upper, &lower) != -1) {
+ if (!BATU_VALID(upper))
+ size = 0;
+ else
+ size = BATU_SIZE(upper);
+ addrmap_set_entry(BATU_VADDR(upper), BATL_PADDR(lower),
+ size, i);
+ }
+#ifdef CONFIG_HIGH_BATS
+ /* High bats are not contiguous with low BAT numbers */
+ if (bat == DBAT3)
+ bat = DBAT4 - 1;
+#endif
+ }
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc86xx/ddr-8641.c b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
new file mode 100644
index 0000000..92ba26d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
+#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
+#endif
+
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ volatile ccsr_ddr_t *ddr;
+
+ switch (ctrl_num) {
+ case 0:
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
+ break;
+ case 1:
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR;
+ break;
+ default:
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (i == 0) {
+ out_be32(&ddr->cs0_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs0_config, regs->cs[i].config);
+
+ } else if (i == 1) {
+ out_be32(&ddr->cs1_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs1_config, regs->cs[i].config);
+
+ } else if (i == 2) {
+ out_be32(&ddr->cs2_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs2_config, regs->cs[i].config);
+
+ } else if (i == 3) {
+ out_be32(&ddr->cs3_bnds, regs->cs[i].bnds);
+ out_be32(&ddr->cs3_config, regs->cs[i].config);
+ }
+ }
+
+ out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3);
+ out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0);
+ out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1);
+ out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+ out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+ out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode);
+ out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
+ out_be32(&ddr->sdram_mode_cntl, regs->ddr_sdram_md_cntl);
+ out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval);
+ out_be32(&ddr->sdram_data_init, regs->ddr_data_init);
+ out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+ out_be32(&ddr->init_addr, regs->ddr_init_addr);
+ out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
+
+ debug("before go\n");
+
+ /*
+ * 200 painful micro-seconds must elapse between
+ * the DDR clock setup and the DDR config enable.
+ */
+ udelay(200);
+ asm volatile("sync;isync");
+
+ out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg);
+
+ /*
+ * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done
+ */
+ while (in_be32(&ddr->sdram_cfg_2) & 0x10) {
+ udelay(10000); /* throttle polling rate */
+ }
+}
diff --git a/arch/powerpc/cpu/mpc86xx/fdt.c b/arch/powerpc/cpu/mpc86xx/fdt.c
new file mode 100644
index 0000000..26a65c5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/fdt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008, 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/mp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern void ft_fixup_num_cores(void *blob);
+extern void ft_srio_setup(void *blob);
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+#ifdef CONFIG_MP
+ int off;
+ u32 bootpg = determine_mp_bootpg(NULL);
+#endif
+
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", bd->bi_busfreq / 4, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "clock-frequency", bd->bi_intfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "soc", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+
+#if defined(CONFIG_MPC8641)
+ do_fixup_by_compat_u32(blob, "fsl,mpc8641-localbus",
+ "bus-frequency", gd->arch.lbc_clk, 1);
+#endif
+ do_fixup_by_compat_u32(blob, "fsl,elbc",
+ "bus-frequency", gd->arch.lbc_clk, 1);
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) \
+ || defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3)
+ fdt_fixup_ethernet(blob);
+#endif
+
+#ifdef CONFIG_SYS_NS16550
+ do_fixup_by_compat_u32(blob, "ns16550",
+ "clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
+#endif
+
+#ifdef CONFIG_MP
+ /* Reserve the boot page so OSes dont use it */
+ off = fdt_add_mem_rsv(blob, bootpg, (u64)4096);
+ if (off < 0)
+ printf("%s: %s\n", __FUNCTION__, fdt_strerror(off));
+
+ ft_fixup_num_cores(blob);
+#endif
+
+#ifdef CONFIG_SYS_SRIO
+ ft_srio_setup(blob);
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc86xx/interrupts.c b/arch/powerpc/cpu/mpc86xx/interrupts.c
new file mode 100644
index 0000000..aff1f6d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/interrupts.c
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 Motorola Inc. (MPC85xx port)
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * (C) Copyright 2004, 2007 Freescale Semiconductor. (MPC86xx Port)
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc86xx.h>
+#include <command.h>
+#include <asm/processor.h>
+#ifdef CONFIG_POST
+#include <post.h>
+#endif
+
+int interrupt_init_cpu(unsigned long *decrementer_count)
+{
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+ volatile ccsr_pic_t *pic = &immr->im_pic;
+
+#ifdef CONFIG_POST
+ /*
+ * The POST word is stored in the PIC's TFRR register which gets
+ * cleared when the PIC is reset. Save it off so we can restore it
+ * later.
+ */
+ ulong post_word = post_word_load();
+#endif
+
+ pic->gcr = MPC86xx_PICGCR_RST;
+ while (pic->gcr & MPC86xx_PICGCR_RST)
+ ;
+ pic->gcr = MPC86xx_PICGCR_MODE;
+
+ *decrementer_count = get_tbclk() / CONFIG_SYS_HZ;
+ debug("interrupt init: tbclk() = %ld MHz, decrementer_count = %ld\n",
+ (get_tbclk() / 1000000),
+ *decrementer_count);
+
+#ifdef CONFIG_INTERRUPTS
+
+ pic->iivpr1 = 0x810001; /* 50220 enable mcm interrupts */
+ debug("iivpr1@%p = %x\n", &pic->iivpr1, pic->iivpr1);
+
+ pic->iivpr2 = 0x810002; /* 50240 enable ddr interrupts */
+ debug("iivpr2@%p = %x\n", &pic->iivpr2, pic->iivpr2);
+
+ pic->iivpr3 = 0x810003; /* 50260 enable lbc interrupts */
+ debug("iivpr3@%p = %x\n", &pic->iivpr3, pic->iivpr3);
+
+#if defined(CONFIG_PCI1) || defined(CONFIG_PCIE1)
+ pic->iivpr8 = 0x810008; /* enable pcie1 interrupts */
+ debug("iivpr8@%p = %x\n", &pic->iivpr8, pic->iivpr8);
+#endif
+#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2)
+ pic->iivpr9 = 0x810009; /* enable pcie2 interrupts */
+ debug("iivpr9@%p = %x\n", &pic->iivpr9, pic->iivpr9);
+#endif
+
+ pic->ctpr = 0; /* 40080 clear current task priority register */
+#endif
+
+#ifdef CONFIG_POST
+ post_word_store(post_word);
+#endif
+
+ return 0;
+}
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+ /* nothing to do here */
+}
+
+/*
+ * Install and free a interrupt handler. Not implemented yet.
+ */
+void irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+}
+
+void irq_free_handler(int vec)
+{
+}
+
+/*
+ * irqinfo - print information about PCI devices,not implemented.
+ */
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ return 0;
+}
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+ puts("external_interrupt (oops!)\n");
+}
diff --git a/arch/powerpc/cpu/mpc86xx/mp.c b/arch/powerpc/cpu/mpc86xx/mp.c
new file mode 100644
index 0000000..de705f0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/mp.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <ioports.h>
+#include <lmb.h>
+#include <asm/io.h>
+#include <asm/mp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int cpu_reset(int nr)
+{
+ /* dummy function so common/cmd_mp.c will build
+ * should be implemented in the future, when cpu_release()
+ * is supported. Be aware there may be a similiar bug
+ * as exists on MPC85xx w/its PIC having a timing window
+ * associated to resetting the core */
+ return 1;
+}
+
+int cpu_status(int nr)
+{
+ /* dummy function so common/cmd_mp.c will build */
+ return 0;
+}
+
+int cpu_disable(int nr)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_CCSRBAR;
+ volatile ccsr_gur_t *gur = &immap->im_gur;
+
+ switch (nr) {
+ case 0:
+ setbits_be32(&gur->devdisr, MPC86xx_DEVDISR_CPU0);
+ break;
+ case 1:
+ setbits_be32(&gur->devdisr, MPC86xx_DEVDISR_CPU1);
+ break;
+ default:
+ printf("Invalid cpu number for disable %d\n", nr);
+ return 1;
+ }
+
+ return 0;
+}
+
+int is_core_disabled(int nr) {
+ immap_t *immap = (immap_t *) CONFIG_SYS_CCSRBAR;
+ ccsr_gur_t *gur = &immap->im_gur;
+ u32 devdisr = in_be32(&gur->devdisr);
+
+ switch (nr) {
+ case 0:
+ return (devdisr & MPC86xx_DEVDISR_CPU0);
+ case 1:
+ return (devdisr & MPC86xx_DEVDISR_CPU1);
+ default:
+ printf("Invalid cpu number for disable %d\n", nr);
+ }
+
+ return 0;
+}
+
+int cpu_release(int nr, int argc, char * const argv[])
+{
+ /* dummy function so common/cmd_mp.c will build
+ * should be implemented in the future */
+ return 1;
+}
+
+u32 determine_mp_bootpg(unsigned int *pagesize)
+{
+ if (pagesize)
+ *pagesize = 4096;
+
+ /* if we have 4G or more of memory, put the boot page at 4Gb-1M */
+ if ((u64)gd->ram_size > 0xfffff000)
+ return (0xfff00000);
+
+ return (gd->ram_size - (1024 * 1024));
+}
+
+void cpu_mp_lmb_reserve(struct lmb *lmb)
+{
+ u32 bootpg = determine_mp_bootpg(NULL);
+
+ /* tell u-boot we stole a page */
+ lmb_reserve(lmb, bootpg, 4096);
+}
+
+/*
+ * Copy the code for other cpus to execute into an
+ * aligned location accessible via BPTR
+ */
+void setup_mp(void)
+{
+ extern ulong __secondary_start_page;
+ ulong fixup = (ulong)&__secondary_start_page;
+ u32 bootpg = determine_mp_bootpg(NULL);
+ u32 bootpg_va;
+
+ if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE) {
+ /* We're not covered by the DDR mapping, set up BAT */
+ write_bat(DBAT7, CONFIG_SYS_SCRATCH_VA | BATU_BL_128K |
+ BATU_VS | BATU_VP,
+ bootpg | BATL_PP_RW | BATL_MEMCOHERENCE);
+ bootpg_va = CONFIG_SYS_SCRATCH_VA;
+ } else {
+ bootpg_va = bootpg;
+ }
+
+ memcpy((void *)bootpg_va, (void *)fixup, 4096);
+ flush_cache(bootpg_va, 4096);
+
+ /* remove the temporary BAT mapping */
+ if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE)
+ write_bat(DBAT7, 0, 0);
+
+ /* If the physical location of bootpg is not at fff00000, set BPTR */
+ if (bootpg != 0xfff00000)
+ out_be32((uint *)(CONFIG_SYS_CCSRBAR + 0x20), 0x80000000 |
+ (bootpg >> 12));
+}
diff --git a/arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c b/arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c
new file mode 100644
index 0000000..0342e34
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/mpc8610_serdes.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_86xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+#define SRDS2_MAX_LANES 4
+
+static u32 serdes1_prtcl_map, serdes2_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x1] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x4] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x7] = {NONE, NONE, NONE, NONE},
+};
+
+static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
+ [0x0] = {PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x4] = {PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x7] = {NONE, NONE, NONE, NONE},
+};
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ int ret = (1 << device) & serdes1_prtcl_map;
+
+ if (ret)
+ return ret;
+
+ return (1 << device) & serdes2_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ immap_t *immap = (immap_t *) CONFIG_SYS_CCSRBAR;
+ ccsr_gur_t *gur = &immap->im_gur;
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC8610_PORDEVSR_IO_SEL) >>
+ MPC8610_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
+ serdes2_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c b/arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c
new file mode 100644
index 0000000..21c5ddb
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/mpc8641_serdes.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/immap_86xx.h>
+#include <asm/fsl_serdes.h>
+
+#define SRDS1_MAX_LANES 4
+#define SRDS2_MAX_LANES 4
+
+static u32 serdes1_prtcl_map, serdes2_prtcl_map;
+
+static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = {
+ [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x6] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1},
+ [0xf] = {PCIE1, PCIE1, PCIE1, PCIE1},
+};
+
+static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = {
+ [0x3] = {PCIE2, PCIE2, PCIE2, PCIE2},
+ [0x5] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x6] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x7] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0x9] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xa] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xb] = {SRIO1, SRIO1, SRIO1, SRIO1},
+ [0xe] = {PCIE2, PCIE2, PCIE2, PCIE2},
+ [0xf] = {PCIE2, PCIE2, PCIE2, PCIE2},
+};
+
+int is_serdes_configured(enum srds_prtcl device)
+{
+ int ret = (1 << device) & serdes1_prtcl_map;
+
+ if (ret)
+ return ret;
+
+ return (1 << device) & serdes2_prtcl_map;
+}
+
+void fsl_serdes_init(void)
+{
+ immap_t *immap = (immap_t *) CONFIG_SYS_CCSRBAR;
+ ccsr_gur_t *gur = &immap->im_gur;
+ u32 pordevsr = in_be32(&gur->pordevsr);
+ u32 srds_cfg = (pordevsr & MPC8641_PORDEVSR_IO_SEL) >>
+ MPC8641_PORDEVSR_IO_SEL_SHIFT;
+ int lane;
+
+ debug("PORDEVSR[IO_SEL_SRDS] = %x\n", srds_cfg);
+
+ if (srds_cfg >= ARRAY_SIZE(serdes1_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+ for (lane = 0; lane < SRDS1_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds_cfg][lane];
+ serdes1_prtcl_map |= (1 << lane_prtcl);
+ }
+
+ if (srds_cfg >= ARRAY_SIZE(serdes2_cfg_tbl)) {
+ printf("Invalid PORDEVSR[IO_SEL_SRDS] = %d\n", srds_cfg);
+ return;
+ }
+
+ for (lane = 0; lane < SRDS2_MAX_LANES; lane++) {
+ enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds_cfg][lane];
+ serdes2_prtcl_map |= (1 << lane_prtcl);
+ }
+}
diff --git a/arch/powerpc/cpu/mpc86xx/release.S b/arch/powerpc/cpu/mpc86xx/release.S
new file mode 100644
index 0000000..67a6f2b
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/release.S
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2004, 2007, 2008 Freescale Semiconductor.
+ * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <config.h>
+#include <mpc86xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/* If this is a multi-cpu system then we need to handle the
+ * 2nd cpu. The assumption is that the 2nd cpu is being
+ * held in boot holdoff mode until the 1st cpu unlocks it
+ * from Linux. We'll do some basic cpu init and then pass
+ * it to the Linux Reset Vector.
+ * Sri: Much of this initialization is not required. Linux
+ * rewrites the bats, and the sprs and also enables the L1 cache.
+ *
+ * Core 0 must copy this to a 1M aligned region and set BPTR
+ * to point to it.
+ */
+ .align 12
+.globl __secondary_start_page
+__secondary_start_page:
+ .space 0x100 /* space over to reset vector loc */
+ mfspr r0, MSSCR0
+ andi. r0, r0, 0x0020
+ rlwinm r0,r0,27,31,31
+ mtspr PIR, r0
+
+ /* Invalidate BATs */
+ li r0, 0
+ mtspr IBAT0U, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT3U, r0
+ mtspr IBAT4U, r0
+ mtspr IBAT5U, r0
+ mtspr IBAT6U, r0
+ mtspr IBAT7U, r0
+ isync
+ mtspr DBAT0U, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT3U, r0
+ mtspr DBAT4U, r0
+ mtspr DBAT5U, r0
+ mtspr DBAT6U, r0
+ mtspr DBAT7U, r0
+ isync
+ sync
+
+ /* enable extended addressing */
+ mfspr r0, HID0
+ lis r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
+ ori r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
+ mtspr HID0, r0
+ sync
+ isync
+
+#ifdef CONFIG_SYS_L2
+ /* init the L2 cache */
+ addis r3, r0, L2_INIT@h
+ ori r3, r3, L2_INIT@l
+ sync
+ mtspr l2cr, r3
+#ifdef CONFIG_ALTIVEC
+ dssall
+#endif
+ /* invalidate the L2 cache */
+ mfspr r3, l2cr
+ rlwinm. r3, r3, 0, 0, 0
+ beq 1f
+
+ mfspr r3, l2cr
+ rlwinm r3, r3, 0, 1, 31
+
+#ifdef CONFIG_ALTIVEC
+ dssall
+#endif
+ sync
+ mtspr l2cr, r3
+ sync
+1: mfspr r3, l2cr
+ oris r3, r3, L2CR_L2I@h
+ mtspr l2cr, r3
+
+invl2:
+ mfspr r3, l2cr
+ andis. r3, r3, L2CR_L2I@h
+ bne invl2
+ sync
+#endif
+
+ /* enable and invalidate the data cache */
+ mfspr r3, HID0
+ li r5, HID0_DCFI|HID0_DLOCK
+ andc r3, r3, r5
+ mtspr HID0, r3 /* no invalidate, unlock */
+ ori r3, r3, HID0_DCE
+ ori r5, r3, HID0_DCFI
+ mtspr HID0, r5 /* enable + invalidate */
+ mtspr HID0, r3 /* enable */
+ sync
+#ifdef CONFIG_SYS_L2
+ sync
+ lis r3, L2_ENABLE@h
+ ori r3, r3, L2_ENABLE@l
+ mtspr l2cr, r3
+ isync
+ sync
+#endif
+
+ /* enable and invalidate the instruction cache*/
+ mfspr r3, HID0
+ li r5, HID0_ICFI|HID0_ILOCK
+ andc r3, r3, r5
+ ori r3, r3, HID0_ICE
+ ori r5, r3, HID0_ICFI
+ mtspr HID0, r5
+ mtspr HID0, r3
+ isync
+ sync
+
+ /* TBEN in HID0 */
+ mfspr r4, HID0
+ oris r4, r4, 0x0400
+ mtspr HID0, r4
+ sync
+ isync
+
+ /* MCP|SYNCBE|ABE in HID1 */
+ mfspr r4, HID1
+ oris r4, r4, 0x8000
+ ori r4, r4, 0x0C00
+ mtspr HID1, r4
+ sync
+ isync
+
+ lis r3, CONFIG_LINUX_RESET_VEC@h
+ ori r3, r3, CONFIG_LINUX_RESET_VEC@l
+ mtlr r3
+ blr
+
+ /* Never Returns, Running in Linux Now */
diff --git a/arch/powerpc/cpu/mpc86xx/speed.c b/arch/powerpc/cpu/mpc86xx/speed.c
new file mode 100644
index 0000000..18c1eea
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/speed.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2004 Freescale Semiconductor.
+ * Jeff Brown
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc86xx.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* used in some defintiions of CONFIG_SYS_CLK_FREQ */
+extern unsigned long get_board_sys_clk(unsigned long dummy);
+
+void get_sys_info(sys_info_t *sysInfo)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile ccsr_gur_t *gur = &immap->im_gur;
+ uint plat_ratio, e600_ratio;
+ uint lcrr_div;
+
+ plat_ratio = (gur->porpllsr) & 0x0000003e;
+ plat_ratio >>= 1;
+
+ switch (plat_ratio) {
+ case 0x0:
+ sysInfo->freqSystemBus = 16 * CONFIG_SYS_CLK_FREQ;
+ break;
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0c:
+ case 0x10:
+ sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ;
+ break;
+ default:
+ sysInfo->freqSystemBus = 0;
+ break;
+ }
+
+ e600_ratio = (gur->porpllsr) & 0x003f0000;
+ e600_ratio >>= 16;
+
+ switch (e600_ratio) {
+ case 0x10:
+ sysInfo->freqProcessor = 2 * sysInfo->freqSystemBus;
+ break;
+ case 0x19:
+ sysInfo->freqProcessor = 5 * sysInfo->freqSystemBus / 2;
+ break;
+ case 0x20:
+ sysInfo->freqProcessor = 3 * sysInfo->freqSystemBus;
+ break;
+ case 0x39:
+ sysInfo->freqProcessor = 7 * sysInfo->freqSystemBus / 2;
+ break;
+ case 0x28:
+ sysInfo->freqProcessor = 4 * sysInfo->freqSystemBus;
+ break;
+ case 0x1d:
+ sysInfo->freqProcessor = 9 * sysInfo->freqSystemBus / 2;
+ break;
+ default:
+ sysInfo->freqProcessor = e600_ratio + sysInfo->freqSystemBus;
+ break;
+ }
+
+#if defined(CONFIG_SYS_LBC_LCRR)
+ /* We will program LCRR to this value later */
+ lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV;
+#else
+ lcrr_div = in_be32(&immap->im_lbc.lcrr) & LCRR_CLKDIV;
+#endif
+ if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) {
+ sysInfo->freqLocalBus = sysInfo->freqSystemBus / (lcrr_div * 2);
+ } else {
+ /* In case anyone cares what the unknown value is */
+ sysInfo->freqLocalBus = lcrr_div;
+ }
+}
+
+
+/*
+ * Measure CPU clock speed (core clock GCLK1, GCLK2)
+ * (Approx. GCLK frequency in Hz)
+ */
+
+int get_clocks(void)
+{
+ sys_info_t sys_info;
+
+ get_sys_info(&sys_info);
+ gd->cpu_clk = sys_info.freqProcessor;
+ gd->bus_clk = sys_info.freqSystemBus;
+ gd->arch.lbc_clk = sys_info.freqLocalBus;
+
+ /*
+ * The base clock for I2C depends on the actual SOC. Unfortunately,
+ * there is no pattern that can be used to determine the frequency, so
+ * the only choice is to look up the actual SOC number and use the value
+ * for that SOC. This information is taken from application note
+ * AN2919.
+ */
+#ifdef CONFIG_MPC8610
+ gd->arch.i2c1_clk = sys_info.freqSystemBus;
+#else
+ gd->arch.i2c1_clk = sys_info.freqSystemBus / 2;
+#endif
+ gd->arch.i2c2_clk = gd->arch.i2c1_clk;
+
+ if (gd->cpu_clk != 0)
+ return 0;
+ else
+ return 1;
+}
+
+
+/*
+ * get_bus_freq
+ * Return system bus freq in Hz
+ */
+
+ulong get_bus_freq(ulong dummy)
+{
+ ulong val;
+ sys_info_t sys_info;
+
+ get_sys_info(&sys_info);
+ val = sys_info.freqSystemBus;
+
+ return val;
+}
diff --git a/arch/powerpc/cpu/mpc86xx/start.S b/arch/powerpc/cpu/mpc86xx/start.S
new file mode 100644
index 0000000..20dfb9e
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/start.S
@@ -0,0 +1,1008 @@
+/*
+ * Copyright 2004, 2007, 2011 Freescale Semiconductor.
+ * Srikanth Srinivasan <srikanth.srinivaan@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot - Startup Code for 86xx PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0xfff00100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating.
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ */
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc86xx.h>
+#include <version.h>
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/*
+ * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions
+ */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+ .text
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ b boot_cold
+
+ /* the boot code is located below the exception table */
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+ STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+ . = 0x2000
+
+boot_cold:
+ /*
+ * NOTE: Only Cpu 0 will ever come here. Other cores go to an
+ * address specified by the BPTR
+ */
+1:
+#ifdef CONFIG_SYS_RAMBOOT
+ /* disable everything */
+ li r0, 0
+ mtspr HID0, r0
+ sync
+ mtmsr 0
+#endif
+
+ /* Invalidate BATs */
+ bl invalidate_bats
+ sync
+ /* Invalidate all of TLB before MMU turn on */
+ bl clear_tlbs
+ sync
+
+#ifdef CONFIG_SYS_L2
+ /* init the L2 cache */
+ lis r3, L2_INIT@h
+ ori r3, r3, L2_INIT@l
+ mtspr l2cr, r3
+ /* invalidate the L2 cache */
+ bl l2cache_invalidate
+ sync
+#endif
+
+ /*
+ * Calculate absolute address in FLASH and jump there
+ *------------------------------------------------------*/
+ lis r3, CONFIG_SYS_MONITOR_BASE_EARLY@h
+ ori r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l
+ addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r3
+ blr
+
+in_flash:
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*------------------------------------------------------*/
+ /* perform low-level init */
+
+ /* enable extended addressing */
+ bl enable_ext_addr
+
+ /* setup the bats */
+ bl early_bats
+
+ /*
+ * Cache must be enabled here for stack-in-cache trick.
+ * This means we need to enable the BATS.
+ * Cache should be turned on after BATs, since by default
+ * everything is write-through.
+ */
+
+ /* enable address translation */
+ mfmsr r5
+ ori r5, r5, (MSR_IR | MSR_DR)
+ lis r3,addr_trans_enabled@h
+ ori r3, r3, addr_trans_enabled@l
+ mtspr SPRN_SRR0,r3
+ mtspr SPRN_SRR1,r5
+ rfi
+
+addr_trans_enabled:
+ /* enable and invalidate the data cache */
+/* bl l1dcache_enable */
+ bl dcache_enable
+ sync
+
+#if 1
+ bl icache_enable
+#endif
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+ bl lock_ram_in_cache
+ sync
+#endif
+
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
+ bl setup_ccsrbar
+#endif
+
+ /* set up the stack pointer in our newly created
+ * cache-ram (r1) */
+ lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h
+ ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l
+
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ GET_GOT /* initialize GOT access */
+
+ /* run low-level CPU init code (from Flash) */
+ bl cpu_init_f
+ sync
+
+#ifdef RUN_DIAG
+
+ /* Load PX_AUX register address in r4 */
+ lis r4, PIXIS_BASE@h
+ ori r4, r4, 0x6
+ /* Load contents of PX_AUX in r3 bits 24 to 31*/
+ lbz r3, 0(r4)
+
+ /* Mask and obtain the bit in r3 */
+ rlwinm. r3, r3, 0, 24, 24
+ /* If not zero, jump and continue with u-boot */
+ bne diag_done
+
+ /* Load back contents of PX_AUX in r3 bits 24 to 31 */
+ lbz r3, 0(r4)
+ /* Set the MSB of the register value */
+ ori r3, r3, 0x80
+ /* Write value in r3 back to PX_AUX */
+ stb r3, 0(r4)
+
+ /* Get the address to jump to in r3*/
+ lis r3, CONFIG_SYS_DIAG_ADDR@h
+ ori r3, r3, CONFIG_SYS_DIAG_ADDR@l
+
+ /* Load the LR with the branch address */
+ mtlr r3
+
+ /* Branch to diagnostic */
+ blr
+
+diag_done:
+#endif
+
+/* bl l2cache_enable */
+
+ /* run 1st part of board init code (from Flash) */
+ bl board_init_f
+ sync
+
+ /* NOTREACHED - board_init_f() does not return */
+
+ .globl invalidate_bats
+invalidate_bats:
+
+ li r0, 0
+ /* invalidate BATs */
+ mtspr IBAT0U, r0
+ mtspr IBAT1U, r0
+ mtspr IBAT2U, r0
+ mtspr IBAT3U, r0
+ mtspr IBAT4U, r0
+ mtspr IBAT5U, r0
+ mtspr IBAT6U, r0
+ mtspr IBAT7U, r0
+
+ isync
+ mtspr DBAT0U, r0
+ mtspr DBAT1U, r0
+ mtspr DBAT2U, r0
+ mtspr DBAT3U, r0
+ mtspr DBAT4U, r0
+ mtspr DBAT5U, r0
+ mtspr DBAT6U, r0
+ mtspr DBAT7U, r0
+
+ isync
+ sync
+ blr
+
+#define CONFIG_BAT_PAIR(n) \
+ lis r4, CONFIG_SYS_IBAT##n##L@h; \
+ ori r4, r4, CONFIG_SYS_IBAT##n##L@l; \
+ lis r3, CONFIG_SYS_IBAT##n##U@h; \
+ ori r3, r3, CONFIG_SYS_IBAT##n##U@l; \
+ mtspr IBAT##n##L, r4; \
+ mtspr IBAT##n##U, r3; \
+ lis r4, CONFIG_SYS_DBAT##n##L@h; \
+ ori r4, r4, CONFIG_SYS_DBAT##n##L@l; \
+ lis r3, CONFIG_SYS_DBAT##n##U@h; \
+ ori r3, r3, CONFIG_SYS_DBAT##n##U@l; \
+ mtspr DBAT##n##L, r4; \
+ mtspr DBAT##n##U, r3;
+
+/*
+ * setup_bats:
+ *
+ * Set up the final BAT registers now that setup is done.
+ *
+ * Assumes that:
+ * 1) Address translation is enabled upon entry
+ * 2) The boot rom is still accessible via 1:1 translation
+ */
+ .globl setup_bats
+setup_bats:
+ mflr r5
+ sync
+
+ /*
+ * When we disable address translation, we will get 1:1 (VA==PA)
+ * translation. The only place we know for sure is safe for that is
+ * the bootrom where we originally started out. Pop back into there.
+ */
+ lis r4, CONFIG_SYS_MONITOR_BASE_EARLY@h
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE_EARLY@l
+ addi r4, r4, trans_disabled - _start + EXC_OFF_SYS_RESET
+
+ /* disable address translation */
+ mfmsr r3
+ rlwinm r3, r3, 0, 28, 25
+ mtspr SRR0, r4
+ mtspr SRR1, r3
+ rfi
+
+trans_disabled:
+#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L) \
+ && defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L)
+ CONFIG_BAT_PAIR(0)
+#endif
+ CONFIG_BAT_PAIR(1)
+ CONFIG_BAT_PAIR(2)
+ CONFIG_BAT_PAIR(3)
+ CONFIG_BAT_PAIR(4)
+ CONFIG_BAT_PAIR(5)
+ CONFIG_BAT_PAIR(6)
+ CONFIG_BAT_PAIR(7)
+
+ sync
+ isync
+
+ /* Turn translation back on and return */
+ mfmsr r3
+ ori r3, r3, (MSR_IR | MSR_DR)
+ mtspr SPRN_SRR0,r5
+ mtspr SPRN_SRR1,r3
+ rfi
+
+/*
+ * early_bats:
+ *
+ * Set up bats needed early on - this is usually the BAT for the
+ * stack-in-cache, the Flash, and CCSR space
+ */
+ .globl early_bats
+early_bats:
+ /* IBAT 3 */
+ lis r4, CONFIG_SYS_IBAT3L@h
+ ori r4, r4, CONFIG_SYS_IBAT3L@l
+ lis r3, CONFIG_SYS_IBAT3U@h
+ ori r3, r3, CONFIG_SYS_IBAT3U@l
+ mtspr IBAT3L, r4
+ mtspr IBAT3U, r3
+ isync
+
+ /* DBAT 3 */
+ lis r4, CONFIG_SYS_DBAT3L@h
+ ori r4, r4, CONFIG_SYS_DBAT3L@l
+ lis r3, CONFIG_SYS_DBAT3U@h
+ ori r3, r3, CONFIG_SYS_DBAT3U@l
+ mtspr DBAT3L, r4
+ mtspr DBAT3U, r3
+ isync
+
+ /* IBAT 5 */
+ lis r4, CONFIG_SYS_IBAT5L@h
+ ori r4, r4, CONFIG_SYS_IBAT5L@l
+ lis r3, CONFIG_SYS_IBAT5U@h
+ ori r3, r3, CONFIG_SYS_IBAT5U@l
+ mtspr IBAT5L, r4
+ mtspr IBAT5U, r3
+ isync
+
+ /* DBAT 5 */
+ lis r4, CONFIG_SYS_DBAT5L@h
+ ori r4, r4, CONFIG_SYS_DBAT5L@l
+ lis r3, CONFIG_SYS_DBAT5U@h
+ ori r3, r3, CONFIG_SYS_DBAT5U@l
+ mtspr DBAT5L, r4
+ mtspr DBAT5U, r3
+ isync
+
+ /* IBAT 6 */
+ lis r4, CONFIG_SYS_IBAT6L_EARLY@h
+ ori r4, r4, CONFIG_SYS_IBAT6L_EARLY@l
+ lis r3, CONFIG_SYS_IBAT6U_EARLY@h
+ ori r3, r3, CONFIG_SYS_IBAT6U_EARLY@l
+ mtspr IBAT6L, r4
+ mtspr IBAT6U, r3
+ isync
+
+ /* DBAT 6 */
+ lis r4, CONFIG_SYS_DBAT6L_EARLY@h
+ ori r4, r4, CONFIG_SYS_DBAT6L_EARLY@l
+ lis r3, CONFIG_SYS_DBAT6U_EARLY@h
+ ori r3, r3, CONFIG_SYS_DBAT6U_EARLY@l
+ mtspr DBAT6L, r4
+ mtspr DBAT6U, r3
+ isync
+
+#if(CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
+ /* IBAT 7 */
+ lis r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@h
+ ori r4, r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@l
+ lis r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@h
+ ori r3, r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@l
+ mtspr IBAT7L, r4
+ mtspr IBAT7U, r3
+ isync
+
+ /* DBAT 7 */
+ lis r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@h
+ ori r4, r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@l
+ lis r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@h
+ ori r3, r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@l
+ mtspr DBAT7L, r4
+ mtspr DBAT7U, r3
+ isync
+#endif
+ blr
+
+ .globl clear_tlbs
+clear_tlbs:
+ addis r3, 0, 0x0000
+ addis r5, 0, 0x4
+ isync
+tlblp:
+ tlbie r3
+ sync
+ addi r3, r3, 0x1000
+ cmp 0, 0, r3, r5
+ blt tlblp
+ blr
+
+ .globl disable_addr_trans
+disable_addr_trans:
+ /* disable address translation */
+ mflr r4
+ mfmsr r3
+ andi. r0, r3, (MSR_IR | MSR_DR)
+ beqlr
+ andc r3, r3, r0
+ mtspr SRR0, r4
+ mtspr SRR1, r3
+ rfi
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+ .globl dc_read
+dc_read:
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+ .globl get_svr
+get_svr:
+ mfspr r3, SVR
+ blr
+
+
+/*
+ * Function: in8
+ * Description: Input 8 bits
+ */
+ .globl in8
+in8:
+ lbz r3,0x0000(r3)
+ blr
+
+/*
+ * Function: out8
+ * Description: Output 8 bits
+ */
+ .globl out8
+out8:
+ stb r4,0x0000(r3)
+ blr
+
+/*
+ * Function: out16
+ * Description: Output 16 bits
+ */
+ .globl out16
+out16:
+ sth r4,0x0000(r3)
+ blr
+
+/*
+ * Function: out16r
+ * Description: Byte reverse and output 16 bits
+ */
+ .globl out16r
+out16r:
+ sthbrx r4,r0,r3
+ blr
+
+/*
+ * Function: out32
+ * Description: Output 32 bits
+ */
+ .globl out32
+out32:
+ stw r4,0x0000(r3)
+ blr
+
+/*
+ * Function: out32r
+ * Description: Byte reverse and output 32 bits
+ */
+ .globl out32r
+out32r:
+ stwbrx r4,r0,r3
+ blr
+
+/*
+ * Function: in16
+ * Description: Input 16 bits
+ */
+ .globl in16
+in16:
+ lhz r3,0x0000(r3)
+ blr
+
+/*
+ * Function: in16r
+ * Description: Input 16 bits and byte reverse
+ */
+ .globl in16r
+in16r:
+ lhbrx r3,r0,r3
+ blr
+
+/*
+ * Function: in32
+ * Description: Input 32 bits
+ */
+ .globl in32
+in32:
+ lwz 3,0x0000(3)
+ blr
+
+/*
+ * Function: in32r
+ * Description: Input 32 bits and byte reverse
+ */
+ .globl in32r
+in32r:
+ lwbrx r3,r0,r3
+ blr
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+/* clear_bss: */
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+ mr r3, r9 /* Init Date pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /* not reached - end relocate_code */
+/*-----------------------------------------------------------------------*/
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ /* enable execptions from RAM vectors */
+ mfmsr r7
+ li r8,MSR_IP
+ andc r7,r7,r8
+ ori r7,r7,MSR_ME /* Enable Machine Check */
+ mtmsr r7
+
+ mtlr r4 /* restore link register */
+ blr
+
+.globl enable_ext_addr
+enable_ext_addr:
+ mfspr r0, HID0
+ lis r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h
+ ori r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l
+ mtspr HID0, r0
+ sync
+ isync
+ blr
+
+#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR)
+.globl setup_ccsrbar
+setup_ccsrbar:
+ /* Special sequence needed to update CCSRBAR itself */
+ lis r4, CONFIG_SYS_CCSRBAR_DEFAULT@h
+ ori r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l
+
+ lis r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h
+ ori r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l
+ srwi r5,r5,12
+ li r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l
+ rlwimi r5,r6,20,8,11
+ stw r5, 0(r4) /* Store physical value of CCSR */
+ isync
+
+ lis r5, CONFIG_SYS_TEXT_BASE@h
+ ori r5,r5,CONFIG_SYS_TEXT_BASE@l
+ lwz r5, 0(r5)
+ isync
+
+ /* Use VA of CCSR to do read */
+ lis r3, CONFIG_SYS_CCSRBAR@h
+ lwz r5, CONFIG_SYS_CCSRBAR@l(r3)
+ isync
+
+ blr
+#endif
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+lock_ram_in_cache:
+ /* Allocate Initial RAM in data cache.
+ */
+ lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+ li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
+ (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+ mtctr r4
+1:
+ dcbz r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+#if 1
+/* Lock the data cache */
+ mfspr r0, HID0
+ ori r0, r0, 0x1000
+ sync
+ mtspr HID0, r0
+ sync
+ blr
+#endif
+#if 0
+ /* Lock the first way of the data cache */
+ mfspr r0, LDSTCR
+ ori r0, r0, 0x0080
+#if defined(CONFIG_ALTIVEC)
+ dssall
+#endif
+ sync
+ mtspr LDSTCR, r0
+ sync
+ isync
+ blr
+#endif
+
+.globl unlock_ram_in_cache
+unlock_ram_in_cache:
+ /* invalidate the INIT_RAM section */
+ lis r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h
+ ori r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l
+ li r4, ((CONFIG_SYS_INIT_RAM_SIZE & ~31) + \
+ (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32
+ mtctr r4
+1: icbi r0, r3
+ addi r3, r3, 32
+ bdnz 1b
+ sync /* Wait for all icbi to complete on bus */
+ isync
+#if 1
+/* Unlock the data cache and invalidate it */
+ mfspr r0, HID0
+ li r3,0x1000
+ andc r0,r0,r3
+ li r3,0x0400
+ or r0,r0,r3
+ sync
+ mtspr HID0, r0
+ sync
+ blr
+#endif
+#if 0
+ /* Unlock the first way of the data cache */
+ mfspr r0, LDSTCR
+ li r3,0x0080
+ andc r0,r0,r3
+#ifdef CONFIG_ALTIVEC
+ dssall
+#endif
+ sync
+ mtspr LDSTCR, r0
+ sync
+ isync
+ li r3,0x0400
+ or r0,r0,r3
+ sync
+ mtspr HID0, r0
+ sync
+ blr
+#endif
+#endif
diff --git a/arch/powerpc/cpu/mpc86xx/traps.c b/arch/powerpc/cpu/mpc86xx/traps.c
new file mode 100644
index 0000000..50069d5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/traps.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/*
+ * End of addressable memory. This may be less than the actual
+ * amount of memory on the system if we're unable to keep all
+ * the memory mapped in.
+ */
+extern ulong get_effective_memsize(void);
+#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize())
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint) sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32)
+ break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS:"
+ " %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP:"
+ " %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr & MSR_EE ? 1 : 0,
+ regs->msr & MSR_PR ? 1 : 0, regs->msr & MSR_FP ? 1 : 0,
+ regs->msr & MSR_ME ? 1 : 0, regs->msr & MSR_IR ? 1 : 0,
+ regs->msr & MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0) {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7) {
+ printf("\n");
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d", regs->nip, signr);
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ", regs);
+ switch ( regs->msr & 0x001F0000) {
+ case (0x80000000>>11):
+ printf("MSS error. MSSSR0: %08x\n", mfspr(SPRN_MSSSR0));
+ break;
+ case (0x80000000>>12):
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000 >> 13):
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000 >> 14):
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000 >> 15):
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL;
+ int i, j;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+ return;
+#endif
+ show_regs(regs);
+
+ p = (unsigned char *)((unsigned long)p & 0xFFFFFFE0);
+ p -= 32;
+ for (i = 0; i < 256; i += 16) {
+ printf("%08x: ", (unsigned int)p + i);
+ for (j = 0; j < 16; j++) {
+ printf("%02x ", p[i + j]);
+ }
+ printf("\n");
+ }
+
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler) (regs))
+ return;
+#endif
+ printf("UnknownException regs@%lx\n", (ulong)regs);
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+/*
+ * Probe an address by reading.
+ * If not present, return -1,
+ * otherwise return 0.
+ */
+int addr_probe(uint *addr)
+{
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc86xx/u-boot.lds b/arch/powerpc/cpu/mpc86xx/u-boot.lds
new file mode 100644
index 0000000..7e357ba
--- /dev/null
+++ b/arch/powerpc/cpu/mpc86xx/u-boot.lds
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2006, 2007 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+
+SECTIONS
+{
+
+ /* Read-only sections, merged into text segment: */
+ .text :
+ {
+ arch/powerpc/cpu/mpc86xx/start.o (.text*)
+ arch/powerpc/cpu/mpc86xx/traps.o (.text*)
+ *(.text*)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ . = ALIGN(4);
+ }
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/mpc8xx/Makefile b/arch/powerpc/cpu/mpc8xx/Makefile
new file mode 100644
index 0000000..ef10e2d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/Makefile
@@ -0,0 +1,65 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+# CFLAGS += -DET_DEBUG
+
+LIB = $(obj)lib$(CPU).o
+
+SSTART-y += start.o
+CSTART-y += traps.o
+COBJS-y += bedbug_860.o
+COBJS-y += commproc.o
+COBJS-y += cpu.o
+COBJS-y += cpu_init.o
+COBJS-y += fec.o
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-y += i2c.o
+COBJS-y += interrupts.o
+COBJS-y += scc.o
+COBJS-y += serial.o
+COBJS-y += speed.o
+COBJS-y += spi.o
+COBJS-y += upatch.o
+COBJS-y += video.o
+SOBJS-y += kgdb.o
+SOBJS-y += plprcr_write.o
+
+SRCS := $(SSTART-y:.o=.S) $(CSTART-y:.o=.c) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+START := $(addprefix $(obj),$(SSTART-y) $(CSTART-y))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/mpc8xx/bedbug_860.c b/arch/powerpc/cpu/mpc8xx/bedbug_860.c
new file mode 100644
index 0000000..c0016f7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/bedbug_860.c
@@ -0,0 +1,314 @@
+/*
+ * Bedbug Functions specific to the MPC860 chip
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+#include <bedbug/type.h>
+
+#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_8xx)
+
+#define MAX_BREAK_POINTS 2
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug860_init __P((void));
+void bedbug860_do_break __P((cmd_tbl_t*,int,int,char*const[]));
+void bedbug860_break_isr __P((struct pt_regs*));
+int bedbug860_find_empty __P((void));
+int bedbug860_set __P((int,unsigned long));
+int bedbug860_clear __P((int));
+
+
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the MPC860. Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug860_init( void )
+{
+ int i;
+ /* -------------------------------------------------- */
+
+ bug_ctx.hw_debug_enabled = 0;
+ bug_ctx.stopped = 0;
+ bug_ctx.current_bp = 0;
+ bug_ctx.regs = NULL;
+
+ bug_ctx.do_break = bedbug860_do_break;
+ bug_ctx.break_isr = bedbug860_break_isr;
+ bug_ctx.find_empty = bedbug860_find_empty;
+ bug_ctx.set = bedbug860_set;
+ bug_ctx.clear = bedbug860_clear;
+
+ for( i = 1; i <= MAX_BREAK_POINTS; ++i )
+ (*bug_ctx.clear)( i );
+
+ puts ("BEDBUG:ready\n");
+ return;
+} /* bedbug_init_breakpoints */
+
+
+
+/* ======================================================================
+ * Set/clear/show one of the hardware breakpoints for the 860. The "off"
+ * string will disable a specific breakpoint. The "show" string will
+ * display the current breakpoints. Otherwise an address will set a
+ * breakpoint at that address. Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug860_do_break (cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ long addr = 0; /* Address to break at */
+ int which_bp; /* Breakpoint number */
+ /* -------------------------------------------------- */
+
+ if (argc < 2) {
+ cmd_usage(cmdtp);
+ return;
+ }
+
+ /* Turn off a breakpoint */
+
+ if( strcmp( argv[ 1 ], "off" ) == 0 )
+ {
+ if( bug_ctx.hw_debug_enabled == 0 )
+ {
+ printf( "No breakpoints enabled\n" );
+ return;
+ }
+
+ which_bp = simple_strtoul( argv[ 2 ], NULL, 10 );
+
+ if( bug_ctx.clear )
+ (*bug_ctx.clear)( which_bp );
+
+ printf( "Breakpoint %d removed\n", which_bp );
+ return;
+ }
+
+ /* Show a list of breakpoints */
+
+ if( strcmp( argv[ 1 ], "show" ) == 0 )
+ {
+ for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp )
+ {
+
+ switch( which_bp )
+ {
+ case 1: addr = GET_CMPA(); break;
+ case 2: addr = GET_CMPB(); break;
+ case 3: addr = GET_CMPC(); break;
+ case 4: addr = GET_CMPD(); break;
+ }
+
+ printf( "Breakpoint [%d]: ", which_bp );
+ if( addr == 0 )
+ printf( "NOT SET\n" );
+ else
+ disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+ }
+ return;
+ }
+
+ /* Set a breakpoint at the address */
+
+ if( !isdigit( argv[ 1 ][ 0 ])) {
+ cmd_usage(cmdtp);
+ return;
+ }
+
+ addr = simple_strtoul( argv[ 1 ], NULL, 16 ) & 0xfffffffc;
+
+ if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 )
+ {
+ printf( "Breakpoint [%d]: ", which_bp );
+ disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+ }
+
+ return;
+} /* bedbug860_do_break */
+
+
+
+/* ======================================================================
+ * Handle a breakpoint. First determine which breakpoint was hit by
+ * looking at the DeBug Status Register (DBSR), clear the breakpoint
+ * and enter a mini main loop. Stay in the loop until the stopped flag
+ * in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug860_break_isr( struct pt_regs *regs )
+{
+ unsigned long addr; /* Address stopped at */
+ unsigned long cause; /* Address stopped at */
+ /* -------------------------------------------------- */
+
+ cause = GET_ICR();
+
+ if( !(cause & 0x00000004)) {
+ printf( "Not an instruction breakpoint (ICR 0x%08lx)\n", cause );
+ return;
+ }
+
+ addr = regs->nip;
+
+ if( addr == GET_CMPA() )
+ {
+ bug_ctx.current_bp = 1;
+ }
+ else if( addr == GET_CMPB() )
+ {
+ bug_ctx.current_bp = 2;
+ }
+ else if( addr == GET_CMPC() )
+ {
+ bug_ctx.current_bp = 3;
+ }
+ else if( addr == GET_CMPD() )
+ {
+ bug_ctx.current_bp = 4;
+ }
+
+ bedbug_main_loop( addr, regs );
+ return;
+} /* bedbug860_break_isr */
+
+
+
+/* ======================================================================
+ * Look through all of the hardware breakpoints available to see if one
+ * is unused.
+ * ====================================================================== */
+
+int bedbug860_find_empty( void )
+{
+ /* -------------------------------------------------- */
+
+ if( GET_CMPA() == 0 )
+ return 1;
+
+ if( GET_CMPB() == 0 )
+ return 2;
+
+ if( GET_CMPC() == 0 )
+ return 3;
+
+ if( GET_CMPD() == 0 )
+ return 4;
+
+ return 0;
+} /* bedbug860_find_empty */
+
+
+
+/* ======================================================================
+ * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint. If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0. Set the break
+ * address in the appropriate IACx register and enable proper address
+ * beakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug860_set( int which_bp, unsigned long addr )
+{
+ /* -------------------------------------------------- */
+
+ /* Only look if which_bp == 0, else use which_bp */
+ if(( bug_ctx.find_empty ) && ( !which_bp ) &&
+ ( which_bp = (*bug_ctx.find_empty)()) == 0 )
+ {
+ printf( "All breakpoints in use\n" );
+ return 0;
+ }
+
+ if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+ {
+ printf( "Invalid break point # %d\n", which_bp );
+ return 0;
+ }
+
+ if( ! bug_ctx.hw_debug_enabled )
+ {
+ bug_ctx.hw_debug_enabled = 1;
+ SET_DER( GET_DER() | 0x00000004 );
+ }
+
+ switch( which_bp )
+ {
+ case 1:
+ SET_CMPA( addr );
+ SET_ICTRL( GET_ICTRL() | 0x80080800 ); /* CTA=Equal,IW0=Match A,SIW0EN */
+ break;
+
+ case 2:
+ SET_CMPB( addr );
+ SET_ICTRL( GET_ICTRL() | 0x10020400 ); /* CTB=Equal,IW1=Match B,SIW1EN */
+ break;
+
+ case 3:
+ SET_CMPC( addr );
+ SET_ICTRL( GET_ICTRL() | 0x02008200 ); /* CTC=Equal,IW2=Match C,SIW2EN */
+ break;
+
+ case 4:
+ SET_CMPD( addr );
+ SET_ICTRL( GET_ICTRL() | 0x00404100 ); /* CTD=Equal,IW3=Match D,SIW3EN */
+ break;
+ }
+
+ return which_bp;
+} /* bedbug860_set */
+
+
+
+/* ======================================================================
+ * Disable a specific breakoint by setting the appropriate IACx register
+ * to zero and claring the instruction address breakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug860_clear( int which_bp )
+{
+ /* -------------------------------------------------- */
+
+ if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+ {
+ printf( "Invalid break point # (%d)\n", which_bp );
+ return -1;
+ }
+
+ switch( which_bp )
+ {
+ case 1:
+ SET_CMPA( 0 );
+ SET_ICTRL( GET_ICTRL() & ~0x80080800 ); /* CTA=Equal,IW0=Match A,SIW0EN */
+ break;
+
+ case 2:
+ SET_CMPB( 0 );
+ SET_ICTRL( GET_ICTRL() & ~0x10020400 ); /* CTB=Equal,IW1=Match B,SIW1EN */
+ break;
+
+ case 3:
+ SET_CMPC( 0 );
+ SET_ICTRL( GET_ICTRL() & ~0x02008200 ); /* CTC=Equal,IW2=Match C,SIW2EN */
+ break;
+
+ case 4:
+ SET_CMPD( 0 );
+ SET_ICTRL( GET_ICTRL() & ~0x00404100 ); /* CTD=Equal,IW3=Match D,SIW3EN */
+ break;
+ }
+
+ return 0;
+} /* bedbug860_clear */
+
+
+/* ====================================================================== */
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/commproc.c b/arch/powerpc/cpu/mpc8xx/commproc.c
new file mode 100644
index 0000000..a364782
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/commproc.c
@@ -0,0 +1,85 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <commproc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+
+int dpram_init (void)
+{
+ /* Reclaim the DP memory for our use. */
+ gd->arch.dp_alloc_base = CPM_DATAONLY_BASE;
+ gd->arch.dp_alloc_top = CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE;
+
+ return (0);
+}
+
+/* Allocate some memory from the dual ported ram. We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint dpram_alloc (uint size)
+{
+ uint addr = gd->arch.dp_alloc_base;
+
+ if ((gd->arch.dp_alloc_base + size) >= gd->arch.dp_alloc_top)
+ return (CPM_DP_NOSPACE);
+
+ gd->arch.dp_alloc_base += size;
+
+ return addr;
+}
+
+uint dpram_base (void)
+{
+ return gd->arch.dp_alloc_base;
+}
+
+/* Allocate some memory from the dual ported ram. We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint dpram_alloc_align (uint size, uint align)
+{
+ uint addr, mask = align - 1;
+
+ addr = (gd->arch.dp_alloc_base + mask) & ~mask;
+
+ if ((addr + size) >= gd->arch.dp_alloc_top)
+ return (CPM_DP_NOSPACE);
+
+ gd->arch.dp_alloc_base = addr + size;
+
+ return addr;
+}
+
+uint dpram_base_align (uint align)
+{
+ uint mask = align - 1;
+
+ return (gd->arch.dp_alloc_base + mask) & ~mask;
+}
+#endif /* CONFIG_SYS_ALLOC_DPRAM */
diff --git a/arch/powerpc/cpu/mpc8xx/config.mk b/arch/powerpc/cpu/mpc8xx/config.mk
new file mode 100644
index 0000000..aa61980
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/config.mk
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2000-2010
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+
+PLATFORM_CPPFLAGS += -DCONFIG_8xx -ffixed-r2 -mstring -mcpu=860 -msoft-float
diff --git a/arch/powerpc/cpu/mpc8xx/cpu.c b/arch/powerpc/cpu/mpc8xx/cpu.c
new file mode 100644
index 0000000..dc33eb3
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/cpu.c
@@ -0,0 +1,659 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * m8xx.c
+ *
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc8xx.h>
+#include <commproc.h>
+#include <netdev.h>
+#include <asm/cache.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *cpu_warning = "\n " \
+ "*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***";
+
+#if ((defined(CONFIG_MPC86x) || defined(CONFIG_MPC855)) && \
+ !defined(CONFIG_MPC862))
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+ char *id_str =
+# if defined(CONFIG_MPC855)
+ "PC855";
+# elif defined(CONFIG_MPC860P)
+ "PC860P";
+# else
+ NULL;
+# endif
+ volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+ uint k, m;
+ char buf[32];
+ char pre = 'X';
+ char *mid = "xx";
+ char *suf;
+
+ /* the highest 16 bits should be 0x0050 for a 860 */
+
+ if ((pvr >> 16) != 0x0050)
+ return -1;
+
+ k = (immr << 16) |
+ immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)];
+ m = 0;
+ suf = "";
+
+ /*
+ * Some boards use sockets so different CPUs can be used.
+ * We have to check chip version in run time.
+ */
+ switch (k) {
+ case 0x00020001: pre = 'P'; break;
+ case 0x00030001: break;
+ case 0x00120003: suf = "A"; break;
+ case 0x00130003: suf = "A3"; break;
+
+ case 0x00200004: suf = "B"; break;
+
+ case 0x00300004: suf = "C"; break;
+ case 0x00310004: suf = "C1"; m = 1; break;
+
+ case 0x00200064: mid = "SR"; suf = "B"; break;
+ case 0x00300065: mid = "SR"; suf = "C"; break;
+ case 0x00310065: mid = "SR"; suf = "C1"; m = 1; break;
+ case 0x05010000: suf = "D3"; m = 1; break;
+ case 0x05020000: suf = "D4"; m = 1; break;
+ /* this value is not documented anywhere */
+ case 0x40000000: pre = 'P'; suf = "D"; m = 1; break;
+ /* MPC866P/MPC866T/MPC859T/MPC859DSL/MPC852T */
+ case 0x08010004: /* Rev. A.0 */
+ suf = "A";
+ /* fall through */
+ case 0x08000003: /* Rev. 0.3 */
+ pre = 'M'; m = 1;
+ if (id_str == NULL)
+ id_str =
+# if defined(CONFIG_MPC852T)
+ "PC852T";
+# elif defined(CONFIG_MPC859T)
+ "PC859T";
+# elif defined(CONFIG_MPC859DSL)
+ "PC859DSL";
+# elif defined(CONFIG_MPC866T)
+ "PC866T";
+# else
+ "PC866x"; /* Unknown chip from MPC866 family */
+# endif
+ break;
+ case 0x09000000: pre = 'M'; mid = suf = ""; m = 1;
+ if (id_str == NULL)
+ id_str = "PC885"; /* 870/875/880/885 */
+ break;
+
+ default: suf = NULL; break;
+ }
+
+ if (id_str == NULL)
+ id_str = "PC86x"; /* Unknown 86x chip */
+ if (suf)
+ printf ("%c%s%sZPnn%s", pre, id_str, mid, suf);
+ else
+ printf ("unknown M%s (0x%08x)", id_str, k);
+
+
+#if defined(CONFIG_SYS_8xx_CPUCLK_MIN) && defined(CONFIG_SYS_8xx_CPUCLK_MAX)
+ printf (" at %s MHz [%d.%d...%d.%d MHz]\n ",
+ strmhz (buf, clock),
+ CONFIG_SYS_8xx_CPUCLK_MIN / 1000000,
+ ((CONFIG_SYS_8xx_CPUCLK_MIN % 1000000) + 50000) / 100000,
+ CONFIG_SYS_8xx_CPUCLK_MAX / 1000000,
+ ((CONFIG_SYS_8xx_CPUCLK_MAX % 1000000) + 50000) / 100000
+ );
+#else
+ printf (" at %s MHz: ", strmhz (buf, clock));
+#endif
+ printf ("%u kB I-Cache %u kB D-Cache",
+ checkicache () >> 10,
+ checkdcache () >> 10
+ );
+
+ /* do we have a FEC (860T/P or 852/859/866/885)? */
+
+ immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+ if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+ printf (" FEC present");
+ }
+
+ if (!m) {
+ puts (cpu_warning);
+ }
+
+ putc ('\n');
+
+#ifdef DEBUG
+ if(clock != measure_gclk()) {
+ printf ("clock %ldHz != %dHz\n", clock, measure_gclk());
+ }
+#endif
+
+ return 0;
+}
+
+#elif defined(CONFIG_MPC862)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+ volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+ uint k, m;
+ char buf[32];
+ char pre = 'X';
+ __maybe_unused char *mid = "xx";
+ char *suf;
+
+ /* the highest 16 bits should be 0x0050 for a 8xx */
+
+ if ((pvr >> 16) != 0x0050)
+ return -1;
+
+ k = (immr << 16) |
+ immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)];
+ m = 0;
+
+ switch (k) {
+
+ /* this value is not documented anywhere */
+ case 0x06000000: mid = "P"; suf = "0"; break;
+ case 0x06010001: mid = "P"; suf = "A"; m = 1; break;
+ case 0x07000003: mid = "P"; suf = "B"; m = 1; break;
+ default: suf = NULL; break;
+ }
+
+#ifndef CONFIG_MPC857
+ if (suf)
+ printf ("%cPC862%sZPnn%s", pre, mid, suf);
+ else
+ printf ("unknown MPC862 (0x%08x)", k);
+#else
+ if (suf)
+ printf ("%cPC857TZPnn%s", pre, suf); /* only 857T tested right now! */
+ else
+ printf ("unknown MPC857 (0x%08x)", k);
+#endif
+
+ printf (" at %s MHz:", strmhz (buf, clock));
+
+ printf (" %u kB I-Cache", checkicache () >> 10);
+ printf (" %u kB D-Cache", checkdcache () >> 10);
+
+ /* lets check and see if we're running on a 862T (or P?) */
+
+ immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+ if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+ printf (" FEC present");
+ }
+
+ if (!m) {
+ puts (cpu_warning);
+ }
+
+ putc ('\n');
+
+ return 0;
+}
+
+#elif defined(CONFIG_MPC823)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+ volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+ uint k, m;
+ char buf[32];
+ char *suf;
+
+ /* the highest 16 bits should be 0x0050 for a 8xx */
+
+ if ((pvr >> 16) != 0x0050)
+ return -1;
+
+ k = (immr << 16) |
+ in_be16(&immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)]);
+ m = 0;
+
+ switch (k) {
+ /* MPC823 */
+ case 0x20000000: suf = "0"; break;
+ case 0x20010000: suf = "0.1"; break;
+ case 0x20020000: suf = "Z2/3"; break;
+ case 0x20020001: suf = "Z3"; break;
+ case 0x21000000: suf = "A"; break;
+ case 0x21010000: suf = "B"; m = 1; break;
+ case 0x21010001: suf = "B2"; m = 1; break;
+ /* MPC823E */
+ case 0x24010000: suf = NULL;
+ puts ("PPC823EZTnnB2");
+ m = 1;
+ break;
+ default:
+ suf = NULL;
+ printf ("unknown MPC823 (0x%08x)", k);
+ break;
+ }
+ if (suf)
+ printf ("PPC823ZTnn%s", suf);
+
+ printf (" at %s MHz:", strmhz (buf, clock));
+
+ printf (" %u kB I-Cache", checkicache () >> 10);
+ printf (" %u kB D-Cache", checkdcache () >> 10);
+
+ /* lets check and see if we're running on a 860T (or P?) */
+
+ immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+ if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+ puts (" FEC present");
+ }
+
+ if (!m) {
+ puts (cpu_warning);
+ }
+
+ putc ('\n');
+
+ return 0;
+}
+
+#elif defined(CONFIG_MPC850)
+
+static int check_CPU (long clock, uint pvr, uint immr)
+{
+ volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+ uint k, m;
+ char buf[32];
+
+ /* the highest 16 bits should be 0x0050 for a 8xx */
+
+ if ((pvr >> 16) != 0x0050)
+ return -1;
+
+ k = (immr << 16) |
+ immap->im_cpm.cp_dparam16[PROFF_REVNUM / sizeof(u16)];
+ m = 0;
+
+ switch (k) {
+ case 0x20020001:
+ printf ("XPC850xxZT");
+ break;
+ case 0x21000065:
+ printf ("XPC850xxZTA");
+ break;
+ case 0x21010067:
+ printf ("XPC850xxZTB");
+ m = 1;
+ break;
+ case 0x21020068:
+ printf ("XPC850xxZTC");
+ m = 1;
+ break;
+ default:
+ printf ("unknown MPC850 (0x%08x)", k);
+ }
+ printf (" at %s MHz:", strmhz (buf, clock));
+
+ printf (" %u kB I-Cache", checkicache () >> 10);
+ printf (" %u kB D-Cache", checkdcache () >> 10);
+
+ /* lets check and see if we're running on a 850T (or P?) */
+
+ immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+ if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) {
+ printf (" FEC present");
+ }
+
+ if (!m) {
+ puts (cpu_warning);
+ }
+
+ putc ('\n');
+
+ return 0;
+}
+#else
+#error CPU undefined
+#endif
+/* ------------------------------------------------------------------------- */
+
+int checkcpu (void)
+{
+ ulong clock = gd->cpu_clk;
+ uint immr = get_immr (0); /* Return full IMMR contents */
+ uint pvr = get_pvr ();
+
+ puts ("CPU: ");
+
+ /* 850 has PARTNUM 20 */
+ /* 801 has PARTNUM 10 */
+ return check_CPU (clock, pvr, immr);
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB) */
+/* the 860 P (plus) has 256 sets of 16 bytes in 4 ways (= 16 kB) */
+
+int checkicache (void)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ u32 cacheon = rd_ic_cst () & IDC_ENABLED;
+
+#ifdef CONFIG_IP86x
+ u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
+#else
+ u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
+#endif
+ u32 m;
+ u32 lines = -1;
+
+ wr_ic_cst (IDC_UNALL);
+ wr_ic_cst (IDC_INVALL);
+ wr_ic_cst (IDC_DISABLE);
+ __asm__ volatile ("isync");
+
+ while (!((m = rd_ic_cst ()) & IDC_CERR2)) {
+ wr_ic_adr (k);
+ wr_ic_cst (IDC_LDLCK);
+ __asm__ volatile ("isync");
+
+ lines++;
+ k += 0x10; /* the number of bytes in a cacheline */
+ }
+
+ wr_ic_cst (IDC_UNALL);
+ wr_ic_cst (IDC_INVALL);
+
+ if (cacheon)
+ wr_ic_cst (IDC_ENABLE);
+ else
+ wr_ic_cst (IDC_DISABLE);
+
+ __asm__ volatile ("isync");
+
+ return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB) */
+/* the 860 P (plus) has 256 sets of 16 bytes in 2 ways (= 8 kB) */
+/* call with cache disabled */
+
+int checkdcache (void)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ u32 cacheon = rd_dc_cst () & IDC_ENABLED;
+
+#ifdef CONFIG_IP86x
+ u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */
+#else
+ u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */
+#endif
+ u32 m;
+ u32 lines = -1;
+
+ wr_dc_cst (IDC_UNALL);
+ wr_dc_cst (IDC_INVALL);
+ wr_dc_cst (IDC_DISABLE);
+
+ while (!((m = rd_dc_cst ()) & IDC_CERR2)) {
+ wr_dc_adr (k);
+ wr_dc_cst (IDC_LDLCK);
+ lines++;
+ k += 0x10; /* the number of bytes in a cacheline */
+ }
+
+ wr_dc_cst (IDC_UNALL);
+ wr_dc_cst (IDC_INVALL);
+
+ if (cacheon)
+ wr_dc_cst (IDC_ENABLE);
+ else
+ wr_dc_cst (IDC_DISABLE);
+
+ return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+
+void upmconfig (uint upm, uint * table, uint size)
+{
+ uint i;
+ uint addr = 0;
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ for (i = 0; i < size; i++) {
+ memctl->memc_mdr = table[i]; /* (16-15) */
+ memctl->memc_mcr = addr | upm; /* (16-16) */
+ addr++;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef CONFIG_LWMON
+
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong msr, addr;
+
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+ immap->im_clkrst.car_plprcr |= PLPRCR_CSR; /* Checkstop Reset enable */
+
+ /* Interrupts and MMU off */
+ __asm__ volatile ("mtspr 81, 0");
+ __asm__ volatile ("mfmsr %0":"=r" (msr));
+
+ msr &= ~0x1030;
+ __asm__ volatile ("mtmsr %0"::"r" (msr));
+
+ /*
+ * Trying to execute the next instruction at a non-existing address
+ * should cause a machine check, resulting in reset
+ */
+#ifdef CONFIG_SYS_RESET_ADDRESS
+ addr = CONFIG_SYS_RESET_ADDRESS;
+#else
+ /*
+ * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, CONFIG_SYS_MONITOR_BASE
+ * - sizeof (ulong) is usually a valid address. Better pick an address
+ * known to be invalid on your system and assign it to CONFIG_SYS_RESET_ADDRESS.
+ * "(ulong)-1" used to be a good choice for many systems...
+ */
+ addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong);
+#endif
+ ((void (*)(void)) addr) ();
+ return 1;
+}
+
+#else /* CONFIG_LWMON */
+
+/*
+ * On the LWMON board, the MCLR reset input of the PIC's on the board
+ * uses a 47K/1n RC combination which has a 47us time constant. The
+ * low signal on the HRESET pin of the CPU is only 512 clocks = 8 us
+ * and thus too short to reset the external hardware. So we use the
+ * watchdog to reset the board.
+ */
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ /* prevent triggering the watchdog */
+ disable_interrupts ();
+
+ /* make sure the watchdog is running */
+ reset_8xx_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+
+ /* wait for watchdog reset */
+ while (1) {};
+
+ /* NOTREACHED */
+ return 1;
+}
+
+#endif /* CONFIG_LWMON */
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ * See sections 14.2 and 14.6 of the User's Manual
+ */
+unsigned long get_tbclk (void)
+{
+ uint immr = get_immr (0); /* Return full IMMR contents */
+ volatile immap_t *immap = (volatile immap_t *)(immr & 0xFFFF0000);
+ ulong oscclk, factor, pll;
+
+ if (immap->im_clkrst.car_sccr & SCCR_TBS) {
+ return (gd->cpu_clk / 16);
+ }
+
+ pll = immap->im_clkrst.car_plprcr;
+
+#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
+
+ /*
+ * For newer PQ1 chips (MPC866/87x/88x families), PLL multiplication
+ * factor is calculated as follows:
+ *
+ * MFN
+ * MFI + -------
+ * MFD + 1
+ * factor = -----------------
+ * (PDF + 1) * 2^S
+ *
+ * For older chips, it's just MF field of PLPRCR plus one.
+ */
+ if ((immr & 0x0FFF) >= MPC8xx_NEW_CLK) { /* MPC866/87x/88x series */
+ factor = (PLPRCR_val(MFI) + PLPRCR_val(MFN)/(PLPRCR_val(MFD)+1))/
+ (PLPRCR_val(PDF)+1) / (1<<PLPRCR_val(S));
+ } else {
+ factor = PLPRCR_val(MF)+1;
+ }
+
+ oscclk = gd->cpu_clk / factor;
+
+ if ((immap->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) {
+ return (oscclk / 4);
+ }
+ return (oscclk / 16);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset (void)
+{
+ int re_enable = disable_interrupts ();
+
+ reset_8xx_watchdog ((immap_t *) CONFIG_SYS_IMMR);
+ if (re_enable)
+ enable_interrupts ();
+}
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_LWMON)
+
+void reset_8xx_watchdog (volatile immap_t * immr)
+{
+# if defined(CONFIG_LWMON)
+ /*
+ * The LWMON board uses a MAX6301 Watchdog
+ * with the trigger pin connected to port PA.7
+ *
+ * (The old board version used a MAX706TESA Watchdog, which
+ * had to be handled exactly the same.)
+ */
+# define WATCHDOG_BIT 0x0100
+ immr->im_ioport.iop_papar &= ~(WATCHDOG_BIT); /* GPIO */
+ immr->im_ioport.iop_padir |= WATCHDOG_BIT; /* Output */
+ immr->im_ioport.iop_paodr &= ~(WATCHDOG_BIT); /* active output */
+
+ immr->im_ioport.iop_padat ^= WATCHDOG_BIT; /* Toggle WDI */
+# elif defined(CONFIG_KUP4K) || defined(CONFIG_KUP4X)
+ /*
+ * The KUP4 boards uses a TPS3705 Watchdog
+ * with the trigger pin connected to port PA.5
+ */
+# define WATCHDOG_BIT 0x0400
+ immr->im_ioport.iop_papar &= ~(WATCHDOG_BIT); /* GPIO */
+ immr->im_ioport.iop_padir |= WATCHDOG_BIT; /* Output */
+ immr->im_ioport.iop_paodr &= ~(WATCHDOG_BIT); /* active output */
+
+ immr->im_ioport.iop_padat ^= WATCHDOG_BIT; /* Toggle WDI */
+# else
+ /*
+ * All other boards use the MPC8xx Internal Watchdog
+ */
+ immr->im_siu_conf.sc_swsr = 0x556c; /* write magic1 */
+ immr->im_siu_conf.sc_swsr = 0xaa39; /* write magic2 */
+# endif /* CONFIG_LWMON */
+}
+#endif /* CONFIG_WATCHDOG */
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(SCC_ENET) && defined(CONFIG_CMD_NET)
+ scc_initialize(bis);
+#endif
+#if defined(FEC_ENET)
+ fec_initialize(bis);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xx/cpu_init.c b/arch/powerpc/cpu/mpc8xx/cpu_init.c
new file mode 100644
index 0000000..49b354d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/cpu_init.c
@@ -0,0 +1,283 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+
+#include <mpc8xx.h>
+#include <commproc.h>
+
+#if defined(CONFIG_SYS_RTCSC) || defined(CONFIG_SYS_RMDS)
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCH) || \
+ defined(CONFIG_SYS_SMC_UCODE_PATCH)
+void cpm_load_patch (volatile immap_t * immr);
+#endif
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ * initialize the UPM's
+ */
+void cpu_init_f (volatile immap_t * immr)
+{
+#ifndef CONFIG_MBX
+ volatile memctl8xx_t *memctl = &immr->im_memctl;
+# ifdef CONFIG_SYS_PLPRCR
+ ulong mfmask;
+# endif
+#endif
+ ulong reg;
+
+ /* SYPCR - contains watchdog control (11-9) */
+
+ immr->im_siu_conf.sc_sypcr = CONFIG_SYS_SYPCR;
+
+#if defined(CONFIG_WATCHDOG)
+ reset_8xx_watchdog (immr);
+#endif /* CONFIG_WATCHDOG */
+
+ /* SIUMCR - contains debug pin configuration (11-6) */
+#ifndef CONFIG_SVM_SC8xx
+ immr->im_siu_conf.sc_siumcr |= CONFIG_SYS_SIUMCR;
+#else
+ immr->im_siu_conf.sc_siumcr = CONFIG_SYS_SIUMCR;
+#endif
+ /* initialize timebase status and control register (11-26) */
+ /* unlock TBSCRK */
+
+ immr->im_sitk.sitk_tbscrk = KAPWR_KEY;
+ immr->im_sit.sit_tbscr = CONFIG_SYS_TBSCR;
+
+ /* initialize the PIT (11-31) */
+
+ immr->im_sitk.sitk_piscrk = KAPWR_KEY;
+ immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+ /* System integration timers. Don't change EBDF! (15-27) */
+
+ immr->im_clkrstk.cark_sccrk = KAPWR_KEY;
+ reg = immr->im_clkrst.car_sccr;
+ reg &= SCCR_MASK;
+ reg |= CONFIG_SYS_SCCR;
+ immr->im_clkrst.car_sccr = reg;
+
+ /* PLL (CPU clock) settings (15-30) */
+
+ immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+
+#ifndef CONFIG_MBX /* MBX board does things different */
+
+ /* If CONFIG_SYS_PLPRCR (set in the various *_config.h files) tries to
+ * set the MF field, then just copy CONFIG_SYS_PLPRCR over car_plprcr,
+ * otherwise OR in CONFIG_SYS_PLPRCR so we do not change the current MF
+ * field value.
+ *
+ * For newer (starting MPC866) chips PLPRCR layout is different.
+ */
+#ifdef CONFIG_SYS_PLPRCR
+ if (get_immr(0xFFFF) >= MPC8xx_NEW_CLK)
+ mfmask = PLPRCR_MFACT_MSK;
+ else
+ mfmask = PLPRCR_MF_MSK;
+
+ if ((CONFIG_SYS_PLPRCR & mfmask) != 0)
+ reg = CONFIG_SYS_PLPRCR; /* reset control bits */
+ else {
+ reg = immr->im_clkrst.car_plprcr;
+ reg &= mfmask; /* isolate MF-related fields */
+ reg |= CONFIG_SYS_PLPRCR; /* reset control bits */
+ }
+ immr->im_clkrst.car_plprcr = reg;
+#endif
+
+ /*
+ * Memory Controller:
+ */
+
+ /* perform BR0 reset that MPC850 Rev. A can't guarantee */
+ reg = memctl->memc_br0;
+ reg &= BR_PS_MSK; /* Clear everything except Port Size bits */
+ reg |= BR_V; /* then add just the "Bank Valid" bit */
+ memctl->memc_br0 = reg;
+
+ /* Map banks 0 (and maybe 1) to the FLASH banks 0 (and 1) at
+ * preliminary addresses - these have to be modified later
+ * when FLASH size has been determined
+ *
+ * Depending on the size of the memory region defined by
+ * CONFIG_SYS_OR0_REMAP some boards (wide address mask) allow to map the
+ * CONFIG_SYS_MONITOR_BASE, while others (narrower address mask) can't
+ * map CONFIG_SYS_MONITOR_BASE.
+ *
+ * For example, for CONFIG_IVMS8, the CONFIG_SYS_MONITOR_BASE is
+ * 0xff000000, but CONFIG_SYS_OR0_REMAP's address mask is 0xfff80000.
+ *
+ * If BR0 wasn't loaded with address base 0xff000000, then BR0's
+ * base address remains as 0x00000000. However, the address mask
+ * have been narrowed to 512Kb, so CONFIG_SYS_MONITOR_BASE wasn't mapped
+ * into the Bank0.
+ *
+ * This is why CONFIG_IVMS8 and similar boards must load BR0 with
+ * CONFIG_SYS_BR0_PRELIM in advance.
+ *
+ * [Thanks to Michael Liao for this explanation.
+ * I owe him a free beer. - wd]
+ */
+
+#if defined(CONFIG_HERMES) || \
+ defined(CONFIG_ICU862) || \
+ defined(CONFIG_IP860) || \
+ defined(CONFIG_IVML24) || \
+ defined(CONFIG_IVMS8) || \
+ defined(CONFIG_LWMON) || \
+ defined(CONFIG_MHPC) || \
+ defined(CONFIG_R360MPI) || \
+ defined(CONFIG_RMU) || \
+ defined(CONFIG_RPXCLASSIC) || \
+ defined(CONFIG_RPXLITE) || \
+ defined(CONFIG_SPC1920) || \
+ defined(CONFIG_SPD823TS)
+
+ memctl->memc_br0 = CONFIG_SYS_BR0_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR0_REMAP)
+ memctl->memc_or0 = CONFIG_SYS_OR0_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+ memctl->memc_or1 = CONFIG_SYS_OR1_REMAP;
+#endif
+#if defined(CONFIG_SYS_OR5_REMAP)
+ memctl->memc_or5 = CONFIG_SYS_OR5_REMAP;
+#endif
+
+ /* now restrict to preliminary range */
+ memctl->memc_br0 = CONFIG_SYS_BR0_PRELIM;
+ memctl->memc_or0 = CONFIG_SYS_OR0_PRELIM;
+
+#if (defined(CONFIG_SYS_OR1_PRELIM) && defined(CONFIG_SYS_BR1_PRELIM))
+ memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM;
+ memctl->memc_br1 = CONFIG_SYS_BR1_PRELIM;
+#endif
+
+#if defined(CONFIG_IP860) /* disable CS0 now that Flash is mapped on CS1 */
+ memctl->memc_br0 = 0;
+#endif
+
+#if defined(CONFIG_SYS_OR2_PRELIM) && defined(CONFIG_SYS_BR2_PRELIM)
+ memctl->memc_or2 = CONFIG_SYS_OR2_PRELIM;
+ memctl->memc_br2 = CONFIG_SYS_BR2_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR3_PRELIM) && defined(CONFIG_SYS_BR3_PRELIM)
+ memctl->memc_or3 = CONFIG_SYS_OR3_PRELIM;
+ memctl->memc_br3 = CONFIG_SYS_BR3_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR4_PRELIM) && defined(CONFIG_SYS_BR4_PRELIM)
+ memctl->memc_or4 = CONFIG_SYS_OR4_PRELIM;
+ memctl->memc_br4 = CONFIG_SYS_BR4_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR5_PRELIM) && defined(CONFIG_SYS_BR5_PRELIM)
+ memctl->memc_or5 = CONFIG_SYS_OR5_PRELIM;
+ memctl->memc_br5 = CONFIG_SYS_BR5_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR6_PRELIM) && defined(CONFIG_SYS_BR6_PRELIM)
+ memctl->memc_or6 = CONFIG_SYS_OR6_PRELIM;
+ memctl->memc_br6 = CONFIG_SYS_BR6_PRELIM;
+#endif
+
+#if defined(CONFIG_SYS_OR7_PRELIM) && defined(CONFIG_SYS_BR7_PRELIM)
+ memctl->memc_or7 = CONFIG_SYS_OR7_PRELIM;
+ memctl->memc_br7 = CONFIG_SYS_BR7_PRELIM;
+#endif
+
+#endif /* ! CONFIG_MBX */
+
+ /*
+ * Reset CPM
+ */
+ immr->im_cpm.cp_cpcr = CPM_CR_RST | CPM_CR_FLG;
+ do { /* Spin until command processed */
+ __asm__ ("eieio");
+ } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+#ifdef CONFIG_MBX
+ /*
+ * on the MBX, things are a little bit different:
+ * - we need to read the VPD to get board information
+ * - the plprcr is set up dynamically
+ * - the memory controller is set up dynamically
+ */
+ mbx_init ();
+#endif /* CONFIG_MBX */
+
+#ifdef CONFIG_RPXCLASSIC
+ rpxclassic_init ();
+#endif
+
+#if defined(CONFIG_RPXLITE) && defined(CONFIG_ENV_IS_IN_NVRAM)
+ rpxlite_init ();
+#endif
+
+#ifdef CONFIG_SYS_RCCR /* must be done before cpm_load_patch() */
+ /* write config value */
+ immr->im_cpm.cp_rccr = CONFIG_SYS_RCCR;
+#endif
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCH) || \
+ defined(CONFIG_SYS_SMC_UCODE_PATCH)
+ cpm_load_patch (immr); /* load mpc8xx microcode patch */
+#endif
+}
+
+/*
+ * initialize higher level parts of CPU like timers
+ */
+int cpu_init_r (void)
+{
+#if defined(CONFIG_SYS_RTCSC) || defined(CONFIG_SYS_RMDS)
+ bd_t *bd = gd->bd;
+ volatile immap_t *immr = (volatile immap_t *) (bd->bi_immr_base);
+#endif
+
+#ifdef CONFIG_SYS_RTCSC
+ /* Unlock RTSC register */
+ immr->im_sitk.sitk_rtcsck = KAPWR_KEY;
+ /* write config value */
+ immr->im_sit.sit_rtcsc = CONFIG_SYS_RTCSC;
+#endif
+
+#ifdef CONFIG_SYS_RMDS
+ /* write config value */
+ immr->im_cpm.cp_rmds = CONFIG_SYS_RMDS;
+#endif
+ return (0);
+}
diff --git a/arch/powerpc/cpu/mpc8xx/fdt.c b/arch/powerpc/cpu/mpc8xx/fdt.c
new file mode 100644
index 0000000..7edd7e4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/fdt.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 (C) Bryan O'Donoghue
+ *
+ * Code copied & edited from Freescale mpc85xx stuff.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "timebase-frequency", get_tbclk(), 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "bus-frequency", bd->bi_busfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
+ "clock-frequency", bd->bi_intfreq, 1);
+ do_fixup_by_compat_u32(blob, "fsl,cpm-brg", "clock-frequency",
+ gd->arch.brg_clk, 1);
+
+ /* Fixup ethernet MAC addresses */
+ fdt_fixup_ethernet(blob);
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+}
diff --git a/arch/powerpc/cpu/mpc8xx/fec.c b/arch/powerpc/cpu/mpc8xx/fec.c
new file mode 100644
index 0000000..d7c9090
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/fec.c
@@ -0,0 +1,1029 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <commproc.h>
+#include <net.h>
+#include <command.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#undef ET_DEBUG
+
+#if defined(CONFIG_CMD_NET) && \
+ (defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FEC1) || defined(CONFIG_ETHER_ON_FEC2))
+
+/* compatibility test, if only FEC_ENET defined assume ETHER on FEC1 */
+#if defined(FEC_ENET) && !defined(CONFIG_ETHER_ON_FEC1) && !defined(CONFIG_ETHER_ON_FEC2)
+#define CONFIG_ETHER_ON_FEC1 1
+#endif
+
+/* define WANT_MII when MII support is required */
+#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_FEC1_PHY) || defined(CONFIG_FEC2_PHY)
+#define WANT_MII
+#else
+#undef WANT_MII
+#endif
+
+#if defined(WANT_MII)
+#include <miiphy.h>
+
+#if !(defined(CONFIG_MII) || defined(CONFIG_CMD_MII))
+#error "CONFIG_MII has to be defined!"
+#endif
+
+#endif
+
+#if defined(CONFIG_RMII) && !defined(WANT_MII)
+#error RMII support is unusable without a working PHY.
+#endif
+
+#ifdef CONFIG_SYS_DISCOVER_PHY
+static int mii_discover_phy(struct eth_device *dev);
+#endif
+
+int fec8xx_miiphy_read(const char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value);
+int fec8xx_miiphy_write(const char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value);
+
+static struct ether_fcc_info_s
+{
+ int ether_index;
+ int fecp_offset;
+ int phy_addr;
+ int actual_phy_addr;
+ int initialized;
+}
+ ether_fcc_info[] = {
+#if defined(CONFIG_ETHER_ON_FEC1)
+ {
+ 0,
+ offsetof(immap_t, im_cpm.cp_fec1),
+#if defined(CONFIG_FEC1_PHY)
+ CONFIG_FEC1_PHY,
+#else
+ -1, /* discover */
+#endif
+ -1,
+ 0,
+
+ },
+#endif
+#if defined(CONFIG_ETHER_ON_FEC2)
+ {
+ 1,
+ offsetof(immap_t, im_cpm.cp_fec2),
+#if defined(CONFIG_FEC2_PHY)
+ CONFIG_FEC2_PHY,
+#else
+ -1,
+#endif
+ -1,
+ 0,
+ },
+#endif
+};
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH 1520
+
+#define TX_BUF_CNT 2
+
+#define TOUT_LOOP 100
+
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+#define PKT_MAXBLR_SIZE 1520
+
+#ifdef __GNUC__
+static char txbuf[DBUF_LENGTH] __attribute__ ((aligned(8)));
+#else
+#error txbuf must be aligned.
+#endif
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * FEC Ethernet Tx and Rx buffer descriptors allocated at the
+ * immr->udata_bd address on Dual-Port RAM
+ * Provide for Double Buffering
+ */
+
+typedef volatile struct CommonBufferDescriptor {
+ cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
+ cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx = NULL;
+
+static int fec_send(struct eth_device *dev, void *packet, int length);
+static int fec_recv(struct eth_device* dev);
+static int fec_init(struct eth_device* dev, bd_t * bd);
+static void fec_halt(struct eth_device* dev);
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+static void __mii_init(void);
+#endif
+
+int fec_initialize(bd_t *bis)
+{
+ struct eth_device* dev;
+ struct ether_fcc_info_s *efis;
+ int i;
+
+ for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) {
+
+ dev = malloc(sizeof(*dev));
+ if (dev == NULL)
+ hang();
+
+ memset(dev, 0, sizeof(*dev));
+
+ /* for FEC1 make sure that the name of the interface is the same
+ as the old one for compatibility reasons */
+ if (i == 0) {
+ sprintf (dev->name, "FEC");
+ } else {
+ sprintf (dev->name, "FEC%d",
+ ether_fcc_info[i].ether_index + 1);
+ }
+
+ efis = &ether_fcc_info[i];
+
+ /*
+ * reset actual phy addr
+ */
+ efis->actual_phy_addr = -1;
+
+ dev->priv = efis;
+ dev->init = fec_init;
+ dev->halt = fec_halt;
+ dev->send = fec_send;
+ dev->recv = fec_recv;
+
+ eth_register(dev);
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+ miiphy_register(dev->name,
+ fec8xx_miiphy_read, fec8xx_miiphy_write);
+#endif
+ }
+ return 1;
+}
+
+static int fec_send(struct eth_device *dev, void *packet, int length)
+{
+ int j, rc;
+ struct ether_fcc_info_s *efis = dev->priv;
+ volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+
+ /* section 16.9.23.3
+ * Wait for ready
+ */
+ j = 0;
+ while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+ udelay(1);
+ j++;
+ }
+ if (j>=TOUT_LOOP) {
+ printf("TX not ready\n");
+ }
+
+ rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx->txbd[txIdx].cbd_datlen = length;
+ rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST;
+ __asm__ ("eieio");
+
+ /* Activate transmit Buffer Descriptor polling */
+ fecp->fec_x_des_active = 0x01000000; /* Descriptor polling active */
+
+ j = 0;
+ while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+#if defined(CONFIG_ICU862)
+ udelay(10);
+#else
+ udelay(1);
+#endif
+ j++;
+ }
+ if (j>=TOUT_LOOP) {
+ printf("TX timeout\n");
+ }
+#ifdef ET_DEBUG
+ printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n",
+ __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc,
+ (rtx->txbd[txIdx].cbd_sc & 0x003C)>>2);
+#endif
+ /* return only status bits */;
+ rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS);
+
+ txIdx = (txIdx + 1) % TX_BUF_CNT;
+
+ return rc;
+}
+
+static int fec_recv (struct eth_device *dev)
+{
+ struct ether_fcc_info_s *efis = dev->priv;
+ volatile fec_t *fecp =
+ (volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
+ int length;
+
+ for (;;) {
+ /* section 16.9.23.2 */
+ if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+
+ length = rtx->rxbd[rxIdx].cbd_datlen;
+
+ if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
+#ifdef ET_DEBUG
+ printf ("%s[%d] err: %x\n",
+ __FUNCTION__, __LINE__,
+ rtx->rxbd[rxIdx].cbd_sc);
+#endif
+ } else {
+ uchar *rx = NetRxPackets[rxIdx];
+
+ length -= 4;
+
+#if defined(CONFIG_CMD_CDP)
+ if ((rx[0] & 1) != 0
+ && memcmp ((uchar *) rx, NetBcastAddr, 6) != 0
+ && !is_cdp_packet((uchar *)rx))
+ rx = NULL;
+#endif
+ /*
+ * Pass the packet up to the protocol layers.
+ */
+ if (rx != NULL)
+ NetReceive (rx, length);
+ }
+
+ /* Give the buffer back to the FEC. */
+ rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
+ (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ } else {
+ rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+
+ __asm__ ("eieio");
+
+ /* Try to fill Buffer Descriptors */
+ fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */
+ }
+
+ return length;
+}
+
+/**************************************************************
+ *
+ * FEC Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+#define FEC_ECNTRL_PINMUX 0x00000004
+#define FEC_ECNTRL_ETHER_EN 0x00000002
+#define FEC_ECNTRL_RESET 0x00000001
+
+#define FEC_RCNTRL_BC_REJ 0x00000010
+#define FEC_RCNTRL_PROM 0x00000008
+#define FEC_RCNTRL_MII_MODE 0x00000004
+#define FEC_RCNTRL_DRT 0x00000002
+#define FEC_RCNTRL_LOOP 0x00000001
+
+#define FEC_TCNTRL_FDEN 0x00000004
+#define FEC_TCNTRL_HBC 0x00000002
+#define FEC_TCNTRL_GTS 0x00000001
+
+#define FEC_RESET_DELAY 50
+
+#if defined(CONFIG_RMII)
+
+static inline void fec_10Mbps(struct eth_device *dev)
+{
+ struct ether_fcc_info_s *efis = dev->priv;
+ int fecidx = efis->ether_index;
+ uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
+
+ if ((unsigned int)fecidx >= 2)
+ hang();
+
+ ((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr |= mask;
+}
+
+static inline void fec_100Mbps(struct eth_device *dev)
+{
+ struct ether_fcc_info_s *efis = dev->priv;
+ int fecidx = efis->ether_index;
+ uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008;
+
+ if ((unsigned int)fecidx >= 2)
+ hang();
+
+ ((volatile immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_cptr &= ~mask;
+}
+
+#endif
+
+static inline void fec_full_duplex(struct eth_device *dev)
+{
+ struct ether_fcc_info_s *efis = dev->priv;
+ volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+
+ fecp->fec_r_cntrl &= ~FEC_RCNTRL_DRT;
+ fecp->fec_x_cntrl |= FEC_TCNTRL_FDEN; /* FD enable */
+}
+
+static inline void fec_half_duplex(struct eth_device *dev)
+{
+ struct ether_fcc_info_s *efis = dev->priv;
+ volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+
+ fecp->fec_r_cntrl |= FEC_RCNTRL_DRT;
+ fecp->fec_x_cntrl &= ~FEC_TCNTRL_FDEN; /* FD disable */
+}
+
+static void fec_pin_init(int fecidx)
+{
+ bd_t *bd = gd->bd;
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ /*
+ * Set MII speed to 2.5 MHz or slightly below.
+ *
+ * According to the MPC860T (Rev. D) Fast ethernet controller user
+ * manual (6.2.14),
+ * the MII management interface clock must be less than or equal
+ * to 2.5 MHz.
+ * This MDC frequency is equal to system clock / (2 * MII_SPEED).
+ * Then MII_SPEED = system_clock / 2 * 2,5 MHz.
+ *
+ * All MII configuration is done via FEC1 registers:
+ */
+ immr->im_cpm.cp_fec1.fec_mii_speed = ((bd->bi_intfreq + 4999999) / 5000000) << 1;
+
+#if defined(CONFIG_NETTA) || defined(CONFIG_NETPHONE) || defined(CONFIG_NETTA2)
+ {
+ volatile fec_t *fecp;
+
+ /*
+ * only two FECs please
+ */
+ if ((unsigned int)fecidx >= 2)
+ hang();
+
+ if (fecidx == 0)
+ fecp = &immr->im_cpm.cp_fec1;
+ else
+ fecp = &immr->im_cpm.cp_fec2;
+
+ /* our PHYs are the limit at 2.5 MHz */
+ fecp->fec_mii_speed <<= 1;
+ }
+#endif
+
+#if defined(CONFIG_MPC885_FAMILY) && defined(WANT_MII)
+ /* use MDC for MII */
+ immr->im_ioport.iop_pdpar |= 0x0080;
+ immr->im_ioport.iop_pddir &= ~0x0080;
+#endif
+
+ if (fecidx == 0) {
+#if defined(CONFIG_ETHER_ON_FEC1)
+
+#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
+
+#if !defined(CONFIG_RMII)
+
+ immr->im_ioport.iop_papar |= 0xf830;
+ immr->im_ioport.iop_padir |= 0x0830;
+ immr->im_ioport.iop_padir &= ~0xf000;
+
+ immr->im_cpm.cp_pbpar |= 0x00001001;
+ immr->im_cpm.cp_pbdir &= ~0x00001001;
+
+ immr->im_ioport.iop_pcpar |= 0x000c;
+ immr->im_ioport.iop_pcdir &= ~0x000c;
+
+ immr->im_cpm.cp_pepar |= 0x00000003;
+ immr->im_cpm.cp_pedir |= 0x00000003;
+ immr->im_cpm.cp_peso &= ~0x00000003;
+
+ immr->im_cpm.cp_cptr &= ~0x00000100;
+
+#else
+
+#if !defined(CONFIG_FEC1_PHY_NORXERR)
+ immr->im_ioport.iop_papar |= 0x1000;
+ immr->im_ioport.iop_padir &= ~0x1000;
+#endif
+ immr->im_ioport.iop_papar |= 0xe810;
+ immr->im_ioport.iop_padir |= 0x0810;
+ immr->im_ioport.iop_padir &= ~0xe000;
+
+ immr->im_cpm.cp_pbpar |= 0x00000001;
+ immr->im_cpm.cp_pbdir &= ~0x00000001;
+
+ immr->im_cpm.cp_cptr |= 0x00000100;
+ immr->im_cpm.cp_cptr &= ~0x00000050;
+
+#endif /* !CONFIG_RMII */
+
+#elif !defined(CONFIG_ICU862)
+ /*
+ * Configure all of port D for MII.
+ */
+ immr->im_ioport.iop_pdpar = 0x1fff;
+
+ /*
+ * Bits moved from Rev. D onward
+ */
+ if ((get_immr(0) & 0xffff) < 0x0501)
+ immr->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */
+ else
+ immr->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */
+#else
+ /*
+ * Configure port A for MII.
+ */
+
+#if defined(CONFIG_ICU862) && defined(CONFIG_SYS_DISCOVER_PHY)
+
+ /*
+ * On the ICU862 board the MII-MDC pin is routed to PD8 pin
+ * * of CPU, so for this board we need to configure Utopia and
+ * * enable PD8 to MII-MDC function
+ */
+ immr->im_ioport.iop_pdpar |= 0x4080;
+#endif
+
+ /*
+ * Has Utopia been configured?
+ */
+ if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) {
+ /*
+ * YES - Use MUXED mode for UTOPIA bus.
+ * This frees Port A for use by MII (see 862UM table 41-6).
+ */
+ immr->im_ioport.utmode &= ~0x80;
+ } else {
+ /*
+ * NO - set SPLIT mode for UTOPIA bus.
+ *
+ * This doesn't really effect UTOPIA (which isn't
+ * enabled anyway) but just tells the 862
+ * to use port A for MII (see 862UM table 41-6).
+ */
+ immr->im_ioport.utmode |= 0x80;
+ }
+#endif /* !defined(CONFIG_ICU862) */
+
+#endif /* CONFIG_ETHER_ON_FEC1 */
+ } else if (fecidx == 1) {
+
+#if defined(CONFIG_ETHER_ON_FEC2)
+
+#if defined(CONFIG_MPC885_FAMILY) /* MPC87x/88x have got 2 FECs and different pinout */
+
+#if !defined(CONFIG_RMII)
+ immr->im_cpm.cp_pepar |= 0x0003fffc;
+ immr->im_cpm.cp_pedir |= 0x0003fffc;
+ immr->im_cpm.cp_peso &= ~0x000087fc;
+ immr->im_cpm.cp_peso |= 0x00037800;
+
+ immr->im_cpm.cp_cptr &= ~0x00000080;
+#else
+
+#if !defined(CONFIG_FEC2_PHY_NORXERR)
+ immr->im_cpm.cp_pepar |= 0x00000010;
+ immr->im_cpm.cp_pedir |= 0x00000010;
+ immr->im_cpm.cp_peso &= ~0x00000010;
+#endif
+ immr->im_cpm.cp_pepar |= 0x00039620;
+ immr->im_cpm.cp_pedir |= 0x00039620;
+ immr->im_cpm.cp_peso |= 0x00031000;
+ immr->im_cpm.cp_peso &= ~0x00008620;
+
+ immr->im_cpm.cp_cptr |= 0x00000080;
+ immr->im_cpm.cp_cptr &= ~0x00000028;
+#endif /* CONFIG_RMII */
+
+#endif /* CONFIG_MPC885_FAMILY */
+
+#endif /* CONFIG_ETHER_ON_FEC2 */
+
+ }
+}
+
+static int fec_reset(volatile fec_t *fecp)
+{
+ int i;
+
+ /* Whack a reset.
+ * A delay is required between a reset of the FEC block and
+ * initialization of other FEC registers because the reset takes
+ * some time to complete. If you don't delay, subsequent writes
+ * to FEC registers might get killed by the reset routine which is
+ * still in progress.
+ */
+
+ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+ for (i = 0;
+ (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+ ++i) {
+ udelay (1);
+ }
+ if (i == FEC_RESET_DELAY)
+ return -1;
+
+ return 0;
+}
+
+static int fec_init (struct eth_device *dev, bd_t * bd)
+{
+ struct ether_fcc_info_s *efis = dev->priv;
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ volatile fec_t *fecp =
+ (volatile fec_t *) (CONFIG_SYS_IMMR + efis->fecp_offset);
+ int i;
+
+ if (efis->ether_index == 0) {
+#if defined(CONFIG_FADS) /* FADS family uses FPGA (BCSR) to control PHYs */
+#if defined(CONFIG_MPC885ADS)
+ *(vu_char *) BCSR5 &= ~(BCSR5_MII1_EN | BCSR5_MII1_RST);
+#else
+ /* configure FADS for fast (FEC) ethernet, half-duplex */
+ /* The LXT970 needs about 50ms to recover from reset, so
+ * wait for it by discovering the PHY before leaving eth_init().
+ */
+ {
+ volatile uint *bcsr4 = (volatile uint *) BCSR4;
+
+ *bcsr4 = (*bcsr4 & ~(BCSR4_FETH_EN | BCSR4_FETHCFG1))
+ | (BCSR4_FETHCFG0 | BCSR4_FETHFDE |
+ BCSR4_FETHRST);
+
+ /* reset the LXT970 PHY */
+ *bcsr4 &= ~BCSR4_FETHRST;
+ udelay (10);
+ *bcsr4 |= BCSR4_FETHRST;
+ udelay (10);
+ }
+#endif /* CONFIG_MPC885ADS */
+#endif /* CONFIG_FADS */
+ }
+
+#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+ /* the MII interface is connected to FEC1
+ * so for the miiphy_xxx function to work we must
+ * call mii_init since fec_halt messes the thing up
+ */
+ if (efis->ether_index != 0)
+ __mii_init();
+#endif
+
+ if (fec_reset(fecp) < 0)
+ printf ("FEC_RESET_DELAY timeout\n");
+
+ /* We use strictly polling mode only
+ */
+ fecp->fec_imask = 0;
+
+ /* Clear any pending interrupt
+ */
+ fecp->fec_ievent = 0xffc0;
+
+ /* No need to set the IVEC register */
+
+ /* Set station address
+ */
+#define ea dev->enetaddr
+ fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | (ea[3]);
+ fecp->fec_addr_high = (ea[4] << 8) | (ea[5]);
+#undef ea
+
+#if defined(CONFIG_CMD_CDP)
+ /*
+ * Turn on multicast address hash table
+ */
+ fecp->fec_hash_table_high = 0xffffffff;
+ fecp->fec_hash_table_low = 0xffffffff;
+#else
+ /* Clear multicast address hash table
+ */
+ fecp->fec_hash_table_high = 0;
+ fecp->fec_hash_table_low = 0;
+#endif
+
+ /* Set maximum receive buffer size.
+ */
+ fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+
+ /* Set maximum frame length
+ */
+ fecp->fec_r_hash = PKT_MAXBUF_SIZE;
+
+ /*
+ * Setup Buffers and Buffer Desriptors
+ */
+ rxIdx = 0;
+ txIdx = 0;
+
+ if (!rtx) {
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+ rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
+ dpram_alloc_align (sizeof (RTXBD), 8));
+#else
+ rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE);
+#endif
+ }
+ /*
+ * Setup Receiver Buffer Descriptors (13.14.24.18)
+ * Settings:
+ * Empty, Wrap
+ */
+ for (i = 0; i < PKTBUFSRX; i++) {
+ rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ rtx->rxbd[i].cbd_datlen = 0; /* Reset */
+ rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+ }
+ rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /*
+ * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+ * Settings:
+ * Last, Tx CRC
+ */
+ for (i = 0; i < TX_BUF_CNT; i++) {
+ rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC;
+ rtx->txbd[i].cbd_datlen = 0; /* Reset */
+ rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
+ }
+ rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /* Set receive and transmit descriptor base
+ */
+ fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
+ fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
+
+ /* Enable MII mode
+ */
+#if 0 /* Full duplex mode */
+ fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE;
+ fecp->fec_x_cntrl = FEC_TCNTRL_FDEN;
+#else /* Half duplex mode */
+ fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT;
+ fecp->fec_x_cntrl = 0;
+#endif
+
+ /* Enable big endian and don't care about SDMA FC.
+ */
+ fecp->fec_fun_code = 0x78000000;
+
+ /*
+ * Setup the pin configuration of the FEC
+ */
+ fec_pin_init (efis->ether_index);
+
+ rxIdx = 0;
+ txIdx = 0;
+
+ /*
+ * Now enable the transmit and receive processing
+ */
+ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
+
+ if (efis->phy_addr == -1) {
+#ifdef CONFIG_SYS_DISCOVER_PHY
+ /*
+ * wait for the PHY to wake up after reset
+ */
+ efis->actual_phy_addr = mii_discover_phy (dev);
+
+ if (efis->actual_phy_addr == -1) {
+ printf ("Unable to discover phy!\n");
+ return -1;
+ }
+#else
+ efis->actual_phy_addr = -1;
+#endif
+ } else {
+ efis->actual_phy_addr = efis->phy_addr;
+ }
+
+#if defined(CONFIG_MII) && defined(CONFIG_RMII)
+ /*
+ * adapt the RMII speed to the speed of the phy
+ */
+ if (miiphy_speed (dev->name, efis->actual_phy_addr) == _100BASET) {
+ fec_100Mbps (dev);
+ } else {
+ fec_10Mbps (dev);
+ }
+#endif
+
+#if defined(CONFIG_MII)
+ /*
+ * adapt to the half/full speed settings
+ */
+ if (miiphy_duplex (dev->name, efis->actual_phy_addr) == FULL) {
+ fec_full_duplex (dev);
+ } else {
+ fec_half_duplex (dev);
+ }
+#endif
+
+ /* And last, try to fill Rx Buffer Descriptors */
+ fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */
+
+ efis->initialized = 1;
+
+ return 0;
+}
+
+
+static void fec_halt(struct eth_device* dev)
+{
+ struct ether_fcc_info_s *efis = dev->priv;
+ volatile fec_t *fecp = (volatile fec_t *)(CONFIG_SYS_IMMR + efis->fecp_offset);
+ int i;
+
+ /* avoid halt if initialized; mii gets stuck otherwise */
+ if (!efis->initialized)
+ return;
+
+ /* Whack a reset.
+ * A delay is required between a reset of the FEC block and
+ * initialization of other FEC registers because the reset takes
+ * some time to complete. If you don't delay, subsequent writes
+ * to FEC registers might get killed by the reset routine which is
+ * still in progress.
+ */
+
+ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+ for (i = 0;
+ (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+ ++i) {
+ udelay (1);
+ }
+ if (i == FEC_RESET_DELAY) {
+ printf ("FEC_RESET_DELAY timeout\n");
+ return;
+ }
+
+ efis->initialized = 0;
+}
+
+#if defined(CONFIG_SYS_DISCOVER_PHY) || defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
+
+/* Make MII read/write commands for the FEC.
+*/
+
+#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \
+ (REG & 0x1f) << 18))
+
+#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
+ (REG & 0x1f) << 18) | \
+ (VAL & 0xffff))
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
+#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
+#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
+#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
+#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
+#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
+#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
+#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
+#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
+#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
+
+/* PHY identification
+ */
+#define PHY_ID_LXT970 0x78100000 /* LXT970 */
+#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */
+#define PHY_ID_82555 0x02a80150 /* Intel 82555 */
+#define PHY_ID_QS6612 0x01814400 /* QS6612 */
+#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */
+#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */
+#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */
+#define PHY_ID_DM9161 0x0181B880 /* Davicom DM9161 */
+#define PHY_ID_KSM8995M 0x00221450 /* MICREL KS8995MA */
+
+/* send command to phy using mii, wait for result */
+static uint
+mii_send(uint mii_cmd)
+{
+ uint mii_reply;
+ volatile fec_t *ep;
+ int cnt;
+
+ ep = &(((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_fec);
+
+ ep->fec_mii_data = mii_cmd; /* command to phy */
+
+ /* wait for mii complete */
+ cnt = 0;
+ while (!(ep->fec_ievent & FEC_ENET_MII)) {
+ if (++cnt > 1000) {
+ printf("mii_send STUCK!\n");
+ break;
+ }
+ }
+ mii_reply = ep->fec_mii_data; /* result from phy */
+ ep->fec_ievent = FEC_ENET_MII; /* clear MII complete */
+#if 0
+ printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
+ __FILE__,__LINE__,__FUNCTION__,mii_cmd,mii_reply);
+#endif
+ return (mii_reply & 0xffff); /* data read from phy */
+}
+#endif
+
+#if defined(CONFIG_SYS_DISCOVER_PHY)
+static int mii_discover_phy(struct eth_device *dev)
+{
+#define MAX_PHY_PASSES 11
+ uint phyno;
+ int pass;
+ uint phytype;
+ int phyaddr;
+
+ phyaddr = -1; /* didn't find a PHY yet */
+ for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) {
+ if (pass > 1) {
+ /* PHY may need more time to recover from reset.
+ * The LXT970 needs 50ms typical, no maximum is
+ * specified, so wait 10ms before try again.
+ * With 11 passes this gives it 100ms to wake up.
+ */
+ udelay(10000); /* wait 10ms */
+ }
+ for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) {
+ phytype = mii_send(mk_mii_read(phyno, MII_PHYSID2));
+#ifdef ET_DEBUG
+ printf("PHY type 0x%x pass %d type ", phytype, pass);
+#endif
+ if (phytype != 0xffff) {
+ phyaddr = phyno;
+ phytype |= mii_send(mk_mii_read(phyno,
+ MII_PHYSID1)) << 16;
+
+#ifdef ET_DEBUG
+ printf("PHY @ 0x%x pass %d type ",phyno,pass);
+ switch (phytype & 0xfffffff0) {
+ case PHY_ID_LXT970:
+ printf("LXT970\n");
+ break;
+ case PHY_ID_LXT971:
+ printf("LXT971\n");
+ break;
+ case PHY_ID_82555:
+ printf("82555\n");
+ break;
+ case PHY_ID_QS6612:
+ printf("QS6612\n");
+ break;
+ case PHY_ID_AMD79C784:
+ printf("AMD79C784\n");
+ break;
+ case PHY_ID_LSI80225B:
+ printf("LSI L80225/B\n");
+ break;
+ case PHY_ID_DM9161:
+ printf("Davicom DM9161\n");
+ break;
+ case PHY_ID_KSM8995M:
+ printf("MICREL KS8995M\n");
+ break;
+ default:
+ printf("0x%08x\n", phytype);
+ break;
+ }
+#endif
+ }
+ }
+ }
+ if (phyaddr < 0) {
+ printf("No PHY device found.\n");
+ }
+ return phyaddr;
+}
+#endif /* CONFIG_SYS_DISCOVER_PHY */
+
+#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) && !defined(CONFIG_BITBANGMII)
+
+/****************************************************************************
+ * mii_init -- Initialize the MII via FEC 1 for MII command without ethernet
+ * This function is a subset of eth_init
+ ****************************************************************************
+ */
+static void __mii_init(void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+
+ if (fec_reset(fecp) < 0)
+ printf ("FEC_RESET_DELAY timeout\n");
+
+ /* We use strictly polling mode only
+ */
+ fecp->fec_imask = 0;
+
+ /* Clear any pending interrupt
+ */
+ fecp->fec_ievent = 0xffc0;
+
+ /* Now enable the transmit and receive processing
+ */
+ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN;
+}
+
+void mii_init (void)
+{
+ int i;
+
+ __mii_init();
+
+ /* Setup the pin configuration of the FEC(s)
+ */
+ for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+ fec_pin_init(ether_fcc_info[i].ether_index);
+}
+
+/*****************************************************************************
+ * Read and write a MII PHY register, routines used by MII Utilities
+ *
+ * FIXME: These routines are expected to return 0 on success, but mii_send
+ * does _not_ return an error code. Maybe 0xFFFF means error, i.e.
+ * no PHY connected...
+ * For now always return 0.
+ * FIXME: These routines only work after calling eth_init() at least once!
+ * Otherwise they hang in mii_send() !!! Sorry!
+ *****************************************************************************/
+
+int fec8xx_miiphy_read(const char *devname, unsigned char addr,
+ unsigned char reg, unsigned short *value)
+{
+ short rdreg; /* register working value */
+
+#ifdef MII_DEBUG
+ printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr);
+#endif
+ rdreg = mii_send(mk_mii_read(addr, reg));
+
+ *value = rdreg;
+#ifdef MII_DEBUG
+ printf ("0x%04x\n", *value);
+#endif
+ return 0;
+}
+
+int fec8xx_miiphy_write(const char *devname, unsigned char addr,
+ unsigned char reg, unsigned short value)
+{
+#ifdef MII_DEBUG
+ printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
+#endif
+ (void)mii_send(mk_mii_write(addr, reg, value));
+
+#ifdef MII_DEBUG
+ printf ("0x%04x\n", value);
+#endif
+ return 0;
+}
+#endif
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/fec.h b/arch/powerpc/cpu/mpc8xx/fec.h
new file mode 100644
index 0000000..a49417c
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/fec.h
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _FEC_H_
+#define _FEC_H_
+
+
+#endif /* _FEC_H_ */
diff --git a/arch/powerpc/cpu/mpc8xx/i2c.c b/arch/powerpc/cpu/mpc8xx/i2c.c
new file mode 100644
index 0000000..3e5ea3a
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/i2c.c
@@ -0,0 +1,704 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Back ported to the 8xx platform (from the 8260 platform) by
+ * Murray.Jensen@cmst.csiro.au, 27-Jan-01.
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_HARD_I2C
+
+#include <commproc.h>
+#include <i2c.h>
+#ifdef CONFIG_LWMON
+#include <watchdog.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* tx/rx timeout (we need the i2c early, so we don't use get_timer()) */
+#define TOUT_LOOP 1000000
+
+#define NUM_RX_BDS 4
+#define NUM_TX_BDS 4
+#define MAX_TX_SPACE 256
+#define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */
+
+typedef struct I2C_BD {
+ unsigned short status;
+ unsigned short length;
+ unsigned char *addr;
+} I2C_BD;
+
+#define BD_I2C_TX_START 0x0400 /* special status for i2c: Start condition */
+
+#define BD_I2C_TX_CL 0x0001 /* collision error */
+#define BD_I2C_TX_UN 0x0002 /* underflow error */
+#define BD_I2C_TX_NAK 0x0004 /* no acknowledge error */
+#define BD_I2C_TX_ERR (BD_I2C_TX_NAK|BD_I2C_TX_UN|BD_I2C_TX_CL)
+
+#define BD_I2C_RX_ERR BD_SC_OV
+
+typedef void (*i2c_ecb_t) (int, int); /* error callback function */
+
+/* This structure keeps track of the bd and buffer space usage. */
+typedef struct i2c_state {
+ int rx_idx; /* index to next free Rx BD */
+ int tx_idx; /* index to next free Tx BD */
+ void *rxbd; /* pointer to next free Rx BD */
+ void *txbd; /* pointer to next free Tx BD */
+ int tx_space; /* number of Tx bytes left */
+ unsigned char *tx_buf; /* pointer to free Tx area */
+ i2c_ecb_t err_cb; /* error callback function */
+} i2c_state_t;
+
+
+/* flags for i2c_send() and i2c_receive() */
+#define I2CF_ENABLE_SECONDARY 0x01 /* secondary_address is valid */
+#define I2CF_START_COND 0x02 /* tx: generate start condition */
+#define I2CF_STOP_COND 0x04 /* tx: generate stop condition */
+
+/* return codes */
+#define I2CERR_NO_BUFFERS 0x01 /* no more BDs or buffer space */
+#define I2CERR_MSG_TOO_LONG 0x02 /* tried to send/receive to much data */
+#define I2CERR_TIMEOUT 0x03 /* timeout in i2c_doio() */
+#define I2CERR_QUEUE_EMPTY 0x04 /* i2c_doio called without send/receive */
+
+/* error callback flags */
+#define I2CECB_RX_ERR 0x10 /* this is a receive error */
+#define I2CECB_RX_ERR_OV 0x02 /* receive overrun error */
+#define I2CECB_RX_MASK 0x0f /* mask for error bits */
+#define I2CECB_TX_ERR 0x20 /* this is a transmit error */
+#define I2CECB_TX_CL 0x01 /* transmit collision error */
+#define I2CECB_TX_UN 0x02 /* transmit underflow error */
+#define I2CECB_TX_NAK 0x04 /* transmit no ack error */
+#define I2CECB_TX_MASK 0x0f /* mask for error bits */
+#define I2CECB_TIMEOUT 0x40 /* this is a timeout error */
+
+/*
+ * Returns the best value of I2BRG to meet desired clock speed of I2C with
+ * input parameters (clock speed, filter, and predivider value).
+ * It returns computer speed value and the difference between it and desired
+ * speed.
+ */
+static inline int
+i2c_roundrate(int hz, int speed, int filter, int modval,
+ int *brgval, int *totspeed)
+{
+ int moddiv = 1 << (5 - (modval & 3)), brgdiv, div;
+
+ debug("\t[I2C] trying hz=%d, speed=%d, filter=%d, modval=%d\n",
+ hz, speed, filter, modval);
+
+ div = moddiv * speed;
+ brgdiv = (hz + div - 1) / div;
+
+ debug("\t\tmoddiv=%d, brgdiv=%d\n", moddiv, brgdiv);
+
+ *brgval = ((brgdiv + 1) / 2) - 3 - (2 * filter);
+
+ if ((*brgval < 0) || (*brgval > 255)) {
+ debug("\t\trejected brgval=%d\n", *brgval);
+ return -1;
+ }
+
+ brgdiv = 2 * (*brgval + 3 + (2 * filter));
+ div = moddiv * brgdiv;
+ *totspeed = hz / div;
+
+ debug("\t\taccepted brgval=%d, totspeed=%d\n", *brgval, *totspeed);
+
+ return 0;
+}
+
+/*
+ * Sets the I2C clock predivider and divider to meet required clock speed.
+ */
+static int i2c_setrate(int hz, int speed)
+{
+ immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile i2c8xx_t *i2c = (i2c8xx_t *) & immap->im_i2c;
+ int brgval,
+ modval, /* 0-3 */
+ bestspeed_diff = speed,
+ bestspeed_brgval = 0,
+ bestspeed_modval = 0,
+ bestspeed_filter = 0,
+ totspeed,
+ filter = 0; /* Use this fixed value */
+
+ for (modval = 0; modval < 4; modval++) {
+ if (i2c_roundrate
+ (hz, speed, filter, modval, &brgval, &totspeed) == 0) {
+ int diff = speed - totspeed;
+
+ if ((diff >= 0) && (diff < bestspeed_diff)) {
+ bestspeed_diff = diff;
+ bestspeed_modval = modval;
+ bestspeed_brgval = brgval;
+ bestspeed_filter = filter;
+ }
+ }
+ }
+
+ debug("[I2C] Best is:\n");
+ debug("[I2C] CPU=%dhz RATE=%d F=%d I2MOD=%08x I2BRG=%08x DIFF=%dhz\n",
+ hz,
+ speed,
+ bestspeed_filter,
+ bestspeed_modval,
+ bestspeed_brgval,
+ bestspeed_diff);
+
+ i2c->i2c_i2mod |=
+ ((bestspeed_modval & 3) << 1) | (bestspeed_filter << 3);
+ i2c->i2c_i2brg = bestspeed_brgval & 0xff;
+
+ debug("[I2C] i2mod=%08x i2brg=%08x\n",
+ i2c->i2c_i2mod,
+ i2c->i2c_i2brg);
+
+ return 1;
+}
+
+void i2c_init(int speed, int slaveaddr)
+{
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
+ volatile i2c8xx_t *i2c = (i2c8xx_t *)&immap->im_i2c;
+ volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+ ulong rbase, tbase;
+ volatile I2C_BD *rxbd, *txbd;
+ uint dpaddr;
+
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+ /* call board specific i2c bus reset routine before accessing the */
+ /* environment, which might be in a chip on that bus. For details */
+ /* about this problem see doc/I2C_Edge_Conditions. */
+ i2c_init_board();
+#endif
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+ iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#else
+ /* Disable relocation */
+ iip->iic_rpbase = 0;
+#endif
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+ dpaddr = iip->iic_rbase;
+ if (dpaddr == 0) {
+ /* need to allocate dual port ram */
+ dpaddr = dpram_alloc_align((NUM_RX_BDS * sizeof(I2C_BD)) +
+ (NUM_TX_BDS * sizeof(I2C_BD)) +
+ MAX_TX_SPACE, 8);
+ }
+#else
+ dpaddr = CPM_I2C_BASE;
+#endif
+
+ /*
+ * initialise data in dual port ram:
+ *
+ * dpaddr->rbase -> rx BD (NUM_RX_BDS * sizeof(I2C_BD) bytes)
+ * tbase -> tx BD (NUM_TX_BDS * sizeof(I2C_BD) bytes)
+ * tx buffer (MAX_TX_SPACE bytes)
+ */
+
+ rbase = dpaddr;
+ tbase = rbase + NUM_RX_BDS * sizeof(I2C_BD);
+
+ /* Initialize Port B I2C pins. */
+ cp->cp_pbpar |= 0x00000030;
+ cp->cp_pbdir |= 0x00000030;
+ cp->cp_pbodr |= 0x00000030;
+
+ /* Disable interrupts */
+ i2c->i2c_i2mod = 0x00;
+ i2c->i2c_i2cmr = 0x00;
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2add = slaveaddr;
+
+ /*
+ * Set the I2C BRG Clock division factor from desired i2c rate
+ * and current CPU rate (we assume sccr dfbgr field is 0;
+ * divide BRGCLK by 1)
+ */
+ debug("[I2C] Setting rate...\n");
+ i2c_setrate(gd->cpu_clk, CONFIG_SYS_I2C_SPEED);
+
+ /* Set I2C controller in master mode */
+ i2c->i2c_i2com = 0x01;
+
+ /* Set SDMA bus arbitration level to 5 (SDCR) */
+ immap->im_siu_conf.sc_sdcr = 0x0001;
+
+ /* Initialize Tx/Rx parameters */
+ iip->iic_rbase = rbase;
+ iip->iic_tbase = tbase;
+ rxbd = (I2C_BD *) ((unsigned char *) &cp->cp_dpmem[iip->iic_rbase]);
+ txbd = (I2C_BD *) ((unsigned char *) &cp->cp_dpmem[iip->iic_tbase]);
+
+ debug("[I2C] rbase = %04x\n", iip->iic_rbase);
+ debug("[I2C] tbase = %04x\n", iip->iic_tbase);
+ debug("[I2C] rxbd = %08x\n", (int)rxbd);
+ debug("[I2C] txbd = %08x\n", (int)txbd);
+
+ /* Set big endian byte order */
+ iip->iic_tfcr = 0x10;
+ iip->iic_rfcr = 0x10;
+
+ /* Set maximum receive size. */
+ iip->iic_mrblr = I2C_RXTX_LEN;
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+ /*
+ * Initialize required parameters if using microcode patch.
+ */
+ iip->iic_rbptr = iip->iic_rbase;
+ iip->iic_tbptr = iip->iic_tbase;
+ iip->iic_rstate = 0;
+ iip->iic_tstate = 0;
+#else
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ do {
+ __asm__ __volatile__("eieio");
+ } while (cp->cp_cpcr & CPM_CR_FLG);
+#endif
+
+ /* Clear events and interrupts */
+ i2c->i2c_i2cer = 0xff;
+ i2c->i2c_i2cmr = 0x00;
+}
+
+static void i2c_newio(i2c_state_t *state)
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
+ volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+
+ debug("[I2C] i2c_newio\n");
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+ iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#endif
+ state->rx_idx = 0;
+ state->tx_idx = 0;
+ state->rxbd = (void *)&cp->cp_dpmem[iip->iic_rbase];
+ state->txbd = (void *)&cp->cp_dpmem[iip->iic_tbase];
+ state->tx_space = MAX_TX_SPACE;
+ state->tx_buf = (uchar *)state->txbd + NUM_TX_BDS * sizeof(I2C_BD);
+ state->err_cb = NULL;
+
+ debug("[I2C] rxbd = %08x\n", (int)state->rxbd);
+ debug("[I2C] txbd = %08x\n", (int)state->txbd);
+ debug("[I2C] tx_buf = %08x\n", (int)state->tx_buf);
+
+ /* clear the buffer memory */
+ memset((char *)state->tx_buf, 0, MAX_TX_SPACE);
+}
+
+static int
+i2c_send(i2c_state_t *state,
+ unsigned char address,
+ unsigned char secondary_address,
+ unsigned int flags, unsigned short size, unsigned char *dataout)
+{
+ volatile I2C_BD *txbd;
+ int i, j;
+
+ debug("[I2C] i2c_send add=%02d sec=%02d flag=%02d size=%d\n",
+ address, secondary_address, flags, size);
+
+ /* trying to send message larger than BD */
+ if (size > I2C_RXTX_LEN)
+ return I2CERR_MSG_TOO_LONG;
+
+ /* no more free bds */
+ if (state->tx_idx >= NUM_TX_BDS || state->tx_space < (2 + size))
+ return I2CERR_NO_BUFFERS;
+
+ txbd = (I2C_BD *) state->txbd;
+ txbd->addr = state->tx_buf;
+
+ debug("[I2C] txbd = %08x\n", (int)txbd);
+
+ if (flags & I2CF_START_COND) {
+ debug("[I2C] Formatting addresses...\n");
+ if (flags & I2CF_ENABLE_SECONDARY) {
+ /* Length of msg + dest addr */
+ txbd->length = size + 2;
+
+ txbd->addr[0] = address << 1;
+ txbd->addr[1] = secondary_address;
+ i = 2;
+ } else {
+ /* Length of msg + dest addr */
+ txbd->length = size + 1;
+ /* Write dest addr to BD */
+ txbd->addr[0] = address << 1;
+ i = 1;
+ }
+ } else {
+ txbd->length = size; /* Length of message */
+ i = 0;
+ }
+
+ /* set up txbd */
+ txbd->status = BD_SC_READY;
+ if (flags & I2CF_START_COND)
+ txbd->status |= BD_I2C_TX_START;
+ if (flags & I2CF_STOP_COND)
+ txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+
+ /* Copy data to send into buffer */
+ debug("[I2C] copy data...\n");
+ for(j = 0; j < size; i++, j++)
+ txbd->addr[i] = dataout[j];
+
+ debug("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+ txbd->length,
+ txbd->status,
+ txbd->addr[0],
+ txbd->addr[1]);
+
+ /* advance state */
+ state->tx_buf += txbd->length;
+ state->tx_space -= txbd->length;
+ state->tx_idx++;
+ state->txbd = (void *) (txbd + 1);
+
+ return 0;
+}
+
+static int
+i2c_receive(i2c_state_t *state,
+ unsigned char address,
+ unsigned char secondary_address,
+ unsigned int flags,
+ unsigned short size_to_expect, unsigned char *datain)
+{
+ volatile I2C_BD *rxbd, *txbd;
+
+ debug("[I2C] i2c_receive %02d %02d %02d\n",
+ address, secondary_address, flags);
+
+ /* Expected to receive too much */
+ if (size_to_expect > I2C_RXTX_LEN)
+ return I2CERR_MSG_TOO_LONG;
+
+ /* no more free bds */
+ if (state->tx_idx >= NUM_TX_BDS || state->rx_idx >= NUM_RX_BDS
+ || state->tx_space < 2)
+ return I2CERR_NO_BUFFERS;
+
+ rxbd = (I2C_BD *) state->rxbd;
+ txbd = (I2C_BD *) state->txbd;
+
+ debug("[I2C] rxbd = %08x\n", (int)rxbd);
+ debug("[I2C] txbd = %08x\n", (int)txbd);
+
+ txbd->addr = state->tx_buf;
+
+ /* set up TXBD for destination address */
+ if (flags & I2CF_ENABLE_SECONDARY) {
+ txbd->length = 2;
+ txbd->addr[0] = address << 1; /* Write data */
+ txbd->addr[1] = secondary_address; /* Internal address */
+ txbd->status = BD_SC_READY;
+ } else {
+ txbd->length = 1 + size_to_expect;
+ txbd->addr[0] = (address << 1) | 0x01;
+ txbd->status = BD_SC_READY;
+ memset(&txbd->addr[1], 0, txbd->length);
+ }
+
+ /* set up rxbd for reception */
+ rxbd->status = BD_SC_EMPTY;
+ rxbd->length = size_to_expect;
+ rxbd->addr = datain;
+
+ txbd->status |= BD_I2C_TX_START;
+ if (flags & I2CF_STOP_COND) {
+ txbd->status |= BD_SC_LAST | BD_SC_WRAP;
+ rxbd->status |= BD_SC_WRAP;
+ }
+
+ debug("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+ txbd->length,
+ txbd->status,
+ txbd->addr[0],
+ txbd->addr[1]);
+ debug("[I2C] rxbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n",
+ rxbd->length,
+ rxbd->status,
+ rxbd->addr[0],
+ rxbd->addr[1]);
+
+ /* advance state */
+ state->tx_buf += txbd->length;
+ state->tx_space -= txbd->length;
+ state->tx_idx++;
+ state->txbd = (void *) (txbd + 1);
+ state->rx_idx++;
+ state->rxbd = (void *) (rxbd + 1);
+
+ return 0;
+}
+
+
+static int i2c_doio(i2c_state_t *state)
+{
+ volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cp = (cpm8xx_t *)&immap->im_cpm;
+ volatile i2c8xx_t *i2c = (i2c8xx_t *)&immap->im_i2c;
+ volatile iic_t *iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
+ volatile I2C_BD *txbd, *rxbd;
+ volatile int j = 0;
+
+ debug("[I2C] i2c_doio\n");
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+ iip = (iic_t *)&cp->cp_dpmem[iip->iic_rpbase];
+#endif
+
+ if (state->tx_idx <= 0 && state->rx_idx <= 0) {
+ debug("[I2C] No I/O is queued\n");
+ return I2CERR_QUEUE_EMPTY;
+ }
+
+ iip->iic_rbptr = iip->iic_rbase;
+ iip->iic_tbptr = iip->iic_tbase;
+
+ /* Enable I2C */
+ debug("[I2C] Enabling I2C...\n");
+ i2c->i2c_i2mod |= 0x01;
+
+ /* Begin transmission */
+ i2c->i2c_i2com |= 0x80;
+
+ /* Loop until transmit & receive completed */
+
+ if (state->tx_idx > 0) {
+ txbd = ((I2C_BD*)state->txbd) - 1;
+
+ debug("[I2C] Transmitting...(txbd=0x%08lx)\n",
+ (ulong)txbd);
+
+ while ((txbd->status & BD_SC_READY) && (j++ < TOUT_LOOP)) {
+ if (ctrlc())
+ return (-1);
+
+ __asm__ __volatile__("eieio");
+ }
+ }
+
+ if ((state->rx_idx > 0) && (j < TOUT_LOOP)) {
+ rxbd = ((I2C_BD*)state->rxbd) - 1;
+
+ debug("[I2C] Receiving...(rxbd=0x%08lx)\n",
+ (ulong)rxbd);
+
+ while ((rxbd->status & BD_SC_EMPTY) && (j++ < TOUT_LOOP)) {
+ if (ctrlc())
+ return (-1);
+
+ __asm__ __volatile__("eieio");
+ }
+ }
+
+ /* Turn off I2C */
+ i2c->i2c_i2mod &= ~0x01;
+
+ if (state->err_cb != NULL) {
+ int n, i, b;
+
+ /*
+ * if we have an error callback function, look at the
+ * error bits in the bd status and pass them back
+ */
+
+ if ((n = state->tx_idx) > 0) {
+ for (i = 0; i < n; i++) {
+ txbd = ((I2C_BD *) state->txbd) - (n - i);
+ if ((b = txbd->status & BD_I2C_TX_ERR) != 0)
+ (*state->err_cb) (I2CECB_TX_ERR | b,
+ i);
+ }
+ }
+
+ if ((n = state->rx_idx) > 0) {
+ for (i = 0; i < n; i++) {
+ rxbd = ((I2C_BD *) state->rxbd) - (n - i);
+ if ((b = rxbd->status & BD_I2C_RX_ERR) != 0)
+ (*state->err_cb) (I2CECB_RX_ERR | b,
+ i);
+ }
+ }
+
+ if (j >= TOUT_LOOP)
+ (*state->err_cb) (I2CECB_TIMEOUT, 0);
+ }
+
+ return (j >= TOUT_LOOP) ? I2CERR_TIMEOUT : 0;
+}
+
+static int had_tx_nak;
+
+static void i2c_test_callback(int flags, int xnum)
+{
+ if ((flags & I2CECB_TX_ERR) && (flags & I2CECB_TX_NAK))
+ had_tx_nak = 1;
+}
+
+int i2c_probe(uchar chip)
+{
+ i2c_state_t state;
+ int rc;
+ uchar buf[1];
+
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+ i2c_newio(&state);
+
+ state.err_cb = i2c_test_callback;
+ had_tx_nak = 0;
+
+ rc = i2c_receive(&state, chip, 0, I2CF_START_COND | I2CF_STOP_COND, 1,
+ buf);
+
+ if (rc != 0)
+ return (rc);
+
+ rc = i2c_doio(&state);
+
+ if ((rc != 0) && (rc != I2CERR_TIMEOUT))
+ return (rc);
+
+ return (had_tx_nak);
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ i2c_state_t state;
+ uchar xaddr[4];
+ int rc;
+
+#ifdef CONFIG_LWMON
+ WATCHDOG_RESET();
+#endif
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+ /*
+ * EEPROM chips that implement "address overflow" are ones like
+ * Catalyst 24WC04/08/16 which has 9/10/11 bits of address and the
+ * extra bits end up in the "chip address" bit slots. This makes
+ * a 24WC08 (1Kbyte) chip look like four 256 byte chips.
+ *
+ * Note that we consider the length of the address field to still
+ * be one byte because the extra address bits are hidden in the
+ * chip address.
+ */
+ chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+ i2c_newio(&state);
+
+ rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen,
+ &xaddr[4 - alen]);
+ if (rc != 0) {
+ printf("i2c_read: i2c_send failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer);
+ if (rc != 0) {
+ printf("i2c_read: i2c_receive failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_doio(&state);
+ if (rc != 0) {
+ printf("i2c_read: i2c_doio failed (%d)\n", rc);
+ return 1;
+ }
+ return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+ i2c_state_t state;
+ uchar xaddr[4];
+ int rc;
+
+ xaddr[0] = (addr >> 24) & 0xFF;
+ xaddr[1] = (addr >> 16) & 0xFF;
+ xaddr[2] = (addr >> 8) & 0xFF;
+ xaddr[3] = addr & 0xFF;
+
+#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
+ /*
+ * EEPROM chips that implement "address overflow" are ones like
+ * Catalyst 24WC04/08/16 which has 9/10/11 bits of address and the
+ * extra bits end up in the "chip address" bit slots. This makes
+ * a 24WC08 (1Kbyte) chip look like four 256 byte chips.
+ *
+ * Note that we consider the length of the address field to still
+ * be one byte because the extra address bits are hidden in the
+ * chip address.
+ */
+ chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
+#endif
+
+ i2c_newio(&state);
+
+ rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen,
+ &xaddr[4 - alen]);
+ if (rc != 0) {
+ printf("i2c_write: first i2c_send failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer);
+ if (rc != 0) {
+ printf("i2c_write: second i2c_send failed (%d)\n", rc);
+ return 1;
+ }
+
+ rc = i2c_doio(&state);
+ if (rc != 0) {
+ printf("i2c_write: i2c_doio failed (%d)\n", rc);
+ return 1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_HARD_I2C */
diff --git a/arch/powerpc/cpu/mpc8xx/interrupts.c b/arch/powerpc/cpu/mpc8xx/interrupts.c
new file mode 100644
index 0000000..5daa6b2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/interrupts.c
@@ -0,0 +1,294 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <mpc8xx_irq.h>
+#include <asm/processor.h>
+#include <commproc.h>
+
+/************************************************************************/
+
+/*
+ * CPM interrupt vector functions.
+ */
+struct interrupt_action {
+ interrupt_handler_t *handler;
+ void *arg;
+};
+
+static struct interrupt_action cpm_vecs[CPMVEC_NR];
+static struct interrupt_action irq_vecs[NR_IRQS];
+
+static void cpm_interrupt_init (void);
+static void cpm_interrupt (void *regs);
+
+/************************************************************************/
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ *decrementer_count = get_tbclk () / CONFIG_SYS_HZ;
+
+ /* disable all interrupts */
+ immr->im_siu_conf.sc_simask = 0;
+
+ /* Configure CPM interrupts */
+ cpm_interrupt_init ();
+
+ return (0);
+}
+
+/************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt (struct pt_regs *regs)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ int irq;
+ ulong simask, newmask;
+ ulong vec, v_bit;
+
+ /*
+ * read the SIVEC register and shift the bits down
+ * to get the irq number
+ */
+ vec = immr->im_siu_conf.sc_sivec;
+ irq = vec >> 26;
+ v_bit = 0x80000000UL >> irq;
+
+ /*
+ * Read Interrupt Mask Register and Mask Interrupts
+ */
+ simask = immr->im_siu_conf.sc_simask;
+ newmask = simask & (~(0xFFFF0000 >> irq));
+ immr->im_siu_conf.sc_simask = newmask;
+
+ if (!(irq & 0x1)) { /* External Interrupt ? */
+ ulong siel;
+
+ /*
+ * Read Interrupt Edge/Level Register
+ */
+ siel = immr->im_siu_conf.sc_siel;
+
+ if (siel & v_bit) { /* edge triggered interrupt ? */
+ /*
+ * Rewrite SIPEND Register to clear interrupt
+ */
+ immr->im_siu_conf.sc_sipend = v_bit;
+ }
+ }
+
+ if (irq_vecs[irq].handler != NULL) {
+ irq_vecs[irq].handler (irq_vecs[irq].arg);
+ } else {
+ printf ("\nBogus External Interrupt IRQ %d Vector %ld\n",
+ irq, vec);
+ /* turn off the bogus interrupt to avoid it from now */
+ simask &= ~v_bit;
+ }
+ /*
+ * Re-Enable old Interrupt Mask
+ */
+ immr->im_siu_conf.sc_simask = simask;
+}
+
+/************************************************************************/
+
+/*
+ * CPM interrupt handler
+ */
+static void cpm_interrupt (void *regs)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ uint vec;
+
+ /*
+ * Get the vector by setting the ACK bit
+ * and then reading the register.
+ */
+ immr->im_cpic.cpic_civr = 1;
+ vec = immr->im_cpic.cpic_civr;
+ vec >>= 11;
+
+ if (cpm_vecs[vec].handler != NULL) {
+ (*cpm_vecs[vec].handler) (cpm_vecs[vec].arg);
+ } else {
+ immr->im_cpic.cpic_cimr &= ~(1 << vec);
+ printf ("Masking bogus CPM interrupt vector 0x%x\n", vec);
+ }
+ /*
+ * After servicing the interrupt,
+ * we have to remove the status indicator.
+ */
+ immr->im_cpic.cpic_cisr |= (1 << vec);
+}
+
+/*
+ * The CPM can generate the error interrupt when there is a race
+ * condition between generating and masking interrupts. All we have
+ * to do is ACK it and return. This is a no-op function so we don't
+ * need any special tests in the interrupt handler.
+ */
+static void cpm_error_interrupt (void *dummy)
+{
+}
+
+/************************************************************************/
+/*
+ * Install and free an interrupt handler
+ */
+void irq_install_handler (int vec, interrupt_handler_t * handler,
+ void *arg)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ if ((vec & CPMVEC_OFFSET) != 0) {
+ /* CPM interrupt */
+ vec &= 0xffff;
+ if (cpm_vecs[vec].handler != NULL) {
+ printf ("CPM interrupt 0x%x replacing 0x%x\n",
+ (uint) handler,
+ (uint) cpm_vecs[vec].handler);
+ }
+ cpm_vecs[vec].handler = handler;
+ cpm_vecs[vec].arg = arg;
+ immr->im_cpic.cpic_cimr |= (1 << vec);
+#if 0
+ printf ("Install CPM interrupt for vector %d ==> %p\n",
+ vec, handler);
+#endif
+ } else {
+ /* SIU interrupt */
+ if (irq_vecs[vec].handler != NULL) {
+ printf ("SIU interrupt %d 0x%x replacing 0x%x\n",
+ vec,
+ (uint) handler,
+ (uint) cpm_vecs[vec].handler);
+ }
+ irq_vecs[vec].handler = handler;
+ irq_vecs[vec].arg = arg;
+ immr->im_siu_conf.sc_simask |= 1 << (31 - vec);
+#if 0
+ printf ("Install SIU interrupt for vector %d ==> %p\n",
+ vec, handler);
+#endif
+ }
+}
+
+void irq_free_handler (int vec)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ if ((vec & CPMVEC_OFFSET) != 0) {
+ /* CPM interrupt */
+ vec &= 0xffff;
+#if 0
+ printf ("Free CPM interrupt for vector %d ==> %p\n",
+ vec, cpm_vecs[vec].handler);
+#endif
+ immr->im_cpic.cpic_cimr &= ~(1 << vec);
+ cpm_vecs[vec].handler = NULL;
+ cpm_vecs[vec].arg = NULL;
+ } else {
+ /* SIU interrupt */
+#if 0
+ printf ("Free CPM interrupt for vector %d ==> %p\n",
+ vec, cpm_vecs[vec].handler);
+#endif
+ immr->im_siu_conf.sc_simask &= ~(1 << (31 - vec));
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
+ }
+}
+
+/************************************************************************/
+
+static void cpm_interrupt_init (void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ /*
+ * Initialize the CPM interrupt controller.
+ */
+
+ immr->im_cpic.cpic_cicr =
+ (CICR_SCD_SCC4 |
+ CICR_SCC_SCC3 |
+ CICR_SCB_SCC2 |
+ CICR_SCA_SCC1) | ((CPM_INTERRUPT / 2) << 13) | CICR_HP_MASK;
+
+ immr->im_cpic.cpic_cimr = 0;
+
+ /*
+ * Install the error handler.
+ */
+ irq_install_handler (CPMVEC_ERROR, cpm_error_interrupt, NULL);
+
+ immr->im_cpic.cpic_cicr |= CICR_IEN;
+
+ /*
+ * Install the cpm interrupt handler
+ */
+ irq_install_handler (CPM_INTERRUPT, cpm_interrupt, NULL);
+}
+
+/************************************************************************/
+
+/*
+ * timer_interrupt - gets called when the decrementer overflows,
+ * with interrupts disabled.
+ * Trivial implementation - no need to be really accurate.
+ */
+void timer_interrupt_cpu (struct pt_regs *regs)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if 0
+ printf ("*** Timer Interrupt *** ");
+#endif
+ /* Reset Timer Expired and Timers Interrupt Status */
+ immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+ __asm__ ("nop");
+ /*
+ Clear TEXPS (and TMIST on older chips). SPLSS (on older
+ chips) is cleared too.
+
+ Bitwise OR is a read-modify-write operation so ALL bits
+ which are cleared by writing `1' would be cleared by
+ operations like
+
+ immr->im_clkrst.car_plprcr |= PLPRCR_TEXPS;
+
+ The same can be achieved by simple writing of the PLPRCR
+ to itself. If a bit value should be preserved, read the
+ register, ZERO the bit and write, not OR, the result back.
+ */
+ immr->im_clkrst.car_plprcr = immr->im_clkrst.car_plprcr;
+}
+
+/************************************************************************/
diff --git a/arch/powerpc/cpu/mpc8xx/kgdb.S b/arch/powerpc/cpu/mpc8xx/kgdb.S
new file mode 100644
index 0000000..2cc8fe6
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/kgdb.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2000 Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <mpc8xx.h>
+#include <version.h>
+
+#define CONFIG_8xx 1 /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+
+ /*
+ * cache flushing routines for kgdb
+ */
+
+ .globl kgdb_flush_cache_all
+kgdb_flush_cache_all:
+ lis r3, IDC_INVALL@h
+ mtspr DC_CST, r3
+ sync
+ lis r3, IDC_INVALL@h
+ mtspr IC_CST, r3
+ SYNC
+ blr
+
+ .globl kgdb_flush_cache_range
+kgdb_flush_cache_range:
+ li r5,CONFIG_SYS_CACHELINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,CONFIG_SYS_CACHELINE_SHIFT
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CONFIG_SYS_CACHELINE_SIZE
+ bdnz 2b
+ SYNC
+ blr
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/plprcr_write.S b/arch/powerpc/cpu/mpc8xx/plprcr_write.S
new file mode 100644
index 0000000..e325671
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/plprcr_write.S
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <mpc8xx.h>
+#include <ppc_asm.tmpl>
+#include <asm/cache.h>
+
+#define CACHE_CMD_ENABLE 0x02000000
+#define CACHE_CMD_DISABLE 0x04000000
+#define CACHE_CMD_LOAD_LOCK 0x06000000
+#define CACHE_CMD_UNLOCK_LINE 0x08000000
+#define CACHE_CMD_UNLOCK_ALL 0x0A000000
+#define CACHE_CMD_INVALIDATE 0x0C000000
+#define SPEED_PLPRCR_WAIT_5CYC 150
+#define _CACHE_ALIGN_SIZE 16
+
+
+ .text
+ .align 2
+ .globl plprcr_write_866
+
+/*
+ * void plprcr_write_866 (long plprcr)
+ * Write PLPRCR, including workaround for device errata SIU4 and SIU9.
+ */
+
+plprcr_write_866:
+ mfspr r10, LR /* save the Link Register value */
+
+ /* turn instruction cache on (no MMU required for instructions)
+ */
+ lis r4, CACHE_CMD_ENABLE@h
+ ori r4, r4, CACHE_CMD_ENABLE@l
+ mtspr IC_CST, r4
+ isync
+
+ /* clear IC_CST error bits
+ */
+ mfspr r4, IC_CST
+
+ bl plprcr_here
+
+plprcr_here:
+ mflr r5
+
+ /* calculate relocation offset
+ */
+ lis r4, plprcr_here@h
+ ori r4, r4, plprcr_here@l
+ sub r5, r5, r4
+
+ /* calculate first address of this function
+ */
+ lis r6, plprcr_write_866@h
+ ori r6, r6, plprcr_write_866@l
+ add r6, r6, r5
+
+ /* calculate end address of this function
+ */
+ lis r7, plprcr_end@h
+ ori r7, r7, plprcr_end@l
+ add r7, r7, r5
+
+ /* load and lock code addresses
+ */
+ mr r5, r6
+
+plprcr_loop:
+ mtspr IC_ADR, r5
+ addi r5, r5, _CACHE_ALIGN_SIZE /* increment by one line */
+
+ lis r4, CACHE_CMD_LOAD_LOCK@h
+ ori r4, r4, CACHE_CMD_LOAD_LOCK@l
+ mtspr IC_CST, r4
+ isync
+
+ cmpw r5, r7
+ blt plprcr_loop
+
+ /* IC_CST error bits not evaluated
+ */
+
+ /* switch PLPRCR
+ */
+ mfspr r4, IMMR /* read IMMR */
+ rlwinm r4, r4, 0, 0, 15 /* only high 16 bits count */
+
+ /* write sequence according to MPC866 Errata
+ */
+ stw r3, PLPRCR(r4)
+ isync
+
+ lis r3, SPEED_PLPRCR_WAIT_5CYC@h
+ ori r3, r3, SPEED_PLPRCR_WAIT_5CYC@l
+
+plprcr_wait:
+ cmpwi r3, 0
+ beq plprcr_wait_end
+ nop
+ subi r3, r3, 1
+ b plprcr_wait
+
+plprcr_wait_end:
+
+ /* unlock instruction cache but leave it enabled
+ */
+ lis r4, CACHE_CMD_UNLOCK_ALL@h
+ ori r4, r4, CACHE_CMD_UNLOCK_ALL@l
+ mtspr IC_CST, r4
+ isync
+
+ mtspr LR, r10 /* restore original Link Register value */
+ blr
+
+plprcr_end:
diff --git a/arch/powerpc/cpu/mpc8xx/scc.c b/arch/powerpc/cpu/mpc8xx/scc.c
new file mode 100644
index 0000000..2ef77b4
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/scc.c
@@ -0,0 +1,558 @@
+/*
+ * File: scc.c
+ * Description:
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * NOTE <<<IMPORTANT: PLEASE READ>>>:
+ * Do not cache Rx/Tx buffers!
+ */
+
+/*
+ * MPC823 <-> MC68160 Connections:
+ *
+ * Setup MPC823 to work with MC68160 Enhanced Ethernet
+ * Serial Tranceiver as follows:
+ *
+ * MPC823 Signal MC68160 Comments
+ * ------ ------ ------- --------
+ * PA-12 ETHTX --------> TX Eth. Port Transmit Data
+ * PB-18 E_TENA --------> TENA Eth. Transmit Port Enable
+ * PA-5 ETHTCK <-------- TCLK Eth. Port Transmit Clock
+ * PA-13 ETHRX <-------- RX Eth. Port Receive Data
+ * PC-8 E_RENA <-------- RENA Eth. Receive Enable
+ * PA-6 ETHRCK <-------- RCLK Eth. Port Receive Clock
+ * PC-9 E_CLSN <-------- CLSN Eth. Port Collision Indication
+ *
+ * FADS Board Signal MC68160 Comments
+ * ----------------- ------- --------
+ * (BCSR1) ETHEN* --------> CS2 Eth. Port Enable
+ * (BSCR4) TPSQEL* --------> TPSQEL Twisted Pair Signal Quality Error Test Enable
+ * (BCSR4) TPFLDL* --------> TPFLDL Twisted Pair Full-Duplex
+ * (BCSR4) ETHLOOP --------> LOOP Eth. Port Diagnostic Loop-Back
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <commproc.h>
+#include <net.h>
+#include <command.h>
+
+#if defined(CONFIG_CMD_NET) && defined(SCC_ENET)
+
+/* Ethernet Transmit and Receive Buffers */
+#define DBUF_LENGTH 1520
+
+#define TX_BUF_CNT 2
+
+#define TOUT_LOOP 10000 /* 10 ms to have a packet sent */
+
+static char txbuf[DBUF_LENGTH];
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * SCC Ethernet Tx and Rx buffer descriptors allocated at the
+ * immr->udata_bd address on Dual-Port RAM
+ * Provide for Double Buffering
+ */
+
+typedef volatile struct CommonBufferDescriptor {
+ cbd_t rxbd[PKTBUFSRX]; /* Rx BD */
+ cbd_t txbd[TX_BUF_CNT]; /* Tx BD */
+} RTXBD;
+
+static RTXBD *rtx;
+
+static int scc_send(struct eth_device *dev, void *packet, int length);
+static int scc_recv(struct eth_device* dev);
+static int scc_init (struct eth_device* dev, bd_t * bd);
+static void scc_halt(struct eth_device* dev);
+
+int scc_initialize(bd_t *bis)
+{
+ struct eth_device* dev;
+
+ dev = (struct eth_device*) malloc(sizeof *dev);
+ memset(dev, 0, sizeof *dev);
+
+ sprintf(dev->name, "SCC");
+ dev->iobase = 0;
+ dev->priv = 0;
+ dev->init = scc_init;
+ dev->halt = scc_halt;
+ dev->send = scc_send;
+ dev->recv = scc_recv;
+
+ eth_register(dev);
+
+ return 1;
+}
+
+static int scc_send(struct eth_device *dev, void *packet, int length)
+{
+ int i, j=0;
+#if 0
+ volatile char *in, *out;
+#endif
+
+ /* section 16.9.23.3
+ * Wait for ready
+ */
+#if 0
+ while (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY);
+ out = (char *)(rtx->txbd[txIdx].cbd_bufaddr);
+ in = packet;
+ for(i = 0; i < length; i++) {
+ *out++ = *in++;
+ }
+ rtx->txbd[txIdx].cbd_datlen = length;
+ rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST);
+ while (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) j++;
+
+#ifdef ET_DEBUG
+ printf("cycles: %d status: %x\n", j, rtx->txbd[txIdx].cbd_sc);
+#endif
+ i = (rtx->txbd[txIdx++].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */;
+
+ /* wrap around buffer index when necessary */
+ if (txIdx >= TX_BUF_CNT) txIdx = 0;
+#endif
+
+ while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+ udelay (1); /* will also trigger Wd if needed */
+ j++;
+ }
+ if (j>=TOUT_LOOP) printf("TX not ready\n");
+ rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx->txbd[txIdx].cbd_datlen = length;
+ rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |BD_ENET_TX_WRAP);
+ while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+ udelay (1); /* will also trigger Wd if needed */
+ j++;
+ }
+ if (j>=TOUT_LOOP) printf("TX timeout\n");
+#ifdef ET_DEBUG
+ printf("cycles: %d status: %x\n", j, rtx->txbd[txIdx].cbd_sc);
+#endif
+ i = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */;
+ return i;
+}
+
+static int scc_recv (struct eth_device *dev)
+{
+ int length;
+
+ for (;;) {
+ /* section 16.9.23.2 */
+ if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+
+ length = rtx->rxbd[rxIdx].cbd_datlen;
+
+ if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
+#ifdef ET_DEBUG
+ printf ("err: %x\n", rtx->rxbd[rxIdx].cbd_sc);
+#endif
+ } else {
+ /* Pass the packet up to the protocol layers. */
+ NetReceive (NetRxPackets[rxIdx], length - 4);
+ }
+
+
+ /* Give the buffer back to the SCC. */
+ rtx->rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx->rxbd[PKTBUFSRX - 1].cbd_sc =
+ (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ } else {
+ rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+ }
+ return length;
+}
+
+/**************************************************************
+ *
+ * SCC Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+static int scc_init (struct eth_device *dev, bd_t * bis)
+{
+
+ int i;
+ scc_enet_t *pram_ptr;
+
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if defined(CONFIG_LWMON)
+ reset_phy();
+#endif
+
+#ifdef CONFIG_FADS
+#if defined(CONFIG_MPC86xADS) || defined(CONFIG_MPC860T)
+ /* The MPC86xADS/FADS860T don't use the MODEM_EN or DATA_VOICE signals. */
+ *((uint *) BCSR4) &= ~BCSR4_ETHLOOP;
+ *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL;
+ *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#else
+ *((uint *) BCSR4) &= ~(BCSR4_ETHLOOP | BCSR4_MODEM_EN);
+ *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL | BCSR4_DATA_VOICE;
+ *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif
+#endif
+
+ pram_ptr = (scc_enet_t *) & (immr->im_cpm.cp_dparam[PROFF_ENET]);
+
+ rxIdx = 0;
+ txIdx = 0;
+
+ if (!rtx) {
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+ rtx = (RTXBD *) (immr->im_cpm.cp_dpmem +
+ dpram_alloc_align (sizeof (RTXBD), 8));
+#else
+ rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_SCC_BASE);
+#endif
+ }
+
+#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
+ /* Configure port A pins for Txd and Rxd.
+ */
+ immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
+ immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
+ immr->im_ioport.iop_paodr &= ~PA_ENET_TXD;
+#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
+ /* Configure port B pins for Txd and Rxd.
+ */
+ immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD);
+ immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
+ immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD;
+#else
+#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
+#endif
+
+#if defined(PC_ENET_LBK)
+ /* Configure port C pins to disable External Loopback
+ */
+ immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
+ immr->im_ioport.iop_pcdir |= PC_ENET_LBK;
+ immr->im_ioport.iop_pcso &= ~PC_ENET_LBK;
+ immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK; /* Disable Loopback */
+#endif /* PC_ENET_LBK */
+
+ /* Configure port C pins to enable CLSN and RENA.
+ */
+ immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+ immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+ immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
+
+ /* Configure port A for TCLK and RCLK.
+ */
+ immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
+ immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
+
+ /*
+ * Configure Serial Interface clock routing -- see section 16.7.5.3
+ * First, clear all SCC bits to zero, then set the ones we want.
+ */
+
+ immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK;
+ immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT;
+
+
+ /*
+ * Initialize SDCR -- see section 16.9.23.7
+ * SDMA configuration register
+ */
+ immr->im_siu_conf.sc_sdcr = 0x01;
+
+
+ /*
+ * Setup SCC Ethernet Parameter RAM
+ */
+
+ pram_ptr->sen_genscc.scc_rfcr = 0x18; /* Normal Operation and Mot byte ordering */
+ pram_ptr->sen_genscc.scc_tfcr = 0x18; /* Mot byte ordering, Normal access */
+
+ pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH; /* max. ET package len 1520 */
+
+ pram_ptr->sen_genscc.scc_rbase = (unsigned int) (&rtx->rxbd[0]); /* Set RXBD tbl start at Dual Port */
+ pram_ptr->sen_genscc.scc_tbase = (unsigned int) (&rtx->txbd[0]); /* Set TXBD tbl start at Dual Port */
+
+ /*
+ * Setup Receiver Buffer Descriptors (13.14.24.18)
+ * Settings:
+ * Empty, Wrap
+ */
+
+ for (i = 0; i < PKTBUFSRX; i++) {
+ rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ rtx->rxbd[i].cbd_datlen = 0; /* Reset */
+ rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+ }
+
+ rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /*
+ * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+ * Settings:
+ * Add PADs to Short FRAMES, Wrap, Last, Tx CRC
+ */
+
+ for (i = 0; i < TX_BUF_CNT; i++) {
+ rtx->txbd[i].cbd_sc =
+ (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+ rtx->txbd[i].cbd_datlen = 0; /* Reset */
+ rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]);
+ }
+
+ rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /*
+ * Enter Command: Initialize Rx Params for SCC
+ */
+
+ do { /* Spin until ready to issue command */
+ __asm__ ("eieio");
+ } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+ /* Issue command */
+ immr->im_cpm.cp_cpcr =
+ ((CPM_CR_INIT_RX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG);
+ do { /* Spin until command processed */
+ __asm__ ("eieio");
+ } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+ /*
+ * Ethernet Specific Parameter RAM
+ * see table 13-16, pg. 660,
+ * pg. 681 (example with suggested settings)
+ */
+
+ pram_ptr->sen_cpres = ~(0x0); /* Preset CRC */
+ pram_ptr->sen_cmask = 0xdebb20e3; /* Constant Mask for CRC */
+ pram_ptr->sen_crcec = 0x0; /* Error Counter CRC (unused) */
+ pram_ptr->sen_alec = 0x0; /* Alignment Error Counter (unused) */
+ pram_ptr->sen_disfc = 0x0; /* Discard Frame Counter (unused) */
+ pram_ptr->sen_pads = 0x8888; /* Short Frame PAD Characters */
+
+ pram_ptr->sen_retlim = 15; /* Retry Limit Threshold */
+ pram_ptr->sen_maxflr = 1518; /* MAX Frame Length Register */
+ pram_ptr->sen_minflr = 64; /* MIN Frame Length Register */
+
+ pram_ptr->sen_maxd1 = DBUF_LENGTH; /* MAX DMA1 Length Register */
+ pram_ptr->sen_maxd2 = DBUF_LENGTH; /* MAX DMA2 Length Register */
+
+ pram_ptr->sen_gaddr1 = 0x0; /* Group Address Filter 1 (unused) */
+ pram_ptr->sen_gaddr2 = 0x0; /* Group Address Filter 2 (unused) */
+ pram_ptr->sen_gaddr3 = 0x0; /* Group Address Filter 3 (unused) */
+ pram_ptr->sen_gaddr4 = 0x0; /* Group Address Filter 4 (unused) */
+
+#define ea eth_get_dev()->enetaddr
+ pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
+ pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
+ pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+
+ pram_ptr->sen_pper = 0x0; /* Persistence (unused) */
+ pram_ptr->sen_iaddr1 = 0x0; /* Individual Address Filter 1 (unused) */
+ pram_ptr->sen_iaddr2 = 0x0; /* Individual Address Filter 2 (unused) */
+ pram_ptr->sen_iaddr3 = 0x0; /* Individual Address Filter 3 (unused) */
+ pram_ptr->sen_iaddr4 = 0x0; /* Individual Address Filter 4 (unused) */
+ pram_ptr->sen_taddrh = 0x0; /* Tmp Address (MSB) (unused) */
+ pram_ptr->sen_taddrm = 0x0; /* Tmp Address (unused) */
+ pram_ptr->sen_taddrl = 0x0; /* Tmp Address (LSB) (unused) */
+
+ /*
+ * Enter Command: Initialize Tx Params for SCC
+ */
+
+ do { /* Spin until ready to issue command */
+ __asm__ ("eieio");
+ } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+ /* Issue command */
+ immr->im_cpm.cp_cpcr =
+ ((CPM_CR_INIT_TX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG);
+ do { /* Spin until command processed */
+ __asm__ ("eieio");
+ } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
+
+ /*
+ * Mask all Events in SCCM - we use polling mode
+ */
+ immr->im_cpm.cp_scc[SCC_ENET].scc_sccm = 0;
+
+ /*
+ * Clear Events in SCCE -- Clear bits by writing 1's
+ */
+
+ immr->im_cpm.cp_scc[SCC_ENET].scc_scce = ~(0x0);
+
+
+ /*
+ * Initialize GSMR High 32-Bits
+ * Settings: Normal Mode
+ */
+
+ immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrh = 0;
+
+ /*
+ * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive
+ * Settings:
+ * TCI = Invert
+ * TPL = 48 bits
+ * TPP = Repeating 10's
+ * MODE = Ethernet
+ */
+
+ immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl = (SCC_GSMRL_TCI |
+ SCC_GSMRL_TPL_48 |
+ SCC_GSMRL_TPP_10 |
+ SCC_GSMRL_MODE_ENET);
+
+ /*
+ * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4
+ */
+
+ immr->im_cpm.cp_scc[SCC_ENET].scc_dsr = 0xd555;
+
+ /*
+ * Initialize the PSMR
+ * Settings:
+ * CRC = 32-Bit CCITT
+ * NIB = Begin searching for SFD 22 bits after RENA
+ * FDE = Full Duplex Enable
+ * LPB = Loopback Enable (Needed when FDE is set)
+ * BRO = Reject broadcast packets
+ * PROMISCOUS = Catch all packets regardless of dest. MAC adress
+ */
+ immr->im_cpm.cp_scc[SCC_ENET].scc_psmr = SCC_PSMR_ENCRC |
+ SCC_PSMR_NIB22 |
+#if defined(CONFIG_SCC_ENET_FULL_DUPLEX)
+ SCC_PSMR_FDE | SCC_PSMR_LPB |
+#endif
+#if defined(CONFIG_SCC_ENET_NO_BROADCAST)
+ SCC_PSMR_BRO |
+#endif
+#if defined(CONFIG_SCC_ENET_PROMISCOUS)
+ SCC_PSMR_PRO |
+#endif
+ 0;
+
+ /*
+ * Configure Ethernet TENA Signal
+ */
+
+#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA))
+ immr->im_ioport.iop_pcpar |= PC_ENET_TENA;
+ immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA))
+ immr->im_cpm.cp_pbpar |= PB_ENET_TENA;
+ immr->im_cpm.cp_pbdir |= PB_ENET_TENA;
+#else
+#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined
+#endif
+
+#if defined(CONFIG_ADS) && defined(CONFIG_MPC860)
+ /*
+ * Port C is used to control the PHY,MC68160.
+ */
+ immr->im_ioport.iop_pcdir |=
+ (PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL);
+
+ immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL;
+ immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL);
+ *((uint *) BCSR1) &= ~BCSR1_ETHEN;
+#endif /* MPC860ADS */
+
+#ifdef CONFIG_RPXCLASSIC
+ *((uchar *) BCSR0) &= ~BCSR0_ETHLPBK;
+ *((uchar *) BCSR0) |= (BCSR0_ETHEN | BCSR0_COLTEST | BCSR0_FULLDPLX);
+#endif
+
+#ifdef CONFIG_RPXLITE
+ *((uchar *) BCSR0) |= BCSR0_ETHEN;
+#endif
+
+#if defined(CONFIG_QS860T)
+ /*
+ * PB27=FDE-, set output low for full duplex
+ * PB26=Link Test Enable, normally high output
+ */
+ immr->im_cpm.cp_pbdir |= 0x00000030;
+ immr->im_cpm.cp_pbdat |= 0x00000020;
+ immr->im_cpm.cp_pbdat &= ~0x00000010;
+#endif /* QS860T */
+
+#ifdef CONFIG_MBX
+ board_ether_init ();
+#endif
+
+#if defined(CONFIG_NETVIA)
+#if defined(PA_ENET_PDN)
+ immr->im_ioport.iop_papar &= ~PA_ENET_PDN;
+ immr->im_ioport.iop_padir |= PA_ENET_PDN;
+ immr->im_ioport.iop_padat |= PA_ENET_PDN;
+#elif defined(PB_ENET_PDN)
+ immr->im_cpm.cp_pbpar &= ~PB_ENET_PDN;
+ immr->im_cpm.cp_pbdir |= PB_ENET_PDN;
+ immr->im_cpm.cp_pbdat |= PB_ENET_PDN;
+#elif defined(PC_ENET_PDN)
+ immr->im_ioport.iop_pcpar &= ~PC_ENET_PDN;
+ immr->im_ioport.iop_pcdir |= PC_ENET_PDN;
+ immr->im_ioport.iop_pcdat |= PC_ENET_PDN;
+#elif defined(PD_ENET_PDN)
+ immr->im_ioport.iop_pdpar &= ~PD_ENET_PDN;
+ immr->im_ioport.iop_pddir |= PD_ENET_PDN;
+ immr->im_ioport.iop_pddat |= PD_ENET_PDN;
+#endif
+#endif
+
+ /*
+ * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive
+ */
+
+ immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |=
+ (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /*
+ * Work around transmit problem with first eth packet
+ */
+#if defined (CONFIG_FADS)
+ udelay (10000); /* wait 10 ms */
+#elif defined(CONFIG_RPXCLASSIC)
+ udelay (100000); /* wait 100 ms */
+#endif
+
+ return 1;
+}
+
+
+static void scc_halt (struct eth_device *dev)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &=
+ ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ immr->im_ioport.iop_pcso &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+}
+
+#if 0
+void restart (void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+ immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |=
+ (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+#endif
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/serial.c b/arch/powerpc/cpu/mpc8xx/serial.c
new file mode 100644
index 0000000..00888e9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/serial.c
@@ -0,0 +1,766 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <commproc.h>
+#include <command.h>
+#include <serial.h>
+#include <watchdog.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_8xx_CONS_NONE) /* No Console at all */
+
+#if defined(CONFIG_8xx_CONS_SMC1) /* Console on SMC1 */
+#define SMC_INDEX 0
+#define PROFF_SMC PROFF_SMC1
+#define CPM_CR_CH_SMC CPM_CR_CH_SMC1
+
+#elif defined(CONFIG_8xx_CONS_SMC2) /* Console on SMC2 */
+#define SMC_INDEX 1
+#define PROFF_SMC PROFF_SMC2
+#define CPM_CR_CH_SMC CPM_CR_CH_SMC2
+
+#endif /* CONFIG_8xx_CONS_SMCx */
+
+#if defined(CONFIG_8xx_CONS_SCC1) /* Console on SCC1 */
+#define SCC_INDEX 0
+#define PROFF_SCC PROFF_SCC1
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC1
+
+#elif defined(CONFIG_8xx_CONS_SCC2) /* Console on SCC2 */
+#define SCC_INDEX 1
+#define PROFF_SCC PROFF_SCC2
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC2
+
+#elif defined(CONFIG_8xx_CONS_SCC3) /* Console on SCC3 */
+#define SCC_INDEX 2
+#define PROFF_SCC PROFF_SCC3
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC3
+
+#elif defined(CONFIG_8xx_CONS_SCC4) /* Console on SCC4 */
+#define SCC_INDEX 3
+#define PROFF_SCC PROFF_SCC4
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC4
+
+#endif /* CONFIG_8xx_CONS_SCCx */
+
+#if !defined(CONFIG_SYS_SMC_RXBUFLEN)
+#define CONFIG_SYS_SMC_RXBUFLEN 1
+#define CONFIG_SYS_MAXIDLE 0
+#else
+#if !defined(CONFIG_SYS_MAXIDLE)
+#error "you must define CONFIG_SYS_MAXIDLE"
+#endif
+#endif
+
+typedef volatile struct serialbuffer {
+ cbd_t rxbd; /* Rx BD */
+ cbd_t txbd; /* Tx BD */
+ uint rxindex; /* index for next character to read */
+ volatile uchar rxbuf[CONFIG_SYS_SMC_RXBUFLEN];/* rx buffers */
+ volatile uchar txbuf; /* tx buffers */
+} serialbuffer_t;
+
+static void serial_setdivisor(volatile cpm8xx_t *cp)
+{
+ int divisor=(gd->cpu_clk + 8*gd->baudrate)/16/gd->baudrate;
+
+ if(divisor/16>0x1000) {
+ /* bad divisor, assume 50MHz clock and 9600 baud */
+ divisor=(50*1000*1000 + 8*9600)/16/9600;
+ }
+
+#ifdef CONFIG_SYS_BRGCLK_PRESCALE
+ divisor /= CONFIG_SYS_BRGCLK_PRESCALE;
+#endif
+
+ if(divisor<=0x1000) {
+ cp->cp_brgc1=((divisor-1)<<1) | CPM_BRG_EN;
+ } else {
+ cp->cp_brgc1=((divisor/16-1)<<1) | CPM_BRG_EN | CPM_BRG_DIV16;
+ }
+}
+
+#if (defined (CONFIG_8xx_CONS_SMC1) || defined (CONFIG_8xx_CONS_SMC2))
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+static void smc_setbrg (void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ *
+ * Wire BRG1 to SMCx
+ */
+
+ cp->cp_simode = 0x00000000;
+
+ serial_setdivisor(cp);
+}
+
+static int smc_init (void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+#if (!defined(CONFIG_8xx_CONS_SMC1)) && (defined(CONFIG_MPC823) || defined(CONFIG_MPC850))
+ volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
+#endif
+ uint dpaddr;
+ volatile serialbuffer_t *rtx;
+
+ /* initialize pointers to SMC */
+
+ sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]);
+ up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+ up = (smc_uart_t *) &cp->cp_dpmem[up->smc_rpbase];
+#else
+ /* Disable relocation */
+ up->smc_rpbase = 0;
+#endif
+
+ /* Disable transmitter/receiver. */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Enable SDMA. */
+ im->im_siu_conf.sc_sdcr = 1;
+
+ /* clear error conditions */
+#ifdef CONFIG_SYS_SDSR
+ im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR;
+#else
+ im->im_sdma.sdma_sdsr = 0x83;
+#endif
+
+ /* clear SDMA interrupt mask */
+#ifdef CONFIG_SYS_SDMR
+ im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR;
+#else
+ im->im_sdma.sdma_sdmr = 0x00;
+#endif
+
+#if defined(CONFIG_8xx_CONS_SMC1)
+ /* Use Port B for SMC1 instead of other functions. */
+ cp->cp_pbpar |= 0x000000c0;
+ cp->cp_pbdir &= ~0x000000c0;
+ cp->cp_pbodr &= ~0x000000c0;
+#else /* CONFIG_8xx_CONS_SMC2 */
+# if defined(CONFIG_MPC823) || defined(CONFIG_MPC850)
+ /* Use Port A for SMC2 instead of other functions. */
+ ip->iop_papar |= 0x00c0;
+ ip->iop_padir &= ~0x00c0;
+ ip->iop_paodr &= ~0x00c0;
+# else /* must be a 860 then */
+ /* Use Port B for SMC2 instead of other functions.
+ */
+ cp->cp_pbpar |= 0x00000c00;
+ cp->cp_pbdir &= ~0x00000c00;
+ cp->cp_pbodr &= ~0x00000c00;
+# endif
+#endif
+
+#if defined(CONFIG_FADS) || defined(CONFIG_ADS)
+ /* Enable RS232 */
+#if defined(CONFIG_8xx_CONS_SMC1)
+ *((uint *) BCSR1) &= ~BCSR1_RS232EN_1;
+#else
+ *((uint *) BCSR1) &= ~BCSR1_RS232EN_2;
+#endif
+#endif /* CONFIG_FADS */
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+ /* Enable Monitor Port Transceiver */
+ *((uchar *) BCSR0) |= BCSR0_ENMONXCVR ;
+#endif /* CONFIG_RPXLITE */
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+ /* allocate
+ * size of struct serialbuffer with bd rx/tx, buffer rx/tx and rx index
+ */
+ dpaddr = dpram_alloc_align((sizeof(serialbuffer_t)), 8);
+#else
+ dpaddr = CPM_SERIAL_BASE ;
+#endif
+
+ rtx = (serialbuffer_t *)&cp->cp_dpmem[dpaddr];
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ rtx->rxbd.cbd_bufaddr = (uint) &rtx->rxbuf;
+ rtx->rxbd.cbd_sc = 0;
+
+ rtx->txbd.cbd_bufaddr = (uint) &rtx->txbuf;
+ rtx->txbd.cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram. */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+#if defined (CONFIG_SYS_SMC_UCODE_PATCH)
+ up->smc_rbptr = up->smc_rbase;
+ up->smc_tbptr = up->smc_tbase;
+ up->smc_rstate = 0;
+ up->smc_tstate = 0;
+#endif
+
+#if defined(CONFIG_MBX)
+ board_serial_init();
+#endif /* CONFIG_MBX */
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+#ifdef CONFIG_SYS_SPC1920_SMC1_CLK4
+ /* clock source is PLD */
+
+ /* set freq to 19200 Baud */
+ *((volatile uchar *) CONFIG_SYS_SPC1920_PLD_BASE+6) = 0x3;
+ /* configure clk4 as input */
+ im->im_ioport.iop_pdpar |= 0x800;
+ im->im_ioport.iop_pddir &= ~0x800;
+
+ cp->cp_simode = ((cp->cp_simode & ~0xf000) | 0x7000);
+#else
+ /* Set up the baud rate generator */
+ smc_setbrg ();
+#endif
+
+ /* Make the first buffer the only buffer. */
+ rtx->txbd.cbd_sc |= BD_SC_WRAP;
+ rtx->rxbd.cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* single/multi character receive. */
+ up->smc_mrblr = CONFIG_SYS_SMC_RXBUFLEN;
+ up->smc_maxidl = CONFIG_SYS_MAXIDLE;
+ rtx->rxindex = 0;
+
+ /* Initialize Tx/Rx parameters. */
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver. */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ return (0);
+}
+
+static void
+smc_putc(const char c)
+{
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+ volatile serialbuffer_t *rtx;
+
+#ifdef CONFIG_MODEM_SUPPORT
+ if (gd->be_quiet)
+ return;
+#endif
+
+ if (c == '\n')
+ smc_putc ('\r');
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+ up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
+#endif
+
+ rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ /* Wait for last character to go. */
+ rtx->txbuf = c;
+ rtx->txbd.cbd_datlen = 1;
+ rtx->txbd.cbd_sc |= BD_SC_READY;
+ __asm__("eieio");
+
+ while (rtx->txbd.cbd_sc & BD_SC_READY) {
+ WATCHDOG_RESET ();
+ __asm__("eieio");
+ }
+}
+
+static void
+smc_puts (const char *s)
+{
+ while (*s) {
+ smc_putc (*s++);
+ }
+}
+
+static int
+smc_getc(void)
+{
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+ volatile serialbuffer_t *rtx;
+ unsigned char c;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+ up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
+#endif
+ rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ /* Wait for character to show up. */
+ while (rtx->rxbd.cbd_sc & BD_SC_EMPTY)
+ WATCHDOG_RESET ();
+
+ /* the characters are read one by one,
+ * use the rxindex to know the next char to deliver
+ */
+ c = *(unsigned char *) (rtx->rxbd.cbd_bufaddr+rtx->rxindex);
+ rtx->rxindex++;
+
+ /* check if all char are readout, then make prepare for next receive */
+ if (rtx->rxindex >= rtx->rxbd.cbd_datlen) {
+ rtx->rxindex = 0;
+ rtx->rxbd.cbd_sc |= BD_SC_EMPTY;
+ }
+ return(c);
+}
+
+static int
+smc_tstc(void)
+{
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+ volatile serialbuffer_t *rtx;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+ up = (smc_uart_t *) &cpmp->cp_dpmem[up->smc_rpbase];
+#endif
+
+ rtx = (serialbuffer_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ return !(rtx->rxbd.cbd_sc & BD_SC_EMPTY);
+}
+
+struct serial_device serial_smc_device =
+{
+ .name = "serial_smc",
+ .start = smc_init,
+ .stop = NULL,
+ .setbrg = smc_setbrg,
+ .getc = smc_getc,
+ .tstc = smc_tstc,
+ .putc = smc_putc,
+ .puts = smc_puts,
+};
+
+#endif /* CONFIG_8xx_CONS_SMC1 || CONFIG_8xx_CONS_SMC2 */
+
+#if defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) || \
+ defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
+
+static void
+scc_setbrg (void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ *
+ * Wire BRG1 to SCCx
+ */
+
+ cp->cp_sicr &= ~(0x000000FF << (8 * SCC_INDEX));
+
+ serial_setdivisor(cp);
+}
+
+static int scc_init (void)
+{
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+ uint dpaddr;
+#if (SCC_INDEX != 2) || !defined(CONFIG_MPC850)
+ volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
+#endif
+
+ /* initialize pointers to SCC */
+
+ sp = (scc_t *) &(cp->cp_scc[SCC_INDEX]);
+ up = (scc_uart_t *) &cp->cp_dparam[PROFF_SCC];
+
+#if defined(CONFIG_LWMON) && defined(CONFIG_8xx_CONS_SCC2)
+ { /* Disable Ethernet, enable Serial */
+ uchar c;
+
+ c = pic_read (0x61);
+ c &= ~0x40; /* enable COM3 */
+ c |= 0x80; /* disable Ethernet */
+ pic_write (0x61, c);
+
+ /* enable RTS2 */
+ cp->cp_pbpar |= 0x2000;
+ cp->cp_pbdat |= 0x2000;
+ cp->cp_pbdir |= 0x2000;
+ }
+#endif /* CONFIG_LWMON */
+
+ /* Disable transmitter/receiver. */
+ sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+#if (SCC_INDEX == 2) && defined(CONFIG_MPC850)
+ /*
+ * The MPC850 has SCC3 on Port B
+ */
+ cp->cp_pbpar |= 0x06;
+ cp->cp_pbdir &= ~0x06;
+ cp->cp_pbodr &= ~0x06;
+
+#elif (SCC_INDEX < 2) || !defined(CONFIG_IP860)
+ /*
+ * Standard configuration for SCC's is on Part A
+ */
+ ip->iop_papar |= ((3 << (2 * SCC_INDEX)));
+ ip->iop_padir &= ~((3 << (2 * SCC_INDEX)));
+ ip->iop_paodr &= ~((3 << (2 * SCC_INDEX)));
+#else
+ /*
+ * The IP860 has SCC3 and SCC4 on Port D
+ */
+ ip->iop_pdpar |= ((3 << (2 * SCC_INDEX)));
+#endif
+
+ /* Allocate space for two buffer descriptors in the DP ram. */
+
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+ dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
+#else
+ dpaddr = CPM_SERIAL2_BASE ;
+#endif
+
+ /* Enable SDMA. */
+ im->im_siu_conf.sc_sdcr = 0x0001;
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+
+ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the baud rate generator. */
+ scc_setbrg ();
+
+ /* Set up the uart parameters in the parameter ram. */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+
+ /* Initialize Tx/Rx parameters. */
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ up->scc_genscc.scc_rfcr = SCC_EB | 0x05;
+ up->scc_genscc.scc_tfcr = SCC_EB | 0x05;
+
+ up->scc_genscc.scc_mrblr = 1; /* Single character receive */
+ up->scc_maxidl = 0; /* disable max idle */
+ up->scc_brkcr = 1; /* send one break character on stop TX */
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = 0x8000;
+ up->scc_char2 = 0x8000;
+ up->scc_char3 = 0x8000;
+ up->scc_char4 = 0x8000;
+ up->scc_char5 = 0x8000;
+ up->scc_char6 = 0x8000;
+ up->scc_char7 = 0x8000;
+ up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Set low latency / small fifo. */
+ sp->scc_gsmrh = SCC_GSMRH_RFW;
+
+ /* Set SCC(x) clock mode to 16x
+ * See 8xx_io/commproc.c for details.
+ *
+ * Wire BRG1 to SCCn
+ */
+
+ /* Set UART mode, clock divider 16 on Tx and Rx */
+ sp->scc_gsmrl &= ~0xF;
+ sp->scc_gsmrl |=
+ (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+ sp->scc_psmr = 0;
+ sp->scc_psmr |= SCU_PSMR_CL;
+
+ /* Mask all interrupts and remove anything pending. */
+ sp->scc_sccm = 0;
+ sp->scc_scce = 0xffff;
+ sp->scc_dsr = 0x7e7e;
+ sp->scc_psmr = 0x3000;
+
+ /* Make the first buffer the only buffer. */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Enable transmitter/receiver. */
+ sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ return (0);
+}
+
+static void
+scc_putc(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+#ifdef CONFIG_MODEM_SUPPORT
+ if (gd->be_quiet)
+ return;
+#endif
+
+ if (c == '\n')
+ scc_putc ('\r');
+
+ up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+ tbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
+
+ /* Wait for last character to go. */
+
+ buf = (char *)tbdf->cbd_bufaddr;
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+ __asm__("eieio");
+
+ while (tbdf->cbd_sc & BD_SC_READY) {
+ __asm__("eieio");
+ WATCHDOG_RESET ();
+ }
+}
+
+static void
+scc_puts (const char *s)
+{
+ while (*s) {
+ scc_putc (*s++);
+ }
+}
+
+static int
+scc_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile unsigned char *buf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+ unsigned char c;
+
+ up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
+
+ /* Wait for character to show up. */
+ buf = (unsigned char *)rbdf->cbd_bufaddr;
+
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ WATCHDOG_RESET ();
+
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+static int
+scc_tstc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+ up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
+struct serial_device serial_scc_device =
+{
+ .name = "serial_scc",
+ .start = scc_init,
+ .stop = NULL,
+ .setbrg = scc_setbrg,
+ .getc = scc_getc,
+ .tstc = scc_tstc,
+ .putc = scc_putc,
+ .puts = scc_puts,
+};
+
+#endif /* CONFIG_8xx_CONS_SCCx */
+
+__weak struct serial_device *default_serial_console(void)
+{
+#if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2)
+ return &serial_smc_device;
+#else
+ return &serial_scc_device;
+#endif
+}
+
+void mpc8xx_serial_initialize(void)
+{
+#if defined(CONFIG_8xx_CONS_SMC1) || defined(CONFIG_8xx_CONS_SMC2)
+ serial_register(&serial_smc_device);
+#endif
+#if defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) || \
+ defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
+ serial_register(&serial_scc_device);
+#endif
+}
+
+#ifdef CONFIG_MODEM_SUPPORT
+void disable_putc(void)
+{
+ gd->be_quiet = 1;
+}
+
+void enable_putc(void)
+{
+ gd->be_quiet = 0;
+}
+#endif
+
+#if defined(CONFIG_CMD_KGDB)
+
+void
+kgdb_serial_init(void)
+{
+ int i = -1;
+
+ if (strcmp(default_serial_console()->name, "serial_smc") == 0)
+ {
+#if defined(CONFIG_8xx_CONS_SMC1)
+ i = 1;
+#elif defined(CONFIG_8xx_CONS_SMC2)
+ i = 2;
+#endif
+ }
+ else if (strcmp(default_serial_console()->name, "serial_scc") == 0)
+ {
+#if defined(CONFIG_8xx_CONS_SCC1)
+ i = 1;
+#elif defined(CONFIG_8xx_CONS_SCC2)
+ i = 2;
+#elif defined(CONFIG_8xx_CONS_SCC3)
+ i = 3;
+#elif defined(CONFIG_8xx_CONS_SCC4)
+ i = 4;
+#endif
+ }
+
+ if (i >= 0)
+ {
+ serial_printf("[on %s%d] ", default_serial_console()->name, i);
+ }
+}
+
+void
+putDebugChar (int c)
+{
+ serial_putc (c);
+}
+
+void
+putDebugStr (const char *str)
+{
+ serial_puts (str);
+}
+
+int
+getDebugChar (void)
+{
+ return serial_getc();
+}
+
+void
+kgdb_interruptible (int yes)
+{
+ return;
+}
+#endif
+
+#endif /* CONFIG_8xx_CONS_NONE */
diff --git a/arch/powerpc/cpu/mpc8xx/speed.c b/arch/powerpc/cpu/mpc8xx/speed.c
new file mode 100644
index 0000000..091b49f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/speed.c
@@ -0,0 +1,416 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_8xx_CPUCLK_DEFAULT) || defined(CONFIG_SYS_MEASURE_CPUCLK) || defined(DEBUG)
+
+#define PITC_SHIFT 16
+#define PITR_SHIFT 16
+/* pitc values to time for 58/8192 seconds (about 70.8 milliseconds) */
+#define SPEED_PIT_COUNTS 58
+#define SPEED_PITC ((SPEED_PIT_COUNTS - 1) << PITC_SHIFT)
+#define SPEED_PITC_INIT ((SPEED_PIT_COUNTS + 1) << PITC_SHIFT)
+
+/* Access functions for the Machine State Register */
+static __inline__ unsigned long get_msr(void)
+{
+ unsigned long msr;
+
+ asm volatile("mfmsr %0" : "=r" (msr) :);
+ return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+ asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Measure CPU clock speed (core clock GCLK1, GCLK2),
+ * also determine bus clock speed (checking bus divider factor)
+ *
+ * (Approx. GCLK frequency in Hz)
+ *
+ * Initializes timer 2 and PIT, but disables them before return.
+ * [Use timer 2, because MPC823 CPUs mask 0.x do not have timers 3 and 4]
+ *
+ * When measuring the CPU clock against the PIT, we count cpu clocks
+ * for 58/8192 seconds with a prescale divide by 177 for the cpu clock.
+ * These strange values for the timing interval and prescaling are used
+ * because the formula for the CPU clock is:
+ *
+ * CPU clock = count * (177 * (8192 / 58))
+ *
+ * = count * 24999.7241
+ *
+ * which is very close to
+ *
+ * = count * 25000
+ *
+ * Since the count gives the CPU clock divided by 25000, we can get
+ * the CPU clock rounded to the nearest 0.1 MHz by
+ *
+ * CPU clock = ((count + 2) / 4) * 100000;
+ *
+ * The rounding is important since the measurement is sometimes going
+ * to be high or low by 0.025 MHz, depending on exactly how the clocks
+ * and counters interact. By rounding we get the exact answer for any
+ * CPU clock that is an even multiple of 0.1 MHz.
+ */
+
+unsigned long measure_gclk(void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ volatile cpmtimer8xx_t *timerp = &immr->im_cpmtimer;
+ ulong timer2_val;
+ ulong msr_val;
+
+#ifdef CONFIG_SYS_8XX_XIN
+ /* dont use OSCM, only use EXTCLK/512 */
+ immr->im_clkrst.car_sccr |= SCCR_RTSEL | SCCR_RTDIV;
+#else
+ immr->im_clkrst.car_sccr &= ~(SCCR_RTSEL | SCCR_RTDIV);
+#endif
+
+ /* Reset + Stop Timer 2, no cascading
+ */
+ timerp->cpmt_tgcr &= ~(TGCR_CAS2 | TGCR_RST2);
+
+ /* Keep stopped, halt in debug mode
+ */
+ timerp->cpmt_tgcr |= (TGCR_FRZ2 | TGCR_STP2);
+
+ /* Timer 2 setup:
+ * Output ref. interrupt disable, int. clock
+ * Prescale by 177. Note that prescaler divides by value + 1
+ * so we must subtract 1 here.
+ */
+ timerp->cpmt_tmr2 = ((177 - 1) << TMR_PS_SHIFT) | TMR_ICLK_IN_GEN;
+
+ timerp->cpmt_tcn2 = 0; /* reset state */
+ timerp->cpmt_tgcr |= TGCR_RST2; /* enable timer 2 */
+
+ /*
+ * PIT setup:
+ *
+ * We want to time for SPEED_PITC_COUNTS counts (of 8192 Hz),
+ * so the count value would be SPEED_PITC_COUNTS - 1.
+ * But there would be an uncertainty in the start time of 1/4
+ * count since when we enable the PIT the count is not
+ * synchronized to the 32768 Hz oscillator. The trick here is
+ * to start the count higher and wait until the PIT count
+ * changes to the required value before starting timer 2.
+ *
+ * One count high should be enough, but occasionally the start
+ * is off by 1 or 2 counts of 32768 Hz. With the start value
+ * set two counts high it seems very reliable.
+ */
+
+ immr->im_sitk.sitk_pitck = KAPWR_KEY; /* PIT initialization */
+ immr->im_sit.sit_pitc = SPEED_PITC_INIT;
+
+ immr->im_sitk.sitk_piscrk = KAPWR_KEY;
+ immr->im_sit.sit_piscr = CONFIG_SYS_PISCR;
+
+ /*
+ * Start measurement - disable interrupts, just in case
+ */
+ msr_val = get_msr ();
+ set_msr (msr_val & ~MSR_EE);
+
+ immr->im_sit.sit_piscr |= PISCR_PTE;
+
+ /* spin until get exact count when we want to start */
+ while (immr->im_sit.sit_pitr > SPEED_PITC);
+
+ timerp->cpmt_tgcr &= ~TGCR_STP2; /* Start Timer 2 */
+ while ((immr->im_sit.sit_piscr & PISCR_PS) == 0);
+ timerp->cpmt_tgcr |= TGCR_STP2; /* Stop Timer 2 */
+
+ /* re-enable external interrupts if they were on */
+ set_msr (msr_val);
+
+ /* Disable timer and PIT
+ */
+ timer2_val = timerp->cpmt_tcn2; /* save before reset timer */
+
+ timerp->cpmt_tgcr &= ~(TGCR_RST2 | TGCR_FRZ2 | TGCR_STP2);
+ immr->im_sit.sit_piscr &= ~PISCR_PTE;
+
+#if defined(CONFIG_SYS_8XX_XIN)
+ /* not using OSCM, using XIN, so scale appropriately */
+ return (((timer2_val + 2) / 4) * (CONFIG_SYS_8XX_XIN/512))/8192 * 100000L;
+#else
+ return ((timer2_val + 2) / 4) * 100000L; /* convert to Hz */
+#endif
+}
+
+#endif
+
+void get_brgclk(uint sccr)
+{
+ uint divider = 0;
+
+ switch((sccr&SCCR_DFBRG11)>>11){
+ case 0:
+ divider = 1;
+ break;
+ case 1:
+ divider = 4;
+ break;
+ case 2:
+ divider = 16;
+ break;
+ case 3:
+ divider = 64;
+ break;
+ }
+ gd->arch.brg_clk = gd->cpu_clk/divider;
+}
+
+#if !defined(CONFIG_8xx_CPUCLK_DEFAULT)
+
+/*
+ * get_clocks() fills in gd->cpu_clock depending on CONFIG_8xx_GCLK_FREQ
+ * or (if it is not defined) measure_gclk() (which uses the ref clock)
+ * from above.
+ */
+int get_clocks (void)
+{
+ uint immr = get_immr (0); /* Return full IMMR contents */
+ volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000);
+ uint sccr = immap->im_clkrst.car_sccr;
+ /*
+ * If for some reason measuring the gclk frequency won't
+ * work, we return the hardwired value.
+ * (For example, the cogent CMA286-60 CPU module has no
+ * separate oscillator for PITRTCLK)
+ */
+#if defined(CONFIG_8xx_GCLK_FREQ)
+ gd->cpu_clk = CONFIG_8xx_GCLK_FREQ;
+#elif defined(CONFIG_8xx_OSCLK)
+#define PLPRCR_val(a) ((pll & PLPRCR_ ## a ## _MSK) >> PLPRCR_ ## a ## _SHIFT)
+ uint pll = immap->im_clkrst.car_plprcr;
+ uint clk;
+
+ if ((immr & 0x0FFF) >= MPC8xx_NEW_CLK) { /* MPC866/87x/88x series */
+ clk = ((CONFIG_8xx_OSCLK / (PLPRCR_val(PDF)+1)) *
+ (PLPRCR_val(MFI) + PLPRCR_val(MFN) / (PLPRCR_val(MFD)+1))) /
+ (1<<PLPRCR_val(S));
+ } else {
+ clk = CONFIG_8xx_OSCLK * (PLPRCR_val(MF)+1);
+ }
+ if (pll & PLPRCR_CSRC) { /* Low frequency division factor is used */
+ gd->cpu_clk = clk / (2 << ((sccr >> 8) & 7));
+ } else { /* High frequency division factor is used */
+ gd->cpu_clk = clk / (1 << ((sccr >> 5) & 7));
+ }
+#else
+ gd->cpu_clk = measure_gclk();
+#endif /* CONFIG_8xx_GCLK_FREQ */
+
+ if ((sccr & SCCR_EBDF11) == 0) {
+ /* No Bus Divider active */
+ gd->bus_clk = gd->cpu_clk;
+ } else {
+ /* The MPC8xx has only one BDF: half clock speed */
+ gd->bus_clk = gd->cpu_clk / 2;
+ }
+
+ get_brgclk(sccr);
+
+ return (0);
+}
+
+#else /* CONFIG_8xx_CPUCLK_DEFAULT defined, use dynamic clock setting */
+
+static long init_pll_866 (long clk);
+
+/* This function sets up PLL (init_pll_866() is called) and
+ * fills gd->cpu_clk and gd->bus_clk according to the environment
+ * variable 'cpuclk' or to CONFIG_8xx_CPUCLK_DEFAULT (if 'cpuclk'
+ * contains invalid value).
+ * This functions requires an MPC866 or newer series CPU.
+ */
+int get_clocks_866 (void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ char tmp[64];
+ long cpuclk = 0;
+ long sccr_reg;
+
+ if (getenv_f("cpuclk", tmp, sizeof (tmp)) > 0)
+ cpuclk = simple_strtoul (tmp, NULL, 10) * 1000000;
+
+ if ((CONFIG_SYS_8xx_CPUCLK_MIN > cpuclk) || (CONFIG_SYS_8xx_CPUCLK_MAX < cpuclk))
+ cpuclk = CONFIG_8xx_CPUCLK_DEFAULT;
+
+ gd->cpu_clk = init_pll_866 (cpuclk);
+#if defined(CONFIG_SYS_MEASURE_CPUCLK)
+ gd->cpu_clk = measure_gclk ();
+#endif
+
+ get_brgclk(immr->im_clkrst.car_sccr);
+
+ /* if cpu clock <= 66 MHz then set bus division factor to 1,
+ * otherwise set it to 2
+ */
+ sccr_reg = immr->im_clkrst.car_sccr;
+ sccr_reg &= ~SCCR_EBDF11;
+
+ if (gd->cpu_clk <= 66000000) {
+ sccr_reg |= SCCR_EBDF00; /* bus division factor = 1 */
+ gd->bus_clk = gd->cpu_clk;
+ } else {
+ sccr_reg |= SCCR_EBDF01; /* bus division factor = 2 */
+ gd->bus_clk = gd->cpu_clk / 2;
+ }
+ immr->im_clkrst.car_sccr = sccr_reg;
+
+ return (0);
+}
+
+/* Adjust sdram refresh rate to actual CPU clock.
+ */
+int sdram_adjust_866 (void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ long mamr;
+
+ mamr = immr->im_memctl.memc_mamr;
+ mamr &= ~MAMR_PTA_MSK;
+ mamr |= ((gd->cpu_clk / CONFIG_SYS_PTA_PER_CLK) << MAMR_PTA_SHIFT);
+ immr->im_memctl.memc_mamr = mamr;
+
+ return (0);
+}
+
+/* Configure PLL for MPC866/859/885 CPU series
+ * PLL multiplication factor is set to the value nearest to the desired clk,
+ * assuming a oscclk of 10 MHz.
+ */
+static long init_pll_866 (long clk)
+{
+ extern void plprcr_write_866 (long);
+
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ long n, plprcr;
+ char mfi, mfn, mfd, s, pdf;
+ long step_mfi, step_mfn;
+
+ if (clk < 20000000) {
+ clk *= 2;
+ pdf = 1;
+ } else {
+ pdf = 0;
+ }
+
+ if (clk < 40000000) {
+ s = 2;
+ step_mfi = CONFIG_8xx_OSCLK / 4;
+ mfd = 7;
+ step_mfn = CONFIG_8xx_OSCLK / 30;
+ } else if (clk < 80000000) {
+ s = 1;
+ step_mfi = CONFIG_8xx_OSCLK / 2;
+ mfd = 14;
+ step_mfn = CONFIG_8xx_OSCLK / 30;
+ } else {
+ s = 0;
+ step_mfi = CONFIG_8xx_OSCLK;
+ mfd = 29;
+ step_mfn = CONFIG_8xx_OSCLK / 30;
+ }
+
+ /* Calculate integer part of multiplication factor
+ */
+ n = clk / step_mfi;
+ mfi = (char)n;
+
+ /* Calculate numerator of fractional part of multiplication factor
+ */
+ n = clk - (n * step_mfi);
+ mfn = (char)(n / step_mfn);
+
+ /* Calculate effective clk
+ */
+ n = ((mfi * step_mfi) + (mfn * step_mfn)) / (pdf + 1);
+
+ immr->im_clkrstk.cark_plprcrk = KAPWR_KEY;
+
+ plprcr = (immr->im_clkrst.car_plprcr & ~(PLPRCR_MFN_MSK
+ | PLPRCR_MFD_MSK | PLPRCR_S_MSK
+ | PLPRCR_MFI_MSK | PLPRCR_DBRMO
+ | PLPRCR_PDF_MSK))
+ | (mfn << PLPRCR_MFN_SHIFT)
+ | (mfd << PLPRCR_MFD_SHIFT)
+ | (s << PLPRCR_S_SHIFT)
+ | (mfi << PLPRCR_MFI_SHIFT)
+ | (pdf << PLPRCR_PDF_SHIFT);
+
+ if( (mfn > 0) && ((mfd / mfn) > 10) )
+ plprcr |= PLPRCR_DBRMO;
+
+ plprcr_write_866 (plprcr); /* set value using SIU4/9 workaround */
+ immr->im_clkrstk.cark_plprcrk = 0x00000000;
+
+ return (n);
+}
+
+#endif /* CONFIG_8xx_CPUCLK_DEFAULT */
+
+#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \
+ && !defined(CONFIG_TQM885D)
+/*
+ * Adjust sdram refresh rate to actual CPU clock
+ * and set timebase source according to actual CPU clock
+ */
+int adjust_sdram_tbs_8xx (void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ long mamr;
+ long sccr;
+
+ mamr = immr->im_memctl.memc_mamr;
+ mamr &= ~MAMR_PTA_MSK;
+ mamr |= ((gd->cpu_clk / CONFIG_SYS_PTA_PER_CLK) << MAMR_PTA_SHIFT);
+ immr->im_memctl.memc_mamr = mamr;
+
+ if (gd->cpu_clk < 67000000) {
+ sccr = immr->im_clkrst.car_sccr;
+ sccr |= SCCR_TBS;
+ immr->im_clkrst.car_sccr = sccr;
+ }
+
+ return (0);
+}
+#endif /* CONFIG_TQM8xxL/M, !TQM866M, !TQM885D */
+
+/* ------------------------------------------------------------------------- */
diff --git a/arch/powerpc/cpu/mpc8xx/spi.c b/arch/powerpc/cpu/mpc8xx/spi.c
new file mode 100644
index 0000000..db34852
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/spi.c
@@ -0,0 +1,556 @@
+/*
+ * Copyright (c) 2001 Navin Boppuri / Prashant Patel
+ * <nboppuri@trinetcommunication.com>,
+ * <pmpatel@trinetcommunication.com>
+ * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de>
+ * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8xx CPM SPI interface.
+ *
+ * Parts of this code are probably not portable and/or specific to
+ * the board which I used for the tests. Please send fixes/complaints
+ * to wd@denx.de
+ *
+ */
+
+#include <common.h>
+#include <mpc8xx.h>
+#include <commproc.h>
+#include <linux/ctype.h>
+#include <malloc.h>
+#include <post.h>
+#include <serial.h>
+
+#if (defined(CONFIG_SPI)) || (CONFIG_POST & CONFIG_SYS_POST_SPI)
+
+/* Warning:
+ * You cannot enable DEBUG for early system initalization, i. e. when
+ * this driver is used to read environment parameters like "baudrate"
+ * from EEPROM which are used to initialize the serial port which is
+ * needed to print the debug messages...
+ */
+#undef DEBUG
+
+#define SPI_EEPROM_WREN 0x06
+#define SPI_EEPROM_RDSR 0x05
+#define SPI_EEPROM_READ 0x03
+#define SPI_EEPROM_WRITE 0x02
+
+/* ---------------------------------------------------------------
+ * Offset for initial SPI buffers in DPRAM:
+ * We need a 520 byte scratch DPRAM area to use at an early stage.
+ * It is used between the two initialization calls (spi_init_f()
+ * and spi_init_r()).
+ * The value 0xb00 makes it far enough from the start of the data
+ * area (as well as from the stack pointer).
+ * --------------------------------------------------------------- */
+#ifndef CONFIG_SYS_SPI_INIT_OFFSET
+#define CONFIG_SYS_SPI_INIT_OFFSET 0xB00
+#endif
+
+#ifdef DEBUG
+
+#define DPRINT(a) printf a;
+/* -----------------------------------------------
+ * Helper functions to peek into tx and rx buffers
+ * ----------------------------------------------- */
+static const char * const hex_digit = "0123456789ABCDEF";
+
+static char quickhex (int i)
+{
+ return hex_digit[i];
+}
+
+static void memdump (void *pv, int num)
+{
+ int i;
+ unsigned char *pc = (unsigned char *) pv;
+
+ for (i = 0; i < num; i++)
+ printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f));
+ printf ("\t");
+ for (i = 0; i < num; i++)
+ printf ("%c", isprint (pc[i]) ? pc[i] : '.');
+ printf ("\n");
+}
+#else /* !DEBUG */
+
+#define DPRINT(a)
+
+#endif /* DEBUG */
+
+/* -------------------
+ * Function prototypes
+ * ------------------- */
+void spi_init (void);
+
+ssize_t spi_read (uchar *, int, uchar *, int);
+ssize_t spi_write (uchar *, int, uchar *, int);
+ssize_t spi_xfer (size_t);
+
+/* -------------------
+ * Variables
+ * ------------------- */
+
+#define MAX_BUFFER 0x104
+
+/* ----------------------------------------------------------------------
+ * Initially we place the RX and TX buffers at a fixed location in DPRAM!
+ * ---------------------------------------------------------------------- */
+static uchar *rxbuf =
+ (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
+ [CONFIG_SYS_SPI_INIT_OFFSET];
+static uchar *txbuf =
+ (uchar *)&((cpm8xx_t *)&((immap_t *)CONFIG_SYS_IMMR)->im_cpm)->cp_dpmem
+ [CONFIG_SYS_SPI_INIT_OFFSET+MAX_BUFFER];
+
+/* **************************************************************************
+ *
+ * Function: spi_init_f
+ *
+ * Description: Init SPI-Controller (ROM part)
+ *
+ * return: ---
+ *
+ * *********************************************************************** */
+void spi_init_f (void)
+{
+ unsigned int dpaddr;
+
+ volatile spi_t *spi;
+ volatile immap_t *immr;
+ volatile cpm8xx_t *cp;
+ volatile cbd_t *tbdf, *rbdf;
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ cp = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+ spi = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+ spi = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+ /* Disable relocation */
+ spi->spi_rpbase = 0;
+#endif
+
+/* 1 */
+ /* ------------------------------------------------
+ * Initialize Port B SPI pins -> page 34-8 MPC860UM
+ * (we are only in Master Mode !)
+ * ------------------------------------------------ */
+
+ /* --------------------------------------------
+ * GPIO or per. Function
+ * PBPAR[28] = 1 [0x00000008] -> PERI: (SPIMISO)
+ * PBPAR[29] = 1 [0x00000004] -> PERI: (SPIMOSI)
+ * PBPAR[30] = 1 [0x00000002] -> PERI: (SPICLK)
+ * PBPAR[31] = 0 [0x00000001] -> GPIO: (CS for PCUE/CCM-EEPROM)
+ * -------------------------------------------- */
+ cp->cp_pbpar |= 0x0000000E; /* set bits */
+ cp->cp_pbpar &= ~0x00000001; /* reset bit */
+
+ /* ----------------------------------------------
+ * In/Out or per. Function 0/1
+ * PBDIR[28] = 1 [0x00000008] -> PERI1: SPIMISO
+ * PBDIR[29] = 1 [0x00000004] -> PERI1: SPIMOSI
+ * PBDIR[30] = 1 [0x00000002] -> PERI1: SPICLK
+ * PBDIR[31] = 1 [0x00000001] -> GPIO OUT: CS for PCUE/CCM-EEPROM
+ * ---------------------------------------------- */
+ cp->cp_pbdir |= 0x0000000F;
+
+ /* ----------------------------------------------
+ * open drain or active output
+ * PBODR[28] = 1 [0x00000008] -> open drain: SPIMISO
+ * PBODR[29] = 0 [0x00000004] -> active output SPIMOSI
+ * PBODR[30] = 0 [0x00000002] -> active output: SPICLK
+ * PBODR[31] = 0 [0x00000001] -> active output: GPIO OUT: CS for PCUE/CCM
+ * ---------------------------------------------- */
+
+ cp->cp_pbodr |= 0x00000008;
+ cp->cp_pbodr &= ~0x00000007;
+
+ /* Initialize the parameter ram.
+ * We need to make sure many things are initialized to zero
+ */
+ spi->spi_rstate = 0;
+ spi->spi_rdp = 0;
+ spi->spi_rbptr = 0;
+ spi->spi_rbc = 0;
+ spi->spi_rxtmp = 0;
+ spi->spi_tstate = 0;
+ spi->spi_tdp = 0;
+ spi->spi_tbptr = 0;
+ spi->spi_tbc = 0;
+ spi->spi_txtmp = 0;
+
+ /* Allocate space for one transmit and one receive buffer
+ * descriptor in the DP ram
+ */
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+ dpaddr = dpram_alloc_align (sizeof(cbd_t)*2, 8);
+#else
+ dpaddr = CPM_SPI_BASE;
+#endif
+
+/* 3 */
+ /* Set up the SPI parameters in the parameter ram */
+ spi->spi_rbase = dpaddr;
+ spi->spi_tbase = dpaddr + sizeof (cbd_t);
+
+ /***********IMPORTANT******************/
+
+ /*
+ * Setting transmit and receive buffer descriptor pointers
+ * initially to rbase and tbase. Only the microcode patches
+ * documentation talks about initializing this pointer. This
+ * is missing from the sample I2C driver. If you dont
+ * initialize these pointers, the kernel hangs.
+ */
+ spi->spi_rbptr = spi->spi_rbase;
+ spi->spi_tbptr = spi->spi_tbase;
+
+/* 4 */
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+ /*
+ * Initialize required parameters if using microcode patch.
+ */
+ spi->spi_rstate = 0;
+ spi->spi_tstate = 0;
+#else
+ /* Init SPI Tx + Rx Parameters */
+ while (cp->cp_cpcr & CPM_CR_FLG)
+ ;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SPI, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ while (cp->cp_cpcr & CPM_CR_FLG)
+ ;
+#endif /* CONFIG_SYS_SPI_UCODE_PATCH */
+
+/* 5 */
+ /* Set SDMA configuration register */
+ immr->im_siu_conf.sc_sdcr = 0x0001;
+
+/* 6 */
+ /* Set to big endian. */
+ spi->spi_tfcr = SMC_EB;
+ spi->spi_rfcr = SMC_EB;
+
+/* 7 */
+ /* Set maximum receive size. */
+ spi->spi_mrblr = MAX_BUFFER;
+
+/* 8 + 9 */
+ /* tx and rx buffer descriptors */
+ tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+ rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+ tbdf->cbd_sc &= ~BD_SC_READY;
+ rbdf->cbd_sc &= ~BD_SC_EMPTY;
+
+ /* Set the bd's rx and tx buffer address pointers */
+ rbdf->cbd_bufaddr = (ulong) rxbuf;
+ tbdf->cbd_bufaddr = (ulong) txbuf;
+
+/* 10 + 11 */
+ cp->cp_spim = 0; /* Mask all SPI events */
+ cp->cp_spie = SPI_EMASK; /* Clear all SPI events */
+
+ return;
+}
+
+/* **************************************************************************
+ *
+ * Function: spi_init_r
+ *
+ * Description: Init SPI-Controller (RAM part) -
+ * The malloc engine is ready and we can move our buffers to
+ * normal RAM
+ *
+ * return: ---
+ *
+ * *********************************************************************** */
+void spi_init_r (void)
+{
+ volatile cpm8xx_t *cp;
+ volatile spi_t *spi;
+ volatile immap_t *immr;
+ volatile cbd_t *tbdf, *rbdf;
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ cp = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+ spi = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+ spi = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+ /* Disable relocation */
+ spi->spi_rpbase = 0;
+#endif
+
+ /* tx and rx buffer descriptors */
+ tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+ rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+ /* Allocate memory for RX and TX buffers */
+ rxbuf = (uchar *) malloc (MAX_BUFFER);
+ txbuf = (uchar *) malloc (MAX_BUFFER);
+
+ rbdf->cbd_bufaddr = (ulong) rxbuf;
+ tbdf->cbd_bufaddr = (ulong) txbuf;
+
+ return;
+}
+
+/****************************************************************************
+ * Function: spi_write
+ **************************************************************************** */
+ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+ int i;
+
+ memset(rxbuf, 0, MAX_BUFFER);
+ memset(txbuf, 0, MAX_BUFFER);
+ *txbuf = SPI_EEPROM_WREN; /* write enable */
+ spi_xfer(1);
+ memcpy(txbuf, addr, alen);
+ *txbuf = SPI_EEPROM_WRITE; /* WRITE memory array */
+ memcpy(alen + txbuf, buffer, len);
+ spi_xfer(alen + len);
+ /* ignore received data */
+ for (i = 0; i < 1000; i++) {
+ *txbuf = SPI_EEPROM_RDSR; /* read status */
+ txbuf[1] = 0;
+ spi_xfer(2);
+ if (!(rxbuf[1] & 1)) {
+ break;
+ }
+ udelay(1000);
+ }
+ if (i >= 1000) {
+ printf ("*** spi_write: Time out while writing!\n");
+ }
+
+ return len;
+}
+
+/****************************************************************************
+ * Function: spi_read
+ **************************************************************************** */
+ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+ memset(rxbuf, 0, MAX_BUFFER);
+ memset(txbuf, 0, MAX_BUFFER);
+ memcpy(txbuf, addr, alen);
+ *txbuf = SPI_EEPROM_READ; /* READ memory array */
+
+ /*
+ * There is a bug in 860T (?) that cuts the last byte of input
+ * if we're reading into DPRAM. The solution we choose here is
+ * to always read len+1 bytes (we have one extra byte at the
+ * end of the buffer).
+ */
+ spi_xfer(alen + len + 1);
+ memcpy(buffer, alen + rxbuf, len);
+
+ return len;
+}
+
+/****************************************************************************
+ * Function: spi_xfer
+ **************************************************************************** */
+ssize_t spi_xfer (size_t count)
+{
+ volatile immap_t *immr;
+ volatile cpm8xx_t *cp;
+ volatile spi_t *spi;
+ cbd_t *tbdf, *rbdf;
+ ushort loop;
+ int tm;
+
+ DPRINT (("*** spi_xfer entered ***\n"));
+
+ immr = (immap_t *) CONFIG_SYS_IMMR;
+ cp = (cpm8xx_t *) &immr->im_cpm;
+
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+ spi = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase];
+#else
+ spi = (spi_t *)&cp->cp_dparam[PROFF_SPI];
+ /* Disable relocation */
+ spi->spi_rpbase = 0;
+#endif
+
+ tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase];
+ rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase];
+
+ /* Set CS for device */
+ cp->cp_pbdat &= ~0x0001;
+
+ /* Setting tx bd status and data length */
+ tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP;
+ tbdf->cbd_datlen = count;
+
+ DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n",
+ tbdf->cbd_datlen));
+
+ /* Setting rx bd status and data length */
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ rbdf->cbd_datlen = 0; /* rx length has no significance */
+
+ loop = cp->cp_spmode & SPMODE_LOOP;
+ cp->cp_spmode = /*SPMODE_DIV16 |*/ /* BRG/16 mode not used here */
+ loop |
+ SPMODE_REV |
+ SPMODE_MSTR |
+ SPMODE_EN |
+ SPMODE_LEN(8) | /* 8 Bits per char */
+ SPMODE_PM(0x8) ; /* medium speed */
+ cp->cp_spim = 0; /* Mask all SPI events */
+ cp->cp_spie = SPI_EMASK; /* Clear all SPI events */
+
+ /* start spi transfer */
+ DPRINT (("*** spi_xfer: Performing transfer ...\n"));
+ cp->cp_spcom |= SPI_STR; /* Start transmit */
+
+ /* --------------------------------
+ * Wait for SPI transmit to get out
+ * or time out (1 second = 1000 ms)
+ * -------------------------------- */
+ for (tm=0; tm<1000; ++tm) {
+ if (cp->cp_spie & SPI_TXB) { /* Tx Buffer Empty */
+ DPRINT (("*** spi_xfer: Tx buffer empty\n"));
+ break;
+ }
+ if ((tbdf->cbd_sc & BD_SC_READY) == 0) {
+ DPRINT (("*** spi_xfer: Tx BD done\n"));
+ break;
+ }
+ udelay (1000);
+ }
+ if (tm >= 1000) {
+ printf ("*** spi_xfer: Time out while xferring to/from SPI!\n");
+ }
+ DPRINT (("*** spi_xfer: ... transfer ended\n"));
+
+#ifdef DEBUG
+ printf ("\nspi_xfer: txbuf after xfer\n");
+ memdump ((void *) txbuf, 16); /* dump of txbuf before transmit */
+ printf ("spi_xfer: rxbuf after xfer\n");
+ memdump ((void *) rxbuf, 16); /* dump of rxbuf after transmit */
+ printf ("\n");
+#endif
+
+ /* Clear CS for device */
+ cp->cp_pbdat |= 0x0001;
+
+ return count;
+}
+#endif /* CONFIG_SPI || (CONFIG_POST & CONFIG_SYS_POST_SPI) */
+
+/*
+ * SPI test
+ *
+ * The Serial Peripheral Interface (SPI) is tested in the local loopback mode.
+ * The interface is configured accordingly and several packets
+ * are transfered. The configurable test parameters are:
+ * TEST_MIN_LENGTH - minimum size of packet to transfer
+ * TEST_MAX_LENGTH - maximum size of packet to transfer
+ * TEST_NUM - number of tests
+ */
+
+#if CONFIG_POST & CONFIG_SYS_POST_SPI
+
+#define TEST_MIN_LENGTH 1
+#define TEST_MAX_LENGTH MAX_BUFFER
+#define TEST_NUM 1
+
+static void packet_fill (char * packet, int length)
+{
+ char c = (char) length;
+ int i;
+
+ for (i = 0; i < length; i++)
+ {
+ packet[i] = c++;
+ }
+}
+
+static int packet_check (char * packet, int length)
+{
+ char c = (char) length;
+ int i;
+
+ for (i = 0; i < length; i++) {
+ if (packet[i] != c++) return -1;
+ }
+
+ return 0;
+}
+
+int spi_post_test (int flags)
+{
+ int res = -1;
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ volatile cpm8xx_t *cp = (cpm8xx_t *) & immr->im_cpm;
+ int i;
+ int l;
+
+ spi_init_f ();
+ spi_init_r ();
+
+ cp->cp_spmode |= SPMODE_LOOP;
+
+ for (i = 0; i < TEST_NUM; i++) {
+ for (l = TEST_MIN_LENGTH; l <= TEST_MAX_LENGTH; l += 8) {
+ packet_fill ((char *)txbuf, l);
+
+ spi_xfer (l);
+
+ if (packet_check ((char *)rxbuf, l) < 0) {
+ goto Done;
+ }
+ }
+ }
+
+ res = 0;
+
+ Done:
+
+ cp->cp_spmode &= ~SPMODE_LOOP;
+
+ /*
+ * SCC2 parameter RAM space overlaps
+ * the SPI parameter RAM space. So we need to restore
+ * the SCC2 configuration if it is used by UART.
+ */
+
+#if !defined(CONFIG_8xx_CONS_NONE)
+ serial_reinit_all ();
+#endif
+
+ if (res != 0) {
+ post_log ("SPI test failed\n");
+ }
+
+ return res;
+}
+#endif /* CONFIG_POST & CONFIG_SYS_POST_SPI */
diff --git a/arch/powerpc/cpu/mpc8xx/start.S b/arch/powerpc/cpu/mpc8xx/start.S
new file mode 100644
index 0000000..5aa50c5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/start.S
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* U-Boot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ * The processor starts at 0x00000100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating,
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ * This works because the cpu gives the FLASH (CS0) the whole
+ * address space at startup, and board_init lies as a echo of
+ * the flash somewhere up there in the memory map.
+ *
+ * board_init will change CS0 to be positioned at the correct
+ * address and (s)dram will be positioned at address 0
+ */
+#include <asm-offsets.h>
+#include <config.h>
+#include <mpc8xx.h>
+#include <version.h>
+
+#define CONFIG_8xx 1 /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/u-boot.h>
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+ .text
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start
+_start:
+ lis r3, CONFIG_SYS_IMMR@h /* position IMMR */
+ mtspr 638, r3
+
+ /* Initialize machine status; enable machine check interrupt */
+ /*----------------------------------------------------------------------*/
+ li r3, MSR_KERNEL /* Set ME, RI flags */
+ mtmsr r3
+ mtspr SRR1, r3 /* Make SRR1 match MSR */
+
+ mfspr r3, ICR /* clear Interrupt Cause Register */
+
+ /* Initialize debug port registers */
+ /*----------------------------------------------------------------------*/
+ xor r0, r0, r0 /* Clear R0 */
+ mtspr LCTRL1, r0 /* Initialize debug port regs */
+ mtspr LCTRL2, r0
+ mtspr COUNTA, r0
+ mtspr COUNTB, r0
+
+ /* Reset the caches */
+ /*----------------------------------------------------------------------*/
+
+ mfspr r3, IC_CST /* Clear error bits */
+ mfspr r3, DC_CST
+
+ lis r3, IDC_UNALL@h /* Unlock all */
+ mtspr IC_CST, r3
+ mtspr DC_CST, r3
+
+ lis r3, IDC_INVALL@h /* Invalidate all */
+ mtspr IC_CST, r3
+ mtspr DC_CST, r3
+
+ lis r3, IDC_DISABLE@h /* Disable data cache */
+ mtspr DC_CST, r3
+
+#if !defined(CONFIG_SYS_DELAYED_ICACHE)
+ /* On IP860 and PCU E,
+ * we cannot enable IC yet
+ */
+ lis r3, IDC_ENABLE@h /* Enable instruction cache */
+#endif
+ mtspr IC_CST, r3
+
+ /* invalidate all tlb's */
+ /*----------------------------------------------------------------------*/
+
+ tlbia
+ isync
+
+ /*
+ * Calculate absolute address in FLASH and jump there
+ *----------------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_MONITOR_BASE@h
+ ori r3, r3, CONFIG_SYS_MONITOR_BASE@l
+ addi r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+ mtlr r3
+ blr
+
+in_flash:
+
+ /* initialize some SPRs that are hard to access from C */
+ /*----------------------------------------------------------------------*/
+
+ lis r3, CONFIG_SYS_IMMR@h /* pass IMMR as arg1 to C routine */
+ ori r1, r3, CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in internal DPRAM */
+ /* Note: R0 is still 0 here */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+
+ /*
+ * Disable serialized ifetch and show cycles
+ * (i.e. set processor to normal mode).
+ * This is also a silicon bug workaround, see errata
+ */
+
+ li r2, 0x0007
+ mtspr ICTRL, r2
+
+ /* Set up debug mode entry */
+
+ lis r2, CONFIG_SYS_DER@h
+ ori r2, r2, CONFIG_SYS_DER@l
+ mtspr DER, r2
+
+ /* let the C-code set up the rest */
+ /* */
+ /* Be careful to keep code relocatable ! */
+ /*----------------------------------------------------------------------*/
+
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
+
+ bl board_init_f /* run 1st part of board init code (from Flash) */
+
+ /* NOTREACHED - board_init_f() does not return */
+
+
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+ /* No FPU on MPC8xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ /* On the MPC8xx, this is a software emulation interrupt. It occurs
+ * for all unimplemented and illegal instructions.
+ */
+ STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = 0x2000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/* Cache functions.
+*/
+ .globl icache_enable
+icache_enable:
+ SYNC
+ lis r3, IDC_INVALL@h
+ mtspr IC_CST, r3
+ lis r3, IDC_ENABLE@h
+ mtspr IC_CST, r3
+ blr
+
+ .globl icache_disable
+icache_disable:
+ SYNC
+ lis r3, IDC_DISABLE@h
+ mtspr IC_CST, r3
+ blr
+
+ .globl icache_status
+icache_status:
+ mfspr r3, IC_CST
+ srwi r3, r3, 31 /* >>31 => select bit 0 */
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+#if 0
+ SYNC
+#endif
+#if 1
+ lis r3, 0x0400 /* Set cache mode with MMU off */
+ mtspr MD_CTR, r3
+#endif
+
+ lis r3, IDC_INVALL@h
+ mtspr DC_CST, r3
+#if 0
+ lis r3, DC_SFWT@h
+ mtspr DC_CST, r3
+#endif
+ lis r3, IDC_ENABLE@h
+ mtspr DC_CST, r3
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ SYNC
+ lis r3, IDC_DISABLE@h
+ mtspr DC_CST, r3
+ lis r3, IDC_INVALL@h
+ mtspr DC_CST, r3
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfspr r3, DC_CST
+ srwi r3, r3, 31 /* >>31 => select bit 0 */
+ blr
+
+ .globl dc_read
+dc_read:
+ mtspr DC_ADR, r3
+ mfspr r3, DC_DAT
+ blr
+
+/*
+ * unsigned int get_immr (unsigned int mask)
+ *
+ * return (mask ? (IMMR & mask) : IMMR);
+ */
+ .globl get_immr
+get_immr:
+ mr r4,r3 /* save mask */
+ mfspr r3, IMMR /* IMMR */
+ cmpwi 0,r4,0 /* mask != 0 ? */
+ beq 4f
+ and r3,r3,r4 /* IMMR & mask */
+4:
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+
+ .globl wr_ic_cst
+wr_ic_cst:
+ mtspr IC_CST, r3
+ blr
+
+ .globl rd_ic_cst
+rd_ic_cst:
+ mfspr r3, IC_CST
+ blr
+
+ .globl wr_ic_adr
+wr_ic_adr:
+ mtspr IC_ADR, r3
+ blr
+
+
+ .globl wr_dc_cst
+wr_dc_cst:
+ mtspr DC_CST, r3
+ blr
+
+ .globl rd_dc_cst
+rd_dc_cst:
+ mfspr r3, DC_CST
+ blr
+
+ .globl wr_dc_adr
+wr_dc_adr:
+ mtspr DC_ADR, r3
+ blr
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+ .globl relocate_code
+relocate_code:
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Global Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, CONFIG_SYS_CACHELINE_SIZE /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+ mtlr r0
+ blr
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 6f
+
+ li r0, 0
+5:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 5b
+6:
+
+ mr r3, r9 /* Global Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+ li r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+ bl trap_reloc
+
+ li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+ li r8, SystemCall - _start + EXC_OFF_SYS_RESET
+3:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 3b
+
+ li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
+ li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+4:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 4b
+
+ mtlr r4 /* restore link register */
+ blr
diff --git a/arch/powerpc/cpu/mpc8xx/traps.c b/arch/powerpc/cpu/mpc8xx/traps.c
new file mode 100644
index 0000000..f0ab78d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/traps.c
@@ -0,0 +1,232 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x02000000
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x000F0000) {
+ case (0x80000000>>12):
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (0x80000000>>13):
+ printf("Transfer error ack signal\n");
+ break;
+ case (0x80000000>>14):
+ printf("Data parity signal\n");
+ break;
+ case (0x80000000>>15):
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void SoftEmuException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xx/upatch.c b/arch/powerpc/cpu/mpc8xx/upatch.c
new file mode 100644
index 0000000..a8cb735
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/upatch.c
@@ -0,0 +1,194 @@
+#include <common.h>
+#include <commproc.h>
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCH) || \
+ defined(CONFIG_SYS_SMC_UCODE_PATCH)
+
+static void UcodeCopy (volatile cpm8xx_t *cpm);
+
+void cpm_load_patch (volatile immap_t *immr)
+{
+ immr->im_cpm.cp_rccr &= ~0x0003; /* Disable microcode program area */
+
+ UcodeCopy ((cpm8xx_t *)&immr->im_cpm); /* Copy ucode patch to DPRAM */
+#ifdef CONFIG_SYS_SPI_UCODE_PATCH
+ {
+ volatile spi_t *spi = (spi_t *) & immr->im_cpm.cp_dparam[PROFF_SPI];
+ /* Activate the microcode per the instructions in the microcode manual */
+ /* NOTE: We're only relocating the SPI parameters (not I2C). */
+ immr->im_cpm.cp_cpmcr1 = 0x802a; /* Write Trap register 1 value */
+ immr->im_cpm.cp_cpmcr2 = 0x8028; /* Write Trap register 2 value */
+ spi->spi_rpbase = CONFIG_SYS_SPI_DPMEM_OFFSET; /* Where to relocte SPI params */
+ }
+#endif
+
+#ifdef CONFIG_SYS_I2C_UCODE_PATCH
+ {
+ volatile iic_t *iip = (iic_t *) & immr->im_cpm.cp_dparam[PROFF_IIC];
+ /* Activate the microcode per the instructions in the microcode manual */
+ /* NOTE: We're only relocating the I2C parameters (not SPI). */
+ immr->im_cpm.cp_cpmcr3 = 0x802e; /* Write Trap register 3 value */
+ immr->im_cpm.cp_cpmcr4 = 0x802c; /* Write Trap register 4 value */
+ iip->iic_rpbase = CONFIG_SYS_I2C_DPMEM_OFFSET; /* Where to relocte I2C params */
+ }
+#endif
+
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+ {
+ volatile smc_uart_t *up = (smc_uart_t *) & immr->im_cpm.cp_dparam[PROFF_SMC1];
+ /* Activate the microcode per the instructions in the microcode manual */
+ /* NOTE: We're only relocating the SMC parameters. */
+ immr->im_cpm.cp_cpmcr1 = 0x8080; /* Write Trap register 1 value */
+ immr->im_cpm.cp_cpmcr2 = 0x8088; /* Write Trap register 2 value */
+ up->smc_rpbase = CONFIG_SYS_SMC_DPMEM_OFFSET; /* Where to relocte SMC params */
+ }
+#endif
+
+ /*
+ * Enable DPRAM microcode to execute from the first 512 bytes
+ * and a 256 byte extension of DPRAM.
+ */
+#ifdef CONFIG_SYS_SMC_UCODE_PATCH
+ immr->im_cpm.cp_rccr |= 0x0002;
+#else
+ immr->im_cpm.cp_rccr |= 0x0001;
+#endif
+}
+
+#if defined(CONFIG_SYS_I2C_UCODE_PATCH) || defined(CONFIG_SYS_SPI_UCODE_PATCh)
+static ulong patch_2000[] = {
+ 0x7FFFEFD9, 0x3FFD0000, 0x7FFB49F7, 0x7FF90000,
+ 0x5FEFADF7, 0x5F88ADF7, 0x5FEFAFF7, 0x5F88AFF7,
+ 0x3A9CFBC8, 0x77CAE1BB, 0xF4DE7FAD, 0xABAE9330,
+ 0x4E08FDCF, 0x6E0FAFF8, 0x7CCF76CF, 0xFDAFF9CF,
+ 0xABF88DC8, 0xAB5879F7, 0xB0927383, 0xDFD079F7,
+ 0xB090E6BB, 0xE5BBE74F, 0xB3FA6F0F, 0x6FFB76CE,
+ 0xEE0CF9CF, 0x2BFBEFEF, 0xCFEEF9CF, 0x76CEAD23,
+ 0x90B3DF99, 0x7FDDD0C1, 0x4BF847FD, 0x7CCF76CE,
+ 0xCFEF77CA, 0x7EAF7FAD, 0x7DFDF0B7, 0xEF7A7FCA,
+ 0x77CAFBC8, 0x6079E722, 0xFBC85FFF, 0xDFFF5FB3,
+ 0xFFFBFBC8, 0xF3C894A5, 0xE7C9EDF9, 0x7F9A7FAD,
+ 0x5F36AFE8, 0x5F5BFFDF, 0xDF95CB9E, 0xAF7D5FC3,
+ 0xAFED8C1B, 0x5FC3AFDD, 0x5FC5DF99, 0x7EFDB0B3,
+ 0x5FB3FFFE, 0xABAE5FB3, 0xFFFE5FD0, 0x600BE6BB,
+ 0x600B5FD0, 0xDFC827FB, 0xEFDF5FCA, 0xCFDE3A9C,
+ 0xE7C9EDF9, 0xF3C87F9E, 0x54CA7FED, 0x2D3A3637,
+ 0x756F7E9A, 0xF1CE37EF, 0x2E677FEE, 0x10EBADF8,
+ 0xEFDECFEA, 0xE52F7D9F, 0xE12BF1CE, 0x5F647E9A,
+ 0x4DF8CFEA, 0x5F717D9B, 0xEFEECFEA, 0x5F73E522,
+ 0xEFDE5F73, 0xCFDA0B61, 0x7385DF61, 0xE7C9EDF9,
+ 0x7E9A30D5, 0x1458BFFF, 0xF3C85FFF, 0xDFFFA7F8,
+ 0x5F5BBFFE, 0x7F7D10D0, 0x144D5F33, 0xBFFFAF78,
+ 0x5F5BBFFD, 0xA7F85F33, 0xBFFE77FD, 0x30BD4E08,
+ 0xFDCFE5FF, 0x6E0FAFF8, 0x7EEF7E9F, 0xFDEFF1CF,
+ 0x5F17ABF8, 0x0D5B5F5B, 0xFFEF79F7, 0x309EAFDD,
+ 0x5F3147F8, 0x5F31AFED, 0x7FDD50AF, 0x497847FD,
+ 0x7F9E7FED, 0x7DFD70A9, 0xEF7E7ECE, 0x6BA07F9E,
+ 0x2D227EFD, 0x30DB5F5B, 0xFFFD5F5B, 0xFFEF5F5B,
+ 0xFFDF0C9C, 0xAFED0A9A, 0xAFDD0C37, 0x5F37AFBD,
+ 0x7FBDB081, 0x5F8147F8,
+};
+
+static ulong patch_2F00[] = {
+ 0x3E303430, 0x34343737, 0xABBF9B99, 0x4B4FBDBD,
+ 0x59949334, 0x9FFF37FB, 0x9B177DD9, 0x936956BB,
+ 0xFBDD697B, 0xDD2FD113, 0x1DB9F7BB, 0x36313963,
+ 0x79373369, 0x3193137F, 0x7331737A, 0xF7BB9B99,
+ 0x9BB19795, 0x77FDFD3D, 0x573B773F, 0x737933F7,
+ 0xB991D115, 0x31699315, 0x31531694, 0xBF4FBDBD,
+ 0x35931497, 0x35376956, 0xBD697B9D, 0x96931313,
+ 0x19797937, 0x69350000,
+};
+#else
+
+static ulong patch_2000[] = {
+ 0x3fff0000, 0x3ffd0000, 0x3ffb0000, 0x3ff90000,
+ 0x5fefeff8, 0x5f91eff8, 0x3ff30000, 0x3ff10000,
+ 0x3a11e710, 0xedf0ccb9, 0xf318ed66, 0x7f0e5fe2,
+ 0x7fedbb38, 0x3afe7468, 0x7fedf4d8, 0x8ffbb92d,
+ 0xb83b77fd, 0xb0bb5eb9, 0xdfda7fed, 0x90bde74d,
+ 0x6f0dcbd3, 0xe7decfed, 0xcb50cfed, 0xcfeddf6d,
+ 0x914d4f74, 0x5eaedfcb, 0x9ee0e7df, 0xefbb6ffb,
+ 0xe7ef7f0e, 0x9ee57fed, 0xebb7effa, 0xeb30affb,
+ 0x7fea90b3, 0x7e0cf09f, 0xbffff318, 0x5fffdfff,
+ 0xac35efea, 0x7fce1fc1, 0xe2ff5fbd, 0xaffbe2ff,
+ 0x5fbfaffb, 0xf9a87d0f, 0xaef8770f, 0x7d0fb0a2,
+ 0xeffbbfff, 0xcfef5fba, 0x7d0fbfff, 0x5fba4cf8,
+ 0x7fddd09b, 0x49f847fd, 0x7efdf097, 0x7fedfffd,
+ 0x7dfdf093, 0xef7e7e1e, 0x5fba7f0e, 0x3a11e710,
+ 0xedf0cc87, 0xfb18ad0a, 0x1f85bbb8, 0x74283b7e,
+ 0x7375e4bb, 0x2ab64fb8, 0x5c7de4bb, 0x32fdffbf,
+ 0x5f0843f8, 0x7ce3e1bb, 0xe74f7ded, 0x6f0f4fe8,
+ 0xc7ba32be, 0x73f2efeb, 0x600b4f78, 0xe5bb760b,
+ 0x5388aef8, 0x4ef80b6a, 0xcfef9ee5, 0xabf8751f,
+ 0xefef5b88, 0x741f4fe8, 0x751e760d, 0x7fdb70dd,
+ 0x741cafce, 0xefcc7fce, 0x751e7088, 0x741ce7bb,
+ 0x334ecfed, 0xafdbefeb, 0xe5bb760b, 0x53ceaef8,
+ 0xafe8e7eb, 0x4bf8771e, 0x7e007fed, 0x4fcbe2cc,
+ 0x7fbc3085, 0x7b0f7a0f, 0x34b177fd, 0xb0e75e93,
+ 0xdf313e3b, 0xaf78741f, 0x741f30cc, 0xcfef5f08,
+ 0x741f3e88, 0xafb8771e, 0x5f437fed, 0x0bafe2cc,
+ 0x741ccfec, 0xe5ca53a9, 0x6fcb4f74, 0x5e89df27,
+ 0x2a923d14, 0x4b8fdf0c, 0x751f741c, 0x6c1eeffa,
+ 0xefea7fce, 0x6ffc309a, 0xefec3fca, 0x308fdf0a,
+ 0xadf85e7a, 0xaf7daefd, 0x5e7adf0a, 0x5e7aafdd,
+ 0x761f1088, 0x1e7c7efd, 0x3089fffe, 0x4908fb18,
+ 0x5fffdfff, 0xafbbf0f7, 0x4ef85f43, 0xadf81489,
+ 0x7a0f7089, 0xcfef5089, 0x7a0fdf0c, 0x5e7cafed,
+ 0xbc6e780f, 0xefef780f, 0xefef790f, 0xa7f85eeb,
+ 0xffef790f, 0xefef790f, 0x1489df0a, 0x5e7aadfd,
+ 0x5f09fffb, 0xe79aded9, 0xeff96079, 0x607ae79a,
+ 0xded8eff9, 0x60795edb, 0x607acfef, 0xefefefdf,
+ 0xefbfef7f, 0xeeffedff, 0xebffe7ff, 0xafefafdf,
+ 0xafbfaf7f, 0xaeffadff, 0xabffa7ff, 0x6fef6fdf,
+ 0x6fbf6f7f, 0x6eff6dff, 0x6bff67ff, 0x2fef2fdf,
+ 0x2fbf2f7f, 0x2eff2dff, 0x2bff27ff, 0x4e08fd1f,
+ 0xe5ff6e0f, 0xaff87eef, 0x7e0ffdef, 0xf11f6079,
+ 0xabf8f51e, 0x7e0af11c, 0x37cfae16, 0x7fec909a,
+ 0xadf8efdc, 0xcfeae52f, 0x7d0fe12b, 0xf11c6079,
+ 0x7e0a4df8, 0xcfea5ea0, 0x7d0befec, 0xcfea5ea2,
+ 0xe522efdc, 0x5ea2cfda, 0x4e08fd1f, 0x6e0faff8,
+ 0x7c1f761f, 0xfdeff91f, 0x6079abf8, 0x761cee00,
+ 0xf91f2bfb, 0xefefcfec, 0xf91f6079, 0x761c27fb,
+ 0xefdf5e83, 0xcfdc7fdd, 0x50f84bf8, 0x47fd7c1f,
+ 0x761ccfcf, 0x7eef7fed, 0x7dfd70ef, 0xef7e7f1e,
+ 0x771efb18, 0x6079e722, 0xe6bbe5bb, 0x2e66e5bb,
+ 0x600b2ee1, 0xe2bbe2bb, 0xe2bbe2bb, 0x2f5ee2bb,
+ 0xe2bb2ff9, 0x6079e2bb,
+};
+
+static ulong patch_2F00[] = {
+ 0x30303030, 0x3e3e3030, 0xaf79b9b3, 0xbaa3b979,
+ 0x9693369f, 0x79f79777, 0x97333fff, 0xfb3b9e9f,
+ 0x79b91d11, 0x9e13f3ff, 0x3f9b6bd9, 0xe173d136,
+ 0x695669d1, 0x697b3daf, 0x79b93a3a, 0x3f979f91,
+ 0x379ff976, 0xf99777fd, 0x9779737d, 0xe9d6bbf9,
+ 0xbfffd9df, 0x97f7fd97, 0x6f7b9bff, 0xf9bd9683,
+ 0x397db973, 0xd97b3b9f, 0xd7f9f733, 0x9993bb9e,
+ 0xe1f9ef93, 0x73773337, 0xb936917d, 0x11f87379,
+ 0xb979d336, 0x8b7ded73, 0x1b7d9337, 0x31f3f22f,
+ 0x3f2327ee, 0xeeeeeeee, 0xeeeeeeee, 0xeeeeeeee,
+ 0xeeeeee4b, 0xf4fbdbd2, 0x58bb1878, 0x577fdfd2,
+ 0xd573b773, 0xf7374b4f, 0xbdbd25b8, 0xb177d2d1,
+ 0x7376856b, 0xbfdd687b, 0xdd2fff8f, 0x78ffff8f,
+ 0xf22f0000,
+};
+#endif
+
+static void UcodeCopy (volatile cpm8xx_t *cpm)
+{
+ vu_long *p;
+ int i;
+
+ p = (vu_long *)&(cpm->cp_dpmem[0x0000]);
+ for (i=0; i < sizeof(patch_2000)/4; ++i) {
+ p[i] = patch_2000[i];
+ }
+
+ p = (vu_long *)&(cpm->cp_dpmem[0x0F00]);
+ for (i=0; i < sizeof(patch_2F00)/4; ++i) {
+ p[i] = patch_2F00[i];
+ }
+}
+
+#endif /* CONFIG_SYS_I2C_UCODE_PATCH, CONFIG_SYS_SPI_UCODE_PATCH */
diff --git a/arch/powerpc/cpu/mpc8xx/video.c b/arch/powerpc/cpu/mpc8xx/video.c
new file mode 100644
index 0000000..1bbf4cc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/video.c
@@ -0,0 +1,1331 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ * (C) Copyright 2002
+ * Wolfgang Denk, wd@denx.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* #define DEBUG */
+
+/************************************************************************/
+/* ** HEADER FILES */
+/************************************************************************/
+
+#include <stdarg.h>
+#include <common.h>
+#include <config.h>
+#include <version.h>
+#include <i2c.h>
+#include <linux/types.h>
+#include <stdio_dev.h>
+
+#ifdef CONFIG_VIDEO
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/************************************************************************/
+/* ** DEBUG SETTINGS */
+/************************************************************************/
+
+#if 0
+#define VIDEO_DEBUG_COLORBARS /* Force colorbars output */
+#endif
+
+/************************************************************************/
+/* ** VIDEO MODE SETTINGS */
+/************************************************************************/
+
+#if 0
+#define VIDEO_MODE_EXTENDED /* Allow screen size bigger than visible area */
+#define VIDEO_MODE_NTSC
+#endif
+
+#define VIDEO_MODE_PAL
+
+#if 0
+#define VIDEO_BLINK /* This enables cursor blinking (under construction) */
+#endif
+
+#define VIDEO_INFO /* Show U-Boot information */
+#define VIDEO_INFO_X VIDEO_LOGO_WIDTH+8
+#define VIDEO_INFO_Y 16
+
+/************************************************************************/
+/* ** VIDEO ENCODER CONSTANTS */
+/************************************************************************/
+
+#ifdef CONFIG_VIDEO_ENCODER_AD7176
+
+#include <video_ad7176.h> /* Sets encoder data, mode, and visible and active area */
+
+#define VIDEO_I2C 1
+#define VIDEO_I2C_ADDR CONFIG_VIDEO_ENCODER_AD7176_ADDR
+#endif
+
+#ifdef CONFIG_VIDEO_ENCODER_AD7177
+
+#include <video_ad7177.h> /* Sets encoder data, mode, and visible and active area */
+
+#define VIDEO_I2C 1
+#define VIDEO_I2C_ADDR CONFIG_VIDEO_ENCODER_AD7177_ADDR
+#endif
+
+#ifdef CONFIG_VIDEO_ENCODER_AD7179
+
+#include <video_ad7179.h> /* Sets encoder data, mode, and visible and active area */
+
+#define VIDEO_I2C 1
+#define VIDEO_I2C_ADDR CONFIG_VIDEO_ENCODER_AD7179_ADDR
+#endif
+
+/************************************************************************/
+/* ** VIDEO MODE CONSTANTS */
+/************************************************************************/
+
+#ifdef VIDEO_MODE_EXTENDED
+#define VIDEO_COLS VIDEO_ACTIVE_COLS
+#define VIDEO_ROWS VIDEO_ACTIVE_ROWS
+#else
+#define VIDEO_COLS VIDEO_VISIBLE_COLS
+#define VIDEO_ROWS VIDEO_VISIBLE_ROWS
+#endif
+
+#define VIDEO_PIXEL_SIZE (VIDEO_MODE_BPP/8)
+#define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE) /* Total size of buffer */
+#define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2) /* Number of ints */
+#define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE) /* Number of bytes per line */
+#define VIDEO_BURST_LEN (VIDEO_COLS/8)
+
+#ifdef VIDEO_MODE_YUYV
+#define VIDEO_BG_COL 0x80D880D8 /* Background color in YUYV format */
+#else
+#define VIDEO_BG_COL 0xF8F8F8F8 /* Background color in RGB format */
+#endif
+
+/************************************************************************/
+/* ** FONT AND LOGO DATA */
+/************************************************************************/
+
+#include <video_font.h> /* Get font data, width and height */
+#include <video_font_data.h>
+
+#ifdef CONFIG_VIDEO_LOGO
+#include <video_logo.h> /* Get logo data, width and height */
+
+#define VIDEO_LOGO_WIDTH DEF_U_BOOT_LOGO_WIDTH
+#define VIDEO_LOGO_HEIGHT DEF_U_BOOT_LOGO_HEIGHT
+#define VIDEO_LOGO_ADDR &u_boot_logo
+#endif
+
+/************************************************************************/
+/* ** VIDEO CONTROLLER CONSTANTS */
+/************************************************************************/
+
+/* VCCR - VIDEO CONTROLLER CONFIGURATION REGISTER */
+
+#define VIDEO_VCCR_VON 0 /* Video controller ON */
+#define VIDEO_VCCR_CSRC 1 /* Clock source */
+#define VIDEO_VCCR_PDF 13 /* Pixel display format */
+#define VIDEO_VCCR_IEN 11 /* Interrupt enable */
+
+/* VSR - VIDEO STATUS REGISTER */
+
+#define VIDEO_VSR_CAS 6 /* Active set */
+#define VIDEO_VSR_EOF 0 /* End of frame */
+
+/* VCMR - VIDEO COMMAND REGISTER */
+
+#define VIDEO_VCMR_BD 0 /* Blank display */
+#define VIDEO_VCMR_ASEL 1 /* Active set selection */
+
+/* VBCB - VIDEO BACKGROUND COLOR BUFFER REGISTER */
+
+#define VIDEO_BCSR4_RESET_BIT 21 /* BCSR4 - Extern video encoder reset */
+#define VIDEO_BCSR4_EXTCLK_BIT 22 /* BCSR4 - Extern clock enable */
+#define VIDEO_BCSR4_VIDLED_BIT 23 /* BCSR4 - Video led disable */
+
+/************************************************************************/
+/* ** CONSOLE CONSTANTS */
+/************************************************************************/
+
+#ifdef CONFIG_VIDEO_LOGO
+#define CONSOLE_ROWS ((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT)
+#define VIDEO_LOGO_SKIP (VIDEO_COLS - VIDEO_LOGO_WIDTH)
+#else
+#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
+#endif
+
+#define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
+#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
+#define CONSOLE_ROW_FIRST (video_console_address)
+#define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
+#define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
+#define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+
+/*
+ * Simple color definitions
+ */
+#define CONSOLE_COLOR_BLACK 0
+#define CONSOLE_COLOR_RED 1
+#define CONSOLE_COLOR_GREEN 2
+#define CONSOLE_COLOR_YELLOW 3
+#define CONSOLE_COLOR_BLUE 4
+#define CONSOLE_COLOR_MAGENTA 5
+#define CONSOLE_COLOR_CYAN 6
+#define CONSOLE_COLOR_GREY 13
+#define CONSOLE_COLOR_GREY2 14
+#define CONSOLE_COLOR_WHITE 15 /* Must remain last / highest */
+
+/************************************************************************/
+/* ** BITOPS MACROS */
+/************************************************************************/
+
+#define HISHORT(i) ((i >> 16)&0xffff)
+#define LOSHORT(i) (i & 0xffff)
+#define HICHAR(s) ((i >> 8)&0xff)
+#define LOCHAR(s) (i & 0xff)
+#define HI(c) ((c >> 4)&0xf)
+#define LO(c) (c & 0xf)
+#define SWAPINT(i) (HISHORT(i) | (LOSHORT(i) << 16))
+#define SWAPSHORT(s) (HICHAR(s) | (LOCHAR(s) << 8))
+#define SWAPCHAR(c) (HI(c) | (LO(c) << 4))
+#define BITMASK(b) (1 << (b))
+#define GETBIT(v,b) (((v) & BITMASK(b)) > 0)
+#define SETBIT(v,b,d) (v = (((d)>0) ? (v) | BITMASK(b): (v) & ~BITMASK(b)))
+
+/************************************************************************/
+/* ** STRUCTURES */
+/************************************************************************/
+
+typedef struct {
+ unsigned char V, Y1, U, Y2;
+} tYUYV;
+
+/* This structure is based on the Video Ram in the MPC823. */
+typedef struct VRAM {
+ unsigned hx:2, /* Horizontal sync */
+ vx:2, /* Vertical sync */
+ fx:2, /* Frame */
+ bx:2, /* Blank */
+ res1:6, /* Reserved */
+ vds:2, /* Video Data Select */
+ inter:1, /* Interrupt */
+ res2:2, /* Reserved */
+ lcyc:11, /* Loop/video cycles */
+ lp:1, /* Loop start/end */
+ lst:1; /* Last entry */
+} VRAM;
+
+/************************************************************************/
+/* ** VARIABLES */
+/************************************************************************/
+
+static int
+ video_panning_range_x = 0, /* Video mode invisible pixels x range */
+ video_panning_range_y = 0, /* Video mode invisible pixels y range */
+ video_panning_value_x = 0, /* Video mode x panning value (absolute) */
+ video_panning_value_y = 0, /* Video mode y panning value (absolute) */
+ video_panning_factor_x = 0, /* Video mode x panning value (-127 +127) */
+ video_panning_factor_y = 0, /* Video mode y panning value (-127 +127) */
+ console_col = 0, /* Cursor col */
+ console_row = 0, /* Cursor row */
+ video_palette[16]; /* Our palette */
+
+static const int video_font_draw_table[] =
+ { 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff };
+
+static char
+ video_color_fg = 0, /* Current fg color index (0-15) */
+ video_color_bg = 0, /* Current bg color index (0-15) */
+ video_enable = 0; /* Video has been initialized? */
+
+static void
+ *video_fb_address, /* Frame buffer address */
+ *video_console_address; /* Console frame buffer start address */
+
+/************************************************************************/
+/* ** MEMORY FUNCTIONS (32bit) */
+/************************************************************************/
+
+static void memsetl (int *p, int c, int v)
+{
+ while (c--)
+ *(p++) = v;
+}
+
+static void memcpyl (int *d, int *s, int c)
+{
+ while (c--)
+ *(d++) = *(s++);
+}
+
+/************************************************************************/
+/* ** VIDEO DRAWING AND COLOR FUNCTIONS */
+/************************************************************************/
+
+static int video_maprgb (int r, int g, int b)
+{
+#ifdef VIDEO_MODE_YUYV
+ unsigned int pR, pG, pB;
+ tYUYV YUYV;
+ unsigned int *ret = (unsigned int *) &YUYV;
+
+ /* Transform (0-255) components to (0-100) */
+
+ pR = r * 100 / 255;
+ pG = g * 100 / 255;
+ pB = b * 100 / 255;
+
+ /* Calculate YUV values (0-255) from RGB beetween 0-100 */
+
+ YUYV.Y1 = YUYV.Y2 = 209 * (pR + pG + pB) / 300 + 16;
+ YUYV.U = pR - (pG * 3 / 4) - (pB / 4) + 128;
+ YUYV.V = pB - (pR / 4) - (pG * 3 / 4) + 128;
+ return *ret;
+#endif
+#ifdef VIDEO_MODE_RGB
+ return ((r >> 3) << 11) | ((g > 2) << 6) | (b >> 3);
+#endif
+}
+
+static void video_setpalette (int color, int r, int g, int b)
+{
+ color &= 0xf;
+
+ video_palette[color] = video_maprgb (r, g, b);
+
+ /* Swap values if our panning offset is odd */
+ if (video_panning_value_x & 1)
+ video_palette[color] = SWAPINT (video_palette[color]);
+}
+
+static void video_fill (int color)
+{
+ memsetl (video_fb_address, VIDEO_PIX_BLOCKS, color);
+}
+
+static void video_setfgcolor (int i)
+{
+ video_color_fg = i & 0xf;
+}
+
+static void video_setbgcolor (int i)
+{
+ video_color_bg = i & 0xf;
+}
+
+static int video_pickcolor (int i)
+{
+ return video_palette[i & 0xf];
+}
+
+/* Absolute console plotting functions */
+
+#ifdef VIDEO_BLINK
+static void video_revchar (int xx, int yy)
+{
+ int rows;
+ u8 *dest;
+
+ dest = video_fb_address + yy * VIDEO_LINE_LEN + xx * 2;
+
+ for (rows = VIDEO_FONT_HEIGHT; rows--; dest += VIDEO_LINE_LEN) {
+ switch (VIDEO_FONT_WIDTH) {
+ case 16:
+ ((u32 *) dest)[6] ^= 0xffffffff;
+ ((u32 *) dest)[7] ^= 0xffffffff;
+ /* FALL THROUGH */
+ case 12:
+ ((u32 *) dest)[4] ^= 0xffffffff;
+ ((u32 *) dest)[5] ^= 0xffffffff;
+ /* FALL THROUGH */
+ case 8:
+ ((u32 *) dest)[2] ^= 0xffffffff;
+ ((u32 *) dest)[3] ^= 0xffffffff;
+ /* FALL THROUGH */
+ case 4:
+ ((u32 *) dest)[0] ^= 0xffffffff;
+ ((u32 *) dest)[1] ^= 0xffffffff;
+ }
+ }
+}
+#endif
+
+static void video_drawchars (int xx, int yy, unsigned char *s, int count)
+{
+ u8 *cdat, *dest, *dest0;
+ int rows, offset, c;
+ u32 eorx, fgx, bgx;
+
+ offset = yy * VIDEO_LINE_LEN + xx * 2;
+ dest0 = video_fb_address + offset;
+
+ fgx = video_pickcolor (video_color_fg);
+ bgx = video_pickcolor (video_color_bg);
+
+ if (xx & 1) {
+ fgx = SWAPINT (fgx);
+ bgx = SWAPINT (bgx);
+ }
+
+ eorx = fgx ^ bgx;
+
+ switch (VIDEO_FONT_WIDTH) {
+ case 4:
+ case 8:
+ while (count--) {
+ c = *s;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
+ rows--;
+ dest += VIDEO_LINE_LEN) {
+ u8 bits = *cdat++;
+
+ ((u32 *) dest)[0] =
+ (video_font_draw_table[bits >> 6] & eorx) ^ bgx;
+ ((u32 *) dest)[1] =
+ (video_font_draw_table[bits >> 4 & 3] & eorx) ^ bgx;
+ if (VIDEO_FONT_WIDTH == 8) {
+ ((u32 *) dest)[2] =
+ (video_font_draw_table[bits >> 2 & 3] & eorx) ^ bgx;
+ ((u32 *) dest)[3] =
+ (video_font_draw_table[bits & 3] & eorx) ^ bgx;
+ }
+ }
+ dest0 += VIDEO_FONT_WIDTH * 2;
+ s++;
+ }
+ break;
+ case 12:
+ case 16:
+ while (count--) {
+ cdat = video_fontdata + (*s) * (VIDEO_FONT_HEIGHT << 1);
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--;
+ dest += VIDEO_LINE_LEN) {
+ u8 bits = *cdat++;
+
+ ((u32 *) dest)[0] =
+ (video_font_draw_table[bits >> 6] & eorx) ^ bgx;
+ ((u32 *) dest)[1] =
+ (video_font_draw_table[bits >> 4 & 3] & eorx) ^ bgx;
+ ((u32 *) dest)[2] =
+ (video_font_draw_table[bits >> 2 & 3] & eorx) ^ bgx;
+ ((u32 *) dest)[3] =
+ (video_font_draw_table[bits & 3] & eorx) ^ bgx;
+ bits = *cdat++;
+ ((u32 *) dest)[4] =
+ (video_font_draw_table[bits >> 6] & eorx) ^ bgx;
+ ((u32 *) dest)[5] =
+ (video_font_draw_table[bits >> 4 & 3] & eorx) ^ bgx;
+ if (VIDEO_FONT_WIDTH == 16) {
+ ((u32 *) dest)[6] =
+ (video_font_draw_table[bits >> 2 & 3] & eorx) ^ bgx;
+ ((u32 *) dest)[7] =
+ (video_font_draw_table[bits & 3] & eorx) ^ bgx;
+ }
+ }
+ s++;
+ dest0 += VIDEO_FONT_WIDTH * 2;
+ }
+ break;
+ }
+}
+
+static inline void video_drawstring (int xx, int yy, char *s)
+{
+ video_drawchars (xx, yy, (unsigned char *)s, strlen (s));
+}
+
+/* Relative to console plotting functions */
+
+static void video_putchars (int xx, int yy, unsigned char *s, int count)
+{
+#ifdef CONFIG_VIDEO_LOGO
+ video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, s, count);
+#else
+ video_drawchars (xx, yy, s, count);
+#endif
+}
+
+static void video_putchar (int xx, int yy, unsigned char c)
+{
+#ifdef CONFIG_VIDEO_LOGO
+ video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1);
+#else
+ video_drawchars (xx, yy, &c, 1);
+#endif
+}
+
+static inline void video_putstring (int xx, int yy, unsigned char *s)
+{
+ video_putchars (xx, yy, (unsigned char *)s, strlen ((char *)s));
+}
+
+/************************************************************************/
+/* ** VIDEO CONTROLLER LOW-LEVEL FUNCTIONS */
+/************************************************************************/
+
+#if !defined(CONFIG_RRVISION)
+static void video_mode_dupefield (VRAM * source, VRAM * dest, int entries)
+{
+ int i;
+
+ for (i = 0; i < entries; i++) {
+ dest[i] = source[i]; /* Copy the entire record */
+ dest[i].fx = (!dest[i].fx) * 3; /* Negate field bit */
+ }
+
+ dest[0].lcyc++; /* Add a cycle to the first entry */
+ dest[entries - 1].lst = 1; /* Set end of ram entries */
+}
+#endif
+
+static void inline video_mode_addentry (VRAM * vr,
+ int Hx, int Vx, int Fx, int Bx,
+ int VDS, int INT, int LCYC, int LP, int LST)
+{
+ vr->hx = Hx;
+ vr->vx = Vx;
+ vr->fx = Fx;
+ vr->bx = Bx;
+ vr->vds = VDS;
+ vr->inter = INT;
+ vr->lcyc = LCYC;
+ vr->lp = LP;
+ vr->lst = LST;
+}
+
+#define ADDENTRY(a,b,c,d,e,f,g,h,i) video_mode_addentry(&vr[entry++],a,b,c,d,e,f,g,h,i)
+
+static int video_mode_generate (void)
+{
+ immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+ VRAM *vr = (VRAM *) (((void *) immap) + 0xb00); /* Pointer to the VRAM table */
+ int DX, X1, X2, DY, Y1, Y2, entry = 0, fifo;
+
+ /* CHECKING PARAMETERS */
+
+ if (video_panning_factor_y < -128)
+ video_panning_factor_y = -128;
+
+ if (video_panning_factor_y > 128)
+ video_panning_factor_y = 128;
+
+ if (video_panning_factor_x < -128)
+ video_panning_factor_x = -128;
+
+ if (video_panning_factor_x > 128)
+ video_panning_factor_x = 128;
+
+ /* Setting panning */
+
+ DX = video_panning_range_x = (VIDEO_ACTIVE_COLS - VIDEO_COLS) * 2;
+ DY = video_panning_range_y = (VIDEO_ACTIVE_ROWS - VIDEO_ROWS) / 2;
+
+ video_panning_value_x = (video_panning_factor_x + 128) * DX / 256;
+ video_panning_value_y = (video_panning_factor_y + 128) * DY / 256;
+
+ /* We assume these are burst units (multiplied by 2, we need it pari) */
+ X1 = video_panning_value_x & 0xfffe;
+ X2 = DX - X1;
+
+ /* We assume these are field line units (divided by 2, we need it pari) */
+ Y1 = video_panning_value_y & 0xfffe;
+ Y2 = DY - Y1;
+
+ debug("X1=%d, X2=%d, Y1=%d, Y2=%d, DX=%d, DY=%d VIDEO_COLS=%d \n",
+ X1, X2, Y1, Y2, DX, DY, VIDEO_COLS);
+
+#ifdef VIDEO_MODE_NTSC
+/*
+ * Hx Vx Fx Bx VDS INT LCYC LP LST
+ *
+ * Retrace blanking
+ */
+ ADDENTRY (0, 0, 3, 0, 1, 0, 3, 1, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 243, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 1440, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+/*
+ * Vertical blanking
+ */
+ ADDENTRY (0, 0, 0, 0, 1, 0, 18, 1, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 243, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+/*
+ * Odd field active area (TOP)
+ */
+ if (Y1 > 0) {
+ ADDENTRY (0, 0, 0, 0, 1, 0, Y1, 1, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 235, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+ }
+/*
+ * Odd field active area
+ */
+ ADDENTRY (0, 0, 0, 0, 1, 0, 240 - DY, 1, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 235, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, 8 + X1, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 0, 0, VIDEO_COLS * 2, 0, 0);
+
+ if (X2 > 0)
+ ADDENTRY (3, 0, 0, 3, 1, 0, X2, 0, 0);
+
+ ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+
+/*
+ * Odd field active area (BOTTOM)
+ */
+ if (Y1 > 0) {
+ ADDENTRY (0, 0, 0, 0, 1, 0, Y2, 1, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 235, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+ }
+/*
+ * Vertical blanking
+ */
+ ADDENTRY (0, 0, 0, 0, 1, 0, 4, 1, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 243, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 32, 1, 0);
+/*
+ * Vertical blanking
+ */
+ ADDENTRY (0, 0, 3, 0, 1, 0, 19, 1, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 243, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 1440, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+/*
+ * Even field active area (TOP)
+ */
+ if (Y1 > 0) {
+ ADDENTRY (0, 0, 3, 0, 1, 0, Y1, 1, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 235, 0, 0);
+ ADDENTRY (3, 0, 3, 3, 1, 0, 1448, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+ }
+/*
+ * Even field active area (CENTER)
+ */
+ ADDENTRY (0, 0, 3, 0, 1, 0, 240 - DY, 1, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 235, 0, 0);
+ ADDENTRY (3, 0, 3, 3, 1, 0, 8 + X1, 0, 0);
+ ADDENTRY (3, 0, 3, 3, 0, 0, VIDEO_COLS * 2, 0, 0);
+
+ if (X2 > 0)
+ ADDENTRY (3, 0, 3, 3, 1, 0, X2, 0, 0);
+
+ ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+/*
+ * Even field active area (BOTTOM)
+ */
+ if (Y1 > 0) {
+ ADDENTRY (0, 0, 3, 0, 1, 0, Y2, 1, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 235, 0, 0);
+ ADDENTRY (3, 0, 3, 3, 1, 0, 1448, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 32, 1, 0);
+ }
+/*
+ * Vertical blanking
+ */
+ ADDENTRY (0, 0, 3, 0, 1, 0, 1, 1, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 243, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 0, 1440, 0, 0);
+ ADDENTRY (3, 0, 3, 0, 1, 1, 32, 1, 1);
+#endif
+
+#ifdef VIDEO_MODE_PAL
+
+#if defined(CONFIG_RRVISION)
+
+#define HPW 160 /* horizontal pulse width (was 139) */
+#define VPW 2 /* vertical pulse width */
+#define HBP 104 /* horizontal back porch (was 112) */
+#define VBP 19 /* vertical back porch (was 19) */
+#define VID_R 240 /* number of rows */
+
+ debug ("[VIDEO CTRL] Starting to add controller entries...");
+/*
+ * Even field
+ */
+ ADDENTRY (0, 3, 0, 3, 1, 0, 2, 0, 0);
+ ADDENTRY (0, 0, 0, 3, 1, 0, HPW, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 0, 0);
+
+ ADDENTRY (0, 0, 0, 3, 1, 0, VPW, 1, 0);
+ ADDENTRY (0, 0, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+
+ ADDENTRY (0, 3, 0, 3, 1, 0, VBP, 1, 0);
+ ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+/*
+ * Active area
+ */
+ ADDENTRY (0, 3, 0, 3, 1, 0, VID_R , 1, 0);
+ ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, HBP, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, 72, 1, 1);
+
+ ADDENTRY (0, 3, 0, 3, 1, 0, 51, 1, 0);
+ ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, HBP +(VIDEO_COLS * 2) + 72 , 1, 0);
+/*
+ * Odd field
+ */
+ ADDENTRY (0, 3, 0, 3, 1, 0, 2, 0, 0);
+ ADDENTRY (0, 0, 0, 3, 1, 0, HPW, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 0, 0);
+
+ ADDENTRY (0, 0, 0, 3, 1, 0, VPW+1, 1, 0);
+ ADDENTRY (0, 0, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+
+ ADDENTRY (0, 3, 0, 3, 1, 0, VBP, 1, 0);
+ ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 1, 0);
+/*
+ * Active area
+ */
+ ADDENTRY (0, 3, 0, 3, 1, 0, VID_R , 1, 0);
+ ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, HBP, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, 72, 1, 1);
+
+ ADDENTRY (0, 3, 0, 3, 1, 0, 51, 1, 0);
+ ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
+ ADDENTRY (3, 3, 0, 3, 1, 0, HBP +(VIDEO_COLS * 2) + 72 , 1, 0);
+
+ debug ("done\n");
+
+#else /* !CONFIG_RRVISION */
+
+/*
+ * Hx Vx Fx Bx VDS INT LCYC LP LST
+ *
+ * vertical; blanking
+ */
+ ADDENTRY (0, 0, 0, 0, 1, 0, 22, 1, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 263, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+/*
+ * active area (TOP)
+ */
+ if (Y1 > 0) {
+ ADDENTRY (0, 0, 0, 0, 1, 0, Y1, 1, 0); /* 11? */
+ ADDENTRY (3, 0, 0, 0, 1, 0, 255, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+ }
+/*
+ * field active area (CENTER)
+ */
+ ADDENTRY (0, 0, 0, 0, 1, 0, 288 - DY, 1, 0); /* 265? */
+ ADDENTRY (3, 0, 0, 0, 1, 0, 255, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, 8 + X1, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 0, 0, VIDEO_COLS * 2, 0, 0);
+
+ if (X2 > 0)
+ ADDENTRY (3, 0, 0, 1, 1, 0, X2, 0, 0);
+
+ ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+/*
+ * field active area (BOTTOM)
+ */
+ if (Y2 > 0) {
+ ADDENTRY (0, 0, 0, 0, 1, 0, Y2, 1, 0); /* 12? */
+ ADDENTRY (3, 0, 0, 0, 1, 0, 255, 0, 0);
+ ADDENTRY (3, 0, 0, 3, 1, 0, 1448, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+ }
+/*
+ * field vertical; blanking
+ */
+ ADDENTRY (0, 0, 0, 0, 1, 0, 2, 1, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 263, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 1440, 0, 0);
+ ADDENTRY (3, 0, 0, 0, 1, 0, 24, 1, 0);
+/*
+ * Create the other field (like this, but whit other field selected,
+ * one more cycle loop and a last identifier)
+ */
+ video_mode_dupefield (vr, &vr[entry], entry);
+#endif /* CONFIG_RRVISION */
+
+#endif /* VIDEO_MODE_PAL */
+
+ /* See what FIFO are we using */
+ fifo = GETBIT (immap->im_vid.vid_vsr, VIDEO_VSR_CAS);
+
+ /* Set number of lines and burst (only one frame for now) */
+ if (fifo) {
+ immap->im_vid.vid_vfcr0 = VIDEO_BURST_LEN |
+ (VIDEO_BURST_LEN << 8) | ((VIDEO_ROWS / 2) << 19);
+ } else {
+ immap->im_vid.vid_vfcr1 = VIDEO_BURST_LEN |
+ (VIDEO_BURST_LEN << 8) | ((VIDEO_ROWS / 2) << 19);
+ }
+
+ SETBIT (immap->im_vid.vid_vcmr, VIDEO_VCMR_ASEL, !fifo);
+
+/*
+ * Wait until changes are applied (not done)
+ * while (GETBIT(immap->im_vid.vid_vsr, VIDEO_VSR_CAS) == fifo) ;
+ */
+
+ /* Return number of VRAM entries */
+ return entry * 2;
+}
+
+static void video_encoder_init (void)
+{
+#ifdef VIDEO_I2C
+ int rc;
+
+ /* Initialize the I2C */
+ debug ("[VIDEO ENCODER] Initializing I2C bus...\n");
+ i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+#ifdef CONFIG_FADS
+ /* Reset ADV7176 chip */
+ debug ("[VIDEO ENCODER] Resetting encoder...\n");
+ (*(int *) BCSR4) &= ~(1 << 21);
+
+ /* Wait for 5 ms inside the reset */
+ debug ("[VIDEO ENCODER] Waiting for encoder reset...\n");
+ udelay (5000);
+
+ /* Take ADV7176 out of reset */
+ (*(int *) BCSR4) |= 1 << 21;
+
+ /* Wait for 5 ms after the reset */
+ udelay (5000);
+#endif /* CONFIG_FADS */
+
+ /* Send configuration */
+#ifdef DEBUG
+ {
+ int i;
+
+ puts ("[VIDEO ENCODER] Configuring the encoder...\n");
+
+ printf ("Sending %zu bytes (@ %08lX) to I2C 0x%lX:\n ",
+ sizeof(video_encoder_data),
+ (ulong)video_encoder_data,
+ (ulong)VIDEO_I2C_ADDR);
+ for (i=0; i<sizeof(video_encoder_data); ++i) {
+ printf(" %02X", video_encoder_data[i]);
+ }
+ putc ('\n');
+ }
+#endif /* DEBUG */
+
+ if ((rc = i2c_write (VIDEO_I2C_ADDR, 0, 1,
+ video_encoder_data,
+ sizeof(video_encoder_data))) != 0) {
+ printf ("i2c_send error: rc=%d\n", rc);
+ return;
+ }
+#endif /* VIDEO_I2C */
+ return;
+}
+
+static void video_ctrl_init (void *memptr)
+{
+ immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+ video_fb_address = memptr;
+
+ /* Set background */
+ debug ("[VIDEO CTRL] Setting background color...\n");
+ immap->im_vid.vid_vbcb = VIDEO_BG_COL;
+
+ /* Show the background */
+ debug ("[VIDEO CTRL] Forcing background...\n");
+ SETBIT (immap->im_vid.vid_vcmr, VIDEO_VCMR_BD, 1);
+
+ /* Turn off video controller */
+ debug ("[VIDEO CTRL] Turning off video controller...\n");
+ SETBIT (immap->im_vid.vid_vccr, VIDEO_VCCR_VON, 0);
+
+#ifdef CONFIG_FADS
+ /* Turn on Video Port LED */
+ debug ("[VIDEO CTRL] Turning off video port led...\n");
+ SETBIT (*(int *) BCSR4, VIDEO_BCSR4_VIDLED_BIT, 1);
+
+ /* Disable internal clock */
+ debug ("[VIDEO CTRL] Disabling internal clock...\n");
+ SETBIT (*(int *) BCSR4, VIDEO_BCSR4_EXTCLK_BIT, 0);
+#endif
+
+ /* Generate and make active a new video mode */
+ debug ("[VIDEO CTRL] Generating video mode...\n");
+ video_mode_generate ();
+
+ /* Start of frame buffer (even and odd frame, to make it working with */
+ /* any selected active set) */
+ debug ("[VIDEO CTRL] Setting frame buffer address...\n");
+ immap->im_vid.vid_vfaa1 =
+ immap->im_vid.vid_vfaa0 = (u32) video_fb_address;
+ immap->im_vid.vid_vfba1 =
+ immap->im_vid.vid_vfba0 =
+ (u32) video_fb_address + VIDEO_LINE_LEN;
+
+ /* YUV, Big endian, SHIFT/CLK/CLK input (BEFORE ENABLING 27MHZ EXT CLOCK) */
+ debug ("[VIDEO CTRL] Setting pixel mode and clocks...\n");
+ immap->im_vid.vid_vccr = 0x2042;
+
+ /* Configure port pins */
+ debug ("[VIDEO CTRL] Configuring input/output pins...\n");
+ immap->im_ioport.iop_pdpar = 0x1fff;
+ immap->im_ioport.iop_pddir = 0x0000;
+
+#ifdef CONFIG_FADS
+ /* Turn on Video Port Clock - ONLY AFTER SET VCCR TO ENABLE EXTERNAL CLOCK */
+ debug ("[VIDEO CTRL] Turning on video clock...\n");
+ SETBIT (*(int *) BCSR4, VIDEO_BCSR4_EXTCLK_BIT, 1);
+
+ /* Turn on Video Port LED */
+ debug ("[VIDEO CTRL] Turning on video port led...\n");
+ SETBIT (*(int *) BCSR4, VIDEO_BCSR4_VIDLED_BIT, 0);
+#endif
+#ifdef CONFIG_RRVISION
+ debug ("PC5->Output(1): enable PAL clock");
+ immap->im_ioport.iop_pcpar &= ~(0x0400);
+ immap->im_ioport.iop_pcdir |= 0x0400 ;
+ immap->im_ioport.iop_pcdat |= 0x0400 ;
+ debug ("PDPAR=0x%04X PDDIR=0x%04X PDDAT=0x%04X\n",
+ immap->im_ioport.iop_pdpar,
+ immap->im_ioport.iop_pddir,
+ immap->im_ioport.iop_pddat);
+ debug ("PCPAR=0x%04X PCDIR=0x%04X PCDAT=0x%04X\n",
+ immap->im_ioport.iop_pcpar,
+ immap->im_ioport.iop_pcdir,
+ immap->im_ioport.iop_pcdat);
+#endif /* CONFIG_RRVISION */
+
+ /* Blanking the screen. */
+ debug ("[VIDEO CTRL] Blanking the screen...\n");
+ video_fill (VIDEO_BG_COL);
+
+ /*
+ * Turns on Aggressive Mode. Normally, turning on the caches
+ * will cause the screen to flicker when the caches try to
+ * fill. This gives the FIFO's for the Video Controller
+ * higher priority and prevents flickering because of
+ * underrun. This may still be an issue when using FLASH,
+ * since accessing data from Flash is so slow.
+ */
+ debug ("[VIDEO CTRL] Turning on aggressive mode...\n");
+ immap->im_siu_conf.sc_sdcr = 0x40;
+
+ /* Turn on video controller */
+ debug ("[VIDEO CTRL] Turning on video controller...\n");
+ SETBIT (immap->im_vid.vid_vccr, VIDEO_VCCR_VON, 1);
+
+ /* Show the display */
+ debug ("[VIDEO CTRL] Enabling the video...\n");
+ SETBIT (immap->im_vid.vid_vcmr, VIDEO_VCMR_BD, 0);
+}
+
+/************************************************************************/
+/* ** CONSOLE FUNCTIONS */
+/************************************************************************/
+
+static void console_scrollup (void)
+{
+ /* Copy up rows ignoring the first one */
+ memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE >> 2);
+
+ /* Clear the last one */
+ memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, VIDEO_BG_COL);
+}
+
+static inline void console_back (void)
+{
+ console_col--;
+
+ if (console_col < 0) {
+ console_col = CONSOLE_COLS - 1;
+ console_row--;
+ if (console_row < 0)
+ console_row = 0;
+ }
+
+ video_putchar ( console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT, ' ');
+}
+
+static inline void console_newline (void)
+{
+ console_row++;
+ console_col = 0;
+
+ /* Check if we need to scroll the terminal */
+ if (console_row >= CONSOLE_ROWS) {
+ /* Scroll everything up */
+ console_scrollup ();
+
+ /* Decrement row number */
+ console_row--;
+ }
+}
+
+void video_putc (const char c)
+{
+ if (!video_enable) {
+ serial_putc (c);
+ return;
+ }
+
+ switch (c) {
+ case 13: /* Simply ignore this */
+ break;
+
+ case '\n': /* Next line, please */
+ console_newline ();
+ break;
+
+ case 9: /* Tab (8 chars alignment) */
+ console_col |= 0x0008; /* Next 8 chars boundary */
+ console_col &= ~0x0007; /* Set this bit to zero */
+
+ if (console_col >= CONSOLE_COLS)
+ console_newline ();
+ break;
+
+ case 8: /* Eat last character */
+ console_back ();
+ break;
+
+ default: /* Add to the console */
+ video_putchar ( console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT, c);
+ console_col++;
+ /* Check if we need to go to next row */
+ if (console_col >= CONSOLE_COLS)
+ console_newline ();
+ }
+}
+
+void video_puts (const char *s)
+{
+ int count = strlen (s);
+
+ if (!video_enable)
+ while (count--)
+ serial_putc (*s++);
+ else
+ while (count--)
+ video_putc (*s++);
+}
+
+/************************************************************************/
+/* ** CURSOR BLINKING FUNCTIONS */
+/************************************************************************/
+
+#ifdef VIDEO_BLINK
+
+#define BLINK_TIMER_ID 0
+#define BLINK_TIMER_HZ 2
+
+static unsigned char blink_enabled = 0;
+static timer_t blink_timer;
+
+static void blink_update (void)
+{
+ static int blink_row = -1, blink_col = -1, blink_old = 0;
+
+ /* Check if we have a new position to invert */
+ if ((console_row != blink_row) || (console_col != blink_col)) {
+ /* Check if we need to reverse last character */
+ if (blink_old)
+ video_revchar ( blink_col * VIDEO_FONT_WIDTH,
+ (blink_row
+#ifdef CONFIG_VIDEO_LOGO
+ + VIDEO_LOGO_HEIGHT
+#endif
+ ) * VIDEO_FONT_HEIGHT);
+
+ /* Update values */
+ blink_row = console_row;
+ blink_col = console_col;
+ blink_old = 0;
+ }
+
+/* Reverse this character */
+ blink_old = !blink_old;
+ video_revchar ( console_col * VIDEO_FONT_WIDTH,
+ (console_row
+#ifdef CONFIG_VIDEO_LOGO
+ + VIDEO_LOGO_HEIGHT
+#endif
+ ) * VIDEO_FONT_HEIGHT);
+
+}
+
+/*
+ * Handler for blinking cursor
+ */
+static void blink_handler (void *arg)
+{
+/* Blink */
+ blink_update ();
+/* Ack the timer */
+ timer_ack (&blink_timer);
+}
+
+int blink_set (int blink)
+{
+ int ret = blink_enabled;
+
+ if (blink)
+ timer_enable (&blink_timer);
+ else
+ timer_disable (&blink_timer);
+
+ blink_enabled = blink;
+
+ return ret;
+}
+
+static inline void blink_close (void)
+{
+ timer_close (&blink_timer);
+}
+
+static inline void blink_init (void)
+{
+ timer_init (&blink_timer,
+ BLINK_TIMER_ID, BLINK_TIMER_HZ,
+ blink_handler);
+}
+#endif
+
+/************************************************************************/
+/* ** LOGO PLOTTING FUNCTIONS */
+/************************************************************************/
+
+#ifdef CONFIG_VIDEO_LOGO
+void easylogo_plot (fastimage_t * image, void *screen, int width, int x,
+ int y)
+{
+ int skip = width - image->width, xcount, ycount = image->height;
+
+#ifdef VIDEO_MODE_YUYV
+ ushort *source = (ushort *) image->data;
+ ushort *dest = (ushort *) screen + y * width + x;
+
+ while (ycount--) {
+ xcount = image->width;
+ while (xcount--)
+ *dest++ = *source++;
+ dest += skip;
+ }
+#endif
+#ifdef VIDEO_MODE_RGB
+ unsigned char
+ *source = (unsigned short *) image->data,
+ *dest = (unsigned short *) screen + ((y * width) + x) * 3;
+
+ while (ycount--) {
+ xcount = image->width * 3;
+ memcpy (dest, source, xcount);
+ source += xcount;
+ dest += ycount;
+ }
+#endif
+}
+
+static void *video_logo (void)
+{
+ u16 *screen = video_fb_address, width = VIDEO_COLS;
+#ifdef VIDEO_INFO
+# ifndef CONFIG_FADS
+ char temp[32];
+# endif
+ char info[80];
+#endif /* VIDEO_INFO */
+
+ easylogo_plot (VIDEO_LOGO_ADDR, screen, width, 0, 0);
+
+#ifdef VIDEO_INFO
+ sprintf (info, "%s (%s - %s) ",
+ U_BOOT_VERSION, U_BOOT_DATE, U_BOOT_TIME);
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, info);
+
+ sprintf (info, "(C) 2002 DENX Software Engineering");
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
+ info);
+
+ sprintf (info, " Wolfgang DENK, wd@denx.de");
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT * 2,
+ info);
+#ifndef CONFIG_FADS /* all normal boards */
+ /* leave one blank line */
+
+ sprintf (info, "MPC823 CPU at %s MHz, %ld MB RAM, %ld MB Flash",
+ strmhz(temp, gd->cpu_clk),
+ gd->ram_size >> 20,
+ gd->bd->bi_flashsize >> 20 );
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT * 4,
+ info);
+#else /* FADS :-( */
+ sprintf (info, "MPC823 CPU at 50 MHz on FADS823 board");
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
+ info);
+
+ sprintf (info, "2MB FLASH - 8MB DRAM - 4MB SRAM");
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y + VIDEO_FONT_HEIGHT * 2,
+ info);
+#endif
+#endif
+
+ return video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN;
+}
+#endif
+
+/************************************************************************/
+/* ** VIDEO HIGH-LEVEL FUNCTIONS */
+/************************************************************************/
+
+static int video_init (void *videobase)
+{
+ /* Initialize the encoder */
+ debug ("[VIDEO] Initializing video encoder...\n");
+ video_encoder_init ();
+
+ /* Initialize the video controller */
+ debug ("[VIDEO] Initializing video controller at %08x...\n",
+ (int) videobase);
+ video_ctrl_init (videobase);
+
+ /* Setting the palette */
+ video_setpalette (CONSOLE_COLOR_BLACK, 0, 0, 0);
+ video_setpalette (CONSOLE_COLOR_RED, 0xFF, 0, 0);
+ video_setpalette (CONSOLE_COLOR_GREEN, 0, 0xFF, 0);
+ video_setpalette (CONSOLE_COLOR_YELLOW, 0xFF, 0xFF, 0);
+ video_setpalette (CONSOLE_COLOR_BLUE, 0, 0, 0xFF);
+ video_setpalette (CONSOLE_COLOR_MAGENTA, 0xFF, 0, 0xFF);
+ video_setpalette (CONSOLE_COLOR_CYAN, 0, 0xFF, 0xFF);
+ video_setpalette (CONSOLE_COLOR_GREY, 0xAA, 0xAA, 0xAA);
+ video_setpalette (CONSOLE_COLOR_GREY2, 0xF8, 0xF8, 0xF8);
+ video_setpalette (CONSOLE_COLOR_WHITE, 0xFF, 0xFF, 0xFF);
+
+#ifndef CONFIG_SYS_WHITE_ON_BLACK
+ video_setfgcolor (CONSOLE_COLOR_BLACK);
+ video_setbgcolor (CONSOLE_COLOR_GREY2);
+#else
+ video_setfgcolor (CONSOLE_COLOR_GREY2);
+ video_setbgcolor (CONSOLE_COLOR_BLACK);
+#endif /* CONFIG_SYS_WHITE_ON_BLACK */
+
+#ifdef CONFIG_VIDEO_LOGO
+ /* Paint the logo and retrieve tv base address */
+ debug ("[VIDEO] Drawing the logo...\n");
+ video_console_address = video_logo ();
+#else
+ video_console_address = video_fb_address;
+#endif
+
+#ifdef VIDEO_BLINK
+ /* Enable the blinking (under construction) */
+ blink_init ();
+ blink_set (0); /* To Fix! */
+#endif
+
+ /* Initialize the console */
+ console_col = 0;
+ console_row = 0;
+ video_enable = 1;
+
+#ifdef VIDEO_MODE_PAL
+# define VIDEO_MODE_TMP1 "PAL"
+#endif
+#ifdef VIDEO_MODE_NTSC
+# define VIDEO_MODE_TMP1 "NTSC"
+#endif
+#ifdef VIDEO_MODE_YUYV
+# define VIDEO_MODE_TMP2 "YCbYCr"
+#endif
+#ifdef VIDEO_MODE_RGB
+# define VIDEO_MODE_TMP2 "RGB"
+#endif
+ debug ( VIDEO_MODE_TMP1
+ " %dx%dx%d (" VIDEO_MODE_TMP2 ") on %s - console %dx%d\n",
+ VIDEO_COLS, VIDEO_ROWS, VIDEO_MODE_BPP,
+ VIDEO_ENCODER_NAME, CONSOLE_COLS, CONSOLE_ROWS);
+ return 0;
+}
+
+int drv_video_init (void)
+{
+ int error, devices = 1;
+
+ struct stdio_dev videodev;
+
+ video_init ((void *)(gd->fb_base)); /* Video initialization */
+
+/* Device initialization */
+
+ memset (&videodev, 0, sizeof (videodev));
+
+ strcpy (videodev.name, "video");
+ videodev.ext = DEV_EXT_VIDEO; /* Video extensions */
+ videodev.flags = DEV_FLAGS_OUTPUT; /* Output only */
+ videodev.putc = video_putc; /* 'putc' function */
+ videodev.puts = video_puts; /* 'puts' function */
+
+ error = stdio_register (&videodev);
+
+ return (error == 0) ? devices : error;
+}
+
+/************************************************************************/
+/* ** ROM capable initialization part - needed to reserve FB memory */
+/************************************************************************/
+
+/*
+ * This is called early in the system initialization to grab memory
+ * for the video controller.
+ * Returns new address for monitor, after reserving video buffer memory
+ *
+ * Note that this is running from ROM, so no write access to global data.
+ */
+ulong video_setmem (ulong addr)
+{
+ /* Allocate pages for the frame buffer. */
+ addr -= VIDEO_SIZE;
+
+ debug ("Reserving %dk for Video Framebuffer at: %08lx\n",
+ VIDEO_SIZE>>10, addr);
+
+ return (addr);
+}
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xx/wlkbd.c b/arch/powerpc/cpu/mpc8xx/wlkbd.c
new file mode 100644
index 0000000..13009e2
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xx/wlkbd.c
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2000
+ * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+
+#ifdef CONFIG_WL_4PPM_KEYBOARD
+
+/* WIP: Wireless keyboard on SMC
+ */
+int drv_wlkbd_init (void)
+{
+ return 0 ;
+}
+
+#endif /* CONFIG_WL_4PPM_KEYBOARD */
diff --git a/arch/powerpc/cpu/mpc8xxx/Makefile b/arch/powerpc/cpu/mpc8xxx/Makefile
new file mode 100644
index 0000000..3dc8e05
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright 2009-2010 Freescale Semiconductor, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# Version 2 as published by the Free Software Foundation.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib8xxx.o
+
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-$(CONFIG_FSL_LAW) += law.o
+
+else
+
+ifneq ($(CPU),mpc83xx)
+COBJS-y += cpu.o
+endif
+
+COBJS-$(CONFIG_OF_LIBFDT) += fdt.o
+COBJS-$(CONFIG_FSL_IFC) += fsl_ifc.o
+COBJS-$(CONFIG_FSL_LBC) += fsl_lbc.o
+COBJS-$(CONFIG_SYS_SRIO) += srio.o
+COBJS-$(CONFIG_FSL_LAW) += law.o
+
+endif
+
+SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
diff --git a/arch/powerpc/cpu/mpc8xxx/cpu.c b/arch/powerpc/cpu/mpc8xxx/cpu.c
new file mode 100644
index 0000000..bc26855
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/cpu.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and
+ * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains
+ * cpu specific common code for 85xx/86xx processors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <tsec.h>
+#include <fm_eth.h>
+#include <netdev.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct cpu_type cpu_type_list[] = {
+#if defined(CONFIG_MPC85xx)
+ CPU_TYPE_ENTRY(8533, 8533, 1),
+ CPU_TYPE_ENTRY(8535, 8535, 1),
+ CPU_TYPE_ENTRY(8536, 8536, 1),
+ CPU_TYPE_ENTRY(8540, 8540, 1),
+ CPU_TYPE_ENTRY(8541, 8541, 1),
+ CPU_TYPE_ENTRY(8543, 8543, 1),
+ CPU_TYPE_ENTRY(8544, 8544, 1),
+ CPU_TYPE_ENTRY(8545, 8545, 1),
+ CPU_TYPE_ENTRY(8547, 8547, 1),
+ CPU_TYPE_ENTRY(8548, 8548, 1),
+ CPU_TYPE_ENTRY(8555, 8555, 1),
+ CPU_TYPE_ENTRY(8560, 8560, 1),
+ CPU_TYPE_ENTRY(8567, 8567, 1),
+ CPU_TYPE_ENTRY(8568, 8568, 1),
+ CPU_TYPE_ENTRY(8569, 8569, 1),
+ CPU_TYPE_ENTRY(8572, 8572, 2),
+ CPU_TYPE_ENTRY(P1010, P1010, 1),
+ CPU_TYPE_ENTRY(P1011, P1011, 1),
+ CPU_TYPE_ENTRY(P1012, P1012, 1),
+ CPU_TYPE_ENTRY(P1013, P1013, 1),
+ CPU_TYPE_ENTRY(P1014, P1014, 1),
+ CPU_TYPE_ENTRY(P1017, P1017, 1),
+ CPU_TYPE_ENTRY(P1020, P1020, 2),
+ CPU_TYPE_ENTRY(P1021, P1021, 2),
+ CPU_TYPE_ENTRY(P1022, P1022, 2),
+ CPU_TYPE_ENTRY(P1023, P1023, 2),
+ CPU_TYPE_ENTRY(P1024, P1024, 2),
+ CPU_TYPE_ENTRY(P1025, P1025, 2),
+ CPU_TYPE_ENTRY(P2010, P2010, 1),
+ CPU_TYPE_ENTRY(P2020, P2020, 2),
+ CPU_TYPE_ENTRY(P2040, P2040, 4),
+ CPU_TYPE_ENTRY(P2041, P2041, 4),
+ CPU_TYPE_ENTRY(P3041, P3041, 4),
+ CPU_TYPE_ENTRY(P4040, P4040, 4),
+ CPU_TYPE_ENTRY(P4080, P4080, 8),
+ CPU_TYPE_ENTRY(P5010, P5010, 1),
+ CPU_TYPE_ENTRY(P5020, P5020, 2),
+ CPU_TYPE_ENTRY(P5021, P5021, 2),
+ CPU_TYPE_ENTRY(P5040, P5040, 4),
+ CPU_TYPE_ENTRY(T4240, T4240, 0),
+ CPU_TYPE_ENTRY(T4120, T4120, 0),
+ CPU_TYPE_ENTRY(T4160, T4160, 0),
+ CPU_TYPE_ENTRY(B4860, B4860, 0),
+ CPU_TYPE_ENTRY(G4860, G4860, 0),
+ CPU_TYPE_ENTRY(G4060, G4060, 0),
+ CPU_TYPE_ENTRY(B4440, B4440, 0),
+ CPU_TYPE_ENTRY(G4440, G4440, 0),
+ CPU_TYPE_ENTRY(B4420, B4420, 0),
+ CPU_TYPE_ENTRY(B4220, B4220, 0),
+ CPU_TYPE_ENTRY(T1040, T1040, 0),
+ CPU_TYPE_ENTRY(T1041, T1041, 0),
+ CPU_TYPE_ENTRY(T1042, T1042, 0),
+ CPU_TYPE_ENTRY(T1020, T1020, 0),
+ CPU_TYPE_ENTRY(T1021, T1021, 0),
+ CPU_TYPE_ENTRY(T1022, T1022, 0),
+ CPU_TYPE_ENTRY(BSC9130, 9130, 1),
+ CPU_TYPE_ENTRY(BSC9131, 9131, 1),
+ CPU_TYPE_ENTRY(BSC9132, 9132, 2),
+ CPU_TYPE_ENTRY(BSC9232, 9232, 2),
+#elif defined(CONFIG_MPC86xx)
+ CPU_TYPE_ENTRY(8610, 8610, 1),
+ CPU_TYPE_ENTRY(8641, 8641, 2),
+ CPU_TYPE_ENTRY(8641D, 8641D, 2),
+#endif
+};
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+static inline u32 init_type(u32 cluster, int init_id)
+{
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 idx = (cluster >> (init_id * 8)) & TP_CLUSTER_INIT_MASK;
+ u32 type = in_be32(&gur->tp_ityp[idx]);
+
+ if (type & TP_ITYP_AV)
+ return type;
+
+ return 0;
+}
+
+u32 compute_ppc_cpumask(void)
+{
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ int i = 0, count = 0;
+ u32 cluster, type, mask = 0;
+
+ do {
+ int j;
+ cluster = in_be32(&gur->tp_cluster[i].lower);
+ for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+ type = init_type(cluster, j);
+ if (type) {
+ if (TP_ITYP_TYPE(type) == TP_ITYP_TYPE_PPC)
+ mask |= 1 << count;
+ count++;
+ }
+ }
+ i++;
+ } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC);
+
+ return mask;
+}
+
+int fsl_qoriq_core_to_cluster(unsigned int core)
+{
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ int i = 0, count = 0;
+ u32 cluster;
+
+ do {
+ int j;
+ cluster = in_be32(&gur->tp_cluster[i].lower);
+ for (j = 0; j < TP_INIT_PER_CLUSTER; j++) {
+ if (init_type(cluster, j)) {
+ if (count == core)
+ return i;
+ count++;
+ }
+ }
+ i++;
+ } while ((cluster & TP_CLUSTER_EOC) != TP_CLUSTER_EOC);
+
+ return -1; /* cannot identify the cluster */
+}
+
+#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+/*
+ * Before chassis genenration 2, the cpumask should be hard-coded.
+ * In case of cpu type unknown or cpumask unset, use 1 as fail save.
+ */
+#define compute_ppc_cpumask() 1
+#define fsl_qoriq_core_to_cluster(x) x
+#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+static struct cpu_type cpu_type_unknown = CPU_TYPE_ENTRY(Unknown, Unknown, 0);
+
+struct cpu_type *identify_cpu(u32 ver)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(cpu_type_list); i++) {
+ if (cpu_type_list[i].soc_ver == ver)
+ return &cpu_type_list[i];
+ }
+ return &cpu_type_unknown;
+}
+
+#define MPC8xxx_PICFRR_NCPU_MASK 0x00001f00
+#define MPC8xxx_PICFRR_NCPU_SHIFT 8
+
+/*
+ * Return a 32-bit mask indicating which cores are present on this SOC.
+ */
+u32 cpu_mask(void)
+{
+ ccsr_pic_t __iomem *pic = (void *)CONFIG_SYS_MPC8xxx_PIC_ADDR;
+ struct cpu_type *cpu = gd->arch.cpu;
+
+ /* better to query feature reporting register than just assume 1 */
+ if (cpu == &cpu_type_unknown)
+ return ((in_be32(&pic->frr) & MPC8xxx_PICFRR_NCPU_MASK) >>
+ MPC8xxx_PICFRR_NCPU_SHIFT) + 1;
+
+ if (cpu->num_cores == 0)
+ return compute_ppc_cpumask();
+
+ return cpu->mask;
+}
+
+/*
+ * Return the number of cores on this SOC.
+ */
+int cpu_numcores(void)
+{
+ struct cpu_type *cpu = gd->arch.cpu;
+
+ /*
+ * Report # of cores in terms of the cpu_mask if we haven't
+ * figured out how many there are yet
+ */
+ if (cpu->num_cores == 0)
+ return hweight32(cpu_mask());
+
+ return cpu->num_cores;
+}
+
+/*
+ * Check if the given core ID is valid
+ *
+ * Returns zero if it isn't, 1 if it is.
+ */
+int is_core_valid(unsigned int core)
+{
+ return !!((1 << core) & cpu_mask());
+}
+
+int probecpu (void)
+{
+ uint svr;
+ uint ver;
+
+ svr = get_svr();
+ ver = SVR_SOC_VER(svr);
+
+ gd->arch.cpu = identify_cpu(ver);
+
+ return 0;
+}
+
+/* Once in memory, compute mask & # cores once and save them off */
+int fixup_cpu(void)
+{
+ struct cpu_type *cpu = gd->arch.cpu;
+
+ if (cpu->num_cores == 0) {
+ cpu->mask = cpu_mask();
+ cpu->num_cores = cpu_numcores();
+ }
+
+ return 0;
+}
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_ETHER_ON_FCC)
+ fec_initialize(bis);
+#endif
+
+#if defined(CONFIG_UEC_ETH)
+ uec_standard_init(bis);
+#endif
+
+#if defined(CONFIG_TSEC_ENET) || defined(CONFIG_MPC85XX_FEC)
+ tsec_standard_init(bis);
+#endif
+
+#ifdef CONFIG_FMAN_ENET
+ fm_standard_init(bis);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/Makefile b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
new file mode 100644
index 0000000..29523aa
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright 2008-2011 Freescale Semiconductor, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# Version 2 as published by the Free Software Foundation.
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)libddr.o
+
+COBJS-$(CONFIG_FSL_DDR1) += main.o util.o ctrl_regs.o options.o \
+ lc_common_dimm_params.o
+
+COBJS-$(CONFIG_FSL_DDR2) += main.o util.o ctrl_regs.o options.o \
+ lc_common_dimm_params.o
+
+COBJS-$(CONFIG_FSL_DDR3) += main.o util.o ctrl_regs.o options.o \
+ lc_common_dimm_params.o
+ifdef CONFIG_DDR_SPD
+SPD := y
+endif
+ifdef CONFIG_SPD_EEPROM
+SPD := y
+endif
+ifdef SPD
+COBJS-$(CONFIG_FSL_DDR1) += ddr1_dimm_params.o
+COBJS-$(CONFIG_FSL_DDR2) += ddr2_dimm_params.o
+COBJS-$(CONFIG_FSL_DDR3) += ddr3_dimm_params.o
+endif
+
+COBJS-$(CONFIG_FSL_DDR_INTERACTIVE) += interactive.o
+
+SRCS := $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h b/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h
new file mode 100644
index 0000000..06706ed
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/common_timing_params.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef COMMON_TIMING_PARAMS_H
+#define COMMON_TIMING_PARAMS_H
+
+typedef struct {
+ /* parameters to constrict */
+
+ unsigned int tCKmin_X_ps;
+ unsigned int tCKmax_ps;
+ unsigned int tCKmax_max_ps;
+ unsigned int tRCD_ps;
+ unsigned int tRP_ps;
+ unsigned int tRAS_ps;
+
+ unsigned int tWR_ps; /* maximum = 63750 ps */
+ unsigned int tWTR_ps; /* maximum = 63750 ps */
+ unsigned int tRFC_ps; /* maximum = 255 ns + 256 ns + .75 ns
+ = 511750 ps */
+
+ unsigned int tRRD_ps; /* maximum = 63750 ps */
+ unsigned int tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */
+
+ unsigned int refresh_rate_ps;
+
+ unsigned int tIS_ps; /* byte 32, spd->ca_setup */
+ unsigned int tIH_ps; /* byte 33, spd->ca_hold */
+ unsigned int tDS_ps; /* byte 34, spd->data_setup */
+ unsigned int tDH_ps; /* byte 35, spd->data_hold */
+ unsigned int tRTP_ps; /* byte 38, spd->trtp */
+ unsigned int tDQSQ_max_ps; /* byte 44, spd->tdqsq */
+ unsigned int tQHS_ps; /* byte 45, spd->tqhs */
+
+ unsigned int ndimms_present;
+ unsigned int lowest_common_SPD_caslat;
+ unsigned int highest_common_derated_caslat;
+ unsigned int additive_latency;
+ unsigned int all_DIMMs_burst_lengths_bitmask;
+ unsigned int all_DIMMs_registered;
+ unsigned int all_DIMMs_unbuffered;
+ unsigned int all_DIMMs_ECC_capable;
+
+ unsigned long long total_mem;
+ unsigned long long base_address;
+
+ /* DDR3 RDIMM */
+ unsigned char rcw[16]; /* Register Control Word 0-15 */
+} common_timing_params_t;
+
+#endif
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
new file mode 100644
index 0000000..26c42f7
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
@@ -0,0 +1,1645 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+#define _DDR_ADDR CONFIG_SYS_MPC8xxx_DDR_ADDR
+
+static u32 fsl_ddr_get_version(void)
+{
+ ccsr_ddr_t *ddr;
+ u32 ver_major_minor_errata;
+
+ ddr = (void *)_DDR_ADDR;
+ ver_major_minor_errata = (in_be32(&ddr->ip_rev1) & 0xFFFF) << 8;
+ ver_major_minor_errata |= (in_be32(&ddr->ip_rev2) & 0xFF00) >> 8;
+
+ return ver_major_minor_errata;
+}
+
+unsigned int picos_to_mclk(unsigned int picos);
+
+/*
+ * Determine Rtt value.
+ *
+ * This should likely be either board or controller specific.
+ *
+ * Rtt(nominal) - DDR2:
+ * 0 = Rtt disabled
+ * 1 = 75 ohm
+ * 2 = 150 ohm
+ * 3 = 50 ohm
+ * Rtt(nominal) - DDR3:
+ * 0 = Rtt disabled
+ * 1 = 60 ohm
+ * 2 = 120 ohm
+ * 3 = 40 ohm
+ * 4 = 20 ohm
+ * 5 = 30 ohm
+ *
+ * FIXME: Apparently 8641 needs a value of 2
+ * FIXME: Old code seys if 667 MHz or higher, use 3 on 8572
+ *
+ * FIXME: There was some effort down this line earlier:
+ *
+ * unsigned int i;
+ * for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL/2; i++) {
+ * if (popts->dimmslot[i].num_valid_cs
+ * && (popts->cs_local_opts[2*i].odt_rd_cfg
+ * || popts->cs_local_opts[2*i].odt_wr_cfg)) {
+ * rtt = 2;
+ * break;
+ * }
+ * }
+ */
+static inline int fsl_ddr_get_rtt(void)
+{
+ int rtt;
+
+#if defined(CONFIG_FSL_DDR1)
+ rtt = 0;
+#elif defined(CONFIG_FSL_DDR2)
+ rtt = 3;
+#else
+ rtt = 0;
+#endif
+
+ return rtt;
+}
+
+/*
+ * compute the CAS write latency according to DDR3 spec
+ * CWL = 5 if tCK >= 2.5ns
+ * 6 if 2.5ns > tCK >= 1.875ns
+ * 7 if 1.875ns > tCK >= 1.5ns
+ * 8 if 1.5ns > tCK >= 1.25ns
+ * 9 if 1.25ns > tCK >= 1.07ns
+ * 10 if 1.07ns > tCK >= 0.935ns
+ * 11 if 0.935ns > tCK >= 0.833ns
+ * 12 if 0.833ns > tCK >= 0.75ns
+ */
+static inline unsigned int compute_cas_write_latency(void)
+{
+ unsigned int cwl;
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+ if (mclk_ps >= 2500)
+ cwl = 5;
+ else if (mclk_ps >= 1875)
+ cwl = 6;
+ else if (mclk_ps >= 1500)
+ cwl = 7;
+ else if (mclk_ps >= 1250)
+ cwl = 8;
+ else if (mclk_ps >= 1070)
+ cwl = 9;
+ else if (mclk_ps >= 935)
+ cwl = 10;
+ else if (mclk_ps >= 833)
+ cwl = 11;
+ else if (mclk_ps >= 750)
+ cwl = 12;
+ else {
+ cwl = 12;
+ printf("Warning: CWL is out of range\n");
+ }
+ return cwl;
+}
+
+/* Chip Select Configuration (CSn_CONFIG) */
+static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const dimm_params_t *dimm_params)
+{
+ unsigned int cs_n_en = 0; /* Chip Select enable */
+ unsigned int intlv_en = 0; /* Memory controller interleave enable */
+ unsigned int intlv_ctl = 0; /* Interleaving control */
+ unsigned int ap_n_en = 0; /* Chip select n auto-precharge enable */
+ unsigned int odt_rd_cfg = 0; /* ODT for reads configuration */
+ unsigned int odt_wr_cfg = 0; /* ODT for writes configuration */
+ unsigned int ba_bits_cs_n = 0; /* Num of bank bits for SDRAM on CSn */
+ unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
+ unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
+ int go_config = 0;
+
+ /* Compute CS_CONFIG only for existing ranks of each DIMM. */
+ switch (i) {
+ case 0:
+ if (dimm_params[dimm_number].n_ranks > 0) {
+ go_config = 1;
+ /* These fields only available in CS0_CONFIG */
+ if (!popts->memctl_interleaving)
+ break;
+ switch (popts->memctl_interleaving_mode) {
+ case FSL_DDR_CACHE_LINE_INTERLEAVING:
+ case FSL_DDR_PAGE_INTERLEAVING:
+ case FSL_DDR_BANK_INTERLEAVING:
+ case FSL_DDR_SUPERBANK_INTERLEAVING:
+ intlv_en = popts->memctl_interleaving;
+ intlv_ctl = popts->memctl_interleaving_mode;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case 1:
+ if ((dimm_number == 0 && dimm_params[0].n_ranks > 1) || \
+ (dimm_number == 1 && dimm_params[1].n_ranks > 0))
+ go_config = 1;
+ break;
+ case 2:
+ if ((dimm_number == 0 && dimm_params[0].n_ranks > 2) || \
+ (dimm_number >= 1 && dimm_params[dimm_number].n_ranks > 0))
+ go_config = 1;
+ break;
+ case 3:
+ if ((dimm_number == 0 && dimm_params[0].n_ranks > 3) || \
+ (dimm_number == 1 && dimm_params[1].n_ranks > 1) || \
+ (dimm_number == 3 && dimm_params[3].n_ranks > 0))
+ go_config = 1;
+ break;
+ default:
+ break;
+ }
+ if (go_config) {
+ unsigned int n_banks_per_sdram_device;
+ cs_n_en = 1;
+ ap_n_en = popts->cs_local_opts[i].auto_precharge;
+ odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
+ odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
+ n_banks_per_sdram_device
+ = dimm_params[dimm_number].n_banks_per_sdram_device;
+ ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
+ row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12;
+ col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8;
+ }
+ ddr->cs[i].config = (0
+ | ((cs_n_en & 0x1) << 31)
+ | ((intlv_en & 0x3) << 29)
+ | ((intlv_ctl & 0xf) << 24)
+ | ((ap_n_en & 0x1) << 23)
+
+ /* XXX: some implementation only have 1 bit starting at left */
+ | ((odt_rd_cfg & 0x7) << 20)
+
+ /* XXX: Some implementation only have 1 bit starting at left */
+ | ((odt_wr_cfg & 0x7) << 16)
+
+ | ((ba_bits_cs_n & 0x3) << 14)
+ | ((row_bits_cs_n & 0x7) << 8)
+ | ((col_bits_cs_n & 0x7) << 0)
+ );
+ debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
+}
+
+/* Chip Select Configuration 2 (CSn_CONFIG_2) */
+/* FIXME: 8572 */
+static void set_csn_config_2(int i, fsl_ddr_cfg_regs_t *ddr)
+{
+ unsigned int pasr_cfg = 0; /* Partial array self refresh config */
+
+ ddr->cs[i].config_2 = ((pasr_cfg & 7) << 24);
+ debug("FSLDDR: cs[%d]_config_2 = 0x%08x\n", i, ddr->cs[i].config_2);
+}
+
+/* -3E = 667 CL5, -25 = CL6 800, -25E = CL5 800 */
+
+#if !defined(CONFIG_FSL_DDR1)
+static inline int avoid_odt_overlap(const dimm_params_t *dimm_params)
+{
+#if CONFIG_DIMM_SLOTS_PER_CTLR == 1
+ if (dimm_params[0].n_ranks == 4)
+ return 1;
+#endif
+
+#if CONFIG_DIMM_SLOTS_PER_CTLR == 2
+ if ((dimm_params[0].n_ranks == 2) &&
+ (dimm_params[1].n_ranks == 2))
+ return 1;
+
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ if (dimm_params[0].n_ranks == 4)
+ return 1;
+#endif
+#endif
+ return 0;
+}
+
+/*
+ * DDR SDRAM Timing Configuration 0 (TIMING_CFG_0)
+ *
+ * Avoid writing for DDR I. The new PQ38 DDR controller
+ * dreams up non-zero default values to be backwards compatible.
+ */
+static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const dimm_params_t *dimm_params)
+{
+ unsigned char trwt_mclk = 0; /* Read-to-write turnaround */
+ unsigned char twrt_mclk = 0; /* Write-to-read turnaround */
+ /* 7.5 ns on -3E; 0 means WL - CL + BL/2 + 1 */
+ unsigned char trrt_mclk = 0; /* Read-to-read turnaround */
+ unsigned char twwt_mclk = 0; /* Write-to-write turnaround */
+
+ /* Active powerdown exit timing (tXARD and tXARDS). */
+ unsigned char act_pd_exit_mclk;
+ /* Precharge powerdown exit timing (tXP). */
+ unsigned char pre_pd_exit_mclk;
+ /* ODT powerdown exit timing (tAXPD). */
+ unsigned char taxpd_mclk;
+ /* Mode register set cycle time (tMRD). */
+ unsigned char tmrd_mclk;
+
+#ifdef CONFIG_FSL_DDR3
+ /*
+ * (tXARD and tXARDS). Empirical?
+ * The DDR3 spec has not tXARD,
+ * we use the tXP instead of it.
+ * tXP=max(3nCK, 7.5ns) for DDR3.
+ * spec has not the tAXPD, we use
+ * tAXPD=1, need design to confirm.
+ */
+ int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */
+ unsigned int data_rate = get_ddr_freq(0);
+ tmrd_mclk = 4;
+ /* set the turnaround time */
+
+ /*
+ * for single quad-rank DIMM and two dual-rank DIMMs
+ * to avoid ODT overlap
+ */
+ if (avoid_odt_overlap(dimm_params)) {
+ twwt_mclk = 2;
+ trrt_mclk = 1;
+ }
+ /* for faster clock, need more time for data setup */
+ trwt_mclk = (data_rate/1000000 > 1800) ? 2 : 1;
+
+ if ((data_rate/1000000 > 1150) || (popts->memctl_interleaving))
+ twrt_mclk = 1;
+
+ if (popts->dynamic_power == 0) { /* powerdown is not used */
+ act_pd_exit_mclk = 1;
+ pre_pd_exit_mclk = 1;
+ taxpd_mclk = 1;
+ } else {
+ /* act_pd_exit_mclk = tXARD, see above */
+ act_pd_exit_mclk = picos_to_mclk(tXP);
+ /* Mode register MR0[A12] is '1' - fast exit */
+ pre_pd_exit_mclk = act_pd_exit_mclk;
+ taxpd_mclk = 1;
+ }
+#else /* CONFIG_FSL_DDR2 */
+ /*
+ * (tXARD and tXARDS). Empirical?
+ * tXARD = 2 for DDR2
+ * tXP=2
+ * tAXPD=8
+ */
+ act_pd_exit_mclk = 2;
+ pre_pd_exit_mclk = 2;
+ taxpd_mclk = 8;
+ tmrd_mclk = 2;
+#endif
+
+ if (popts->trwt_override)
+ trwt_mclk = popts->trwt;
+
+ ddr->timing_cfg_0 = (0
+ | ((trwt_mclk & 0x3) << 30) /* RWT */
+ | ((twrt_mclk & 0x3) << 28) /* WRT */
+ | ((trrt_mclk & 0x3) << 26) /* RRT */
+ | ((twwt_mclk & 0x3) << 24) /* WWT */
+ | ((act_pd_exit_mclk & 0x7) << 20) /* ACT_PD_EXIT */
+ | ((pre_pd_exit_mclk & 0xF) << 16) /* PRE_PD_EXIT */
+ | ((taxpd_mclk & 0xf) << 8) /* ODT_PD_EXIT */
+ | ((tmrd_mclk & 0xf) << 0) /* MRS_CYC */
+ );
+ debug("FSLDDR: timing_cfg_0 = 0x%08x\n", ddr->timing_cfg_0);
+}
+#endif /* defined(CONFIG_FSL_DDR2) */
+
+/* DDR SDRAM Timing Configuration 3 (TIMING_CFG_3) */
+static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency)
+{
+ /* Extended precharge to activate interval (tRP) */
+ unsigned int ext_pretoact = 0;
+ /* Extended Activate to precharge interval (tRAS) */
+ unsigned int ext_acttopre = 0;
+ /* Extended activate to read/write interval (tRCD) */
+ unsigned int ext_acttorw = 0;
+ /* Extended refresh recovery time (tRFC) */
+ unsigned int ext_refrec;
+ /* Extended MCAS latency from READ cmd */
+ unsigned int ext_caslat = 0;
+ /* Extended last data to precharge interval (tWR) */
+ unsigned int ext_wrrec = 0;
+ /* Control Adjust */
+ unsigned int cntl_adj = 0;
+
+ ext_pretoact = picos_to_mclk(common_dimm->tRP_ps) >> 4;
+ ext_acttopre = picos_to_mclk(common_dimm->tRAS_ps) >> 4;
+ ext_acttorw = picos_to_mclk(common_dimm->tRCD_ps) >> 4;
+ ext_caslat = (2 * cas_latency - 1) >> 4;
+ ext_refrec = (picos_to_mclk(common_dimm->tRFC_ps) - 8) >> 4;
+ /* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
+ ext_wrrec = (picos_to_mclk(common_dimm->tWR_ps) +
+ (popts->OTF_burst_chop_en ? 2 : 0)) >> 4;
+
+ ddr->timing_cfg_3 = (0
+ | ((ext_pretoact & 0x1) << 28)
+ | ((ext_acttopre & 0x2) << 24)
+ | ((ext_acttorw & 0x1) << 22)
+ | ((ext_refrec & 0x1F) << 16)
+ | ((ext_caslat & 0x3) << 12)
+ | ((ext_wrrec & 0x1) << 8)
+ | ((cntl_adj & 0x7) << 0)
+ );
+ debug("FSLDDR: timing_cfg_3 = 0x%08x\n", ddr->timing_cfg_3);
+}
+
+/* DDR SDRAM Timing Configuration 1 (TIMING_CFG_1) */
+static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency)
+{
+ /* Precharge-to-activate interval (tRP) */
+ unsigned char pretoact_mclk;
+ /* Activate to precharge interval (tRAS) */
+ unsigned char acttopre_mclk;
+ /* Activate to read/write interval (tRCD) */
+ unsigned char acttorw_mclk;
+ /* CASLAT */
+ unsigned char caslat_ctrl;
+ /* Refresh recovery time (tRFC) ; trfc_low */
+ unsigned char refrec_ctrl;
+ /* Last data to precharge minimum interval (tWR) */
+ unsigned char wrrec_mclk;
+ /* Activate-to-activate interval (tRRD) */
+ unsigned char acttoact_mclk;
+ /* Last write data pair to read command issue interval (tWTR) */
+ unsigned char wrtord_mclk;
+ /* DDR_SDRAM_MODE doesn't support 9,11,13,15 */
+ static const u8 wrrec_table[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0};
+
+ pretoact_mclk = picos_to_mclk(common_dimm->tRP_ps);
+ acttopre_mclk = picos_to_mclk(common_dimm->tRAS_ps);
+ acttorw_mclk = picos_to_mclk(common_dimm->tRCD_ps);
+
+ /*
+ * Translate CAS Latency to a DDR controller field value:
+ *
+ * CAS Lat DDR I DDR II Ctrl
+ * Clocks SPD Bit SPD Bit Value
+ * ------- ------- ------- -----
+ * 1.0 0 0001
+ * 1.5 1 0010
+ * 2.0 2 2 0011
+ * 2.5 3 0100
+ * 3.0 4 3 0101
+ * 3.5 5 0110
+ * 4.0 4 0111
+ * 4.5 1000
+ * 5.0 5 1001
+ */
+#if defined(CONFIG_FSL_DDR1)
+ caslat_ctrl = (cas_latency + 1) & 0x07;
+#elif defined(CONFIG_FSL_DDR2)
+ caslat_ctrl = 2 * cas_latency - 1;
+#else
+ /*
+ * if the CAS latency more than 8 cycle,
+ * we need set extend bit for it at
+ * TIMING_CFG_3[EXT_CASLAT]
+ */
+ caslat_ctrl = 2 * cas_latency - 1;
+#endif
+
+ refrec_ctrl = picos_to_mclk(common_dimm->tRFC_ps) - 8;
+ wrrec_mclk = picos_to_mclk(common_dimm->tWR_ps);
+
+ if (wrrec_mclk > 16)
+ printf("Error: WRREC doesn't support more than 16 clocks\n");
+ else
+ wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+ if (popts->OTF_burst_chop_en)
+ wrrec_mclk += 2;
+
+ acttoact_mclk = picos_to_mclk(common_dimm->tRRD_ps);
+ /*
+ * JEDEC has min requirement for tRRD
+ */
+#if defined(CONFIG_FSL_DDR3)
+ if (acttoact_mclk < 4)
+ acttoact_mclk = 4;
+#endif
+ wrtord_mclk = picos_to_mclk(common_dimm->tWTR_ps);
+ /*
+ * JEDEC has some min requirements for tWTR
+ */
+#if defined(CONFIG_FSL_DDR2)
+ if (wrtord_mclk < 2)
+ wrtord_mclk = 2;
+#elif defined(CONFIG_FSL_DDR3)
+ if (wrtord_mclk < 4)
+ wrtord_mclk = 4;
+#endif
+ if (popts->OTF_burst_chop_en)
+ wrtord_mclk += 2;
+
+ ddr->timing_cfg_1 = (0
+ | ((pretoact_mclk & 0x0F) << 28)
+ | ((acttopre_mclk & 0x0F) << 24)
+ | ((acttorw_mclk & 0xF) << 20)
+ | ((caslat_ctrl & 0xF) << 16)
+ | ((refrec_ctrl & 0xF) << 12)
+ | ((wrrec_mclk & 0x0F) << 8)
+ | ((acttoact_mclk & 0x0F) << 4)
+ | ((wrtord_mclk & 0x0F) << 0)
+ );
+ debug("FSLDDR: timing_cfg_1 = 0x%08x\n", ddr->timing_cfg_1);
+}
+
+/* DDR SDRAM Timing Configuration 2 (TIMING_CFG_2) */
+static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency,
+ unsigned int additive_latency)
+{
+ /* Additive latency */
+ unsigned char add_lat_mclk;
+ /* CAS-to-preamble override */
+ unsigned short cpo;
+ /* Write latency */
+ unsigned char wr_lat;
+ /* Read to precharge (tRTP) */
+ unsigned char rd_to_pre;
+ /* Write command to write data strobe timing adjustment */
+ unsigned char wr_data_delay;
+ /* Minimum CKE pulse width (tCKE) */
+ unsigned char cke_pls;
+ /* Window for four activates (tFAW) */
+ unsigned short four_act;
+
+ /* FIXME add check that this must be less than acttorw_mclk */
+ add_lat_mclk = additive_latency;
+ cpo = popts->cpo_override;
+
+#if defined(CONFIG_FSL_DDR1)
+ /*
+ * This is a lie. It should really be 1, but if it is
+ * set to 1, bits overlap into the old controller's
+ * otherwise unused ACSM field. If we leave it 0, then
+ * the HW will magically treat it as 1 for DDR 1. Oh Yea.
+ */
+ wr_lat = 0;
+#elif defined(CONFIG_FSL_DDR2)
+ wr_lat = cas_latency - 1;
+#else
+ wr_lat = compute_cas_write_latency();
+#endif
+
+ rd_to_pre = picos_to_mclk(common_dimm->tRTP_ps);
+ /*
+ * JEDEC has some min requirements for tRTP
+ */
+#if defined(CONFIG_FSL_DDR2)
+ if (rd_to_pre < 2)
+ rd_to_pre = 2;
+#elif defined(CONFIG_FSL_DDR3)
+ if (rd_to_pre < 4)
+ rd_to_pre = 4;
+#endif
+ if (additive_latency)
+ rd_to_pre += additive_latency;
+ if (popts->OTF_burst_chop_en)
+ rd_to_pre += 2; /* according to UM */
+
+ wr_data_delay = popts->write_data_delay;
+ cke_pls = picos_to_mclk(popts->tCKE_clock_pulse_width_ps);
+ four_act = picos_to_mclk(popts->tFAW_window_four_activates_ps);
+
+ ddr->timing_cfg_2 = (0
+ | ((add_lat_mclk & 0xf) << 28)
+ | ((cpo & 0x1f) << 23)
+ | ((wr_lat & 0xf) << 19)
+ | ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
+ | ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
+ | ((cke_pls & 0x7) << 6)
+ | ((four_act & 0x3f) << 0)
+ );
+ debug("FSLDDR: timing_cfg_2 = 0x%08x\n", ddr->timing_cfg_2);
+}
+
+/* DDR SDRAM Register Control Word */
+static void set_ddr_sdram_rcw(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm)
+{
+ if (common_dimm->all_DIMMs_registered
+ && !common_dimm->all_DIMMs_unbuffered) {
+ if (popts->rcw_override) {
+ ddr->ddr_sdram_rcw_1 = popts->rcw_1;
+ ddr->ddr_sdram_rcw_2 = popts->rcw_2;
+ } else {
+ ddr->ddr_sdram_rcw_1 =
+ common_dimm->rcw[0] << 28 | \
+ common_dimm->rcw[1] << 24 | \
+ common_dimm->rcw[2] << 20 | \
+ common_dimm->rcw[3] << 16 | \
+ common_dimm->rcw[4] << 12 | \
+ common_dimm->rcw[5] << 8 | \
+ common_dimm->rcw[6] << 4 | \
+ common_dimm->rcw[7];
+ ddr->ddr_sdram_rcw_2 =
+ common_dimm->rcw[8] << 28 | \
+ common_dimm->rcw[9] << 24 | \
+ common_dimm->rcw[10] << 20 | \
+ common_dimm->rcw[11] << 16 | \
+ common_dimm->rcw[12] << 12 | \
+ common_dimm->rcw[13] << 8 | \
+ common_dimm->rcw[14] << 4 | \
+ common_dimm->rcw[15];
+ }
+ debug("FSLDDR: ddr_sdram_rcw_1 = 0x%08x\n", ddr->ddr_sdram_rcw_1);
+ debug("FSLDDR: ddr_sdram_rcw_2 = 0x%08x\n", ddr->ddr_sdram_rcw_2);
+ }
+}
+
+/* DDR SDRAM control configuration (DDR_SDRAM_CFG) */
+static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm)
+{
+ unsigned int mem_en; /* DDR SDRAM interface logic enable */
+ unsigned int sren; /* Self refresh enable (during sleep) */
+ unsigned int ecc_en; /* ECC enable. */
+ unsigned int rd_en; /* Registered DIMM enable */
+ unsigned int sdram_type; /* Type of SDRAM */
+ unsigned int dyn_pwr; /* Dynamic power management mode */
+ unsigned int dbw; /* DRAM dta bus width */
+ unsigned int eight_be = 0; /* 8-beat burst enable, DDR2 is zero */
+ unsigned int ncap = 0; /* Non-concurrent auto-precharge */
+ unsigned int threeT_en; /* Enable 3T timing */
+ unsigned int twoT_en; /* Enable 2T timing */
+ unsigned int ba_intlv_ctl; /* Bank (CS) interleaving control */
+ unsigned int x32_en = 0; /* x32 enable */
+ unsigned int pchb8 = 0; /* precharge bit 8 enable */
+ unsigned int hse; /* Global half strength override */
+ unsigned int mem_halt = 0; /* memory controller halt */
+ unsigned int bi = 0; /* Bypass initialization */
+
+ mem_en = 1;
+ sren = popts->self_refresh_in_sleep;
+ if (common_dimm->all_DIMMs_ECC_capable) {
+ /* Allow setting of ECC only if all DIMMs are ECC. */
+ ecc_en = popts->ECC_mode;
+ } else {
+ ecc_en = 0;
+ }
+
+ if (common_dimm->all_DIMMs_registered
+ && !common_dimm->all_DIMMs_unbuffered) {
+ rd_en = 1;
+ twoT_en = 0;
+ } else {
+ rd_en = 0;
+ twoT_en = popts->twoT_en;
+ }
+
+ sdram_type = CONFIG_FSL_SDRAM_TYPE;
+
+ dyn_pwr = popts->dynamic_power;
+ dbw = popts->data_bus_width;
+ /* 8-beat burst enable DDR-III case
+ * we must clear it when use the on-the-fly mode,
+ * must set it when use the 32-bits bus mode.
+ */
+ if (sdram_type == SDRAM_TYPE_DDR3) {
+ if (popts->burst_length == DDR_BL8)
+ eight_be = 1;
+ if (popts->burst_length == DDR_OTF)
+ eight_be = 0;
+ if (dbw == 0x1)
+ eight_be = 1;
+ }
+
+ threeT_en = popts->threeT_en;
+ ba_intlv_ctl = popts->ba_intlv_ctl;
+ hse = popts->half_strength_driver_enable;
+
+ ddr->ddr_sdram_cfg = (0
+ | ((mem_en & 0x1) << 31)
+ | ((sren & 0x1) << 30)
+ | ((ecc_en & 0x1) << 29)
+ | ((rd_en & 0x1) << 28)
+ | ((sdram_type & 0x7) << 24)
+ | ((dyn_pwr & 0x1) << 21)
+ | ((dbw & 0x3) << 19)
+ | ((eight_be & 0x1) << 18)
+ | ((ncap & 0x1) << 17)
+ | ((threeT_en & 0x1) << 16)
+ | ((twoT_en & 0x1) << 15)
+ | ((ba_intlv_ctl & 0x7F) << 8)
+ | ((x32_en & 0x1) << 5)
+ | ((pchb8 & 0x1) << 4)
+ | ((hse & 0x1) << 3)
+ | ((mem_halt & 0x1) << 1)
+ | ((bi & 0x1) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_cfg = 0x%08x\n", ddr->ddr_sdram_cfg);
+}
+
+/* DDR SDRAM control configuration 2 (DDR_SDRAM_CFG_2) */
+static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const unsigned int unq_mrs_en)
+{
+ unsigned int frc_sr = 0; /* Force self refresh */
+ unsigned int sr_ie = 0; /* Self-refresh interrupt enable */
+ unsigned int dll_rst_dis; /* DLL reset disable */
+ unsigned int dqs_cfg; /* DQS configuration */
+ unsigned int odt_cfg = 0; /* ODT configuration */
+ unsigned int num_pr; /* Number of posted refreshes */
+ unsigned int slow = 0; /* DDR will be run less than 1250 */
+ unsigned int obc_cfg; /* On-The-Fly Burst Chop Cfg */
+ unsigned int ap_en; /* Address Parity Enable */
+ unsigned int d_init; /* DRAM data initialization */
+ unsigned int rcw_en = 0; /* Register Control Word Enable */
+ unsigned int md_en = 0; /* Mirrored DIMM Enable */
+ unsigned int qd_en = 0; /* quad-rank DIMM Enable */
+ int i;
+
+ dll_rst_dis = 1; /* Make this configurable */
+ dqs_cfg = popts->DQS_config;
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (popts->cs_local_opts[i].odt_rd_cfg
+ || popts->cs_local_opts[i].odt_wr_cfg) {
+ odt_cfg = SDRAM_CFG2_ODT_ONLY_READ;
+ break;
+ }
+ }
+
+ num_pr = 1; /* Make this configurable */
+
+ /*
+ * 8572 manual says
+ * {TIMING_CFG_1[PRETOACT]
+ * + [DDR_SDRAM_CFG_2[NUM_PR]
+ * * ({EXT_REFREC || REFREC} + 8 + 2)]}
+ * << DDR_SDRAM_INTERVAL[REFINT]
+ */
+#if defined(CONFIG_FSL_DDR3)
+ obc_cfg = popts->OTF_burst_chop_en;
+#else
+ obc_cfg = 0;
+#endif
+
+#if (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7)
+ slow = get_ddr_freq(0) < 1249000000;
+#endif
+
+ if (popts->registered_dimm_en) {
+ rcw_en = 1;
+ ap_en = popts->ap_en;
+ } else {
+ ap_en = 0;
+ }
+
+#if defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER)
+ /* Use the DDR controller to auto initialize memory. */
+ d_init = popts->ECC_init_using_memctl;
+ ddr->ddr_data_init = CONFIG_MEM_INIT_VALUE;
+ debug("DDR: ddr_data_init = 0x%08x\n", ddr->ddr_data_init);
+#else
+ /* Memory will be initialized via DMA, or not at all. */
+ d_init = 0;
+#endif
+
+#if defined(CONFIG_FSL_DDR3)
+ md_en = popts->mirrored_dimm;
+#endif
+ qd_en = popts->quad_rank_present ? 1 : 0;
+ ddr->ddr_sdram_cfg_2 = (0
+ | ((frc_sr & 0x1) << 31)
+ | ((sr_ie & 0x1) << 30)
+ | ((dll_rst_dis & 0x1) << 29)
+ | ((dqs_cfg & 0x3) << 26)
+ | ((odt_cfg & 0x3) << 21)
+ | ((num_pr & 0xf) << 12)
+ | ((slow & 1) << 11)
+ | (qd_en << 9)
+ | (unq_mrs_en << 8)
+ | ((obc_cfg & 0x1) << 6)
+ | ((ap_en & 0x1) << 5)
+ | ((d_init & 0x1) << 4)
+ | ((rcw_en & 0x1) << 2)
+ | ((md_en & 0x1) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);
+}
+
+/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
+static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const unsigned int unq_mrs_en)
+{
+ unsigned short esdmode2 = 0; /* Extended SDRAM mode 2 */
+ unsigned short esdmode3 = 0; /* Extended SDRAM mode 3 */
+
+#if defined(CONFIG_FSL_DDR3)
+ int i;
+ unsigned int rtt_wr = 0; /* Rtt_WR - dynamic ODT off */
+ unsigned int srt = 0; /* self-refresh temerature, normal range */
+ unsigned int asr = 0; /* auto self-refresh disable */
+ unsigned int cwl = compute_cas_write_latency() - 5;
+ unsigned int pasr = 0; /* partial array self refresh disable */
+
+ if (popts->rtt_override)
+ rtt_wr = popts->rtt_wr_override_value;
+ else
+ rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
+ esdmode2 = (0
+ | ((rtt_wr & 0x3) << 9)
+ | ((srt & 0x1) << 7)
+ | ((asr & 0x1) << 6)
+ | ((cwl & 0x7) << 3)
+ | ((pasr & 0x7) << 0));
+#endif
+ ddr->ddr_sdram_mode_2 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
+
+#ifdef CONFIG_FSL_DDR3
+ if (unq_mrs_en) { /* unique mode registers are supported */
+ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (popts->rtt_override)
+ rtt_wr = popts->rtt_wr_override_value;
+ else
+ rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
+
+ esdmode2 &= 0xF9FF; /* clear bit 10, 9 */
+ esdmode2 |= (rtt_wr & 0x3) << 9;
+ switch (i) {
+ case 1:
+ ddr->ddr_sdram_mode_4 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ break;
+ case 2:
+ ddr->ddr_sdram_mode_6 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ break;
+ case 3:
+ ddr->ddr_sdram_mode_8 = (0
+ | ((esdmode2 & 0xFFFF) << 16)
+ | ((esdmode3 & 0xFFFF) << 0)
+ );
+ break;
+ }
+ }
+ debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
+ ddr->ddr_sdram_mode_4);
+ debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
+ ddr->ddr_sdram_mode_6);
+ debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
+ ddr->ddr_sdram_mode_8);
+ }
+#endif
+}
+
+/* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
+static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm)
+{
+ unsigned int refint; /* Refresh interval */
+ unsigned int bstopre; /* Precharge interval */
+
+ refint = picos_to_mclk(common_dimm->refresh_rate_ps);
+
+ bstopre = popts->bstopre;
+
+ /* refint field used 0x3FFF in earlier controllers */
+ ddr->ddr_sdram_interval = (0
+ | ((refint & 0xFFFF) << 16)
+ | ((bstopre & 0x3FFF) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
+}
+
+#if defined(CONFIG_FSL_DDR3)
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency,
+ unsigned int additive_latency,
+ const unsigned int unq_mrs_en)
+{
+ unsigned short esdmode; /* Extended SDRAM mode */
+ unsigned short sdmode; /* SDRAM mode */
+
+ /* Mode Register - MR1 */
+ unsigned int qoff = 0; /* Output buffer enable 0=yes, 1=no */
+ unsigned int tdqs_en = 0; /* TDQS Enable: 0=no, 1=yes */
+ unsigned int rtt;
+ unsigned int wrlvl_en = 0; /* Write level enable: 0=no, 1=yes */
+ unsigned int al = 0; /* Posted CAS# additive latency (AL) */
+ unsigned int dic = 0; /* Output driver impedance, 40ohm */
+ unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal),
+ 1=Disable (Test/Debug) */
+
+ /* Mode Register - MR0 */
+ unsigned int dll_on; /* DLL control for precharge PD, 0=off, 1=on */
+ unsigned int wr = 0; /* Write Recovery */
+ unsigned int dll_rst; /* DLL Reset */
+ unsigned int mode; /* Normal=0 or Test=1 */
+ unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
+ /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+ unsigned int bt;
+ unsigned int bl; /* BL: Burst Length */
+
+ unsigned int wr_mclk;
+ /*
+ * DDR_SDRAM_MODE doesn't support 9,11,13,15
+ * Please refer JEDEC Standard No. 79-3E for Mode Register MR0
+ * for this table
+ */
+ static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
+
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+ int i;
+
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[0].odt_rtt_norm;
+
+ if (additive_latency == (cas_latency - 1))
+ al = 1;
+ if (additive_latency == (cas_latency - 2))
+ al = 2;
+
+ if (popts->quad_rank_present)
+ dic = 1; /* output driver impedance 240/7 ohm */
+
+ /*
+ * The esdmode value will also be used for writing
+ * MR1 during write leveling for DDR3, although the
+ * bits specifically related to the write leveling
+ * scheme will be handled automatically by the DDR
+ * controller. so we set the wrlvl_en = 0 here.
+ */
+ esdmode = (0
+ | ((qoff & 0x1) << 12)
+ | ((tdqs_en & 0x1) << 11)
+ | ((rtt & 0x4) << 7) /* rtt field is split */
+ | ((wrlvl_en & 0x1) << 7)
+ | ((rtt & 0x2) << 5) /* rtt field is split */
+ | ((dic & 0x2) << 4) /* DIC field is split */
+ | ((al & 0x3) << 3)
+ | ((rtt & 0x1) << 2) /* rtt field is split */
+ | ((dic & 0x1) << 1) /* DIC field is split */
+ | ((dll_en & 0x1) << 0)
+ );
+
+ /*
+ * DLL control for precharge PD
+ * 0=slow exit DLL off (tXPDLL)
+ * 1=fast exit DLL on (tXP)
+ */
+ dll_on = 1;
+
+ wr_mclk = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps;
+ if (wr_mclk <= 16) {
+ wr = wr_table[wr_mclk - 5];
+ } else {
+ printf("Error: unsupported write recovery for mode register "
+ "wr_mclk = %d\n", wr_mclk);
+ }
+
+ dll_rst = 0; /* dll no reset */
+ mode = 0; /* normal mode */
+
+ /* look up table to get the cas latency bits */
+ if (cas_latency >= 5 && cas_latency <= 16) {
+ unsigned char cas_latency_table[] = {
+ 0x2, /* 5 clocks */
+ 0x4, /* 6 clocks */
+ 0x6, /* 7 clocks */
+ 0x8, /* 8 clocks */
+ 0xa, /* 9 clocks */
+ 0xc, /* 10 clocks */
+ 0xe, /* 11 clocks */
+ 0x1, /* 12 clocks */
+ 0x3, /* 13 clocks */
+ 0x5, /* 14 clocks */
+ 0x7, /* 15 clocks */
+ 0x9, /* 16 clocks */
+ };
+ caslat = cas_latency_table[cas_latency - 5];
+ } else {
+ printf("Error: unsupported cas latency for mode register\n");
+ }
+
+ bt = 0; /* Nibble sequential */
+
+ switch (popts->burst_length) {
+ case DDR_BL8:
+ bl = 0;
+ break;
+ case DDR_OTF:
+ bl = 1;
+ break;
+ case DDR_BC4:
+ bl = 2;
+ break;
+ default:
+ printf("Error: invalid burst length of %u specified. "
+ " Defaulting to on-the-fly BC4 or BL8 beats.\n",
+ popts->burst_length);
+ bl = 1;
+ break;
+ }
+
+ sdmode = (0
+ | ((dll_on & 0x1) << 12)
+ | ((wr & 0x7) << 9)
+ | ((dll_rst & 0x1) << 8)
+ | ((mode & 0x1) << 7)
+ | (((caslat >> 1) & 0x7) << 4)
+ | ((bt & 0x1) << 3)
+ | ((caslat & 1) << 2)
+ | ((bl & 0x3) << 0)
+ );
+
+ ddr->ddr_sdram_mode = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+
+ debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+
+ if (unq_mrs_en) { /* unique mode registers are supported */
+ for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ if (popts->rtt_override)
+ rtt = popts->rtt_override_value;
+ else
+ rtt = popts->cs_local_opts[i].odt_rtt_norm;
+
+ esdmode &= 0xFDBB; /* clear bit 9,6,2 */
+ esdmode |= (0
+ | ((rtt & 0x4) << 7) /* rtt field is split */
+ | ((rtt & 0x2) << 5) /* rtt field is split */
+ | ((rtt & 0x1) << 2) /* rtt field is split */
+ );
+ switch (i) {
+ case 1:
+ ddr->ddr_sdram_mode_3 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ case 2:
+ ddr->ddr_sdram_mode_5 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ case 3:
+ ddr->ddr_sdram_mode_7 = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ break;
+ }
+ }
+ debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
+ ddr->ddr_sdram_mode_3);
+ debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+ ddr->ddr_sdram_mode_5);
+ debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+ ddr->ddr_sdram_mode_5);
+ }
+}
+
+#else /* !CONFIG_FSL_DDR3 */
+
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts,
+ const common_timing_params_t *common_dimm,
+ unsigned int cas_latency,
+ unsigned int additive_latency,
+ const unsigned int unq_mrs_en)
+{
+ unsigned short esdmode; /* Extended SDRAM mode */
+ unsigned short sdmode; /* SDRAM mode */
+
+ /*
+ * FIXME: This ought to be pre-calculated in a
+ * technology-specific routine,
+ * e.g. compute_DDR2_mode_register(), and then the
+ * sdmode and esdmode passed in as part of common_dimm.
+ */
+
+ /* Extended Mode Register */
+ unsigned int mrs = 0; /* Mode Register Set */
+ unsigned int outputs = 0; /* 0=Enabled, 1=Disabled */
+ unsigned int rdqs_en = 0; /* RDQS Enable: 0=no, 1=yes */
+ unsigned int dqs_en = 0; /* DQS# Enable: 0=enable, 1=disable */
+ unsigned int ocd = 0; /* 0x0=OCD not supported,
+ 0x7=OCD default state */
+ unsigned int rtt;
+ unsigned int al; /* Posted CAS# additive latency (AL) */
+ unsigned int ods = 0; /* Output Drive Strength:
+ 0 = Full strength (18ohm)
+ 1 = Reduced strength (4ohm) */
+ unsigned int dll_en = 0; /* DLL Enable 0=Enable (Normal),
+ 1=Disable (Test/Debug) */
+
+ /* Mode Register (MR) */
+ unsigned int mr; /* Mode Register Definition */
+ unsigned int pd; /* Power-Down Mode */
+ unsigned int wr; /* Write Recovery */
+ unsigned int dll_res; /* DLL Reset */
+ unsigned int mode; /* Normal=0 or Test=1 */
+ unsigned int caslat = 0;/* CAS# latency */
+ /* BT: Burst Type (0=Sequential, 1=Interleaved) */
+ unsigned int bt;
+ unsigned int bl; /* BL: Burst Length */
+
+#if defined(CONFIG_FSL_DDR2)
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+#endif
+ dqs_en = !popts->DQS_config;
+ rtt = fsl_ddr_get_rtt();
+
+ al = additive_latency;
+
+ esdmode = (0
+ | ((mrs & 0x3) << 14)
+ | ((outputs & 0x1) << 12)
+ | ((rdqs_en & 0x1) << 11)
+ | ((dqs_en & 0x1) << 10)
+ | ((ocd & 0x7) << 7)
+ | ((rtt & 0x2) << 5) /* rtt field is split */
+ | ((al & 0x7) << 3)
+ | ((rtt & 0x1) << 2) /* rtt field is split */
+ | ((ods & 0x1) << 1)
+ | ((dll_en & 0x1) << 0)
+ );
+
+ mr = 0; /* FIXME: CHECKME */
+
+ /*
+ * 0 = Fast Exit (Normal)
+ * 1 = Slow Exit (Low Power)
+ */
+ pd = 0;
+
+#if defined(CONFIG_FSL_DDR1)
+ wr = 0; /* Historical */
+#elif defined(CONFIG_FSL_DDR2)
+ wr = (common_dimm->tWR_ps + mclk_ps - 1) / mclk_ps - 1;
+#endif
+ dll_res = 0;
+ mode = 0;
+
+#if defined(CONFIG_FSL_DDR1)
+ if (1 <= cas_latency && cas_latency <= 4) {
+ unsigned char mode_caslat_table[4] = {
+ 0x5, /* 1.5 clocks */
+ 0x2, /* 2.0 clocks */
+ 0x6, /* 2.5 clocks */
+ 0x3 /* 3.0 clocks */
+ };
+ caslat = mode_caslat_table[cas_latency - 1];
+ } else {
+ printf("Warning: unknown cas_latency %d\n", cas_latency);
+ }
+#elif defined(CONFIG_FSL_DDR2)
+ caslat = cas_latency;
+#endif
+ bt = 0;
+
+ switch (popts->burst_length) {
+ case DDR_BL4:
+ bl = 2;
+ break;
+ case DDR_BL8:
+ bl = 3;
+ break;
+ default:
+ printf("Error: invalid burst length of %u specified. "
+ " Defaulting to 4 beats.\n",
+ popts->burst_length);
+ bl = 2;
+ break;
+ }
+
+ sdmode = (0
+ | ((mr & 0x3) << 14)
+ | ((pd & 0x1) << 12)
+ | ((wr & 0x7) << 9)
+ | ((dll_res & 0x1) << 8)
+ | ((mode & 0x1) << 7)
+ | ((caslat & 0x7) << 4)
+ | ((bt & 0x1) << 3)
+ | ((bl & 0x7) << 0)
+ );
+
+ ddr->ddr_sdram_mode = (0
+ | ((esdmode & 0xFFFF) << 16)
+ | ((sdmode & 0xFFFF) << 0)
+ );
+ debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+}
+#endif
+
+/* DDR SDRAM Data Initialization (DDR_DATA_INIT) */
+static void set_ddr_data_init(fsl_ddr_cfg_regs_t *ddr)
+{
+ unsigned int init_value; /* Initialization value */
+
+#ifdef CONFIG_MEM_INIT_VALUE
+ init_value = CONFIG_MEM_INIT_VALUE;
+#else
+ init_value = 0xDEADBEEF;
+#endif
+ ddr->ddr_data_init = init_value;
+}
+
+/*
+ * DDR SDRAM Clock Control (DDR_SDRAM_CLK_CNTL)
+ * The old controller on the 8540/60 doesn't have this register.
+ * Hope it's OK to set it (to 0) anyway.
+ */
+static void set_ddr_sdram_clk_cntl(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts)
+{
+ unsigned int clk_adjust; /* Clock adjust */
+
+ clk_adjust = popts->clk_adjust;
+ ddr->ddr_sdram_clk_cntl = (clk_adjust & 0xF) << 23;
+ debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl);
+}
+
+/* DDR Initialization Address (DDR_INIT_ADDR) */
+static void set_ddr_init_addr(fsl_ddr_cfg_regs_t *ddr)
+{
+ unsigned int init_addr = 0; /* Initialization address */
+
+ ddr->ddr_init_addr = init_addr;
+}
+
+/* DDR Initialization Address (DDR_INIT_EXT_ADDR) */
+static void set_ddr_init_ext_addr(fsl_ddr_cfg_regs_t *ddr)
+{
+ unsigned int uia = 0; /* Use initialization address */
+ unsigned int init_ext_addr = 0; /* Initialization address */
+
+ ddr->ddr_init_ext_addr = (0
+ | ((uia & 0x1) << 31)
+ | (init_ext_addr & 0xF)
+ );
+}
+
+/* DDR SDRAM Timing Configuration 4 (TIMING_CFG_4) */
+static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
+ const memctl_options_t *popts)
+{
+ unsigned int rwt = 0; /* Read-to-write turnaround for same CS */
+ unsigned int wrt = 0; /* Write-to-read turnaround for same CS */
+ unsigned int rrt = 0; /* Read-to-read turnaround for same CS */
+ unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
+ unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
+
+#if defined(CONFIG_FSL_DDR3)
+ if (popts->burst_length == DDR_BL8) {
+ /* We set BL/2 for fixed BL8 */
+ rrt = 0; /* BL/2 clocks */
+ wwt = 0; /* BL/2 clocks */
+ } else {
+ /* We need to set BL/2 + 2 to BC4 and OTF */
+ rrt = 2; /* BL/2 + 2 clocks */
+ wwt = 2; /* BL/2 + 2 clocks */
+ }
+ dll_lock = 1; /* tDLLK = 512 clocks from spec */
+#endif
+ ddr->timing_cfg_4 = (0
+ | ((rwt & 0xf) << 28)
+ | ((wrt & 0xf) << 24)
+ | ((rrt & 0xf) << 20)
+ | ((wwt & 0xf) << 16)
+ | (dll_lock & 0x3)
+ );
+ debug("FSLDDR: timing_cfg_4 = 0x%08x\n", ddr->timing_cfg_4);
+}
+
+/* DDR SDRAM Timing Configuration 5 (TIMING_CFG_5) */
+static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
+{
+ unsigned int rodt_on = 0; /* Read to ODT on */
+ unsigned int rodt_off = 0; /* Read to ODT off */
+ unsigned int wodt_on = 0; /* Write to ODT on */
+ unsigned int wodt_off = 0; /* Write to ODT off */
+
+#if defined(CONFIG_FSL_DDR3)
+ /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
+ rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1;
+ rodt_off = 4; /* 4 clocks */
+ wodt_on = 1; /* 1 clocks */
+ wodt_off = 4; /* 4 clocks */
+#endif
+
+ ddr->timing_cfg_5 = (0
+ | ((rodt_on & 0x1f) << 24)
+ | ((rodt_off & 0x7) << 20)
+ | ((wodt_on & 0x1f) << 12)
+ | ((wodt_off & 0x7) << 8)
+ );
+ debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
+}
+
+/* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
+static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
+{
+ unsigned int zqinit = 0;/* POR ZQ Calibration Time (tZQinit) */
+ /* Normal Operation Full Calibration Time (tZQoper) */
+ unsigned int zqoper = 0;
+ /* Normal Operation Short Calibration Time (tZQCS) */
+ unsigned int zqcs = 0;
+
+ if (zq_en) {
+ zqinit = 9; /* 512 clocks */
+ zqoper = 8; /* 256 clocks */
+ zqcs = 6; /* 64 clocks */
+ }
+
+ ddr->ddr_zq_cntl = (0
+ | ((zq_en & 0x1) << 31)
+ | ((zqinit & 0xF) << 24)
+ | ((zqoper & 0xF) << 16)
+ | ((zqcs & 0xF) << 8)
+ );
+ debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl);
+}
+
+/* DDR Write Leveling Control (DDR_WRLVL_CNTL) */
+static void set_ddr_wrlvl_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int wrlvl_en,
+ const memctl_options_t *popts)
+{
+ /*
+ * First DQS pulse rising edge after margining mode
+ * is programmed (tWL_MRD)
+ */
+ unsigned int wrlvl_mrd = 0;
+ /* ODT delay after margining mode is programmed (tWL_ODTEN) */
+ unsigned int wrlvl_odten = 0;
+ /* DQS/DQS_ delay after margining mode is programmed (tWL_DQSEN) */
+ unsigned int wrlvl_dqsen = 0;
+ /* WRLVL_SMPL: Write leveling sample time */
+ unsigned int wrlvl_smpl = 0;
+ /* WRLVL_WLR: Write leveling repeition time */
+ unsigned int wrlvl_wlr = 0;
+ /* WRLVL_START: Write leveling start time */
+ unsigned int wrlvl_start = 0;
+
+ /* suggest enable write leveling for DDR3 due to fly-by topology */
+ if (wrlvl_en) {
+ /* tWL_MRD min = 40 nCK, we set it 64 */
+ wrlvl_mrd = 0x6;
+ /* tWL_ODTEN 128 */
+ wrlvl_odten = 0x7;
+ /* tWL_DQSEN min = 25 nCK, we set it 32 */
+ wrlvl_dqsen = 0x5;
+ /*
+ * Write leveling sample time at least need 6 clocks
+ * higher than tWLO to allow enough time for progagation
+ * delay and sampling the prime data bits.
+ */
+ wrlvl_smpl = 0xf;
+ /*
+ * Write leveling repetition time
+ * at least tWLO + 6 clocks clocks
+ * we set it 64
+ */
+ wrlvl_wlr = 0x6;
+ /*
+ * Write leveling start time
+ * The value use for the DQS_ADJUST for the first sample
+ * when write leveling is enabled. It probably needs to be
+ * overriden per platform.
+ */
+ wrlvl_start = 0x8;
+ /*
+ * Override the write leveling sample and start time
+ * according to specific board
+ */
+ if (popts->wrlvl_override) {
+ wrlvl_smpl = popts->wrlvl_sample;
+ wrlvl_start = popts->wrlvl_start;
+ }
+ }
+
+ ddr->ddr_wrlvl_cntl = (0
+ | ((wrlvl_en & 0x1) << 31)
+ | ((wrlvl_mrd & 0x7) << 24)
+ | ((wrlvl_odten & 0x7) << 20)
+ | ((wrlvl_dqsen & 0x7) << 16)
+ | ((wrlvl_smpl & 0xf) << 12)
+ | ((wrlvl_wlr & 0x7) << 8)
+ | ((wrlvl_start & 0x1F) << 0)
+ );
+ debug("FSLDDR: wrlvl_cntl = 0x%08x\n", ddr->ddr_wrlvl_cntl);
+ ddr->ddr_wrlvl_cntl_2 = popts->wrlvl_ctl_2;
+ debug("FSLDDR: wrlvl_cntl_2 = 0x%08x\n", ddr->ddr_wrlvl_cntl_2);
+ ddr->ddr_wrlvl_cntl_3 = popts->wrlvl_ctl_3;
+ debug("FSLDDR: wrlvl_cntl_3 = 0x%08x\n", ddr->ddr_wrlvl_cntl_3);
+
+}
+
+/* DDR Self Refresh Counter (DDR_SR_CNTR) */
+static void set_ddr_sr_cntr(fsl_ddr_cfg_regs_t *ddr, unsigned int sr_it)
+{
+ /* Self Refresh Idle Threshold */
+ ddr->ddr_sr_cntr = (sr_it & 0xF) << 16;
+}
+
+static void set_ddr_eor(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
+{
+ if (popts->addr_hash) {
+ ddr->ddr_eor = 0x40000000; /* address hash enable */
+ puts("Address hashing enabled.\n");
+ }
+}
+
+static void set_ddr_cdr1(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
+{
+ ddr->ddr_cdr1 = popts->ddr_cdr1;
+ debug("FSLDDR: ddr_cdr1 = 0x%08x\n", ddr->ddr_cdr1);
+}
+
+static void set_ddr_cdr2(fsl_ddr_cfg_regs_t *ddr, const memctl_options_t *popts)
+{
+ ddr->ddr_cdr2 = popts->ddr_cdr2;
+ debug("FSLDDR: ddr_cdr2 = 0x%08x\n", ddr->ddr_cdr2);
+}
+
+unsigned int
+check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
+{
+ unsigned int res = 0;
+
+ /*
+ * Check that DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] are
+ * not set at the same time.
+ */
+ if (ddr->ddr_sdram_cfg & 0x10000000
+ && ddr->ddr_sdram_cfg & 0x00008000) {
+ printf("Error: DDR_SDRAM_CFG[RD_EN] and DDR_SDRAM_CFG[2T_EN] "
+ " should not be set at the same time.\n");
+ res++;
+ }
+
+ return res;
+}
+
+unsigned int
+compute_fsl_memctl_config_regs(const memctl_options_t *popts,
+ fsl_ddr_cfg_regs_t *ddr,
+ const common_timing_params_t *common_dimm,
+ const dimm_params_t *dimm_params,
+ unsigned int dbw_cap_adj,
+ unsigned int size_only)
+{
+ unsigned int i;
+ unsigned int cas_latency;
+ unsigned int additive_latency;
+ unsigned int sr_it;
+ unsigned int zq_en;
+ unsigned int wrlvl_en;
+ unsigned int ip_rev = 0;
+ unsigned int unq_mrs_en = 0;
+ int cs_en = 1;
+
+ memset(ddr, 0, sizeof(fsl_ddr_cfg_regs_t));
+
+ if (common_dimm == NULL) {
+ printf("Error: subset DIMM params struct null pointer\n");
+ return 1;
+ }
+
+ /*
+ * Process overrides first.
+ *
+ * FIXME: somehow add dereated caslat to this
+ */
+ cas_latency = (popts->cas_latency_override)
+ ? popts->cas_latency_override_value
+ : common_dimm->lowest_common_SPD_caslat;
+
+ additive_latency = (popts->additive_latency_override)
+ ? popts->additive_latency_override_value
+ : common_dimm->additive_latency;
+
+ sr_it = (popts->auto_self_refresh_en)
+ ? popts->sr_it
+ : 0;
+ /* ZQ calibration */
+ zq_en = (popts->zq_en) ? 1 : 0;
+ /* write leveling */
+ wrlvl_en = (popts->wrlvl_en) ? 1 : 0;
+
+ /* Chip Select Memory Bounds (CSn_BNDS) */
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+ unsigned long long ea, sa;
+ unsigned int cs_per_dimm
+ = CONFIG_CHIP_SELECTS_PER_CTRL / CONFIG_DIMM_SLOTS_PER_CTLR;
+ unsigned int dimm_number
+ = i / cs_per_dimm;
+ unsigned long long rank_density
+ = dimm_params[dimm_number].rank_density >> dbw_cap_adj;
+
+ if (dimm_params[dimm_number].n_ranks == 0) {
+ debug("Skipping setup of CS%u "
+ "because n_ranks on DIMM %u is 0\n", i, dimm_number);
+ continue;
+ }
+ if (popts->memctl_interleaving) {
+ switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
+ case FSL_DDR_CS0_CS1_CS2_CS3:
+ break;
+ case FSL_DDR_CS0_CS1:
+ case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+ if (i > 1)
+ cs_en = 0;
+ break;
+ case FSL_DDR_CS2_CS3:
+ default:
+ if (i > 0)
+ cs_en = 0;
+ break;
+ }
+ sa = common_dimm->base_address;
+ ea = sa + common_dimm->total_mem - 1;
+ } else if (!popts->memctl_interleaving) {
+ /*
+ * If memory interleaving between controllers is NOT
+ * enabled, the starting address for each memory
+ * controller is distinct. However, because rank
+ * interleaving is enabled, the starting and ending
+ * addresses of the total memory on that memory
+ * controller needs to be programmed into its
+ * respective CS0_BNDS.
+ */
+ switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
+ case FSL_DDR_CS0_CS1_CS2_CS3:
+ sa = common_dimm->base_address;
+ ea = sa + common_dimm->total_mem - 1;
+ break;
+ case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+ if ((i >= 2) && (dimm_number == 0)) {
+ sa = dimm_params[dimm_number].base_address +
+ 2 * rank_density;
+ ea = sa + 2 * rank_density - 1;
+ } else {
+ sa = dimm_params[dimm_number].base_address;
+ ea = sa + 2 * rank_density - 1;
+ }
+ break;
+ case FSL_DDR_CS0_CS1:
+ if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
+ sa = dimm_params[dimm_number].base_address;
+ ea = sa + rank_density - 1;
+ if (i != 1)
+ sa += (i % cs_per_dimm) * rank_density;
+ ea += (i % cs_per_dimm) * rank_density;
+ } else {
+ sa = 0;
+ ea = 0;
+ }
+ if (i == 0)
+ ea += rank_density;
+ break;
+ case FSL_DDR_CS2_CS3:
+ if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
+ sa = dimm_params[dimm_number].base_address;
+ ea = sa + rank_density - 1;
+ if (i != 3)
+ sa += (i % cs_per_dimm) * rank_density;
+ ea += (i % cs_per_dimm) * rank_density;
+ } else {
+ sa = 0;
+ ea = 0;
+ }
+ if (i == 2)
+ ea += (rank_density >> dbw_cap_adj);
+ break;
+ default: /* No bank(chip-select) interleaving */
+ sa = dimm_params[dimm_number].base_address;
+ ea = sa + rank_density - 1;
+ if (dimm_params[dimm_number].n_ranks > (i % cs_per_dimm)) {
+ sa += (i % cs_per_dimm) * rank_density;
+ ea += (i % cs_per_dimm) * rank_density;
+ } else {
+ sa = 0;
+ ea = 0;
+ }
+ break;
+ }
+ }
+
+ sa >>= 24;
+ ea >>= 24;
+
+ if (cs_en) {
+ ddr->cs[i].bnds = (0
+ | ((sa & 0xFFF) << 16)/* starting address MSB */
+ | ((ea & 0xFFF) << 0) /* ending address MSB */
+ );
+ } else {
+ debug("FSLDDR: setting bnds to 0 for inactive CS\n");
+ ddr->cs[i].bnds = 0;
+ }
+
+ debug("FSLDDR: cs[%d]_bnds = 0x%08x\n", i, ddr->cs[i].bnds);
+ set_csn_config(dimm_number, i, ddr, popts, dimm_params);
+ set_csn_config_2(i, ddr);
+ }
+
+ /*
+ * In the case we only need to compute the ddr sdram size, we only need
+ * to set csn registers, so return from here.
+ */
+ if (size_only)
+ return 0;
+
+ set_ddr_eor(ddr, popts);
+
+#if !defined(CONFIG_FSL_DDR1)
+ set_timing_cfg_0(ddr, popts, dimm_params);
+#endif
+
+ set_timing_cfg_3(ddr, popts, common_dimm, cas_latency);
+ set_timing_cfg_1(ddr, popts, common_dimm, cas_latency);
+ set_timing_cfg_2(ddr, popts, common_dimm,
+ cas_latency, additive_latency);
+
+ set_ddr_cdr1(ddr, popts);
+ set_ddr_cdr2(ddr, popts);
+ set_ddr_sdram_cfg(ddr, popts, common_dimm);
+ ip_rev = fsl_ddr_get_version();
+ if (ip_rev > 0x40400)
+ unq_mrs_en = 1;
+
+ set_ddr_sdram_cfg_2(ddr, popts, unq_mrs_en);
+ set_ddr_sdram_mode(ddr, popts, common_dimm,
+ cas_latency, additive_latency, unq_mrs_en);
+ set_ddr_sdram_mode_2(ddr, popts, unq_mrs_en);
+ set_ddr_sdram_interval(ddr, popts, common_dimm);
+ set_ddr_data_init(ddr);
+ set_ddr_sdram_clk_cntl(ddr, popts);
+ set_ddr_init_addr(ddr);
+ set_ddr_init_ext_addr(ddr);
+ set_timing_cfg_4(ddr, popts);
+ set_timing_cfg_5(ddr, cas_latency);
+
+ set_ddr_zq_cntl(ddr, zq_en);
+ set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
+
+ set_ddr_sr_cntr(ddr, sr_it);
+
+ set_ddr_sdram_rcw(ddr, popts, common_dimm);
+
+ return check_fsl_memctl_config_regs(ddr);
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h b/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h
new file mode 100644
index 0000000..4dd55fc
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef FSL_DDR_MAIN_H
+#define FSL_DDR_MAIN_H
+
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_ddr_dimm_params.h>
+
+#include "common_timing_params.h"
+
+#if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM)
+/*
+ * Bind the main DDR setup driver's generic names
+ * to this specific DDR technology.
+ */
+static __inline__ int
+compute_dimm_parameters(const generic_spd_eeprom_t *spd,
+ dimm_params_t *pdimm,
+ unsigned int dimm_number)
+{
+ return ddr_compute_dimm_parameters(spd, pdimm, dimm_number);
+}
+#endif
+
+/*
+ * Data Structures
+ *
+ * All data structures have to be on the stack
+ */
+#define CONFIG_SYS_NUM_DDR_CTLRS CONFIG_NUM_DDR_CONTROLLERS
+#define CONFIG_SYS_DIMM_SLOTS_PER_CTLR CONFIG_DIMM_SLOTS_PER_CTLR
+
+typedef struct {
+ generic_spd_eeprom_t
+ spd_installed_dimms[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR];
+ struct dimm_params_s
+ dimm_params[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR];
+ memctl_options_t memctl_opts[CONFIG_SYS_NUM_DDR_CTLRS];
+ common_timing_params_t common_timing_params[CONFIG_SYS_NUM_DDR_CTLRS];
+ fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CONFIG_SYS_NUM_DDR_CTLRS];
+} fsl_ddr_info_t;
+
+/* Compute steps */
+#define STEP_GET_SPD (1 << 0)
+#define STEP_COMPUTE_DIMM_PARMS (1 << 1)
+#define STEP_COMPUTE_COMMON_PARMS (1 << 2)
+#define STEP_GATHER_OPTS (1 << 3)
+#define STEP_ASSIGN_ADDRESSES (1 << 4)
+#define STEP_COMPUTE_REGS (1 << 5)
+#define STEP_PROGRAM_REGS (1 << 6)
+#define STEP_ALL 0xFFF
+
+unsigned long long
+fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
+ unsigned int size_only);
+
+const char *step_to_string(unsigned int step);
+
+unsigned int compute_fsl_memctl_config_regs(const memctl_options_t *popts,
+ fsl_ddr_cfg_regs_t *ddr,
+ const common_timing_params_t *common_dimm,
+ const dimm_params_t *dimm_parameters,
+ unsigned int dbw_capacity_adjust,
+ unsigned int size_only);
+unsigned int compute_lowest_common_dimm_parameters(
+ const dimm_params_t *dimm_params,
+ common_timing_params_t *outpdimm,
+ unsigned int number_of_dimms);
+unsigned int populate_memctl_options(int all_DIMMs_registered,
+ memctl_options_t *popts,
+ dimm_params_t *pdimm,
+ unsigned int ctrl_num);
+void check_interleaving_options(fsl_ddr_info_t *pinfo);
+
+unsigned int mclk_to_picos(unsigned int mclk);
+unsigned int get_memory_clk_period_ps(void);
+unsigned int picos_to_mclk(unsigned int picos);
+void fsl_ddr_set_lawbar(
+ const common_timing_params_t *memctl_common_params,
+ unsigned int memctl_interleaved,
+ unsigned int ctrl_num);
+
+int fsl_ddr_interactive_env_var_exists(void);
+unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set);
+void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
+ unsigned int ctrl_num);
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+unsigned int check_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr);
+
+/* processor specific function */
+void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num);
+
+/* board specific function */
+int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
+ unsigned int controller_number,
+ unsigned int dimm_number);
+#endif
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c
new file mode 100644
index 0000000..376be2f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr1_dimm_params.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ * DDR I DDR II
+ * Bit Size Size
+ * --- ----- ------
+ * 7 high 512MB 512MB
+ * 6 256MB 256MB
+ * 5 128MB 128MB
+ * 4 64MB 16GB
+ * 3 32MB 8GB
+ * 2 16MB 4GB
+ * 1 2GB 2GB
+ * 0 low 1GB 1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ */
+
+static unsigned long long
+compute_ranksize(unsigned int mem_type, unsigned char row_dens)
+{
+ unsigned long long bsize;
+
+ /* Bottom 2 bits up to the top. */
+ bsize = ((row_dens >> 2) | ((row_dens & 3) << 6));
+ bsize <<= 24ULL;
+ debug("DDR: DDR I rank density = 0x%16llx\n", bsize);
+
+ return bsize;
+}
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II. No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+static unsigned int
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
+{
+ /* Table look up the lower nibble, allow DDR I & II. */
+ unsigned int tenths_ps[16] = {
+ 0,
+ 100,
+ 200,
+ 300,
+ 400,
+ 500,
+ 600,
+ 700,
+ 800,
+ 900,
+ 250, /* This and the next 3 entries valid ... */
+ 330, /* ... only for tCK calculations. */
+ 660,
+ 750,
+ 0, /* undefined */
+ 0 /* undefined */
+ };
+
+ unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+ unsigned int tenth_ns = spd_val & 0x0F;
+ unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+ return ps;
+}
+
+static unsigned int
+convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val)
+{
+ unsigned int tenth_ns = (spd_val & 0xF0) >> 4;
+ unsigned int hundredth_ns = spd_val & 0x0F;
+ unsigned int ps = tenth_ns * 100 + hundredth_ns * 10;
+
+ return ps;
+}
+
+static unsigned int byte40_table_ps[8] = {
+ 0,
+ 250,
+ 330,
+ 500,
+ 660,
+ 750,
+ 0, /* supposed to be RFC, but not sure what that means */
+ 0 /* Undefined */
+};
+
+static unsigned int
+compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
+{
+ unsigned int trfc_ps;
+
+ trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000
+ + byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
+
+ return trfc_ps;
+}
+
+static unsigned int
+compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
+{
+ unsigned int trc_ps;
+
+ trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
+
+ return trc_ps;
+}
+
+/*
+ * tCKmax from DDR I SPD Byte 43
+ *
+ * Bits 7:2 == whole ns
+ * Bits 1:0 == quarter ns
+ * 00 == 0.00 ns
+ * 01 == 0.25 ns
+ * 10 == 0.50 ns
+ * 11 == 0.75 ns
+ *
+ * Returns picoseconds.
+ */
+static unsigned int
+compute_tckmax_from_spd_ps(unsigned int byte43)
+{
+ return (byte43 >> 2) * 1000 + (byte43 & 0x3) * 250;
+}
+
+/*
+ * Determine Refresh Rate. Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+static unsigned int
+determine_refresh_rate_ps(const unsigned int spd_refresh)
+{
+ unsigned int refresh_time_ps[8] = {
+ 15625000, /* 0 Normal 1.00x */
+ 3900000, /* 1 Reduced .25x */
+ 7800000, /* 2 Extended .50x */
+ 31300000, /* 3 Extended 2.00x */
+ 62500000, /* 4 Extended 4.00x */
+ 125000000, /* 5 Extended 8.00x */
+ 15625000, /* 6 Normal 1.00x filler */
+ 15625000, /* 7 Normal 1.00x filler */
+ };
+
+ return refresh_time_ps[spd_refresh & 0x7];
+}
+
+/*
+ * The purpose of this function is to compute a suitable
+ * CAS latency given the DRAM clock period. The SPD only
+ * defines at most 3 CAS latencies. Typically the slower in
+ * frequency the DIMM runs at, the shorter its CAS latency can be.
+ * If the DIMM is operating at a sufficiently low frequency,
+ * it may be able to run at a CAS latency shorter than the
+ * shortest SPD-defined CAS latency.
+ *
+ * If a CAS latency is not found, 0 is returned.
+ *
+ * Do this by finding in the standard speed bin table the longest
+ * tCKmin that doesn't exceed the value of mclk_ps (tCK).
+ *
+ * An assumption made is that the SDRAM device allows the
+ * CL to be programmed for a value that is lower than those
+ * advertised by the SPD. This is not always the case,
+ * as those modes not defined in the SPD are optional.
+ *
+ * CAS latency de-rating based upon values JEDEC Standard No. 79-E
+ * Table 11.
+ *
+ * ordinal 2, ddr1_speed_bins[1] contains tCK for CL=2
+ */
+ /* CL2.0 CL2.5 CL3.0 */
+unsigned short ddr1_speed_bins[] = {0, 7500, 6000, 5000 };
+
+unsigned int
+compute_derated_DDR1_CAS_latency(unsigned int mclk_ps)
+{
+ const unsigned int num_speed_bins = ARRAY_SIZE(ddr1_speed_bins);
+ unsigned int lowest_tCKmin_found = 0;
+ unsigned int lowest_tCKmin_CL = 0;
+ unsigned int i;
+
+ debug("mclk_ps = %u\n", mclk_ps);
+
+ for (i = 0; i < num_speed_bins; i++) {
+ unsigned int x = ddr1_speed_bins[i];
+ debug("i=%u, x = %u, lowest_tCKmin_found = %u\n",
+ i, x, lowest_tCKmin_found);
+ if (x && lowest_tCKmin_found <= x && x <= mclk_ps) {
+ lowest_tCKmin_found = x;
+ lowest_tCKmin_CL = i + 1;
+ }
+ }
+
+ debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL);
+
+ return lowest_tCKmin_CL;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR1 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ * FIXME: use #define for the retvals
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr1_spd_eeprom_t *spd,
+ dimm_params_t *pdimm,
+ unsigned int dimm_number)
+{
+ unsigned int retval;
+
+ if (spd->mem_type) {
+ if (spd->mem_type != SPD_MEMTYPE_DDR) {
+ printf("DIMM %u: is not a DDR1 SPD.\n", dimm_number);
+ return 1;
+ }
+ } else {
+ memset(pdimm, 0, sizeof(dimm_params_t));
+ return 1;
+ }
+
+ retval = ddr1_spd_check(spd);
+ if (retval) {
+ printf("DIMM %u: failed checksum\n", dimm_number);
+ return 2;
+ }
+
+ /*
+ * The part name in ASCII in the SPD EEPROM is not null terminated.
+ * Guarantee null termination here by presetting all bytes to 0
+ * and copying the part name in ASCII from the SPD onto it
+ */
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = spd->nrows;
+ pdimm->rank_density = compute_ranksize(spd->mem_type, spd->bank_dens);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ pdimm->data_width = spd->dataw_lsb;
+ pdimm->primary_sdram_width = spd->primw;
+ pdimm->ec_sdram_width = spd->ecw;
+
+ /*
+ * FIXME: Need to determine registered_dimm status.
+ * 1 == register buffered
+ * 0 == unbuffered
+ */
+ pdimm->registered_dimm = 0; /* unbuffered */
+
+ /* SDRAM device parameters */
+ pdimm->n_row_addr = spd->nrow_addr;
+ pdimm->n_col_addr = spd->ncol_addr;
+ pdimm->n_banks_per_sdram_device = spd->nbanks;
+ pdimm->edc_config = spd->config;
+ pdimm->burst_lengths_bitmask = spd->burstl;
+ pdimm->row_density = spd->bank_dens;
+
+ /*
+ * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+ * The SPD clk_cycle field (tCKmin) is measured in tenths of
+ * nanoseconds and represented as BCD.
+ */
+ pdimm->tCKmin_X_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
+ pdimm->tCKmin_X_minus_1_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
+ pdimm->tCKmin_X_minus_2_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
+
+ pdimm->tCKmax_ps = compute_tckmax_from_spd_ps(spd->tckmax);
+
+ /*
+ * Compute CAS latencies defined by SPD
+ * The SPD caslat_X should have at least 1 and at most 3 bits set.
+ *
+ * If cas_lat after masking is 0, the __ilog2 function returns
+ * 255 into the variable. This behavior is abused once.
+ */
+ pdimm->caslat_X = __ilog2(spd->cas_lat);
+ pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
+ & ~(1 << pdimm->caslat_X));
+ pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat
+ & ~(1 << pdimm->caslat_X)
+ & ~(1 << pdimm->caslat_X_minus_1));
+
+ /* Compute CAS latencies below that defined by SPD */
+ pdimm->caslat_lowest_derated
+ = compute_derated_DDR1_CAS_latency(get_memory_clk_period_ps());
+
+ /* Compute timing parameters */
+ pdimm->tRCD_ps = spd->trcd * 250;
+ pdimm->tRP_ps = spd->trp * 250;
+ pdimm->tRAS_ps = spd->tras * 1000;
+
+ pdimm->tWR_ps = mclk_to_picos(3);
+ pdimm->tWTR_ps = mclk_to_picos(1);
+ pdimm->tRFC_ps = compute_trfc_ps_from_spd(0, spd->trfc);
+
+ pdimm->tRRD_ps = spd->trrd * 250;
+ pdimm->tRC_ps = compute_trc_ps_from_spd(0, spd->trc);
+
+ pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
+
+ pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
+ pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
+ pdimm->tDS_ps
+ = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
+ pdimm->tDH_ps
+ = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
+
+ pdimm->tRTP_ps = mclk_to_picos(2); /* By the book. */
+ pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
+ pdimm->tQHS_ps = spd->tqhs * 10;
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c
new file mode 100644
index 0000000..f637f3d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr2_dimm_params.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Study these table from Byte 31 of JEDEC SPD Spec.
+ *
+ * DDR I DDR II
+ * Bit Size Size
+ * --- ----- ------
+ * 7 high 512MB 512MB
+ * 6 256MB 256MB
+ * 5 128MB 128MB
+ * 4 64MB 16GB
+ * 3 32MB 8GB
+ * 2 16MB 4GB
+ * 1 2GB 2GB
+ * 0 low 1GB 1GB
+ *
+ * Reorder Table to be linear by stripping the bottom
+ * 2 or 5 bits off and shifting them up to the top.
+ *
+ */
+static unsigned long long
+compute_ranksize(unsigned int mem_type, unsigned char row_dens)
+{
+ unsigned long long bsize;
+
+ /* Bottom 5 bits up to the top. */
+ bsize = ((row_dens >> 5) | ((row_dens & 31) << 3));
+ bsize <<= 27ULL;
+ debug("DDR: DDR II rank density = 0x%16llx\n", bsize);
+
+ return bsize;
+}
+
+/*
+ * Convert a two-nibble BCD value into a cycle time.
+ * While the spec calls for nano-seconds, picos are returned.
+ *
+ * This implements the tables for bytes 9, 23 and 25 for both
+ * DDR I and II. No allowance for distinguishing the invalid
+ * fields absent for DDR I yet present in DDR II is made.
+ * (That is, cycle times of .25, .33, .66 and .75 ns are
+ * allowed for both DDR II and I.)
+ */
+static unsigned int
+convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
+{
+ /* Table look up the lower nibble, allow DDR I & II. */
+ unsigned int tenths_ps[16] = {
+ 0,
+ 100,
+ 200,
+ 300,
+ 400,
+ 500,
+ 600,
+ 700,
+ 800,
+ 900,
+ 250, /* This and the next 3 entries valid ... */
+ 330, /* ... only for tCK calculations. */
+ 660,
+ 750,
+ 0, /* undefined */
+ 0 /* undefined */
+ };
+
+ unsigned int whole_ns = (spd_val & 0xF0) >> 4;
+ unsigned int tenth_ns = spd_val & 0x0F;
+ unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
+
+ return ps;
+}
+
+static unsigned int
+convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val)
+{
+ unsigned int tenth_ns = (spd_val & 0xF0) >> 4;
+ unsigned int hundredth_ns = spd_val & 0x0F;
+ unsigned int ps = tenth_ns * 100 + hundredth_ns * 10;
+
+ return ps;
+}
+
+static unsigned int byte40_table_ps[8] = {
+ 0,
+ 250,
+ 330,
+ 500,
+ 660,
+ 750,
+ 0, /* supposed to be RFC, but not sure what that means */
+ 0 /* Undefined */
+};
+
+static unsigned int
+compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
+{
+ unsigned int trfc_ps;
+
+ trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000
+ + byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
+
+ return trfc_ps;
+}
+
+static unsigned int
+compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
+{
+ unsigned int trc_ps;
+
+ trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
+
+ return trc_ps;
+}
+
+/*
+ * Determine Refresh Rate. Ignore self refresh bit on DDR I.
+ * Table from SPD Spec, Byte 12, converted to picoseconds and
+ * filled in with "default" normal values.
+ */
+static unsigned int
+determine_refresh_rate_ps(const unsigned int spd_refresh)
+{
+ unsigned int refresh_time_ps[8] = {
+ 15625000, /* 0 Normal 1.00x */
+ 3900000, /* 1 Reduced .25x */
+ 7800000, /* 2 Extended .50x */
+ 31300000, /* 3 Extended 2.00x */
+ 62500000, /* 4 Extended 4.00x */
+ 125000000, /* 5 Extended 8.00x */
+ 15625000, /* 6 Normal 1.00x filler */
+ 15625000, /* 7 Normal 1.00x filler */
+ };
+
+ return refresh_time_ps[spd_refresh & 0x7];
+}
+
+/*
+ * The purpose of this function is to compute a suitable
+ * CAS latency given the DRAM clock period. The SPD only
+ * defines at most 3 CAS latencies. Typically the slower in
+ * frequency the DIMM runs at, the shorter its CAS latency can.
+ * be. If the DIMM is operating at a sufficiently low frequency,
+ * it may be able to run at a CAS latency shorter than the
+ * shortest SPD-defined CAS latency.
+ *
+ * If a CAS latency is not found, 0 is returned.
+ *
+ * Do this by finding in the standard speed bin table the longest
+ * tCKmin that doesn't exceed the value of mclk_ps (tCK).
+ *
+ * An assumption made is that the SDRAM device allows the
+ * CL to be programmed for a value that is lower than those
+ * advertised by the SPD. This is not always the case,
+ * as those modes not defined in the SPD are optional.
+ *
+ * CAS latency de-rating based upon values JEDEC Standard No. 79-2C
+ * Table 40, "DDR2 SDRAM stanadard speed bins and tCK, tRCD, tRP, tRAS,
+ * and tRC for corresponding bin"
+ *
+ * ordinal 2, ddr2_speed_bins[1] contains tCK for CL=3
+ * Not certain if any good value exists for CL=2
+ */
+ /* CL2 CL3 CL4 CL5 CL6 CL7*/
+unsigned short ddr2_speed_bins[] = { 0, 5000, 3750, 3000, 2500, 1875 };
+
+unsigned int
+compute_derated_DDR2_CAS_latency(unsigned int mclk_ps)
+{
+ const unsigned int num_speed_bins = ARRAY_SIZE(ddr2_speed_bins);
+ unsigned int lowest_tCKmin_found = 0;
+ unsigned int lowest_tCKmin_CL = 0;
+ unsigned int i;
+
+ debug("mclk_ps = %u\n", mclk_ps);
+
+ for (i = 0; i < num_speed_bins; i++) {
+ unsigned int x = ddr2_speed_bins[i];
+ debug("i=%u, x = %u, lowest_tCKmin_found = %u\n",
+ i, x, lowest_tCKmin_found);
+ if (x && x <= mclk_ps && x >= lowest_tCKmin_found ) {
+ lowest_tCKmin_found = x;
+ lowest_tCKmin_CL = i + 2;
+ }
+ }
+
+ debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL);
+
+ return lowest_tCKmin_CL;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR2 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ * FIXME: use #define for the retvals
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd,
+ dimm_params_t *pdimm,
+ unsigned int dimm_number)
+{
+ unsigned int retval;
+
+ if (spd->mem_type) {
+ if (spd->mem_type != SPD_MEMTYPE_DDR2) {
+ printf("DIMM %u: is not a DDR2 SPD.\n", dimm_number);
+ return 1;
+ }
+ } else {
+ memset(pdimm, 0, sizeof(dimm_params_t));
+ return 1;
+ }
+
+ retval = ddr2_spd_check(spd);
+ if (retval) {
+ printf("DIMM %u: failed checksum\n", dimm_number);
+ return 2;
+ }
+
+ /*
+ * The part name in ASCII in the SPD EEPROM is not null terminated.
+ * Guarantee null termination here by presetting all bytes to 0
+ * and copying the part name in ASCII from the SPD onto it
+ */
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1;
+ pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ pdimm->data_width = spd->dataw;
+ pdimm->primary_sdram_width = spd->primw;
+ pdimm->ec_sdram_width = spd->ecw;
+
+ /* These are all the types defined by the JEDEC DDR2 SPD 1.3 spec */
+ switch (spd->dimm_type) {
+ case DDR2_SPD_DIMMTYPE_RDIMM:
+ case DDR2_SPD_DIMMTYPE_72B_SO_RDIMM:
+ case DDR2_SPD_DIMMTYPE_MINI_RDIMM:
+ /* Registered/buffered DIMMs */
+ pdimm->registered_dimm = 1;
+ break;
+
+ case DDR2_SPD_DIMMTYPE_UDIMM:
+ case DDR2_SPD_DIMMTYPE_SO_DIMM:
+ case DDR2_SPD_DIMMTYPE_MICRO_DIMM:
+ case DDR2_SPD_DIMMTYPE_MINI_UDIMM:
+ /* Unbuffered DIMMs */
+ pdimm->registered_dimm = 0;
+ break;
+
+ case DDR2_SPD_DIMMTYPE_72B_SO_CDIMM:
+ default:
+ printf("unknown dimm_type 0x%02X\n", spd->dimm_type);
+ return 1;
+ }
+
+ /* SDRAM device parameters */
+ pdimm->n_row_addr = spd->nrow_addr;
+ pdimm->n_col_addr = spd->ncol_addr;
+ pdimm->n_banks_per_sdram_device = spd->nbanks;
+ pdimm->edc_config = spd->config;
+ pdimm->burst_lengths_bitmask = spd->burstl;
+ pdimm->row_density = spd->rank_dens;
+
+ /*
+ * Calculate the Maximum Data Rate based on the Minimum Cycle time.
+ * The SPD clk_cycle field (tCKmin) is measured in tenths of
+ * nanoseconds and represented as BCD.
+ */
+ pdimm->tCKmin_X_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
+ pdimm->tCKmin_X_minus_1_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
+ pdimm->tCKmin_X_minus_2_ps
+ = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
+
+ pdimm->tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax);
+
+ /*
+ * Compute CAS latencies defined by SPD
+ * The SPD caslat_X should have at least 1 and at most 3 bits set.
+ *
+ * If cas_lat after masking is 0, the __ilog2 function returns
+ * 255 into the variable. This behavior is abused once.
+ */
+ pdimm->caslat_X = __ilog2(spd->cas_lat);
+ pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
+ & ~(1 << pdimm->caslat_X));
+ pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat
+ & ~(1 << pdimm->caslat_X)
+ & ~(1 << pdimm->caslat_X_minus_1));
+
+ /* Compute CAS latencies below that defined by SPD */
+ pdimm->caslat_lowest_derated
+ = compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps());
+
+ /* Compute timing parameters */
+ pdimm->tRCD_ps = spd->trcd * 250;
+ pdimm->tRP_ps = spd->trp * 250;
+ pdimm->tRAS_ps = spd->tras * 1000;
+
+ pdimm->tWR_ps = spd->twr * 250;
+ pdimm->tWTR_ps = spd->twtr * 250;
+ pdimm->tRFC_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc);
+
+ pdimm->tRRD_ps = spd->trrd * 250;
+ pdimm->tRC_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc);
+
+ pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
+
+ pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
+ pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
+ pdimm->tDS_ps
+ = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
+ pdimm->tDH_ps
+ = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
+
+ pdimm->tRTP_ps = spd->trtp * 250;
+ pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
+ pdimm->tQHS_ps = spd->tqhs * 10;
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
new file mode 100644
index 0000000..3e7c269
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ddr3_dimm_params.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ *
+ * calculate the organization and timing parameter
+ * from ddr3 spd, please refer to the spec
+ * JEDEC standard No.21-C 4_01_02_11R18.pdf
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * each rank size =
+ * sdram capacity(bit) / 8 * primary bus width / sdram width
+ *
+ * where: sdram capacity = spd byte4[3:0]
+ * primary bus width = spd byte8[2:0]
+ * sdram width = spd byte7[2:0]
+ *
+ * SPD byte4 - sdram density and banks
+ * bit[3:0] size(bit) size(byte)
+ * 0000 256Mb 32MB
+ * 0001 512Mb 64MB
+ * 0010 1Gb 128MB
+ * 0011 2Gb 256MB
+ * 0100 4Gb 512MB
+ * 0101 8Gb 1GB
+ * 0110 16Gb 2GB
+ *
+ * SPD byte8 - module memory bus width
+ * bit[2:0] primary bus width
+ * 000 8bits
+ * 001 16bits
+ * 010 32bits
+ * 011 64bits
+ *
+ * SPD byte7 - module organiztion
+ * bit[2:0] sdram device width
+ * 000 4bits
+ * 001 8bits
+ * 010 16bits
+ * 011 32bits
+ *
+ */
+static unsigned long long
+compute_ranksize(const ddr3_spd_eeprom_t *spd)
+{
+ unsigned long long bsize;
+
+ int nbit_sdram_cap_bsize = 0;
+ int nbit_primary_bus_width = 0;
+ int nbit_sdram_width = 0;
+
+ if ((spd->density_banks & 0xf) < 7)
+ nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+ if ((spd->bus_width & 0x7) < 4)
+ nbit_primary_bus_width = (spd->bus_width & 0x7) + 3;
+ if ((spd->organization & 0x7) < 4)
+ nbit_sdram_width = (spd->organization & 0x7) + 2;
+
+ bsize = 1ULL << (nbit_sdram_cap_bsize - 3
+ + nbit_primary_bus_width - nbit_sdram_width);
+
+ debug("DDR: DDR III rank density = 0x%16llx\n", bsize);
+
+ return bsize;
+}
+
+/*
+ * ddr_compute_dimm_parameters for DDR3 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ */
+unsigned int
+ddr_compute_dimm_parameters(const ddr3_spd_eeprom_t *spd,
+ dimm_params_t *pdimm,
+ unsigned int dimm_number)
+{
+ unsigned int retval;
+ unsigned int mtb_ps;
+ int ftb_10th_ps;
+ int i;
+
+ if (spd->mem_type) {
+ if (spd->mem_type != SPD_MEMTYPE_DDR3) {
+ printf("DIMM %u: is not a DDR3 SPD.\n", dimm_number);
+ return 1;
+ }
+ } else {
+ memset(pdimm, 0, sizeof(dimm_params_t));
+ return 1;
+ }
+
+ retval = ddr3_spd_check(spd);
+ if (retval) {
+ printf("DIMM %u: failed checksum\n", dimm_number);
+ return 2;
+ }
+
+ /*
+ * The part name in ASCII in the SPD EEPROM is not null terminated.
+ * Guarantee null termination here by presetting all bytes to 0
+ * and copying the part name in ASCII from the SPD onto it
+ */
+ memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+ if ((spd->info_size_crc & 0xF) > 1)
+ memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+ /* DIMM organization parameters */
+ pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+ pdimm->rank_density = compute_ranksize(spd);
+ pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+ pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+ if ((spd->bus_width >> 3) & 0x3)
+ pdimm->ec_sdram_width = 8;
+ else
+ pdimm->ec_sdram_width = 0;
+ pdimm->data_width = pdimm->primary_sdram_width
+ + pdimm->ec_sdram_width;
+
+ /* These are the types defined by the JEDEC DDR3 SPD spec */
+ pdimm->mirrored_dimm = 0;
+ pdimm->registered_dimm = 0;
+ switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) {
+ case DDR3_SPD_MODULETYPE_RDIMM:
+ case DDR3_SPD_MODULETYPE_MINI_RDIMM:
+ case DDR3_SPD_MODULETYPE_72B_SO_RDIMM:
+ /* Registered/buffered DIMMs */
+ pdimm->registered_dimm = 1;
+ for (i = 0; i < 16; i += 2) {
+ u8 rcw = spd->mod_section.registered.rcw[i/2];
+ pdimm->rcw[i] = (rcw >> 0) & 0x0F;
+ pdimm->rcw[i+1] = (rcw >> 4) & 0x0F;
+ }
+ break;
+
+ case DDR3_SPD_MODULETYPE_UDIMM:
+ case DDR3_SPD_MODULETYPE_SO_DIMM:
+ case DDR3_SPD_MODULETYPE_MICRO_DIMM:
+ case DDR3_SPD_MODULETYPE_MINI_UDIMM:
+ case DDR3_SPD_MODULETYPE_MINI_CDIMM:
+ case DDR3_SPD_MODULETYPE_72B_SO_UDIMM:
+ case DDR3_SPD_MODULETYPE_72B_SO_CDIMM:
+ case DDR3_SPD_MODULETYPE_LRDIMM:
+ case DDR3_SPD_MODULETYPE_16B_SO_DIMM:
+ case DDR3_SPD_MODULETYPE_32B_SO_DIMM:
+ /* Unbuffered DIMMs */
+ if (spd->mod_section.unbuffered.addr_mapping & 0x1)
+ pdimm->mirrored_dimm = 1;
+ break;
+
+ default:
+ printf("unknown module_type 0x%02X\n", spd->module_type);
+ return 1;
+ }
+
+ /* SDRAM device parameters */
+ pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+ pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+ pdimm->n_banks_per_sdram_device = 8 << ((spd->density_banks >> 4) & 0x7);
+
+ /*
+ * The SPD spec has not the ECC bit,
+ * We consider the DIMM as ECC capability
+ * when the extension bus exist
+ */
+ if (pdimm->ec_sdram_width)
+ pdimm->edc_config = 0x02;
+ else
+ pdimm->edc_config = 0x00;
+
+ /*
+ * The SPD spec has not the burst length byte
+ * but DDR3 spec has nature BL8 and BC4,
+ * BL8 -bit3, BC4 -bit2
+ */
+ pdimm->burst_lengths_bitmask = 0x0c;
+ pdimm->row_density = __ilog2(pdimm->rank_density);
+
+ /* MTB - medium timebase
+ * The unit in the SPD spec is ns,
+ * We convert it to ps.
+ * eg: MTB = 0.125ns (125ps)
+ */
+ mtb_ps = (spd->mtb_dividend * 1000) /spd->mtb_divisor;
+ pdimm->mtb_ps = mtb_ps;
+
+ /*
+ * FTB - fine timebase
+ * use 1/10th of ps as our unit to avoid floating point
+ * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps
+ */
+ ftb_10th_ps =
+ ((spd->ftb_div & 0xf0) >> 4) * 10 / (spd->ftb_div & 0x0f);
+ pdimm->ftb_10th_ps = ftb_10th_ps;
+ /*
+ * sdram minimum cycle time
+ * we assume the MTB is 0.125ns
+ * eg:
+ * tCK_min=15 MTB (1.875ns) ->DDR3-1066
+ * =12 MTB (1.5ns) ->DDR3-1333
+ * =10 MTB (1.25ns) ->DDR3-1600
+ */
+ pdimm->tCKmin_X_ps = spd->tCK_min * mtb_ps +
+ (spd->fine_tCK_min * ftb_10th_ps) / 10;
+
+ /*
+ * CAS latency supported
+ * bit4 - CL4
+ * bit5 - CL5
+ * bit18 - CL18
+ */
+ pdimm->caslat_X = ((spd->caslat_msb << 8) | spd->caslat_lsb) << 4;
+
+ /*
+ * min CAS latency time
+ * eg: tAA_min =
+ * DDR3-800D 100 MTB (12.5ns)
+ * DDR3-1066F 105 MTB (13.125ns)
+ * DDR3-1333H 108 MTB (13.5ns)
+ * DDR3-1600H 90 MTB (11.25ns)
+ */
+ pdimm->tAA_ps = spd->tAA_min * mtb_ps +
+ (spd->fine_tAA_min * ftb_10th_ps) / 10;
+
+ /*
+ * min write recovery time
+ * eg:
+ * tWR_min = 120 MTB (15ns) -> all speed grades.
+ */
+ pdimm->tWR_ps = spd->tWR_min * mtb_ps;
+
+ /*
+ * min RAS to CAS delay time
+ * eg: tRCD_min =
+ * DDR3-800 100 MTB (12.5ns)
+ * DDR3-1066F 105 MTB (13.125ns)
+ * DDR3-1333H 108 MTB (13.5ns)
+ * DDR3-1600H 90 MTB (11.25)
+ */
+ pdimm->tRCD_ps = spd->tRCD_min * mtb_ps +
+ (spd->fine_tRCD_min * ftb_10th_ps) / 10;
+
+ /*
+ * min row active to row active delay time
+ * eg: tRRD_min =
+ * DDR3-800(1KB page) 80 MTB (10ns)
+ * DDR3-1333(1KB page) 48 MTB (6ns)
+ */
+ pdimm->tRRD_ps = spd->tRRD_min * mtb_ps;
+
+ /*
+ * min row precharge delay time
+ * eg: tRP_min =
+ * DDR3-800D 100 MTB (12.5ns)
+ * DDR3-1066F 105 MTB (13.125ns)
+ * DDR3-1333H 108 MTB (13.5ns)
+ * DDR3-1600H 90 MTB (11.25ns)
+ */
+ pdimm->tRP_ps = spd->tRP_min * mtb_ps +
+ (spd->fine_tRP_min * ftb_10th_ps) / 10;
+
+ /* min active to precharge delay time
+ * eg: tRAS_min =
+ * DDR3-800D 300 MTB (37.5ns)
+ * DDR3-1066F 300 MTB (37.5ns)
+ * DDR3-1333H 288 MTB (36ns)
+ * DDR3-1600H 280 MTB (35ns)
+ */
+ pdimm->tRAS_ps = (((spd->tRAS_tRC_ext & 0xf) << 8) | spd->tRAS_min_lsb)
+ * mtb_ps;
+ /*
+ * min active to actice/refresh delay time
+ * eg: tRC_min =
+ * DDR3-800D 400 MTB (50ns)
+ * DDR3-1066F 405 MTB (50.625ns)
+ * DDR3-1333H 396 MTB (49.5ns)
+ * DDR3-1600H 370 MTB (46.25ns)
+ */
+ pdimm->tRC_ps = (((spd->tRAS_tRC_ext & 0xf0) << 4) | spd->tRC_min_lsb)
+ * mtb_ps + (spd->fine_tRC_min * ftb_10th_ps) / 10;
+ /*
+ * min refresh recovery delay time
+ * eg: tRFC_min =
+ * 512Mb 720 MTB (90ns)
+ * 1Gb 880 MTB (110ns)
+ * 2Gb 1280 MTB (160ns)
+ */
+ pdimm->tRFC_ps = ((spd->tRFC_min_msb << 8) | spd->tRFC_min_lsb)
+ * mtb_ps;
+ /*
+ * min internal write to read command delay time
+ * eg: tWTR_min = 40 MTB (7.5ns) - all speed bins.
+ * tWRT is at least 4 mclk independent of operating freq.
+ */
+ pdimm->tWTR_ps = spd->tWTR_min * mtb_ps;
+
+ /*
+ * min internal read to precharge command delay time
+ * eg: tRTP_min = 40 MTB (7.5ns) - all speed bins.
+ * tRTP is at least 4 mclk independent of operating freq.
+ */
+ pdimm->tRTP_ps = spd->tRTP_min * mtb_ps;
+
+ /*
+ * Average periodic refresh interval
+ * tREFI = 7.8 us at normal temperature range
+ * = 3.9 us at ext temperature range
+ */
+ pdimm->refresh_rate_ps = 7800000;
+
+ /*
+ * min four active window delay time
+ * eg: tFAW_min =
+ * DDR3-800(1KB page) 320 MTB (40ns)
+ * DDR3-1066(1KB page) 300 MTB (37.5ns)
+ * DDR3-1333(1KB page) 240 MTB (30ns)
+ * DDR3-1600(1KB page) 240 MTB (30ns)
+ */
+ pdimm->tFAW_ps = (((spd->tFAW_msb & 0xf) << 8) | spd->tFAW_min)
+ * mtb_ps;
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
new file mode 100644
index 0000000..46257c9
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
@@ -0,0 +1,1868 @@
+/*
+ * Copyright 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 or any later versionas published by the Free Software Foundation.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ * York Sun [at freescale.com]
+ */
+
+#include <common.h>
+#include <linux/ctype.h>
+#include <asm/types.h>
+
+#include <asm/fsl_ddr_sdram.h>
+#include "ddr.h"
+
+/* Option parameter Structures */
+struct options_string {
+ const char *option_name;
+ size_t offset;
+ unsigned int size;
+ const char printhex;
+};
+
+static unsigned int picos_to_mhz(unsigned int picos)
+{
+ return 1000000 / picos;
+}
+
+static void print_option_table(const struct options_string *table,
+ int table_size,
+ const void *base)
+{
+ unsigned int i;
+ unsigned int *ptr;
+ unsigned long long *ptr_l;
+
+ for (i = 0; i < table_size; i++) {
+ switch (table[i].size) {
+ case 4:
+ ptr = (unsigned int *) (base + table[i].offset);
+ if (table[i].printhex) {
+ printf("%s = 0x%08X\n",
+ table[i].option_name, *ptr);
+ } else {
+ printf("%s = %u\n",
+ table[i].option_name, *ptr);
+ }
+ break;
+ case 8:
+ ptr_l = (unsigned long long *) (base + table[i].offset);
+ printf("%s = %llu\n",
+ table[i].option_name, *ptr_l);
+ break;
+ default:
+ printf("Unrecognized size!\n");
+ break;
+ }
+ }
+}
+
+static int handle_option_table(const struct options_string *table,
+ int table_size,
+ void *base,
+ const char *opt,
+ const char *val)
+{
+ unsigned int i;
+ unsigned int value, *ptr;
+ unsigned long long value_l, *ptr_l;
+
+ for (i = 0; i < table_size; i++) {
+ if (strcmp(table[i].option_name, opt) != 0)
+ continue;
+ switch (table[i].size) {
+ case 4:
+ value = simple_strtoul(val, NULL, 0);
+ ptr = base + table[i].offset;
+ *ptr = value;
+ break;
+ case 8:
+ value_l = simple_strtoull(val, NULL, 0);
+ ptr_l = base + table[i].offset;
+ *ptr_l = value_l;
+ break;
+ default:
+ printf("Unrecognized size!\n");
+ break;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+static void fsl_ddr_generic_edit(void *pdata,
+ void *pend,
+ unsigned int element_size,
+ unsigned int element_num,
+ unsigned int value)
+{
+ char *pcdata = (char *)pdata; /* BIG ENDIAN ONLY */
+
+ pcdata += element_num * element_size;
+ if ((pcdata + element_size) > (char *) pend) {
+ printf("trying to write past end of data\n");
+ return;
+ }
+
+ switch (element_size) {
+ case 1:
+ __raw_writeb(value, pcdata);
+ break;
+ case 2:
+ __raw_writew(value, pcdata);
+ break;
+ case 4:
+ __raw_writel(value, pcdata);
+ break;
+ default:
+ printf("unexpected element size %u\n", element_size);
+ break;
+ }
+}
+
+static void fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo,
+ unsigned int ctrl_num,
+ unsigned int dimm_num,
+ unsigned int element_num,
+ unsigned int value)
+{
+ generic_spd_eeprom_t *pspd;
+
+ pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]);
+ fsl_ddr_generic_edit(pspd, pspd + 1, 1, element_num, value);
+}
+
+#define COMMON_TIMING(x) {#x, offsetof(common_timing_params_t, x), \
+ sizeof((common_timing_params_t *)0)->x, 0}
+
+static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
+ unsigned int ctrl_num,
+ const char *optname_str,
+ const char *value_str)
+{
+ common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num];
+
+ static const struct options_string options[] = {
+ COMMON_TIMING(tCKmin_X_ps),
+ COMMON_TIMING(tCKmax_ps),
+ COMMON_TIMING(tCKmax_max_ps),
+ COMMON_TIMING(tRCD_ps),
+ COMMON_TIMING(tRP_ps),
+ COMMON_TIMING(tRAS_ps),
+ COMMON_TIMING(tWR_ps),
+ COMMON_TIMING(tWTR_ps),
+ COMMON_TIMING(tRFC_ps),
+ COMMON_TIMING(tRRD_ps),
+ COMMON_TIMING(tRC_ps),
+ COMMON_TIMING(refresh_rate_ps),
+ COMMON_TIMING(tIS_ps),
+ COMMON_TIMING(tIH_ps),
+ COMMON_TIMING(tDS_ps),
+ COMMON_TIMING(tDH_ps),
+ COMMON_TIMING(tRTP_ps),
+ COMMON_TIMING(tDQSQ_max_ps),
+ COMMON_TIMING(tQHS_ps),
+ COMMON_TIMING(ndimms_present),
+ COMMON_TIMING(lowest_common_SPD_caslat),
+ COMMON_TIMING(highest_common_derated_caslat),
+ COMMON_TIMING(additive_latency),
+ COMMON_TIMING(all_DIMMs_burst_lengths_bitmask),
+ COMMON_TIMING(all_DIMMs_registered),
+ COMMON_TIMING(all_DIMMs_unbuffered),
+ COMMON_TIMING(all_DIMMs_ECC_capable),
+ COMMON_TIMING(total_mem),
+ COMMON_TIMING(base_address),
+ };
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ if (handle_option_table(options, n_opts, p, optname_str, value_str))
+ return;
+
+ printf("Error: couldn't find option string %s\n", optname_str);
+}
+
+#define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \
+ sizeof((dimm_params_t *)0)->x, 0}
+
+static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
+ unsigned int ctrl_num,
+ unsigned int dimm_num,
+ const char *optname_str,
+ const char *value_str)
+{
+ dimm_params_t *p = &(pinfo->dimm_params[ctrl_num][dimm_num]);
+
+ static const struct options_string options[] = {
+ DIMM_PARM(n_ranks),
+ DIMM_PARM(data_width),
+ DIMM_PARM(primary_sdram_width),
+ DIMM_PARM(ec_sdram_width),
+ DIMM_PARM(registered_dimm),
+
+ DIMM_PARM(n_row_addr),
+ DIMM_PARM(n_col_addr),
+ DIMM_PARM(edc_config),
+ DIMM_PARM(n_banks_per_sdram_device),
+ DIMM_PARM(burst_lengths_bitmask),
+ DIMM_PARM(row_density),
+
+ DIMM_PARM(tCKmin_X_ps),
+ DIMM_PARM(tCKmin_X_minus_1_ps),
+ DIMM_PARM(tCKmin_X_minus_2_ps),
+ DIMM_PARM(tCKmax_ps),
+
+ DIMM_PARM(caslat_X),
+ DIMM_PARM(caslat_X_minus_1),
+ DIMM_PARM(caslat_X_minus_2),
+
+ DIMM_PARM(caslat_lowest_derated),
+
+ DIMM_PARM(tRCD_ps),
+ DIMM_PARM(tRP_ps),
+ DIMM_PARM(tRAS_ps),
+ DIMM_PARM(tWR_ps),
+ DIMM_PARM(tWTR_ps),
+ DIMM_PARM(tRFC_ps),
+ DIMM_PARM(tRRD_ps),
+ DIMM_PARM(tRC_ps),
+ DIMM_PARM(refresh_rate_ps),
+
+ DIMM_PARM(tIS_ps),
+ DIMM_PARM(tIH_ps),
+ DIMM_PARM(tDS_ps),
+ DIMM_PARM(tDH_ps),
+ DIMM_PARM(tRTP_ps),
+ DIMM_PARM(tDQSQ_max_ps),
+ DIMM_PARM(tQHS_ps),
+
+ DIMM_PARM(rank_density),
+ DIMM_PARM(capacity),
+ DIMM_PARM(base_address),
+ };
+
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ if (handle_option_table(options, n_opts, p, optname_str, value_str))
+ return;
+
+ printf("couldn't find option string %s\n", optname_str);
+}
+
+static void print_dimm_parameters(const dimm_params_t *pdimm)
+{
+ static const struct options_string options[] = {
+ DIMM_PARM(n_ranks),
+ DIMM_PARM(data_width),
+ DIMM_PARM(primary_sdram_width),
+ DIMM_PARM(ec_sdram_width),
+ DIMM_PARM(registered_dimm),
+
+ DIMM_PARM(n_row_addr),
+ DIMM_PARM(n_col_addr),
+ DIMM_PARM(edc_config),
+ DIMM_PARM(n_banks_per_sdram_device),
+
+ DIMM_PARM(tCKmin_X_ps),
+ DIMM_PARM(tCKmin_X_minus_1_ps),
+ DIMM_PARM(tCKmin_X_minus_2_ps),
+ DIMM_PARM(tCKmax_ps),
+
+ DIMM_PARM(caslat_X),
+ DIMM_PARM(tAA_ps),
+ DIMM_PARM(caslat_X_minus_1),
+ DIMM_PARM(caslat_X_minus_2),
+ DIMM_PARM(caslat_lowest_derated),
+
+ DIMM_PARM(tRCD_ps),
+ DIMM_PARM(tRP_ps),
+ DIMM_PARM(tRAS_ps),
+ DIMM_PARM(tWR_ps),
+ DIMM_PARM(tWTR_ps),
+ DIMM_PARM(tRFC_ps),
+ DIMM_PARM(tRRD_ps),
+ DIMM_PARM(tRC_ps),
+ DIMM_PARM(refresh_rate_ps),
+
+ DIMM_PARM(tIS_ps),
+ DIMM_PARM(tIH_ps),
+ DIMM_PARM(tDS_ps),
+ DIMM_PARM(tDH_ps),
+ DIMM_PARM(tRTP_ps),
+ DIMM_PARM(tDQSQ_max_ps),
+ DIMM_PARM(tQHS_ps),
+ };
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ if (pdimm->n_ranks == 0) {
+ printf("DIMM not present\n");
+ return;
+ }
+ printf("DIMM organization parameters:\n");
+ printf("module part name = %s\n", pdimm->mpart);
+ printf("rank_density = %llu bytes (%llu megabytes)\n",
+ pdimm->rank_density, pdimm->rank_density / 0x100000);
+ printf("capacity = %llu bytes (%llu megabytes)\n",
+ pdimm->capacity, pdimm->capacity / 0x100000);
+ printf("burst_lengths_bitmask = %02X\n",
+ pdimm->burst_lengths_bitmask);
+ printf("base_addresss = %llu (%08llX %08llX)\n",
+ pdimm->base_address,
+ (pdimm->base_address >> 32),
+ pdimm->base_address & 0xFFFFFFFF);
+ print_option_table(options, n_opts, pdimm);
+}
+
+static void print_lowest_common_dimm_parameters(
+ const common_timing_params_t *plcd_dimm_params)
+{
+ static const struct options_string options[] = {
+ COMMON_TIMING(tCKmax_max_ps),
+ COMMON_TIMING(tRCD_ps),
+ COMMON_TIMING(tRP_ps),
+ COMMON_TIMING(tRAS_ps),
+ COMMON_TIMING(tWR_ps),
+ COMMON_TIMING(tWTR_ps),
+ COMMON_TIMING(tRFC_ps),
+ COMMON_TIMING(tRRD_ps),
+ COMMON_TIMING(tRC_ps),
+ COMMON_TIMING(refresh_rate_ps),
+ COMMON_TIMING(tIS_ps),
+ COMMON_TIMING(tDS_ps),
+ COMMON_TIMING(tDH_ps),
+ COMMON_TIMING(tRTP_ps),
+ COMMON_TIMING(tDQSQ_max_ps),
+ COMMON_TIMING(tQHS_ps),
+ COMMON_TIMING(lowest_common_SPD_caslat),
+ COMMON_TIMING(highest_common_derated_caslat),
+ COMMON_TIMING(additive_latency),
+ COMMON_TIMING(ndimms_present),
+ COMMON_TIMING(all_DIMMs_registered),
+ COMMON_TIMING(all_DIMMs_unbuffered),
+ COMMON_TIMING(all_DIMMs_ECC_capable),
+ };
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ /* Clock frequencies */
+ printf("tCKmin_X_ps = %u (%u MHz)\n",
+ plcd_dimm_params->tCKmin_X_ps,
+ picos_to_mhz(plcd_dimm_params->tCKmin_X_ps));
+ printf("tCKmax_ps = %u (%u MHz)\n",
+ plcd_dimm_params->tCKmax_ps,
+ picos_to_mhz(plcd_dimm_params->tCKmax_ps));
+ printf("all_DIMMs_burst_lengths_bitmask = %02X\n",
+ plcd_dimm_params->all_DIMMs_burst_lengths_bitmask);
+
+ print_option_table(options, n_opts, plcd_dimm_params);
+
+ printf("total_mem = %llu (%llu megabytes)\n",
+ plcd_dimm_params->total_mem,
+ plcd_dimm_params->total_mem / 0x100000);
+ printf("base_address = %llu (%llu megabytes)\n",
+ plcd_dimm_params->base_address,
+ plcd_dimm_params->base_address / 0x100000);
+}
+
+#define CTRL_OPTIONS(x) {#x, offsetof(memctl_options_t, x), \
+ sizeof((memctl_options_t *)0)->x, 0}
+#define CTRL_OPTIONS_CS(x, y) {"cs" #x "_" #y, \
+ offsetof(memctl_options_t, cs_local_opts[x].y), \
+ sizeof((memctl_options_t *)0)->cs_local_opts[x].y, 0}
+
+static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
+ unsigned int ctl_num,
+ const char *optname_str,
+ const char *value_str)
+{
+ memctl_options_t *p = &(pinfo->memctl_opts[ctl_num]);
+ /*
+ * This array all on the stack and *computed* each time this
+ * function is rung.
+ */
+ static const struct options_string options[] = {
+ CTRL_OPTIONS_CS(0, odt_rd_cfg),
+ CTRL_OPTIONS_CS(0, odt_wr_cfg),
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
+ CTRL_OPTIONS_CS(1, odt_rd_cfg),
+ CTRL_OPTIONS_CS(1, odt_wr_cfg),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CTRL_OPTIONS_CS(2, odt_rd_cfg),
+ CTRL_OPTIONS_CS(2, odt_wr_cfg),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CTRL_OPTIONS_CS(3, odt_rd_cfg),
+ CTRL_OPTIONS_CS(3, odt_wr_cfg),
+#endif
+#if defined(CONFIG_FSL_DDR3)
+ CTRL_OPTIONS_CS(0, odt_rtt_norm),
+ CTRL_OPTIONS_CS(0, odt_rtt_wr),
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
+ CTRL_OPTIONS_CS(1, odt_rtt_norm),
+ CTRL_OPTIONS_CS(1, odt_rtt_wr),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CTRL_OPTIONS_CS(2, odt_rtt_norm),
+ CTRL_OPTIONS_CS(2, odt_rtt_wr),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CTRL_OPTIONS_CS(3, odt_rtt_norm),
+ CTRL_OPTIONS_CS(3, odt_rtt_wr),
+#endif
+#endif
+ CTRL_OPTIONS(memctl_interleaving),
+ CTRL_OPTIONS(memctl_interleaving_mode),
+ CTRL_OPTIONS(ba_intlv_ctl),
+ CTRL_OPTIONS(ECC_mode),
+ CTRL_OPTIONS(ECC_init_using_memctl),
+ CTRL_OPTIONS(DQS_config),
+ CTRL_OPTIONS(self_refresh_in_sleep),
+ CTRL_OPTIONS(dynamic_power),
+ CTRL_OPTIONS(data_bus_width),
+ CTRL_OPTIONS(burst_length),
+ CTRL_OPTIONS(cas_latency_override),
+ CTRL_OPTIONS(cas_latency_override_value),
+ CTRL_OPTIONS(use_derated_caslat),
+ CTRL_OPTIONS(additive_latency_override),
+ CTRL_OPTIONS(additive_latency_override_value),
+ CTRL_OPTIONS(clk_adjust),
+ CTRL_OPTIONS(cpo_override),
+ CTRL_OPTIONS(write_data_delay),
+ CTRL_OPTIONS(half_strength_driver_enable),
+
+ /*
+ * These can probably be changed to 2T_EN and 3T_EN
+ * (using a leading numerical character) without problem
+ */
+ CTRL_OPTIONS(twoT_en),
+ CTRL_OPTIONS(threeT_en),
+ CTRL_OPTIONS(ap_en),
+ CTRL_OPTIONS(bstopre),
+ CTRL_OPTIONS(wrlvl_override),
+ CTRL_OPTIONS(wrlvl_sample),
+ CTRL_OPTIONS(wrlvl_start),
+ CTRL_OPTIONS(rcw_override),
+ CTRL_OPTIONS(rcw_1),
+ CTRL_OPTIONS(rcw_2),
+ CTRL_OPTIONS(ddr_cdr1),
+ CTRL_OPTIONS(ddr_cdr2),
+ CTRL_OPTIONS(tCKE_clock_pulse_width_ps),
+ CTRL_OPTIONS(tFAW_window_four_activates_ps),
+ CTRL_OPTIONS(trwt_override),
+ CTRL_OPTIONS(trwt),
+ };
+
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ if (handle_option_table(options, n_opts, p,
+ optname_str, value_str))
+ return;
+
+ printf("couldn't find option string %s\n", optname_str);
+}
+
+#define CFG_REGS(x) {#x, offsetof(fsl_ddr_cfg_regs_t, x), \
+ sizeof((fsl_ddr_cfg_regs_t *)0)->x, 1}
+#define CFG_REGS_CS(x, y) {"cs" #x "_" #y, \
+ offsetof(fsl_ddr_cfg_regs_t, cs[x].y), \
+ sizeof((fsl_ddr_cfg_regs_t *)0)->cs[x].y, 1}
+
+static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
+{
+ unsigned int i;
+ static const struct options_string options[] = {
+ CFG_REGS_CS(0, bnds),
+ CFG_REGS_CS(0, config),
+ CFG_REGS_CS(0, config_2),
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
+ CFG_REGS_CS(1, bnds),
+ CFG_REGS_CS(1, config),
+ CFG_REGS_CS(1, config_2),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CFG_REGS_CS(2, bnds),
+ CFG_REGS_CS(2, config),
+ CFG_REGS_CS(2, config_2),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CFG_REGS_CS(3, bnds),
+ CFG_REGS_CS(3, config),
+ CFG_REGS_CS(3, config_2),
+#endif
+ CFG_REGS(timing_cfg_3),
+ CFG_REGS(timing_cfg_0),
+ CFG_REGS(timing_cfg_1),
+ CFG_REGS(timing_cfg_2),
+ CFG_REGS(ddr_sdram_cfg),
+ CFG_REGS(ddr_sdram_cfg_2),
+ CFG_REGS(ddr_sdram_mode),
+ CFG_REGS(ddr_sdram_mode_2),
+ CFG_REGS(ddr_sdram_mode_3),
+ CFG_REGS(ddr_sdram_mode_4),
+ CFG_REGS(ddr_sdram_mode_5),
+ CFG_REGS(ddr_sdram_mode_6),
+ CFG_REGS(ddr_sdram_mode_7),
+ CFG_REGS(ddr_sdram_mode_8),
+ CFG_REGS(ddr_sdram_interval),
+ CFG_REGS(ddr_data_init),
+ CFG_REGS(ddr_sdram_clk_cntl),
+ CFG_REGS(ddr_init_addr),
+ CFG_REGS(ddr_init_ext_addr),
+ CFG_REGS(timing_cfg_4),
+ CFG_REGS(timing_cfg_5),
+ CFG_REGS(ddr_zq_cntl),
+ CFG_REGS(ddr_wrlvl_cntl),
+ CFG_REGS(ddr_wrlvl_cntl_2),
+ CFG_REGS(ddr_wrlvl_cntl_3),
+ CFG_REGS(ddr_sr_cntr),
+ CFG_REGS(ddr_sdram_rcw_1),
+ CFG_REGS(ddr_sdram_rcw_2),
+ CFG_REGS(ddr_cdr1),
+ CFG_REGS(ddr_cdr2),
+ CFG_REGS(err_disable),
+ CFG_REGS(err_int_en),
+ CFG_REGS(ddr_eor),
+ };
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ print_option_table(options, n_opts, ddr);
+
+ for (i = 0; i < 32; i++)
+ printf("debug_%02d = 0x%08X\n", i+1, ddr->debug[i]);
+}
+
+static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
+ unsigned int ctrl_num,
+ const char *regname,
+ const char *value_str)
+{
+ unsigned int i;
+ fsl_ddr_cfg_regs_t *ddr;
+ char buf[20];
+ static const struct options_string options[] = {
+ CFG_REGS_CS(0, bnds),
+ CFG_REGS_CS(0, config),
+ CFG_REGS_CS(0, config_2),
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
+ CFG_REGS_CS(1, bnds),
+ CFG_REGS_CS(1, config),
+ CFG_REGS_CS(1, config_2),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CFG_REGS_CS(2, bnds),
+ CFG_REGS_CS(2, config),
+ CFG_REGS_CS(2, config_2),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3)
+ CFG_REGS_CS(3, bnds),
+ CFG_REGS_CS(3, config),
+ CFG_REGS_CS(3, config_2),
+#endif
+ CFG_REGS(timing_cfg_3),
+ CFG_REGS(timing_cfg_0),
+ CFG_REGS(timing_cfg_1),
+ CFG_REGS(timing_cfg_2),
+ CFG_REGS(ddr_sdram_cfg),
+ CFG_REGS(ddr_sdram_cfg_2),
+ CFG_REGS(ddr_sdram_mode),
+ CFG_REGS(ddr_sdram_mode_2),
+ CFG_REGS(ddr_sdram_mode_3),
+ CFG_REGS(ddr_sdram_mode_4),
+ CFG_REGS(ddr_sdram_mode_5),
+ CFG_REGS(ddr_sdram_mode_6),
+ CFG_REGS(ddr_sdram_mode_7),
+ CFG_REGS(ddr_sdram_mode_8),
+ CFG_REGS(ddr_sdram_interval),
+ CFG_REGS(ddr_data_init),
+ CFG_REGS(ddr_sdram_clk_cntl),
+ CFG_REGS(ddr_init_addr),
+ CFG_REGS(ddr_init_ext_addr),
+ CFG_REGS(timing_cfg_4),
+ CFG_REGS(timing_cfg_5),
+ CFG_REGS(ddr_zq_cntl),
+ CFG_REGS(ddr_wrlvl_cntl),
+ CFG_REGS(ddr_wrlvl_cntl_2),
+ CFG_REGS(ddr_wrlvl_cntl_3),
+ CFG_REGS(ddr_sr_cntr),
+ CFG_REGS(ddr_sdram_rcw_1),
+ CFG_REGS(ddr_sdram_rcw_2),
+ CFG_REGS(ddr_cdr1),
+ CFG_REGS(ddr_cdr2),
+ CFG_REGS(err_disable),
+ CFG_REGS(err_int_en),
+ CFG_REGS(ddr_sdram_rcw_2),
+ CFG_REGS(ddr_sdram_rcw_2),
+ CFG_REGS(ddr_eor),
+ };
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ debug("fsl_ddr_regs_edit: ctrl_num = %u, "
+ "regname = %s, value = %s\n",
+ ctrl_num, regname, value_str);
+ if (ctrl_num > CONFIG_NUM_DDR_CONTROLLERS)
+ return;
+
+ ddr = &(pinfo->fsl_ddr_config_reg[ctrl_num]);
+
+ if (handle_option_table(options, n_opts, ddr, regname, value_str))
+ return;
+
+ for (i = 0; i < 32; i++) {
+ unsigned int value = simple_strtoul(value_str, NULL, 0);
+ sprintf(buf, "debug_%u", i + 1);
+ if (strcmp(buf, regname) == 0) {
+ ddr->debug[i] = value;
+ return;
+ }
+ }
+ printf("Error: couldn't find register string %s\n", regname);
+}
+
+#define CTRL_OPTIONS_HEX(x) {#x, offsetof(memctl_options_t, x), \
+ sizeof((memctl_options_t *)0)->x, 1}
+
+static void print_memctl_options(const memctl_options_t *popts)
+{
+ static const struct options_string options[] = {
+ CTRL_OPTIONS_CS(0, odt_rd_cfg),
+ CTRL_OPTIONS_CS(0, odt_wr_cfg),
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
+ CTRL_OPTIONS_CS(1, odt_rd_cfg),
+ CTRL_OPTIONS_CS(1, odt_wr_cfg),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CTRL_OPTIONS_CS(2, odt_rd_cfg),
+ CTRL_OPTIONS_CS(2, odt_wr_cfg),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3)
+ CTRL_OPTIONS_CS(3, odt_rd_cfg),
+ CTRL_OPTIONS_CS(3, odt_wr_cfg),
+#endif
+#if defined(CONFIG_FSL_DDR3)
+ CTRL_OPTIONS_CS(0, odt_rtt_norm),
+ CTRL_OPTIONS_CS(0, odt_rtt_wr),
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
+ CTRL_OPTIONS_CS(1, odt_rtt_norm),
+ CTRL_OPTIONS_CS(1, odt_rtt_wr),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
+ CTRL_OPTIONS_CS(2, odt_rtt_norm),
+ CTRL_OPTIONS_CS(2, odt_rtt_wr),
+#endif
+#if (CONFIG_CHIP_SELECTS_PER_CTRL > 3)
+ CTRL_OPTIONS_CS(3, odt_rtt_norm),
+ CTRL_OPTIONS_CS(3, odt_rtt_wr),
+#endif
+#endif
+ CTRL_OPTIONS(memctl_interleaving),
+ CTRL_OPTIONS(memctl_interleaving_mode),
+ CTRL_OPTIONS_HEX(ba_intlv_ctl),
+ CTRL_OPTIONS(ECC_mode),
+ CTRL_OPTIONS(ECC_init_using_memctl),
+ CTRL_OPTIONS(DQS_config),
+ CTRL_OPTIONS(self_refresh_in_sleep),
+ CTRL_OPTIONS(dynamic_power),
+ CTRL_OPTIONS(data_bus_width),
+ CTRL_OPTIONS(burst_length),
+ CTRL_OPTIONS(cas_latency_override),
+ CTRL_OPTIONS(cas_latency_override_value),
+ CTRL_OPTIONS(use_derated_caslat),
+ CTRL_OPTIONS(additive_latency_override),
+ CTRL_OPTIONS(additive_latency_override_value),
+ CTRL_OPTIONS(clk_adjust),
+ CTRL_OPTIONS(cpo_override),
+ CTRL_OPTIONS(write_data_delay),
+ CTRL_OPTIONS(half_strength_driver_enable),
+ /*
+ * These can probably be changed to 2T_EN and 3T_EN
+ * (using a leading numerical character) without problem
+ */
+ CTRL_OPTIONS(twoT_en),
+ CTRL_OPTIONS(threeT_en),
+ CTRL_OPTIONS(registered_dimm_en),
+ CTRL_OPTIONS(ap_en),
+ CTRL_OPTIONS(bstopre),
+ CTRL_OPTIONS(wrlvl_override),
+ CTRL_OPTIONS(wrlvl_sample),
+ CTRL_OPTIONS(wrlvl_start),
+ CTRL_OPTIONS(rcw_override),
+ CTRL_OPTIONS(rcw_1),
+ CTRL_OPTIONS(rcw_2),
+ CTRL_OPTIONS_HEX(ddr_cdr1),
+ CTRL_OPTIONS_HEX(ddr_cdr2),
+ CTRL_OPTIONS(tCKE_clock_pulse_width_ps),
+ CTRL_OPTIONS(tFAW_window_four_activates_ps),
+ CTRL_OPTIONS(trwt_override),
+ CTRL_OPTIONS(trwt),
+ };
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ print_option_table(options, n_opts, popts);
+}
+
+#ifdef CONFIG_FSL_DDR1
+void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd)
+{
+ unsigned int i;
+
+ printf("%-3d : %02x %s\n", 0, spd->info_size,
+ " spd->info_size, * 0 # bytes written into serial memory *");
+ printf("%-3d : %02x %s\n", 1, spd->chip_size,
+ " spd->chip_size, * 1 Total # bytes of SPD memory device *");
+ printf("%-3d : %02x %s\n", 2, spd->mem_type,
+ " spd->mem_type, * 2 Fundamental memory type *");
+ printf("%-3d : %02x %s\n", 3, spd->nrow_addr,
+ " spd->nrow_addr, * 3 # of Row Addresses on this assembly *");
+ printf("%-3d : %02x %s\n", 4, spd->ncol_addr,
+ " spd->ncol_addr, * 4 # of Column Addrs on this assembly *");
+ printf("%-3d : %02x %s\n", 5, spd->nrows,
+ " spd->nrows * 5 # of DIMM Banks *");
+ printf("%-3d : %02x %s\n", 6, spd->dataw_lsb,
+ " spd->dataw_lsb, * 6 Data Width lsb of this assembly *");
+ printf("%-3d : %02x %s\n", 7, spd->dataw_msb,
+ " spd->dataw_msb, * 7 Data Width msb of this assembly *");
+ printf("%-3d : %02x %s\n", 8, spd->voltage,
+ " spd->voltage, * 8 Voltage intf std of this assembly *");
+ printf("%-3d : %02x %s\n", 9, spd->clk_cycle,
+ " spd->clk_cycle, * 9 SDRAM Cycle time at CL=X *");
+ printf("%-3d : %02x %s\n", 10, spd->clk_access,
+ " spd->clk_access, * 10 SDRAM Access from Clock at CL=X *");
+ printf("%-3d : %02x %s\n", 11, spd->config,
+ " spd->config, * 11 DIMM Configuration type *");
+ printf("%-3d : %02x %s\n", 12, spd->refresh,
+ " spd->refresh, * 12 Refresh Rate/Type *");
+ printf("%-3d : %02x %s\n", 13, spd->primw,
+ " spd->primw, * 13 Primary SDRAM Width *");
+ printf("%-3d : %02x %s\n", 14, spd->ecw,
+ " spd->ecw, * 14 Error Checking SDRAM width *");
+ printf("%-3d : %02x %s\n", 15, spd->min_delay,
+ " spd->min_delay, * 15 Back to Back Random Access *");
+ printf("%-3d : %02x %s\n", 16, spd->burstl,
+ " spd->burstl, * 16 Burst Lengths Supported *");
+ printf("%-3d : %02x %s\n", 17, spd->nbanks,
+ " spd->nbanks, * 17 # of Banks on Each SDRAM Device *");
+ printf("%-3d : %02x %s\n", 18, spd->cas_lat,
+ " spd->cas_lat, * 18 CAS# Latencies Supported *");
+ printf("%-3d : %02x %s\n", 19, spd->cs_lat,
+ " spd->cs_lat, * 19 Chip Select Latency *");
+ printf("%-3d : %02x %s\n", 20, spd->write_lat,
+ " spd->write_lat, * 20 Write Latency/Recovery *");
+ printf("%-3d : %02x %s\n", 21, spd->mod_attr,
+ " spd->mod_attr, * 21 SDRAM Module Attributes *");
+ printf("%-3d : %02x %s\n", 22, spd->dev_attr,
+ " spd->dev_attr, * 22 SDRAM Device Attributes *");
+ printf("%-3d : %02x %s\n", 23, spd->clk_cycle2,
+ " spd->clk_cycle2, * 23 Min SDRAM Cycle time at CL=X-1 *");
+ printf("%-3d : %02x %s\n", 24, spd->clk_access2,
+ " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
+ printf("%-3d : %02x %s\n", 25, spd->clk_cycle3,
+ " spd->clk_cycle3, * 25 Min SDRAM Cycle time at CL=X-2 *");
+ printf("%-3d : %02x %s\n", 26, spd->clk_access3,
+ " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
+ printf("%-3d : %02x %s\n", 27, spd->trp,
+ " spd->trp, * 27 Min Row Precharge Time (tRP)*");
+ printf("%-3d : %02x %s\n", 28, spd->trrd,
+ " spd->trrd, * 28 Min Row Active to Row Active (tRRD) *");
+ printf("%-3d : %02x %s\n", 29, spd->trcd,
+ " spd->trcd, * 29 Min RAS to CAS Delay (tRCD) *");
+ printf("%-3d : %02x %s\n", 30, spd->tras,
+ " spd->tras, * 30 Minimum RAS Pulse Width (tRAS) *");
+ printf("%-3d : %02x %s\n", 31, spd->bank_dens,
+ " spd->bank_dens, * 31 Density of each bank on module *");
+ printf("%-3d : %02x %s\n", 32, spd->ca_setup,
+ " spd->ca_setup, * 32 Cmd + Addr signal input setup time *");
+ printf("%-3d : %02x %s\n", 33, spd->ca_hold,
+ " spd->ca_hold, * 33 Cmd and Addr signal input hold time *");
+ printf("%-3d : %02x %s\n", 34, spd->data_setup,
+ " spd->data_setup, * 34 Data signal input setup time *");
+ printf("%-3d : %02x %s\n", 35, spd->data_hold,
+ " spd->data_hold, * 35 Data signal input hold time *");
+ printf("%-3d : %02x %s\n", 36, spd->res_36_40[0],
+ " spd->res_36_40[0], * 36 Reserved / tWR *");
+ printf("%-3d : %02x %s\n", 37, spd->res_36_40[1],
+ " spd->res_36_40[1], * 37 Reserved / tWTR *");
+ printf("%-3d : %02x %s\n", 38, spd->res_36_40[2],
+ " spd->res_36_40[2], * 38 Reserved / tRTP *");
+ printf("%-3d : %02x %s\n", 39, spd->res_36_40[3],
+ " spd->res_36_40[3], * 39 Reserved / mem_probe *");
+ printf("%-3d : %02x %s\n", 40, spd->res_36_40[4],
+ " spd->res_36_40[4], * 40 Reserved / trc,trfc extensions *");
+ printf("%-3d : %02x %s\n", 41, spd->trc,
+ " spd->trc, * 41 Min Active to Auto refresh time tRC *");
+ printf("%-3d : %02x %s\n", 42, spd->trfc,
+ " spd->trfc, * 42 Min Auto to Active period tRFC *");
+ printf("%-3d : %02x %s\n", 43, spd->tckmax,
+ " spd->tckmax, * 43 Max device cycle time tCKmax *");
+ printf("%-3d : %02x %s\n", 44, spd->tdqsq,
+ " spd->tdqsq, * 44 Max DQS to DQ skew *");
+ printf("%-3d : %02x %s\n", 45, spd->tqhs,
+ " spd->tqhs, * 45 Max Read DataHold skew tQHS *");
+ printf("%-3d : %02x %s\n", 46, spd->res_46,
+ " spd->res_46, * 46 Reserved/ PLL Relock time *");
+ printf("%-3d : %02x %s\n", 47, spd->dimm_height,
+ " spd->dimm_height * 47 SDRAM DIMM Height *");
+
+ printf("%-3d-%3d: ", 48, 61);
+
+ for (i = 0; i < 14; i++)
+ printf("%02x", spd->res_48_61[i]);
+
+ printf(" * 48-61 IDD in SPD and Reserved space *\n");
+
+ printf("%-3d : %02x %s\n", 62, spd->spd_rev,
+ " spd->spd_rev, * 62 SPD Data Revision Code *");
+ printf("%-3d : %02x %s\n", 63, spd->cksum,
+ " spd->cksum, * 63 Checksum for bytes 0-62 *");
+ printf("%-3d-%3d: ", 64, 71);
+
+ for (i = 0; i < 8; i++)
+ printf("%02x", spd->mid[i]);
+
+ printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
+ printf("%-3d : %02x %s\n", 72, spd->mloc,
+ " spd->mloc, * 72 Manufacturing Location *");
+
+ printf("%-3d-%3d: >>", 73, 90);
+
+ for (i = 0; i < 18; i++)
+ printf("%c", spd->mpart[i]);
+
+ printf("<<* 73 Manufacturer's Part Number *\n");
+
+ printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1],
+ "* 91 Revision Code *");
+ printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1],
+ "* 93 Manufacturing Date *");
+ printf("%-3d-%3d: ", 95, 98);
+
+ for (i = 0; i < 4; i++)
+ printf("%02x", spd->sernum[i]);
+
+ printf("* 95 Assembly Serial Number *\n");
+
+ printf("%-3d-%3d: ", 99, 127);
+
+ for (i = 0; i < 27; i++)
+ printf("%02x", spd->mspec[i]);
+
+ printf("* 99 Manufacturer Specific Data *\n");
+}
+#endif
+
+#ifdef CONFIG_FSL_DDR2
+void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd)
+{
+ unsigned int i;
+
+ printf("%-3d : %02x %s\n", 0, spd->info_size,
+ " spd->info_size, * 0 # bytes written into serial memory *");
+ printf("%-3d : %02x %s\n", 1, spd->chip_size,
+ " spd->chip_size, * 1 Total # bytes of SPD memory device *");
+ printf("%-3d : %02x %s\n", 2, spd->mem_type,
+ " spd->mem_type, * 2 Fundamental memory type *");
+ printf("%-3d : %02x %s\n", 3, spd->nrow_addr,
+ " spd->nrow_addr, * 3 # of Row Addresses on this assembly *");
+ printf("%-3d : %02x %s\n", 4, spd->ncol_addr,
+ " spd->ncol_addr, * 4 # of Column Addrs on this assembly *");
+ printf("%-3d : %02x %s\n", 5, spd->mod_ranks,
+ " spd->mod_ranks * 5 # of Module Rows on this assembly *");
+ printf("%-3d : %02x %s\n", 6, spd->dataw,
+ " spd->dataw, * 6 Data Width of this assembly *");
+ printf("%-3d : %02x %s\n", 7, spd->res_7,
+ " spd->res_7, * 7 Reserved *");
+ printf("%-3d : %02x %s\n", 8, spd->voltage,
+ " spd->voltage, * 8 Voltage intf std of this assembly *");
+ printf("%-3d : %02x %s\n", 9, spd->clk_cycle,
+ " spd->clk_cycle, * 9 SDRAM Cycle time at CL=X *");
+ printf("%-3d : %02x %s\n", 10, spd->clk_access,
+ " spd->clk_access, * 10 SDRAM Access from Clock at CL=X *");
+ printf("%-3d : %02x %s\n", 11, spd->config,
+ " spd->config, * 11 DIMM Configuration type *");
+ printf("%-3d : %02x %s\n", 12, spd->refresh,
+ " spd->refresh, * 12 Refresh Rate/Type *");
+ printf("%-3d : %02x %s\n", 13, spd->primw,
+ " spd->primw, * 13 Primary SDRAM Width *");
+ printf("%-3d : %02x %s\n", 14, spd->ecw,
+ " spd->ecw, * 14 Error Checking SDRAM width *");
+ printf("%-3d : %02x %s\n", 15, spd->res_15,
+ " spd->res_15, * 15 Reserved *");
+ printf("%-3d : %02x %s\n", 16, spd->burstl,
+ " spd->burstl, * 16 Burst Lengths Supported *");
+ printf("%-3d : %02x %s\n", 17, spd->nbanks,
+ " spd->nbanks, * 17 # of Banks on Each SDRAM Device *");
+ printf("%-3d : %02x %s\n", 18, spd->cas_lat,
+ " spd->cas_lat, * 18 CAS# Latencies Supported *");
+ printf("%-3d : %02x %s\n", 19, spd->mech_char,
+ " spd->mech_char, * 19 Mechanical Characteristics *");
+ printf("%-3d : %02x %s\n", 20, spd->dimm_type,
+ " spd->dimm_type, * 20 DIMM type *");
+ printf("%-3d : %02x %s\n", 21, spd->mod_attr,
+ " spd->mod_attr, * 21 SDRAM Module Attributes *");
+ printf("%-3d : %02x %s\n", 22, spd->dev_attr,
+ " spd->dev_attr, * 22 SDRAM Device Attributes *");
+ printf("%-3d : %02x %s\n", 23, spd->clk_cycle2,
+ " spd->clk_cycle2, * 23 Min SDRAM Cycle time at CL=X-1 *");
+ printf("%-3d : %02x %s\n", 24, spd->clk_access2,
+ " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
+ printf("%-3d : %02x %s\n", 25, spd->clk_cycle3,
+ " spd->clk_cycle3, * 25 Min SDRAM Cycle time at CL=X-2 *");
+ printf("%-3d : %02x %s\n", 26, spd->clk_access3,
+ " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
+ printf("%-3d : %02x %s\n", 27, spd->trp,
+ " spd->trp, * 27 Min Row Precharge Time (tRP)*");
+ printf("%-3d : %02x %s\n", 28, spd->trrd,
+ " spd->trrd, * 28 Min Row Active to Row Active (tRRD) *");
+ printf("%-3d : %02x %s\n", 29, spd->trcd,
+ " spd->trcd, * 29 Min RAS to CAS Delay (tRCD) *");
+ printf("%-3d : %02x %s\n", 30, spd->tras,
+ " spd->tras, * 30 Minimum RAS Pulse Width (tRAS) *");
+ printf("%-3d : %02x %s\n", 31, spd->rank_dens,
+ " spd->rank_dens, * 31 Density of each rank on module *");
+ printf("%-3d : %02x %s\n", 32, spd->ca_setup,
+ " spd->ca_setup, * 32 Cmd + Addr signal input setup time *");
+ printf("%-3d : %02x %s\n", 33, spd->ca_hold,
+ " spd->ca_hold, * 33 Cmd and Addr signal input hold time *");
+ printf("%-3d : %02x %s\n", 34, spd->data_setup,
+ " spd->data_setup, * 34 Data signal input setup time *");
+ printf("%-3d : %02x %s\n", 35, spd->data_hold,
+ " spd->data_hold, * 35 Data signal input hold time *");
+ printf("%-3d : %02x %s\n", 36, spd->twr,
+ " spd->twr, * 36 Write Recovery time tWR *");
+ printf("%-3d : %02x %s\n", 37, spd->twtr,
+ " spd->twtr, * 37 Int write to read delay tWTR *");
+ printf("%-3d : %02x %s\n", 38, spd->trtp,
+ " spd->trtp, * 38 Int read to precharge delay tRTP *");
+ printf("%-3d : %02x %s\n", 39, spd->mem_probe,
+ " spd->mem_probe, * 39 Mem analysis probe characteristics *");
+ printf("%-3d : %02x %s\n", 40, spd->trctrfc_ext,
+ " spd->trctrfc_ext, * 40 Extensions to trc and trfc *");
+ printf("%-3d : %02x %s\n", 41, spd->trc,
+ " spd->trc, * 41 Min Active to Auto refresh time tRC *");
+ printf("%-3d : %02x %s\n", 42, spd->trfc,
+ " spd->trfc, * 42 Min Auto to Active period tRFC *");
+ printf("%-3d : %02x %s\n", 43, spd->tckmax,
+ " spd->tckmax, * 43 Max device cycle time tCKmax *");
+ printf("%-3d : %02x %s\n", 44, spd->tdqsq,
+ " spd->tdqsq, * 44 Max DQS to DQ skew *");
+ printf("%-3d : %02x %s\n", 45, spd->tqhs,
+ " spd->tqhs, * 45 Max Read DataHold skew tQHS *");
+ printf("%-3d : %02x %s\n", 46, spd->pll_relock,
+ " spd->pll_relock, * 46 PLL Relock time *");
+ printf("%-3d : %02x %s\n", 47, spd->Tcasemax,
+ " spd->Tcasemax, * 47 Tcasemax *");
+ printf("%-3d : %02x %s\n", 48, spd->psiTAdram,
+ " spd->psiTAdram, * 48 Thermal Resistance of DRAM Package "
+ "from Top (Case) to Ambient (Psi T-A DRAM) *");
+ printf("%-3d : %02x %s\n", 49, spd->dt0_mode,
+ " spd->dt0_mode, * 49 DRAM Case Temperature Rise from "
+ "Ambient due to Activate-Precharge/Mode Bits "
+ "(DT0/Mode Bits) *)");
+ printf("%-3d : %02x %s\n", 50, spd->dt2n_dt2q,
+ " spd->dt2n_dt2q, * 50 DRAM Case Temperature Rise from "
+ "Ambient due to Precharge/Quiet Standby "
+ "(DT2N/DT2Q) *");
+ printf("%-3d : %02x %s\n", 51, spd->dt2p,
+ " spd->dt2p, * 51 DRAM Case Temperature Rise from "
+ "Ambient due to Precharge Power-Down (DT2P) *");
+ printf("%-3d : %02x %s\n", 52, spd->dt3n,
+ " spd->dt3n, * 52 DRAM Case Temperature Rise from "
+ "Ambient due to Active Standby (DT3N) *");
+ printf("%-3d : %02x %s\n", 53, spd->dt3pfast,
+ " spd->dt3pfast, * 53 DRAM Case Temperature Rise from "
+ "Ambient due to Active Power-Down with Fast PDN Exit "
+ "(DT3Pfast) *");
+ printf("%-3d : %02x %s\n", 54, spd->dt3pslow,
+ " spd->dt3pslow, * 54 DRAM Case Temperature Rise from "
+ "Ambient due to Active Power-Down with Slow PDN Exit "
+ "(DT3Pslow) *");
+ printf("%-3d : %02x %s\n", 55, spd->dt4r_dt4r4w,
+ " spd->dt4r_dt4r4w, * 55 DRAM Case Temperature Rise from "
+ "Ambient due to Page Open Burst Read/DT4R4W Mode Bit "
+ "(DT4R/DT4R4W Mode Bit) *");
+ printf("%-3d : %02x %s\n", 56, spd->dt5b,
+ " spd->dt5b, * 56 DRAM Case Temperature Rise from "
+ "Ambient due to Burst Refresh (DT5B) *");
+ printf("%-3d : %02x %s\n", 57, spd->dt7,
+ " spd->dt7, * 57 DRAM Case Temperature Rise from "
+ "Ambient due to Bank Interleave Reads with "
+ "Auto-Precharge (DT7) *");
+ printf("%-3d : %02x %s\n", 58, spd->psiTApll,
+ " spd->psiTApll, * 58 Thermal Resistance of PLL Package form"
+ " Top (Case) to Ambient (Psi T-A PLL) *");
+ printf("%-3d : %02x %s\n", 59, spd->psiTAreg,
+ " spd->psiTAreg, * 59 Thermal Reisitance of Register Package"
+ " from Top (Case) to Ambient (Psi T-A Register) *");
+ printf("%-3d : %02x %s\n", 60, spd->dtpllactive,
+ " spd->dtpllactive, * 60 PLL Case Temperature Rise from "
+ "Ambient due to PLL Active (DT PLL Active) *");
+ printf("%-3d : %02x %s\n", 61, spd->dtregact,
+ " spd->dtregact, "
+ "* 61 Register Case Temperature Rise from Ambient due to "
+ "Register Active/Mode Bit (DT Register Active/Mode Bit) *");
+ printf("%-3d : %02x %s\n", 62, spd->spd_rev,
+ " spd->spd_rev, * 62 SPD Data Revision Code *");
+ printf("%-3d : %02x %s\n", 63, spd->cksum,
+ " spd->cksum, * 63 Checksum for bytes 0-62 *");
+
+ printf("%-3d-%3d: ", 64, 71);
+
+ for (i = 0; i < 8; i++)
+ printf("%02x", spd->mid[i]);
+
+ printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
+
+ printf("%-3d : %02x %s\n", 72, spd->mloc,
+ " spd->mloc, * 72 Manufacturing Location *");
+
+ printf("%-3d-%3d: >>", 73, 90);
+ for (i = 0; i < 18; i++)
+ printf("%c", spd->mpart[i]);
+
+
+ printf("<<* 73 Manufacturer's Part Number *\n");
+
+ printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1],
+ "* 91 Revision Code *");
+ printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1],
+ "* 93 Manufacturing Date *");
+ printf("%-3d-%3d: ", 95, 98);
+
+ for (i = 0; i < 4; i++)
+ printf("%02x", spd->sernum[i]);
+
+ printf("* 95 Assembly Serial Number *\n");
+
+ printf("%-3d-%3d: ", 99, 127);
+ for (i = 0; i < 27; i++)
+ printf("%02x", spd->mspec[i]);
+
+
+ printf("* 99 Manufacturer Specific Data *\n");
+}
+#endif
+
+#ifdef CONFIG_FSL_DDR3
+void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd)
+{
+ unsigned int i;
+
+ /* General Section: Bytes 0-59 */
+
+#define PRINT_NXS(x, y, z...) printf("%-3d : %02x " z "\n", x, (u8)y);
+#define PRINT_NNXXS(n0, n1, x0, x1, s) \
+ printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1);
+
+ PRINT_NXS(0, spd->info_size_crc,
+ "info_size_crc bytes written into serial memory, "
+ "CRC coverage");
+ PRINT_NXS(1, spd->spd_rev,
+ "spd_rev SPD Revision");
+ PRINT_NXS(2, spd->mem_type,
+ "mem_type Key Byte / DRAM Device Type");
+ PRINT_NXS(3, spd->module_type,
+ "module_type Key Byte / Module Type");
+ PRINT_NXS(4, spd->density_banks,
+ "density_banks SDRAM Density and Banks");
+ PRINT_NXS(5, spd->addressing,
+ "addressing SDRAM Addressing");
+ PRINT_NXS(6, spd->module_vdd,
+ "module_vdd Module Nominal Voltage, VDD");
+ PRINT_NXS(7, spd->organization,
+ "organization Module Organization");
+ PRINT_NXS(8, spd->bus_width,
+ "bus_width Module Memory Bus Width");
+ PRINT_NXS(9, spd->ftb_div,
+ "ftb_div Fine Timebase (FTB) Dividend / Divisor");
+ PRINT_NXS(10, spd->mtb_dividend,
+ "mtb_dividend Medium Timebase (MTB) Dividend");
+ PRINT_NXS(11, spd->mtb_divisor,
+ "mtb_divisor Medium Timebase (MTB) Divisor");
+ PRINT_NXS(12, spd->tCK_min,
+ "tCK_min SDRAM Minimum Cycle Time");
+ PRINT_NXS(13, spd->res_13,
+ "res_13 Reserved");
+ PRINT_NXS(14, spd->caslat_lsb,
+ "caslat_lsb CAS Latencies Supported, LSB");
+ PRINT_NXS(15, spd->caslat_msb,
+ "caslat_msb CAS Latencies Supported, MSB");
+ PRINT_NXS(16, spd->tAA_min,
+ "tAA_min Min CAS Latency Time");
+ PRINT_NXS(17, spd->tWR_min,
+ "tWR_min Min Write REcovery Time");
+ PRINT_NXS(18, spd->tRCD_min,
+ "tRCD_min Min RAS# to CAS# Delay Time");
+ PRINT_NXS(19, spd->tRRD_min,
+ "tRRD_min Min Row Active to Row Active Delay Time");
+ PRINT_NXS(20, spd->tRP_min,
+ "tRP_min Min Row Precharge Delay Time");
+ PRINT_NXS(21, spd->tRAS_tRC_ext,
+ "tRAS_tRC_ext Upper Nibbles for tRAS and tRC");
+ PRINT_NXS(22, spd->tRAS_min_lsb,
+ "tRAS_min_lsb Min Active to Precharge Delay Time, LSB");
+ PRINT_NXS(23, spd->tRC_min_lsb,
+ "tRC_min_lsb Min Active to Active/Refresh Delay Time, LSB");
+ PRINT_NXS(24, spd->tRFC_min_lsb,
+ "tRFC_min_lsb Min Refresh Recovery Delay Time LSB");
+ PRINT_NXS(25, spd->tRFC_min_msb,
+ "tRFC_min_msb Min Refresh Recovery Delay Time MSB");
+ PRINT_NXS(26, spd->tWTR_min,
+ "tWTR_min Min Internal Write to Read Command Delay Time");
+ PRINT_NXS(27, spd->tRTP_min,
+ "tRTP_min "
+ "Min Internal Read to Precharge Command Delay Time");
+ PRINT_NXS(28, spd->tFAW_msb,
+ "tFAW_msb Upper Nibble for tFAW");
+ PRINT_NXS(29, spd->tFAW_min,
+ "tFAW_min Min Four Activate Window Delay Time");
+ PRINT_NXS(30, spd->opt_features,
+ "opt_features SDRAM Optional Features");
+ PRINT_NXS(31, spd->therm_ref_opt,
+ "therm_ref_opt SDRAM Thermal and Refresh Opts");
+ PRINT_NXS(32, spd->therm_sensor,
+ "therm_sensor SDRAM Thermal Sensor");
+ PRINT_NXS(33, spd->device_type,
+ "device_type SDRAM Device Type");
+ PRINT_NXS(34, spd->fine_tCK_min,
+ "fine_tCK_min Fine offset for tCKmin");
+ PRINT_NXS(35, spd->fine_tAA_min,
+ "fine_tAA_min Fine offset for tAAmin");
+ PRINT_NXS(36, spd->fine_tRCD_min,
+ "fine_tRCD_min Fine offset for tRCDmin");
+ PRINT_NXS(37, spd->fine_tRP_min,
+ "fine_tRP_min Fine offset for tRPmin");
+ PRINT_NXS(38, spd->fine_tRC_min,
+ "fine_tRC_min Fine offset for tRCmin");
+
+ printf("%-3d-%3d: ", 39, 59); /* Reserved, General Section */
+
+ for (i = 39; i <= 59; i++)
+ printf("%02x ", spd->res_39_59[i - 39]);
+
+ puts("\n");
+
+ switch (spd->module_type) {
+ case 0x02: /* UDIMM */
+ case 0x03: /* SO-DIMM */
+ case 0x04: /* Micro-DIMM */
+ case 0x06: /* Mini-UDIMM */
+ PRINT_NXS(60, spd->mod_section.unbuffered.mod_height,
+ "mod_height (Unbuffered) Module Nominal Height");
+ PRINT_NXS(61, spd->mod_section.unbuffered.mod_thickness,
+ "mod_thickness (Unbuffered) Module Maximum Thickness");
+ PRINT_NXS(62, spd->mod_section.unbuffered.ref_raw_card,
+ "ref_raw_card (Unbuffered) Reference Raw Card Used");
+ PRINT_NXS(63, spd->mod_section.unbuffered.addr_mapping,
+ "addr_mapping (Unbuffered) Address mapping from "
+ "Edge Connector to DRAM");
+ break;
+ case 0x01: /* RDIMM */
+ case 0x05: /* Mini-RDIMM */
+ PRINT_NXS(60, spd->mod_section.registered.mod_height,
+ "mod_height (Registered) Module Nominal Height");
+ PRINT_NXS(61, spd->mod_section.registered.mod_thickness,
+ "mod_thickness (Registered) Module Maximum Thickness");
+ PRINT_NXS(62, spd->mod_section.registered.ref_raw_card,
+ "ref_raw_card (Registered) Reference Raw Card Used");
+ PRINT_NXS(63, spd->mod_section.registered.modu_attr,
+ "modu_attr (Registered) DIMM Module Attributes");
+ PRINT_NXS(64, spd->mod_section.registered.thermal,
+ "thermal (Registered) Thermal Heat "
+ "Spreader Solution");
+ PRINT_NXS(65, spd->mod_section.registered.reg_id_lo,
+ "reg_id_lo (Registered) Register Manufacturer ID "
+ "Code, LSB");
+ PRINT_NXS(66, spd->mod_section.registered.reg_id_hi,
+ "reg_id_hi (Registered) Register Manufacturer ID "
+ "Code, MSB");
+ PRINT_NXS(67, spd->mod_section.registered.reg_rev,
+ "reg_rev (Registered) Register "
+ "Revision Number");
+ PRINT_NXS(68, spd->mod_section.registered.reg_type,
+ "reg_type (Registered) Register Type");
+ for (i = 69; i <= 76; i++) {
+ printf("%-3d : %02x rcw[%d]\n", i,
+ spd->mod_section.registered.rcw[i-69], i-69);
+ }
+ break;
+ default:
+ /* Module-specific Section, Unsupported Module Type */
+ printf("%-3d-%3d: ", 60, 116);
+
+ for (i = 60; i <= 116; i++)
+ printf("%02x", spd->mod_section.uc[i - 60]);
+
+ break;
+ }
+
+ /* Unique Module ID: Bytes 117-125 */
+ PRINT_NXS(117, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106");
+ PRINT_NXS(118, spd->mmid_msb, "Module MfgID Code MSB - JEP-106");
+ PRINT_NXS(119, spd->mloc, "Mfg Location");
+ PRINT_NNXXS(120, 121, spd->mdate[0], spd->mdate[1], "Mfg Date");
+
+ printf("%-3d-%3d: ", 122, 125);
+
+ for (i = 122; i <= 125; i++)
+ printf("%02x ", spd->sernum[i - 122]);
+ printf(" Module Serial Number\n");
+
+ /* CRC: Bytes 126-127 */
+ PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], " SPD CRC");
+
+ /* Other Manufacturer Fields and User Space: Bytes 128-255 */
+ printf("%-3d-%3d: ", 128, 145);
+ for (i = 128; i <= 145; i++)
+ printf("%02x ", spd->mpart[i - 128]);
+ printf(" Mfg's Module Part Number\n");
+
+ PRINT_NNXXS(146, 147, spd->mrev[0], spd->mrev[1],
+ "Module Revision code");
+
+ PRINT_NXS(148, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106");
+ PRINT_NXS(149, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106");
+
+ printf("%-3d-%3d: ", 150, 175);
+ for (i = 150; i <= 175; i++)
+ printf("%02x ", spd->msd[i - 150]);
+ printf(" Mfg's Specific Data\n");
+
+ printf("%-3d-%3d: ", 176, 255);
+ for (i = 176; i <= 255; i++)
+ printf("%02x", spd->cust[i - 176]);
+ printf(" Mfg's Specific Data\n");
+
+}
+#endif
+
+static inline void generic_spd_dump(const generic_spd_eeprom_t *spd)
+{
+#if defined(CONFIG_FSL_DDR1)
+ ddr1_spd_dump(spd);
+#elif defined(CONFIG_FSL_DDR2)
+ ddr2_spd_dump(spd);
+#elif defined(CONFIG_FSL_DDR3)
+ ddr3_spd_dump(spd);
+#endif
+}
+
+static void fsl_ddr_printinfo(const fsl_ddr_info_t *pinfo,
+ unsigned int ctrl_mask,
+ unsigned int dimm_mask,
+ unsigned int do_mask)
+{
+ unsigned int i, j, retval;
+
+ /* STEP 1: DIMM SPD data */
+ if (do_mask & STEP_GET_SPD) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (!(ctrl_mask & (1 << i)))
+ continue;
+
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ if (!(dimm_mask & (1 << j)))
+ continue;
+
+ printf("SPD info: Controller=%u "
+ "DIMM=%u\n", i, j);
+ generic_spd_dump(
+ &(pinfo->spd_installed_dimms[i][j]));
+ printf("\n");
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ /* STEP 2: DIMM Parameters */
+ if (do_mask & STEP_COMPUTE_DIMM_PARMS) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (!(ctrl_mask & (1 << i)))
+ continue;
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ if (!(dimm_mask & (1 << j)))
+ continue;
+ printf("DIMM parameters: Controller=%u "
+ "DIMM=%u\n", i, j);
+ print_dimm_parameters(
+ &(pinfo->dimm_params[i][j]));
+ printf("\n");
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ /* STEP 3: Common Parameters */
+ if (do_mask & STEP_COMPUTE_COMMON_PARMS) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (!(ctrl_mask & (1 << i)))
+ continue;
+ printf("\"lowest common\" DIMM parameters: "
+ "Controller=%u\n", i);
+ print_lowest_common_dimm_parameters(
+ &pinfo->common_timing_params[i]);
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ /* STEP 4: User Configuration Options */
+ if (do_mask & STEP_GATHER_OPTS) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (!(ctrl_mask & (1 << i)))
+ continue;
+ printf("User Config Options: Controller=%u\n", i);
+ print_memctl_options(&pinfo->memctl_opts[i]);
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ /* STEP 5: Address assignment */
+ if (do_mask & STEP_ASSIGN_ADDRESSES) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (!(ctrl_mask & (1 << i)))
+ continue;
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ printf("Address Assignment: Controller=%u "
+ "DIMM=%u\n", i, j);
+ printf("Don't have this functionality yet\n");
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ /* STEP 6: computed controller register values */
+ if (do_mask & STEP_COMPUTE_REGS) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (!(ctrl_mask & (1 << i)))
+ continue;
+ printf("Computed Register Values: Controller=%u\n", i);
+ print_fsl_memctl_config_regs(
+ &pinfo->fsl_ddr_config_reg[i]);
+ retval = check_fsl_memctl_config_regs(
+ &pinfo->fsl_ddr_config_reg[i]);
+ if (retval) {
+ printf("check_fsl_memctl_config_regs "
+ "result = %u\n", retval);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+}
+
+struct data_strings {
+ const char *data_name;
+ unsigned int step_mask;
+ unsigned int dimm_number_required;
+};
+
+#define DATA_OPTIONS(name, step, dimm) {#name, step, dimm}
+
+static unsigned int fsl_ddr_parse_interactive_cmd(
+ char **argv,
+ int argc,
+ unsigned int *pstep_mask,
+ unsigned int *pctlr_mask,
+ unsigned int *pdimm_mask,
+ unsigned int *pdimm_number_required
+ ) {
+
+ static const struct data_strings options[] = {
+ DATA_OPTIONS(spd, STEP_GET_SPD, 1),
+ DATA_OPTIONS(dimmparms, STEP_COMPUTE_DIMM_PARMS, 1),
+ DATA_OPTIONS(commonparms, STEP_COMPUTE_COMMON_PARMS, 0),
+ DATA_OPTIONS(opts, STEP_GATHER_OPTS, 0),
+ DATA_OPTIONS(addresses, STEP_ASSIGN_ADDRESSES, 0),
+ DATA_OPTIONS(regs, STEP_COMPUTE_REGS, 0),
+ };
+ static const unsigned int n_opts = ARRAY_SIZE(options);
+
+ unsigned int i, j;
+ unsigned int error = 0;
+
+ for (i = 1; i < argc; i++) {
+ unsigned int matched = 0;
+
+ for (j = 0; j < n_opts; j++) {
+ if (strcmp(options[j].data_name, argv[i]) != 0)
+ continue;
+ *pstep_mask |= options[j].step_mask;
+ *pdimm_number_required =
+ options[j].dimm_number_required;
+ matched = 1;
+ break;
+ }
+
+ if (matched)
+ continue;
+
+ if (argv[i][0] == 'c') {
+ char c = argv[i][1];
+ if (isdigit(c))
+ *pctlr_mask |= 1 << (c - '0');
+ continue;
+ }
+
+ if (argv[i][0] == 'd') {
+ char c = argv[i][1];
+ if (isdigit(c))
+ *pdimm_mask |= 1 << (c - '0');
+ continue;
+ }
+
+ printf("unknown arg %s\n", argv[i]);
+ *pstep_mask = 0;
+ error = 1;
+ break;
+ }
+
+ return error;
+}
+
+int fsl_ddr_interactive_env_var_exists(void)
+{
+ char buffer[CONFIG_SYS_CBSIZE];
+
+ if (getenv_f("ddr_interactive", buffer, CONFIG_SYS_CBSIZE) >= 0)
+ return 1;
+
+ return 0;
+}
+
+unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set)
+{
+ unsigned long long ddrsize;
+ const char *prompt = "FSL DDR>";
+ char buffer[CONFIG_SYS_CBSIZE];
+ char buffer2[CONFIG_SYS_CBSIZE];
+ char *p = NULL;
+ char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */
+ int argc;
+ unsigned int next_step = STEP_GET_SPD;
+ const char *usage = {
+ "commands:\n"
+ "print print SPD and intermediate computed data\n"
+ "reset reboot machine\n"
+ "recompute reload SPD and options to default and recompute regs\n"
+ "edit modify spd, parameter, or option\n"
+ "compute recompute registers from current next_step to end\n"
+ "copy copy parameters\n"
+ "next_step shows current next_step\n"
+ "help this message\n"
+ "go program the memory controller and continue with u-boot\n"
+ };
+
+ if (var_is_set) {
+ if (getenv_f("ddr_interactive", buffer2, CONFIG_SYS_CBSIZE) > 0) {
+ p = buffer2;
+ } else {
+ var_is_set = 0;
+ }
+ }
+
+ /*
+ * The strategy for next_step is that it points to the next
+ * step in the computation process that needs to be done.
+ */
+ while (1) {
+ if (var_is_set) {
+ char *pend = strchr(p, ';');
+ if (pend) {
+ /* found command separator, copy sub-command */
+ *pend = '\0';
+ strcpy(buffer, p);
+ p = pend + 1;
+ } else {
+ /* separator not found, copy whole string */
+ strcpy(buffer, p);
+ p = NULL;
+ var_is_set = 0;
+ }
+ } else {
+ /*
+ * No need to worry for buffer overflow here in
+ * this function; readline() maxes out at CFG_CBSIZE
+ */
+ readline_into_buffer(prompt, buffer, 0);
+ }
+ argc = parse_line(buffer, argv);
+ if (argc == 0)
+ continue;
+
+
+ if (strcmp(argv[0], "help") == 0) {
+ puts(usage);
+ continue;
+ }
+
+ if (strcmp(argv[0], "next_step") == 0) {
+ printf("next_step = 0x%02X (%s)\n",
+ next_step,
+ step_to_string(next_step));
+ continue;
+ }
+
+ if (strcmp(argv[0], "copy") == 0) {
+ unsigned int error = 0;
+ unsigned int step_mask = 0;
+ unsigned int src_ctlr_mask = 0;
+ unsigned int src_dimm_mask = 0;
+ unsigned int dimm_number_required = 0;
+ unsigned int src_ctlr_num = 0;
+ unsigned int src_dimm_num = 0;
+ unsigned int dst_ctlr_num = -1;
+ unsigned int dst_dimm_num = -1;
+ unsigned int i, num_dest_parms;
+
+ if (argc == 1) {
+ printf("copy <src c#> <src d#> <spd|dimmparms|commonparms|opts|addresses|regs> <dst c#> <dst d#>\n");
+ continue;
+ }
+
+ error = fsl_ddr_parse_interactive_cmd(
+ argv, argc,
+ &step_mask,
+ &src_ctlr_mask,
+ &src_dimm_mask,
+ &dimm_number_required
+ );
+
+ /* XXX: only dimm_number_required and step_mask will
+ be used by this function. Parse the controller and
+ DIMM number separately because it is easier. */
+
+ if (error)
+ continue;
+
+ /* parse source destination controller / DIMM */
+
+ num_dest_parms = dimm_number_required ? 2 : 1;
+
+ for (i = 0; i < argc; i++) {
+ if (argv[i][0] == 'c') {
+ char c = argv[i][1];
+ if (isdigit(c)) {
+ src_ctlr_num = (c - '0');
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < argc; i++) {
+ if (argv[i][0] == 'd') {
+ char c = argv[i][1];
+ if (isdigit(c)) {
+ src_dimm_num = (c - '0');
+ break;
+ }
+ }
+ }
+
+ /* parse destination controller / DIMM */
+
+ for (i = argc - 1; i >= argc - num_dest_parms; i--) {
+ if (argv[i][0] == 'c') {
+ char c = argv[i][1];
+ if (isdigit(c)) {
+ dst_ctlr_num = (c - '0');
+ break;
+ }
+ }
+ }
+
+ for (i = argc - 1; i >= argc - num_dest_parms; i--) {
+ if (argv[i][0] == 'd') {
+ char c = argv[i][1];
+ if (isdigit(c)) {
+ dst_dimm_num = (c - '0');
+ break;
+ }
+ }
+ }
+
+ /* TODO: validate inputs */
+
+ debug("src_ctlr_num = %u, src_dimm_num = %u, dst_ctlr_num = %u, dst_dimm_num = %u, step_mask = %x\n",
+ src_ctlr_num, src_dimm_num, dst_ctlr_num, dst_dimm_num, step_mask);
+
+
+ switch (step_mask) {
+
+ case STEP_GET_SPD:
+ memcpy(&(pinfo->spd_installed_dimms[dst_ctlr_num][dst_dimm_num]),
+ &(pinfo->spd_installed_dimms[src_ctlr_num][src_dimm_num]),
+ sizeof(pinfo->spd_installed_dimms[0][0]));
+ break;
+
+ case STEP_COMPUTE_DIMM_PARMS:
+ memcpy(&(pinfo->dimm_params[dst_ctlr_num][dst_dimm_num]),
+ &(pinfo->dimm_params[src_ctlr_num][src_dimm_num]),
+ sizeof(pinfo->dimm_params[0][0]));
+ break;
+
+ case STEP_COMPUTE_COMMON_PARMS:
+ memcpy(&(pinfo->common_timing_params[dst_ctlr_num]),
+ &(pinfo->common_timing_params[src_ctlr_num]),
+ sizeof(pinfo->common_timing_params[0]));
+ break;
+
+ case STEP_GATHER_OPTS:
+ memcpy(&(pinfo->memctl_opts[dst_ctlr_num]),
+ &(pinfo->memctl_opts[src_ctlr_num]),
+ sizeof(pinfo->memctl_opts[0]));
+ break;
+
+ /* someday be able to have addresses to copy addresses... */
+
+ case STEP_COMPUTE_REGS:
+ memcpy(&(pinfo->fsl_ddr_config_reg[dst_ctlr_num]),
+ &(pinfo->fsl_ddr_config_reg[src_ctlr_num]),
+ sizeof(pinfo->memctl_opts[0]));
+ break;
+
+ default:
+ printf("unexpected step_mask value\n");
+ }
+
+ continue;
+
+ }
+
+ if (strcmp(argv[0], "edit") == 0) {
+ unsigned int error = 0;
+ unsigned int step_mask = 0;
+ unsigned int ctlr_mask = 0;
+ unsigned int dimm_mask = 0;
+ char *p_element = NULL;
+ char *p_value = NULL;
+ unsigned int dimm_number_required = 0;
+ unsigned int ctrl_num;
+ unsigned int dimm_num;
+
+ if (argc == 1) {
+ /* Only the element and value must be last */
+ printf("edit <c#> <d#> "
+ "<spd|dimmparms|commonparms|opts|"
+ "addresses|regs> <element> <value>\n");
+ printf("for spd, specify byte number for "
+ "element\n");
+ continue;
+ }
+
+ error = fsl_ddr_parse_interactive_cmd(
+ argv, argc - 2,
+ &step_mask,
+ &ctlr_mask,
+ &dimm_mask,
+ &dimm_number_required
+ );
+
+ if (error)
+ continue;
+
+
+ /* Check arguments */
+
+ /* ERROR: If no steps were found */
+ if (step_mask == 0) {
+ printf("Error: No valid steps were specified "
+ "in argument.\n");
+ continue;
+ }
+
+ /* ERROR: If multiple steps were found */
+ if (step_mask & (step_mask - 1)) {
+ printf("Error: Multiple steps specified in "
+ "argument.\n");
+ continue;
+ }
+
+ /* ERROR: Controller not specified */
+ if (ctlr_mask == 0) {
+ printf("Error: controller number not "
+ "specified or no element and "
+ "value specified\n");
+ continue;
+ }
+
+ if (ctlr_mask & (ctlr_mask - 1)) {
+ printf("Error: multiple controllers "
+ "specified, %X\n", ctlr_mask);
+ continue;
+ }
+
+ /* ERROR: DIMM number not specified */
+ if (dimm_number_required && dimm_mask == 0) {
+ printf("Error: DIMM number number not "
+ "specified or no element and "
+ "value specified\n");
+ continue;
+ }
+
+ if (dimm_mask & (dimm_mask - 1)) {
+ printf("Error: multipled DIMMs specified\n");
+ continue;
+ }
+
+ p_element = argv[argc - 2];
+ p_value = argv[argc - 1];
+
+ ctrl_num = __ilog2(ctlr_mask);
+ dimm_num = __ilog2(dimm_mask);
+
+ switch (step_mask) {
+ case STEP_GET_SPD:
+ {
+ unsigned int element_num;
+ unsigned int value;
+
+ element_num = simple_strtoul(p_element,
+ NULL, 0);
+ value = simple_strtoul(p_value,
+ NULL, 0);
+ fsl_ddr_spd_edit(pinfo,
+ ctrl_num,
+ dimm_num,
+ element_num,
+ value);
+ next_step = STEP_COMPUTE_DIMM_PARMS;
+ }
+ break;
+
+ case STEP_COMPUTE_DIMM_PARMS:
+ fsl_ddr_dimm_parameters_edit(
+ pinfo, ctrl_num, dimm_num,
+ p_element, p_value);
+ next_step = STEP_COMPUTE_COMMON_PARMS;
+ break;
+
+ case STEP_COMPUTE_COMMON_PARMS:
+ lowest_common_dimm_parameters_edit(pinfo,
+ ctrl_num, p_element, p_value);
+ next_step = STEP_GATHER_OPTS;
+ break;
+
+ case STEP_GATHER_OPTS:
+ fsl_ddr_options_edit(pinfo, ctrl_num,
+ p_element, p_value);
+ next_step = STEP_ASSIGN_ADDRESSES;
+ break;
+
+ case STEP_ASSIGN_ADDRESSES:
+ printf("editing of address assignment "
+ "not yet implemented\n");
+ break;
+
+ case STEP_COMPUTE_REGS:
+ {
+ fsl_ddr_regs_edit(pinfo,
+ ctrl_num,
+ p_element,
+ p_value);
+ next_step = STEP_PROGRAM_REGS;
+ }
+ break;
+
+ default:
+ printf("programming error\n");
+ while (1)
+ ;
+ break;
+ }
+ continue;
+ }
+
+ if (strcmp(argv[0], "reset") == 0) {
+ /*
+ * Reboot machine.
+ * Args don't seem to matter because this
+ * doesn't return
+ */
+ do_reset(NULL, 0, 0, NULL);
+ printf("Reset didn't work\n");
+ }
+
+ if (strcmp(argv[0], "recompute") == 0) {
+ /*
+ * Recalculate everything, starting with
+ * loading SPD EEPROM from DIMMs
+ */
+ next_step = STEP_GET_SPD;
+ ddrsize = fsl_ddr_compute(pinfo, next_step, 0);
+ continue;
+ }
+
+ if (strcmp(argv[0], "compute") == 0) {
+ /*
+ * Compute rest of steps starting at
+ * the current next_step/
+ */
+ ddrsize = fsl_ddr_compute(pinfo, next_step, 0);
+ continue;
+ }
+
+ if (strcmp(argv[0], "print") == 0) {
+ unsigned int error = 0;
+ unsigned int step_mask = 0;
+ unsigned int ctlr_mask = 0;
+ unsigned int dimm_mask = 0;
+ unsigned int dimm_number_required = 0;
+
+ if (argc == 1) {
+ printf("print [c<n>] [d<n>] [spd] [dimmparms] "
+ "[commonparms] [opts] [addresses] [regs]\n");
+ continue;
+ }
+
+ error = fsl_ddr_parse_interactive_cmd(
+ argv, argc,
+ &step_mask,
+ &ctlr_mask,
+ &dimm_mask,
+ &dimm_number_required
+ );
+
+ if (error)
+ continue;
+
+ /* If no particular controller was found, print all */
+ if (ctlr_mask == 0)
+ ctlr_mask = 0xFF;
+
+ /* If no particular dimm was found, print all dimms. */
+ if (dimm_mask == 0)
+ dimm_mask = 0xFF;
+
+ /* If no steps were found, print all steps. */
+ if (step_mask == 0)
+ step_mask = STEP_ALL;
+
+ fsl_ddr_printinfo(pinfo, ctlr_mask,
+ dimm_mask, step_mask);
+ continue;
+ }
+
+ if (strcmp(argv[0], "go") == 0) {
+ if (next_step)
+ ddrsize = fsl_ddr_compute(pinfo, next_step, 0);
+ break;
+ }
+
+ printf("unknown command %s\n", argv[0]);
+ }
+
+ debug("end of memory = %llu\n", (u64)ddrsize);
+
+ return ddrsize;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
new file mode 100644
index 0000000..e958e13
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/lc_common_dimm_params.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+#if defined(CONFIG_FSL_DDR3)
+static unsigned int
+compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
+ common_timing_params_t *outpdimm,
+ unsigned int number_of_dimms)
+{
+ unsigned int i;
+ unsigned int tAAmin_ps = 0;
+ unsigned int tCKmin_X_ps = 0;
+ unsigned int common_caslat;
+ unsigned int caslat_actual;
+ unsigned int retry = 16;
+ unsigned int tmp;
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+
+ /* compute the common CAS latency supported between slots */
+ tmp = dimm_params[0].caslat_X;
+ for (i = 1; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks)
+ tmp &= dimm_params[i].caslat_X;
+ }
+ common_caslat = tmp;
+
+ /* compute the max tAAmin tCKmin between slots */
+ for (i = 0; i < number_of_dimms; i++) {
+ tAAmin_ps = max(tAAmin_ps, dimm_params[i].tAA_ps);
+ tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps);
+ }
+ /* validate if the memory clk is in the range of dimms */
+ if (mclk_ps < tCKmin_X_ps) {
+ printf("DDR clock (MCLK cycle %u ps) is faster than "
+ "the slowest DIMM(s) (tCKmin %u ps) can support.\n",
+ mclk_ps, tCKmin_X_ps);
+ }
+ /* determine the acutal cas latency */
+ caslat_actual = (tAAmin_ps + mclk_ps - 1) / mclk_ps;
+ /* check if the dimms support the CAS latency */
+ while (!(common_caslat & (1 << caslat_actual)) && retry > 0) {
+ caslat_actual++;
+ retry--;
+ }
+ /* once the caculation of caslat_actual is completed
+ * we must verify that this CAS latency value does not
+ * exceed tAAmax, which is 20 ns for all DDR3 speed grades
+ */
+ if (caslat_actual * mclk_ps > 20000) {
+ printf("The choosen cas latency %d is too large\n",
+ caslat_actual);
+ }
+ outpdimm->lowest_common_SPD_caslat = caslat_actual;
+
+ return 0;
+}
+#endif
+
+/*
+ * compute_lowest_common_dimm_parameters()
+ *
+ * Determine the worst-case DIMM timing parameters from the set of DIMMs
+ * whose parameters have been computed into the array pointed to
+ * by dimm_params.
+ */
+unsigned int
+compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
+ common_timing_params_t *outpdimm,
+ const unsigned int number_of_dimms)
+{
+ unsigned int i, j;
+
+ unsigned int tCKmin_X_ps = 0;
+ unsigned int tCKmax_ps = 0xFFFFFFFF;
+ unsigned int tCKmax_max_ps = 0;
+ unsigned int tRCD_ps = 0;
+ unsigned int tRP_ps = 0;
+ unsigned int tRAS_ps = 0;
+ unsigned int tWR_ps = 0;
+ unsigned int tWTR_ps = 0;
+ unsigned int tRFC_ps = 0;
+ unsigned int tRRD_ps = 0;
+ unsigned int tRC_ps = 0;
+ unsigned int refresh_rate_ps = 0;
+ unsigned int tIS_ps = 0;
+ unsigned int tIH_ps = 0;
+ unsigned int tDS_ps = 0;
+ unsigned int tDH_ps = 0;
+ unsigned int tRTP_ps = 0;
+ unsigned int tDQSQ_max_ps = 0;
+ unsigned int tQHS_ps = 0;
+
+ unsigned int temp1, temp2;
+ unsigned int additive_latency = 0;
+#if !defined(CONFIG_FSL_DDR3)
+ const unsigned int mclk_ps = get_memory_clk_period_ps();
+ unsigned int lowest_good_caslat;
+ unsigned int not_ok;
+
+ debug("using mclk_ps = %u\n", mclk_ps);
+#endif
+
+ temp1 = 0;
+ for (i = 0; i < number_of_dimms; i++) {
+ /*
+ * If there are no ranks on this DIMM,
+ * it probably doesn't exist, so skip it.
+ */
+ if (dimm_params[i].n_ranks == 0) {
+ temp1++;
+ continue;
+ }
+ if (dimm_params[i].n_ranks == 4 && i != 0) {
+ printf("Found Quad-rank DIMM in wrong bank, ignored."
+ " Software may not run as expected.\n");
+ temp1++;
+ continue;
+ }
+
+ /*
+ * check if quad-rank DIMM is plugged if
+ * CONFIG_CHIP_SELECT_QUAD_CAPABLE is not defined
+ * Only the board with proper design is capable
+ */
+#ifndef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ if (dimm_params[i].n_ranks == 4 && \
+ CONFIG_CHIP_SELECTS_PER_CTRL/CONFIG_DIMM_SLOTS_PER_CTLR < 4) {
+ printf("Found Quad-rank DIMM, not able to support.");
+ temp1++;
+ continue;
+ }
+#endif
+ /*
+ * Find minimum tCKmax_ps to find fastest slow speed,
+ * i.e., this is the slowest the whole system can go.
+ */
+ tCKmax_ps = min(tCKmax_ps, dimm_params[i].tCKmax_ps);
+
+ /* Either find maximum value to determine slowest
+ * speed, delay, time, period, etc */
+ tCKmin_X_ps = max(tCKmin_X_ps, dimm_params[i].tCKmin_X_ps);
+ tCKmax_max_ps = max(tCKmax_max_ps, dimm_params[i].tCKmax_ps);
+ tRCD_ps = max(tRCD_ps, dimm_params[i].tRCD_ps);
+ tRP_ps = max(tRP_ps, dimm_params[i].tRP_ps);
+ tRAS_ps = max(tRAS_ps, dimm_params[i].tRAS_ps);
+ tWR_ps = max(tWR_ps, dimm_params[i].tWR_ps);
+ tWTR_ps = max(tWTR_ps, dimm_params[i].tWTR_ps);
+ tRFC_ps = max(tRFC_ps, dimm_params[i].tRFC_ps);
+ tRRD_ps = max(tRRD_ps, dimm_params[i].tRRD_ps);
+ tRC_ps = max(tRC_ps, dimm_params[i].tRC_ps);
+ tIS_ps = max(tIS_ps, dimm_params[i].tIS_ps);
+ tIH_ps = max(tIH_ps, dimm_params[i].tIH_ps);
+ tDS_ps = max(tDS_ps, dimm_params[i].tDS_ps);
+ tDH_ps = max(tDH_ps, dimm_params[i].tDH_ps);
+ tRTP_ps = max(tRTP_ps, dimm_params[i].tRTP_ps);
+ tQHS_ps = max(tQHS_ps, dimm_params[i].tQHS_ps);
+ refresh_rate_ps = max(refresh_rate_ps,
+ dimm_params[i].refresh_rate_ps);
+
+ /*
+ * Find maximum tDQSQ_max_ps to find slowest.
+ *
+ * FIXME: is finding the slowest value the correct
+ * strategy for this parameter?
+ */
+ tDQSQ_max_ps = max(tDQSQ_max_ps, dimm_params[i].tDQSQ_max_ps);
+ }
+
+ outpdimm->ndimms_present = number_of_dimms - temp1;
+
+ if (temp1 == number_of_dimms) {
+ debug("no dimms this memory controller\n");
+ return 0;
+ }
+
+ outpdimm->tCKmin_X_ps = tCKmin_X_ps;
+ outpdimm->tCKmax_ps = tCKmax_ps;
+ outpdimm->tCKmax_max_ps = tCKmax_max_ps;
+ outpdimm->tRCD_ps = tRCD_ps;
+ outpdimm->tRP_ps = tRP_ps;
+ outpdimm->tRAS_ps = tRAS_ps;
+ outpdimm->tWR_ps = tWR_ps;
+ outpdimm->tWTR_ps = tWTR_ps;
+ outpdimm->tRFC_ps = tRFC_ps;
+ outpdimm->tRRD_ps = tRRD_ps;
+ outpdimm->tRC_ps = tRC_ps;
+ outpdimm->refresh_rate_ps = refresh_rate_ps;
+ outpdimm->tIS_ps = tIS_ps;
+ outpdimm->tIH_ps = tIH_ps;
+ outpdimm->tDS_ps = tDS_ps;
+ outpdimm->tDH_ps = tDH_ps;
+ outpdimm->tRTP_ps = tRTP_ps;
+ outpdimm->tDQSQ_max_ps = tDQSQ_max_ps;
+ outpdimm->tQHS_ps = tQHS_ps;
+
+ /* Determine common burst length for all DIMMs. */
+ temp1 = 0xff;
+ for (i = 0; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks) {
+ temp1 &= dimm_params[i].burst_lengths_bitmask;
+ }
+ }
+ outpdimm->all_DIMMs_burst_lengths_bitmask = temp1;
+
+ /* Determine if all DIMMs registered buffered. */
+ temp1 = temp2 = 0;
+ for (i = 0; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks) {
+ if (dimm_params[i].registered_dimm) {
+ temp1 = 1;
+ printf("Detected RDIMM %s\n",
+ dimm_params[i].mpart);
+ } else {
+ temp2 = 1;
+ printf("Detected UDIMM %s\n",
+ dimm_params[i].mpart);
+ }
+ }
+ }
+
+ outpdimm->all_DIMMs_registered = 0;
+ outpdimm->all_DIMMs_unbuffered = 0;
+ if (temp1 && !temp2) {
+ outpdimm->all_DIMMs_registered = 1;
+ } else if (!temp1 && temp2) {
+ outpdimm->all_DIMMs_unbuffered = 1;
+ } else {
+ printf("ERROR: Mix of registered buffered and unbuffered "
+ "DIMMs detected!\n");
+ }
+
+ temp1 = 0;
+ if (outpdimm->all_DIMMs_registered)
+ for (j = 0; j < 16; j++) {
+ outpdimm->rcw[j] = dimm_params[0].rcw[j];
+ for (i = 1; i < number_of_dimms; i++) {
+ if (!dimm_params[i].n_ranks)
+ continue;
+ if (dimm_params[i].rcw[j] != dimm_params[0].rcw[j]) {
+ temp1 = 1;
+ break;
+ }
+ }
+ }
+
+ if (temp1 != 0)
+ printf("ERROR: Mix different RDIMM detected!\n");
+
+#if defined(CONFIG_FSL_DDR3)
+ if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms))
+ return 1;
+#else
+ /*
+ * Compute a CAS latency suitable for all DIMMs
+ *
+ * Strategy for SPD-defined latencies: compute only
+ * CAS latency defined by all DIMMs.
+ */
+
+ /*
+ * Step 1: find CAS latency common to all DIMMs using bitwise
+ * operation.
+ */
+ temp1 = 0xFF;
+ for (i = 0; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks) {
+ temp2 = 0;
+ temp2 |= 1 << dimm_params[i].caslat_X;
+ temp2 |= 1 << dimm_params[i].caslat_X_minus_1;
+ temp2 |= 1 << dimm_params[i].caslat_X_minus_2;
+ /*
+ * FIXME: If there was no entry for X-2 (X-1) in
+ * the SPD, then caslat_X_minus_2
+ * (caslat_X_minus_1) contains either 255 or
+ * 0xFFFFFFFF because that's what the glorious
+ * __ilog2 function returns for an input of 0.
+ * On 32-bit PowerPC, left shift counts with bit
+ * 26 set (that the value of 255 or 0xFFFFFFFF
+ * will have), cause the destination register to
+ * be 0. That is why this works.
+ */
+ temp1 &= temp2;
+ }
+ }
+
+ /*
+ * Step 2: check each common CAS latency against tCK of each
+ * DIMM's SPD.
+ */
+ lowest_good_caslat = 0;
+ temp2 = 0;
+ while (temp1) {
+ not_ok = 0;
+ temp2 = __ilog2(temp1);
+ debug("checking common caslat = %u\n", temp2);
+
+ /* Check if this CAS latency will work on all DIMMs at tCK. */
+ for (i = 0; i < number_of_dimms; i++) {
+ if (!dimm_params[i].n_ranks) {
+ continue;
+ }
+ if (dimm_params[i].caslat_X == temp2) {
+ if (mclk_ps >= dimm_params[i].tCKmin_X_ps) {
+ debug("CL = %u ok on DIMM %u at tCK=%u"
+ " ps with its tCKmin_X_ps of %u\n",
+ temp2, i, mclk_ps,
+ dimm_params[i].tCKmin_X_ps);
+ continue;
+ } else {
+ not_ok++;
+ }
+ }
+
+ if (dimm_params[i].caslat_X_minus_1 == temp2) {
+ unsigned int tCKmin_X_minus_1_ps
+ = dimm_params[i].tCKmin_X_minus_1_ps;
+ if (mclk_ps >= tCKmin_X_minus_1_ps) {
+ debug("CL = %u ok on DIMM %u at "
+ "tCK=%u ps with its "
+ "tCKmin_X_minus_1_ps of %u\n",
+ temp2, i, mclk_ps,
+ tCKmin_X_minus_1_ps);
+ continue;
+ } else {
+ not_ok++;
+ }
+ }
+
+ if (dimm_params[i].caslat_X_minus_2 == temp2) {
+ unsigned int tCKmin_X_minus_2_ps
+ = dimm_params[i].tCKmin_X_minus_2_ps;
+ if (mclk_ps >= tCKmin_X_minus_2_ps) {
+ debug("CL = %u ok on DIMM %u at "
+ "tCK=%u ps with its "
+ "tCKmin_X_minus_2_ps of %u\n",
+ temp2, i, mclk_ps,
+ tCKmin_X_minus_2_ps);
+ continue;
+ } else {
+ not_ok++;
+ }
+ }
+ }
+
+ if (!not_ok) {
+ lowest_good_caslat = temp2;
+ }
+
+ temp1 &= ~(1 << temp2);
+ }
+
+ debug("lowest common SPD-defined CAS latency = %u\n",
+ lowest_good_caslat);
+ outpdimm->lowest_common_SPD_caslat = lowest_good_caslat;
+
+
+ /*
+ * Compute a common 'de-rated' CAS latency.
+ *
+ * The strategy here is to find the *highest* dereated cas latency
+ * with the assumption that all of the DIMMs will support a dereated
+ * CAS latency higher than or equal to their lowest dereated value.
+ */
+ temp1 = 0;
+ for (i = 0; i < number_of_dimms; i++) {
+ temp1 = max(temp1, dimm_params[i].caslat_lowest_derated);
+ }
+ outpdimm->highest_common_derated_caslat = temp1;
+ debug("highest common dereated CAS latency = %u\n", temp1);
+#endif /* #if defined(CONFIG_FSL_DDR3) */
+
+ /* Determine if all DIMMs ECC capable. */
+ temp1 = 1;
+ for (i = 0; i < number_of_dimms; i++) {
+ if (dimm_params[i].n_ranks &&
+ !(dimm_params[i].edc_config & EDC_ECC)) {
+ temp1 = 0;
+ break;
+ }
+ }
+ if (temp1) {
+ debug("all DIMMs ECC capable\n");
+ } else {
+ debug("Warning: not all DIMMs ECC capable, cant enable ECC\n");
+ }
+ outpdimm->all_DIMMs_ECC_capable = temp1;
+
+#ifndef CONFIG_FSL_DDR3
+ /* FIXME: move to somewhere else to validate. */
+ if (mclk_ps > tCKmax_max_ps) {
+ printf("Warning: some of the installed DIMMs "
+ "can not operate this slowly.\n");
+ return 1;
+ }
+#endif
+ /*
+ * Compute additive latency.
+ *
+ * For DDR1, additive latency should be 0.
+ *
+ * For DDR2, with ODT enabled, use "a value" less than ACTTORW,
+ * which comes from Trcd, and also note that:
+ * add_lat + caslat must be >= 4
+ *
+ * For DDR3, we use the AL=0
+ *
+ * When to use additive latency for DDR2:
+ *
+ * I. Because you are using CL=3 and need to do ODT on writes and
+ * want functionality.
+ * 1. Are you going to use ODT? (Does your board not have
+ * additional termination circuitry for DQ, DQS, DQS_,
+ * DM, RDQS, RDQS_ for x4/x8 configs?)
+ * 2. If so, is your lowest supported CL going to be 3?
+ * 3. If so, then you must set AL=1 because
+ *
+ * WL >= 3 for ODT on writes
+ * RL = AL + CL
+ * WL = RL - 1
+ * ->
+ * WL = AL + CL - 1
+ * AL + CL - 1 >= 3
+ * AL + CL >= 4
+ * QED
+ *
+ * RL >= 3 for ODT on reads
+ * RL = AL + CL
+ *
+ * Since CL aren't usually less than 2, AL=0 is a minimum,
+ * so the WL-derived AL should be the -- FIXME?
+ *
+ * II. Because you are using auto-precharge globally and want to
+ * use additive latency (posted CAS) to get more bandwidth.
+ * 1. Are you going to use auto-precharge mode globally?
+ *
+ * Use addtivie latency and compute AL to be 1 cycle less than
+ * tRCD, i.e. the READ or WRITE command is in the cycle
+ * immediately following the ACTIVATE command..
+ *
+ * III. Because you feel like it or want to do some sort of
+ * degraded-performance experiment.
+ * 1. Do you just want to use additive latency because you feel
+ * like it?
+ *
+ * Validation: AL is less than tRCD, and within the other
+ * read-to-precharge constraints.
+ */
+
+ additive_latency = 0;
+
+#if defined(CONFIG_FSL_DDR2)
+ if (lowest_good_caslat < 4) {
+ additive_latency = (picos_to_mclk(tRCD_ps) > lowest_good_caslat)
+ ? picos_to_mclk(tRCD_ps) - lowest_good_caslat : 0;
+ if (mclk_to_picos(additive_latency) > tRCD_ps) {
+ additive_latency = picos_to_mclk(tRCD_ps);
+ debug("setting additive_latency to %u because it was "
+ " greater than tRCD_ps\n", additive_latency);
+ }
+ }
+
+#elif defined(CONFIG_FSL_DDR3)
+ /*
+ * The system will not use the global auto-precharge mode.
+ * However, it uses the page mode, so we set AL=0
+ */
+ additive_latency = 0;
+#endif
+
+ /*
+ * Validate additive latency
+ * FIXME: move to somewhere else to validate
+ *
+ * AL <= tRCD(min)
+ */
+ if (mclk_to_picos(additive_latency) > tRCD_ps) {
+ printf("Error: invalid additive latency exceeds tRCD(min).\n");
+ return 1;
+ }
+
+ /*
+ * RL = CL + AL; RL >= 3 for ODT_RD_CFG to be enabled
+ * WL = RL - 1; WL >= 3 for ODT_WL_CFG to be enabled
+ * ADD_LAT (the register) must be set to a value less
+ * than ACTTORW if WL = 1, then AL must be set to 1
+ * RD_TO_PRE (the register) must be set to a minimum
+ * tRTP + AL if AL is nonzero
+ */
+
+ /*
+ * Additive latency will be applied only if the memctl option to
+ * use it.
+ */
+ outpdimm->additive_latency = additive_latency;
+
+ debug("tCKmin_ps = %u\n", outpdimm->tCKmin_X_ps);
+ debug("tRCD_ps = %u\n", outpdimm->tRCD_ps);
+ debug("tRP_ps = %u\n", outpdimm->tRP_ps);
+ debug("tRAS_ps = %u\n", outpdimm->tRAS_ps);
+ debug("tWR_ps = %u\n", outpdimm->tWR_ps);
+ debug("tWTR_ps = %u\n", outpdimm->tWTR_ps);
+ debug("tRFC_ps = %u\n", outpdimm->tRFC_ps);
+ debug("tRRD_ps = %u\n", outpdimm->tRRD_ps);
+ debug("tRC_ps = %u\n", outpdimm->tRC_ps);
+
+ return 0;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
new file mode 100644
index 0000000..7a8636d
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
@@ -0,0 +1,667 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+/*
+ * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
+ * Based on code from spd_sdram.c
+ * Author: James Yang [at freescale.com]
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/fsl_ddr_sdram.h>
+#include <asm/fsl_law.h>
+
+#include "ddr.h"
+
+void fsl_ddr_set_lawbar(
+ const common_timing_params_t *memctl_common_params,
+ unsigned int memctl_interleaved,
+ unsigned int ctrl_num);
+void fsl_ddr_set_intl3r(const unsigned int granule_size);
+
+/* processor specific function */
+extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num);
+
+#if defined(SPD_EEPROM_ADDRESS) || \
+ defined(SPD_EEPROM_ADDRESS1) || defined(SPD_EEPROM_ADDRESS2) || \
+ defined(SPD_EEPROM_ADDRESS3) || defined(SPD_EEPROM_ADDRESS4)
+#if (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+ [0][0] = SPD_EEPROM_ADDRESS,
+};
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 1) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+ [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */
+ [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */
+};
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+ [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */
+ [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */
+};
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 2) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+ [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */
+ [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */
+ [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */
+ [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */
+};
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+ [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */
+ [1][0] = SPD_EEPROM_ADDRESS2, /* controller 2 */
+ [2][0] = SPD_EEPROM_ADDRESS3, /* controller 3 */
+};
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
+ [0][0] = SPD_EEPROM_ADDRESS1, /* controller 1 */
+ [0][1] = SPD_EEPROM_ADDRESS2, /* controller 1 */
+ [1][0] = SPD_EEPROM_ADDRESS3, /* controller 2 */
+ [1][1] = SPD_EEPROM_ADDRESS4, /* controller 2 */
+ [2][0] = SPD_EEPROM_ADDRESS5, /* controller 3 */
+ [2][1] = SPD_EEPROM_ADDRESS6, /* controller 3 */
+};
+
+#endif
+
+static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
+{
+ int ret = i2c_read(i2c_address, 0, 1, (uchar *)spd,
+ sizeof(generic_spd_eeprom_t));
+
+ if (ret) {
+ if (i2c_address ==
+#ifdef SPD_EEPROM_ADDRESS
+ SPD_EEPROM_ADDRESS
+#elif defined(SPD_EEPROM_ADDRESS1)
+ SPD_EEPROM_ADDRESS1
+#endif
+ ) {
+ printf("DDR: failed to read SPD from address %u\n",
+ i2c_address);
+ } else {
+ debug("DDR: failed to read SPD from address %u\n",
+ i2c_address);
+ }
+ memset(spd, 0, sizeof(generic_spd_eeprom_t));
+ }
+}
+
+__attribute__((weak, alias("__get_spd")))
+void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address);
+
+void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ unsigned int i2c_address = 0;
+
+ if (ctrl_num >= CONFIG_NUM_DDR_CONTROLLERS) {
+ printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
+ return;
+ }
+
+ for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
+ i2c_address = spd_i2c_addr[ctrl_num][i];
+ get_spd(&(ctrl_dimms_spd[i]), i2c_address);
+ }
+}
+#else
+void fsl_ddr_get_spd(generic_spd_eeprom_t *ctrl_dimms_spd,
+ unsigned int ctrl_num)
+{
+}
+#endif /* SPD_EEPROM_ADDRESSx */
+
+/*
+ * ASSUMPTIONS:
+ * - Same number of CONFIG_DIMM_SLOTS_PER_CTLR on each controller
+ * - Same memory data bus width on all controllers
+ *
+ * NOTES:
+ *
+ * The memory controller and associated documentation use confusing
+ * terminology when referring to the orgranization of DRAM.
+ *
+ * Here is a terminology translation table:
+ *
+ * memory controller/documention |industry |this code |signals
+ * -------------------------------|-----------|-----------|-----------------
+ * physical bank/bank |rank |rank |chip select (CS)
+ * logical bank/sub-bank |bank |bank |bank address (BA)
+ * page/row |row |page |row address
+ * ??? |column |column |column address
+ *
+ * The naming confusion is further exacerbated by the descriptions of the
+ * memory controller interleaving feature, where accesses are interleaved
+ * _BETWEEN_ two seperate memory controllers. This is configured only in
+ * CS0_CONFIG[INTLV_CTL] of each memory controller.
+ *
+ * memory controller documentation | number of chip selects
+ * | per memory controller supported
+ * --------------------------------|-----------------------------------------
+ * cache line interleaving | 1 (CS0 only)
+ * page interleaving | 1 (CS0 only)
+ * bank interleaving | 1 (CS0 only)
+ * superbank interleraving | depends on bank (chip select)
+ * | interleraving [rank interleaving]
+ * | mode used on every memory controller
+ *
+ * Even further confusing is the existence of the interleaving feature
+ * _WITHIN_ each memory controller. The feature is referred to in
+ * documentation as chip select interleaving or bank interleaving,
+ * although it is configured in the DDR_SDRAM_CFG field.
+ *
+ * Name of field | documentation name | this code
+ * -----------------------------|-----------------------|------------------
+ * DDR_SDRAM_CFG[BA_INTLV_CTL] | Bank (chip select) | rank interleaving
+ * | interleaving
+ */
+
+const char *step_string_tbl[] = {
+ "STEP_GET_SPD",
+ "STEP_COMPUTE_DIMM_PARMS",
+ "STEP_COMPUTE_COMMON_PARMS",
+ "STEP_GATHER_OPTS",
+ "STEP_ASSIGN_ADDRESSES",
+ "STEP_COMPUTE_REGS",
+ "STEP_PROGRAM_REGS",
+ "STEP_ALL"
+};
+
+const char * step_to_string(unsigned int step) {
+
+ unsigned int s = __ilog2(step);
+
+ if ((1 << s) != step)
+ return step_string_tbl[7];
+
+ return step_string_tbl[s];
+}
+
+static unsigned long long __step_assign_addresses(fsl_ddr_info_t *pinfo,
+ unsigned int dbw_cap_adj[])
+{
+ int i, j;
+ unsigned long long total_mem, current_mem_base, total_ctlr_mem;
+ unsigned long long rank_density, ctlr_density = 0;
+
+ /*
+ * If a reduced data width is requested, but the SPD
+ * specifies a physically wider device, adjust the
+ * computed dimm capacities accordingly before
+ * assigning addresses.
+ */
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ unsigned int found = 0;
+
+ switch (pinfo->memctl_opts[i].data_bus_width) {
+ case 2:
+ /* 16-bit */
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ unsigned int dw;
+ if (!pinfo->dimm_params[i][j].n_ranks)
+ continue;
+ dw = pinfo->dimm_params[i][j].primary_sdram_width;
+ if ((dw == 72 || dw == 64)) {
+ dbw_cap_adj[i] = 2;
+ break;
+ } else if ((dw == 40 || dw == 32)) {
+ dbw_cap_adj[i] = 1;
+ break;
+ }
+ }
+ break;
+
+ case 1:
+ /* 32-bit */
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ unsigned int dw;
+ dw = pinfo->dimm_params[i][j].data_width;
+ if (pinfo->dimm_params[i][j].n_ranks
+ && (dw == 72 || dw == 64)) {
+ /*
+ * FIXME: can't really do it
+ * like this because this just
+ * further reduces the memory
+ */
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ dbw_cap_adj[i] = 1;
+ }
+ break;
+
+ case 0:
+ /* 64-bit */
+ break;
+
+ default:
+ printf("unexpected data bus width "
+ "specified controller %u\n", i);
+ return 1;
+ }
+ debug("dbw_cap_adj[%d]=%d\n", i, dbw_cap_adj[i]);
+ }
+
+ current_mem_base = 0ull;
+ total_mem = 0;
+ if (pinfo->memctl_opts[0].memctl_interleaving) {
+ rank_density = pinfo->dimm_params[0][0].rank_density >>
+ dbw_cap_adj[0];
+ switch (pinfo->memctl_opts[0].ba_intlv_ctl &
+ FSL_DDR_CS0_CS1_CS2_CS3) {
+ case FSL_DDR_CS0_CS1_CS2_CS3:
+ ctlr_density = 4 * rank_density;
+ break;
+ case FSL_DDR_CS0_CS1:
+ case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+ ctlr_density = 2 * rank_density;
+ break;
+ case FSL_DDR_CS2_CS3:
+ default:
+ ctlr_density = rank_density;
+ break;
+ }
+ debug("rank density is 0x%llx, ctlr density is 0x%llx\n",
+ rank_density, ctlr_density);
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (pinfo->memctl_opts[i].memctl_interleaving) {
+ switch (pinfo->memctl_opts[i].memctl_interleaving_mode) {
+ case FSL_DDR_CACHE_LINE_INTERLEAVING:
+ case FSL_DDR_PAGE_INTERLEAVING:
+ case FSL_DDR_BANK_INTERLEAVING:
+ case FSL_DDR_SUPERBANK_INTERLEAVING:
+ total_ctlr_mem = 2 * ctlr_density;
+ break;
+ case FSL_DDR_3WAY_1KB_INTERLEAVING:
+ case FSL_DDR_3WAY_4KB_INTERLEAVING:
+ case FSL_DDR_3WAY_8KB_INTERLEAVING:
+ total_ctlr_mem = 3 * ctlr_density;
+ break;
+ case FSL_DDR_4WAY_1KB_INTERLEAVING:
+ case FSL_DDR_4WAY_4KB_INTERLEAVING:
+ case FSL_DDR_4WAY_8KB_INTERLEAVING:
+ total_ctlr_mem = 4 * ctlr_density;
+ break;
+ default:
+ panic("Unknown interleaving mode");
+ }
+ pinfo->common_timing_params[i].base_address =
+ current_mem_base;
+ pinfo->common_timing_params[i].total_mem =
+ total_ctlr_mem;
+ total_mem = current_mem_base + total_ctlr_mem;
+ debug("ctrl %d base 0x%llx\n", i, current_mem_base);
+ debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
+ } else {
+ /* when 3rd controller not interleaved */
+ current_mem_base = total_mem;
+ total_ctlr_mem = 0;
+ pinfo->common_timing_params[i].base_address =
+ current_mem_base;
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ unsigned long long cap =
+ pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i];
+ pinfo->dimm_params[i][j].base_address =
+ current_mem_base;
+ debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base);
+ current_mem_base += cap;
+ total_ctlr_mem += cap;
+ }
+ debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
+ pinfo->common_timing_params[i].total_mem =
+ total_ctlr_mem;
+ total_mem += total_ctlr_mem;
+ }
+ }
+ } else {
+ /*
+ * Simple linear assignment if memory
+ * controllers are not interleaved.
+ */
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ total_ctlr_mem = 0;
+ pinfo->common_timing_params[i].base_address =
+ current_mem_base;
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ /* Compute DIMM base addresses. */
+ unsigned long long cap =
+ pinfo->dimm_params[i][j].capacity >> dbw_cap_adj[i];
+ pinfo->dimm_params[i][j].base_address =
+ current_mem_base;
+ debug("ctrl %d dimm %d base 0x%llx\n", i, j, current_mem_base);
+ current_mem_base += cap;
+ total_ctlr_mem += cap;
+ }
+ debug("ctrl %d total 0x%llx\n", i, total_ctlr_mem);
+ pinfo->common_timing_params[i].total_mem =
+ total_ctlr_mem;
+ total_mem += total_ctlr_mem;
+ }
+ }
+ debug("Total mem by %s is 0x%llx\n", __func__, total_mem);
+
+ return total_mem;
+}
+
+/* Use weak function to allow board file to override the address assignment */
+__attribute__((weak, alias("__step_assign_addresses")))
+unsigned long long step_assign_addresses(fsl_ddr_info_t *pinfo,
+ unsigned int dbw_cap_adj[]);
+
+unsigned long long
+fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
+ unsigned int size_only)
+{
+ unsigned int i, j;
+ unsigned long long total_mem = 0;
+
+ fsl_ddr_cfg_regs_t *ddr_reg = pinfo->fsl_ddr_config_reg;
+ common_timing_params_t *timing_params = pinfo->common_timing_params;
+
+ /* data bus width capacity adjust shift amount */
+ unsigned int dbw_capacity_adjust[CONFIG_NUM_DDR_CONTROLLERS];
+
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ dbw_capacity_adjust[i] = 0;
+ }
+
+ debug("starting at step %u (%s)\n",
+ start_step, step_to_string(start_step));
+
+ switch (start_step) {
+ case STEP_GET_SPD:
+#if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM)
+ /* STEP 1: Gather all DIMM SPD data */
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ fsl_ddr_get_spd(pinfo->spd_installed_dimms[i], i);
+ }
+
+ case STEP_COMPUTE_DIMM_PARMS:
+ /* STEP 2: Compute DIMM parameters from SPD data */
+
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ unsigned int retval;
+ generic_spd_eeprom_t *spd =
+ &(pinfo->spd_installed_dimms[i][j]);
+ dimm_params_t *pdimm =
+ &(pinfo->dimm_params[i][j]);
+
+ retval = compute_dimm_parameters(spd, pdimm, i);
+#ifdef CONFIG_SYS_DDR_RAW_TIMING
+ if (!i && !j && retval) {
+ printf("SPD error on controller %d! "
+ "Trying fallback to raw timing "
+ "calculation\n", i);
+ fsl_ddr_get_dimm_params(pdimm, i, j);
+ }
+#else
+ if (retval == 2) {
+ printf("Error: compute_dimm_parameters"
+ " non-zero returned FATAL value "
+ "for memctl=%u dimm=%u\n", i, j);
+ return 0;
+ }
+#endif
+ if (retval) {
+ debug("Warning: compute_dimm_parameters"
+ " non-zero return value for memctl=%u "
+ "dimm=%u\n", i, j);
+ }
+ }
+ }
+
+#elif defined(CONFIG_SYS_DDR_RAW_TIMING)
+ case STEP_COMPUTE_DIMM_PARMS:
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
+ dimm_params_t *pdimm =
+ &(pinfo->dimm_params[i][j]);
+ fsl_ddr_get_dimm_params(pdimm, i, j);
+ }
+ }
+ debug("Filling dimm parameters from board specific file\n");
+#endif
+ case STEP_COMPUTE_COMMON_PARMS:
+ /*
+ * STEP 3: Compute a common set of timing parameters
+ * suitable for all of the DIMMs on each memory controller
+ */
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ debug("Computing lowest common DIMM"
+ " parameters for memctl=%u\n", i);
+ compute_lowest_common_dimm_parameters(
+ pinfo->dimm_params[i],
+ &timing_params[i],
+ CONFIG_DIMM_SLOTS_PER_CTLR);
+ }
+
+ case STEP_GATHER_OPTS:
+ /* STEP 4: Gather configuration requirements from user */
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ debug("Reloading memory controller "
+ "configuration options for memctl=%u\n", i);
+ /*
+ * This "reloads" the memory controller options
+ * to defaults. If the user "edits" an option,
+ * next_step points to the step after this,
+ * which is currently STEP_ASSIGN_ADDRESSES.
+ */
+ populate_memctl_options(
+ timing_params[i].all_DIMMs_registered,
+ &pinfo->memctl_opts[i],
+ pinfo->dimm_params[i], i);
+ }
+ case STEP_ASSIGN_ADDRESSES:
+ /* STEP 5: Assign addresses to chip selects */
+ check_interleaving_options(pinfo);
+ total_mem = step_assign_addresses(pinfo, dbw_capacity_adjust);
+
+ case STEP_COMPUTE_REGS:
+ /* STEP 6: compute controller register values */
+ debug("FSL Memory ctrl register computation\n");
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (timing_params[i].ndimms_present == 0) {
+ memset(&ddr_reg[i], 0,
+ sizeof(fsl_ddr_cfg_regs_t));
+ continue;
+ }
+
+ compute_fsl_memctl_config_regs(
+ &pinfo->memctl_opts[i],
+ &ddr_reg[i], &timing_params[i],
+ pinfo->dimm_params[i],
+ dbw_capacity_adjust[i],
+ size_only);
+ }
+
+ default:
+ break;
+ }
+
+ {
+ /*
+ * Compute the amount of memory available just by
+ * looking for the highest valid CSn_BNDS value.
+ * This allows us to also experiment with using
+ * only CS0 when using dual-rank DIMMs.
+ */
+ unsigned int max_end = 0;
+
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ for (j = 0; j < CONFIG_CHIP_SELECTS_PER_CTRL; j++) {
+ fsl_ddr_cfg_regs_t *reg = &ddr_reg[i];
+ if (reg->cs[j].config & 0x80000000) {
+ unsigned int end;
+ end = reg->cs[j].bnds & 0xFFF;
+ if (end > max_end) {
+ max_end = end;
+ }
+ }
+ }
+ }
+
+ total_mem = 1 + (((unsigned long long)max_end << 24ULL)
+ | 0xFFFFFFULL);
+ }
+
+ return total_mem;
+}
+
+/*
+ * fsl_ddr_sdram() -- this is the main function to be called by
+ * initdram() in the board file.
+ *
+ * It returns amount of memory configured in bytes.
+ */
+phys_size_t fsl_ddr_sdram(void)
+{
+ unsigned int i;
+ unsigned int law_memctl = LAW_TRGT_IF_DDR_1;
+ unsigned long long total_memory;
+ fsl_ddr_info_t info;
+
+ /* Reset info structure. */
+ memset(&info, 0, sizeof(fsl_ddr_info_t));
+
+ /* Compute it once normally. */
+#ifdef CONFIG_FSL_DDR_INTERACTIVE
+ if (tstc() && (getc() == 'd')) { /* we got a key press of 'd' */
+ total_memory = fsl_ddr_interactive(&info, 0);
+ } else if (fsl_ddr_interactive_env_var_exists()) {
+ total_memory = fsl_ddr_interactive(&info, 1);
+ } else
+#endif
+ total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0);
+
+ /* setup 3-way interleaving before enabling DDRC */
+ if (info.memctl_opts[0].memctl_interleaving) {
+ switch (info.memctl_opts[0].memctl_interleaving_mode) {
+ case FSL_DDR_3WAY_1KB_INTERLEAVING:
+ case FSL_DDR_3WAY_4KB_INTERLEAVING:
+ case FSL_DDR_3WAY_8KB_INTERLEAVING:
+ fsl_ddr_set_intl3r(
+ info.memctl_opts[0].memctl_interleaving_mode);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Program configuration registers. */
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ debug("Programming controller %u\n", i);
+ if (info.common_timing_params[i].ndimms_present == 0) {
+ debug("No dimms present on controller %u; "
+ "skipping programming\n", i);
+ continue;
+ }
+
+ fsl_ddr_set_memctl_regs(&(info.fsl_ddr_config_reg[i]), i);
+ }
+
+ /* program LAWs */
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ if (info.memctl_opts[i].memctl_interleaving) {
+ switch (info.memctl_opts[i].memctl_interleaving_mode) {
+ case FSL_DDR_CACHE_LINE_INTERLEAVING:
+ case FSL_DDR_PAGE_INTERLEAVING:
+ case FSL_DDR_BANK_INTERLEAVING:
+ case FSL_DDR_SUPERBANK_INTERLEAVING:
+ if (i == 0) {
+ law_memctl = LAW_TRGT_IF_DDR_INTRLV;
+ fsl_ddr_set_lawbar(&info.common_timing_params[i],
+ law_memctl, i);
+ } else if (i == 2) {
+ law_memctl = LAW_TRGT_IF_DDR_INTLV_34;
+ fsl_ddr_set_lawbar(&info.common_timing_params[i],
+ law_memctl, i);
+ }
+ break;
+ case FSL_DDR_3WAY_1KB_INTERLEAVING:
+ case FSL_DDR_3WAY_4KB_INTERLEAVING:
+ case FSL_DDR_3WAY_8KB_INTERLEAVING:
+ law_memctl = LAW_TRGT_IF_DDR_INTLV_123;
+ if (i == 0) {
+ fsl_ddr_set_lawbar(&info.common_timing_params[i],
+ law_memctl, i);
+ }
+ break;
+ case FSL_DDR_4WAY_1KB_INTERLEAVING:
+ case FSL_DDR_4WAY_4KB_INTERLEAVING:
+ case FSL_DDR_4WAY_8KB_INTERLEAVING:
+ law_memctl = LAW_TRGT_IF_DDR_INTLV_1234;
+ if (i == 0)
+ fsl_ddr_set_lawbar(&info.common_timing_params[i],
+ law_memctl, i);
+ /* place holder for future 4-way interleaving */
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (i) {
+ case 0:
+ law_memctl = LAW_TRGT_IF_DDR_1;
+ break;
+ case 1:
+ law_memctl = LAW_TRGT_IF_DDR_2;
+ break;
+ case 2:
+ law_memctl = LAW_TRGT_IF_DDR_3;
+ break;
+ case 3:
+ law_memctl = LAW_TRGT_IF_DDR_4;
+ break;
+ default:
+ break;
+ }
+ fsl_ddr_set_lawbar(&info.common_timing_params[i],
+ law_memctl, i);
+ }
+ }
+
+ debug("total_memory by %s = %llu\n", __func__, total_memory);
+
+#if !defined(CONFIG_PHYS_64BIT)
+ /* Check for 4G or more. Bad. */
+ if (total_memory >= (1ull << 32)) {
+ printf("Detected %lld MB of memory\n", total_memory >> 20);
+ printf(" This U-Boot only supports < 4G of DDR\n");
+ printf(" You could rebuild it with CONFIG_PHYS_64BIT\n");
+ printf(" "); /* re-align to match init_func_ram print */
+ total_memory = CONFIG_MAX_MEM_MAPPED;
+ }
+#endif
+
+ return total_memory;
+}
+
+/*
+ * fsl_ddr_sdram_size() - This function only returns the size of the total
+ * memory without setting ddr control registers.
+ */
+phys_size_t
+fsl_ddr_sdram_size(void)
+{
+ fsl_ddr_info_t info;
+ unsigned long long total_memory = 0;
+
+ memset(&info, 0 , sizeof(fsl_ddr_info_t));
+
+ /* Compute it once normally. */
+ total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 1);
+
+ return total_memory;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/options.c b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
new file mode 100644
index 0000000..2f13b8f
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/options.c
@@ -0,0 +1,1148 @@
+/*
+ * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <common.h>
+#include <hwconfig.h>
+#include <asm/fsl_ddr_sdram.h>
+
+#include "ddr.h"
+
+/*
+ * Use our own stack based buffer before relocation to allow accessing longer
+ * hwconfig strings that might be in the environment before we've relocated.
+ * This is pretty fragile on both the use of stack and if the buffer is big
+ * enough. However we will get a warning from getenv_f for the later.
+ */
+
+/* Board-specific functions defined in each board's ddr.c */
+extern void fsl_ddr_board_options(memctl_options_t *popts,
+ dimm_params_t *pdimm,
+ unsigned int ctrl_num);
+
+struct dynamic_odt {
+ unsigned int odt_rd_cfg;
+ unsigned int odt_wr_cfg;
+ unsigned int odt_rtt_norm;
+ unsigned int odt_rtt_wr;
+};
+
+#ifdef CONFIG_FSL_DDR3
+static const struct dynamic_odt single_Q[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS_AND_OTHER_DIMM,
+ DDR3_RTT_20_OHM,
+ DDR3_RTT_120_OHM
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER, /* tied high */
+ DDR3_RTT_OFF,
+ DDR3_RTT_120_OHM
+ },
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS_AND_OTHER_DIMM,
+ DDR3_RTT_20_OHM,
+ DDR3_RTT_120_OHM
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER, /* tied high */
+ DDR3_RTT_OFF,
+ DDR3_RTT_120_OHM
+ }
+};
+
+static const struct dynamic_odt single_D[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_ALL,
+ DDR3_RTT_40_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR3_RTT_OFF,
+ DDR3_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt single_S[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_ALL,
+ DDR3_RTT_40_OHM,
+ DDR3_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+};
+
+static const struct dynamic_odt dual_DD[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_SAME_DIMM,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR3_RTT_30_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_SAME_DIMM,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR3_RTT_30_OHM,
+ DDR3_RTT_OFF
+ }
+};
+
+static const struct dynamic_odt dual_DS[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_SAME_DIMM,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR3_RTT_30_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs2 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_ALL,
+ DDR3_RTT_20_OHM,
+ DDR3_RTT_120_OHM
+ },
+ {0, 0, 0, 0}
+};
+static const struct dynamic_odt dual_SD[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_ALL,
+ DDR3_RTT_20_OHM,
+ DDR3_RTT_120_OHM
+ },
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_SAME_DIMM,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR3_RTT_20_OHM,
+ DDR3_RTT_OFF
+ }
+};
+
+static const struct dynamic_odt dual_SS[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_ALL,
+ DDR3_RTT_30_OHM,
+ DDR3_RTT_120_OHM
+ },
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_ALL,
+ DDR3_RTT_30_OHM,
+ DDR3_RTT_120_OHM
+ },
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt dual_D0[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_SAME_DIMM,
+ DDR3_RTT_40_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR3_RTT_OFF,
+ DDR3_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt dual_0D[4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_SAME_DIMM,
+ DDR3_RTT_40_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR3_RTT_OFF,
+ DDR3_RTT_OFF
+ }
+};
+
+static const struct dynamic_odt dual_S0[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR3_RTT_40_OHM,
+ DDR3_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+
+};
+
+static const struct dynamic_odt dual_0S[4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR3_RTT_40_OHM,
+ DDR3_RTT_OFF
+ },
+ {0, 0, 0, 0}
+
+};
+
+static const struct dynamic_odt odt_unknown[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR3_RTT_120_OHM,
+ DDR3_RTT_OFF
+ }
+};
+#else /* CONFIG_FSL_DDR3 */
+static const struct dynamic_odt single_Q[4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt single_D[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_ALL,
+ DDR2_RTT_150_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt single_S[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_ALL,
+ DDR2_RTT_150_OHM,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+};
+
+static const struct dynamic_odt dual_DD[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ },
+ { /* cs2 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ }
+};
+
+static const struct dynamic_odt dual_DS[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ },
+ { /* cs2 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt dual_SD[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ }
+};
+
+static const struct dynamic_odt dual_SS[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_OTHER_DIMM,
+ FSL_DDR_ODT_OTHER_DIMM,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt dual_D0[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_ALL,
+ DDR2_RTT_150_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+static const struct dynamic_odt dual_0D[4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_ALL,
+ DDR2_RTT_150_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ }
+};
+
+static const struct dynamic_odt dual_S0[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR2_RTT_150_OHM,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+
+};
+
+static const struct dynamic_odt dual_0S[4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR2_RTT_150_OHM,
+ DDR2_RTT_OFF
+ },
+ {0, 0, 0, 0}
+
+};
+
+static const struct dynamic_odt odt_unknown[4] = {
+ { /* cs0 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs1 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ },
+ { /* cs2 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_CS,
+ DDR2_RTT_75_OHM,
+ DDR2_RTT_OFF
+ },
+ { /* cs3 */
+ FSL_DDR_ODT_NEVER,
+ FSL_DDR_ODT_NEVER,
+ DDR2_RTT_OFF,
+ DDR2_RTT_OFF
+ }
+};
+#endif
+
+/*
+ * Automatically seleect bank interleaving mode based on DIMMs
+ * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null.
+ * This function only deal with one or two slots per controller.
+ */
+static inline unsigned int auto_bank_intlv(dimm_params_t *pdimm)
+{
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+ if (pdimm[0].n_ranks == 4)
+ return FSL_DDR_CS0_CS1_CS2_CS3;
+ else if (pdimm[0].n_ranks == 2)
+ return FSL_DDR_CS0_CS1;
+#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ if (pdimm[0].n_ranks == 4)
+ return FSL_DDR_CS0_CS1_CS2_CS3;
+#endif
+ if (pdimm[0].n_ranks == 2) {
+ if (pdimm[1].n_ranks == 2)
+ return FSL_DDR_CS0_CS1_CS2_CS3;
+ else
+ return FSL_DDR_CS0_CS1;
+ }
+#endif
+ return 0;
+}
+
+unsigned int populate_memctl_options(int all_DIMMs_registered,
+ memctl_options_t *popts,
+ dimm_params_t *pdimm,
+ unsigned int ctrl_num)
+{
+ unsigned int i;
+ char buffer[HWCONFIG_BUFFER_SIZE];
+ char *buf = NULL;
+#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
+ const struct dynamic_odt *pdodt = odt_unknown;
+#endif
+ ulong ddr_freq;
+
+ /*
+ * Extract hwconfig from environment since we have not properly setup
+ * the environment but need it for ddr config params
+ */
+ if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
+ buf = buffer;
+
+#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
+ /* Chip select options. */
+ if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
+ switch (pdimm[0].n_ranks) {
+ case 1:
+ pdodt = single_S;
+ break;
+ case 2:
+ pdodt = single_D;
+ break;
+ case 4:
+ pdodt = single_Q;
+ break;
+ }
+ } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
+ switch (pdimm[0].n_ranks) {
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ case 4:
+ pdodt = single_Q;
+ if (pdimm[1].n_ranks)
+ printf("Error: Quad- and Dual-rank DIMMs "
+ "cannot be used together\n");
+ break;
+#endif
+ case 2:
+ switch (pdimm[1].n_ranks) {
+ case 2:
+ pdodt = dual_DD;
+ break;
+ case 1:
+ pdodt = dual_DS;
+ break;
+ case 0:
+ pdodt = dual_D0;
+ break;
+ }
+ break;
+ case 1:
+ switch (pdimm[1].n_ranks) {
+ case 2:
+ pdodt = dual_SD;
+ break;
+ case 1:
+ pdodt = dual_SS;
+ break;
+ case 0:
+ pdodt = dual_S0;
+ break;
+ }
+ break;
+ case 0:
+ switch (pdimm[1].n_ranks) {
+ case 2:
+ pdodt = dual_0D;
+ break;
+ case 1:
+ pdodt = dual_0S;
+ break;
+ }
+ break;
+ }
+ }
+#endif
+
+ /* Pick chip-select local options. */
+ for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+#if defined(CONFIG_FSL_DDR3) || defined(CONFIG_FSL_DDR2)
+ popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
+ popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
+ popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
+ popts->cs_local_opts[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
+#else
+ popts->cs_local_opts[i].odt_rd_cfg = FSL_DDR_ODT_NEVER;
+ popts->cs_local_opts[i].odt_wr_cfg = FSL_DDR_ODT_CS;
+#endif
+ popts->cs_local_opts[i].auto_precharge = 0;
+ }
+
+ /* Pick interleaving mode. */
+
+ /*
+ * 0 = no interleaving
+ * 1 = interleaving between 2 controllers
+ */
+ popts->memctl_interleaving = 0;
+
+ /*
+ * 0 = cacheline
+ * 1 = page
+ * 2 = (logical) bank
+ * 3 = superbank (only if CS interleaving is enabled)
+ */
+ popts->memctl_interleaving_mode = 0;
+
+ /*
+ * 0: cacheline: bit 30 of the 36-bit physical addr selects the memctl
+ * 1: page: bit to the left of the column bits selects the memctl
+ * 2: bank: bit to the left of the bank bits selects the memctl
+ * 3: superbank: bit to the left of the chip select selects the memctl
+ *
+ * NOTE: ba_intlv (rank interleaving) is independent of memory
+ * controller interleaving; it is only within a memory controller.
+ * Must use superbank interleaving if rank interleaving is used and
+ * memory controller interleaving is enabled.
+ */
+
+ /*
+ * 0 = no
+ * 0x40 = CS0,CS1
+ * 0x20 = CS2,CS3
+ * 0x60 = CS0,CS1 + CS2,CS3
+ * 0x04 = CS0,CS1,CS2,CS3
+ */
+ popts->ba_intlv_ctl = 0;
+
+ /* Memory Organization Parameters */
+ popts->registered_dimm_en = all_DIMMs_registered;
+
+ /* Operational Mode Paramters */
+
+ /* Pick ECC modes */
+ popts->ECC_mode = 0; /* 0 = disabled, 1 = enabled */
+#ifdef CONFIG_DDR_ECC
+ if (hwconfig_sub_f("fsl_ddr", "ecc", buf)) {
+ if (hwconfig_subarg_cmp_f("fsl_ddr", "ecc", "on", buf))
+ popts->ECC_mode = 1;
+ } else
+ popts->ECC_mode = 1;
+#endif
+ popts->ECC_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
+
+ /*
+ * Choose DQS config
+ * 0 for DDR1
+ * 1 for DDR2
+ */
+#if defined(CONFIG_FSL_DDR1)
+ popts->DQS_config = 0;
+#elif defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3)
+ popts->DQS_config = 1;
+#endif
+
+ /* Choose self-refresh during sleep. */
+ popts->self_refresh_in_sleep = 1;
+
+ /* Choose dynamic power management mode. */
+ popts->dynamic_power = 0;
+
+ /*
+ * check first dimm for primary sdram width
+ * presuming all dimms are similar
+ * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
+ */
+#if defined(CONFIG_FSL_DDR1) || defined(CONFIG_FSL_DDR2)
+ if (pdimm[0].n_ranks != 0) {
+ if ((pdimm[0].data_width >= 64) && \
+ (pdimm[0].data_width <= 72))
+ popts->data_bus_width = 0;
+ else if ((pdimm[0].data_width >= 32) || \
+ (pdimm[0].data_width <= 40))
+ popts->data_bus_width = 1;
+ else {
+ panic("Error: data width %u is invalid!\n",
+ pdimm[0].data_width);
+ }
+ }
+#else
+ if (pdimm[0].n_ranks != 0) {
+ if (pdimm[0].primary_sdram_width == 64)
+ popts->data_bus_width = 0;
+ else if (pdimm[0].primary_sdram_width == 32)
+ popts->data_bus_width = 1;
+ else if (pdimm[0].primary_sdram_width == 16)
+ popts->data_bus_width = 2;
+ else {
+ panic("Error: primary sdram width %u is invalid!\n",
+ pdimm[0].primary_sdram_width);
+ }
+ }
+#endif
+
+ /* Choose burst length. */
+#if defined(CONFIG_FSL_DDR3)
+#if defined(CONFIG_E500MC)
+ popts->OTF_burst_chop_en = 0; /* on-the-fly burst chop disable */
+ popts->burst_length = DDR_BL8; /* Fixed 8-beat burst len */
+#else
+ if ((popts->data_bus_width == 1) || (popts->data_bus_width == 2)) {
+ /* 32-bit or 16-bit bus */
+ popts->OTF_burst_chop_en = 0;
+ popts->burst_length = DDR_BL8;
+ } else {
+ popts->OTF_burst_chop_en = 1; /* on-the-fly burst chop */
+ popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */
+ }
+#endif
+#else
+ popts->burst_length = DDR_BL4; /* has to be 4 for DDR2 */
+#endif
+
+ /* Choose ddr controller address mirror mode */
+#if defined(CONFIG_FSL_DDR3)
+ popts->mirrored_dimm = pdimm[0].mirrored_dimm;
+#endif
+
+ /* Global Timing Parameters. */
+ debug("mclk_ps = %u ps\n", get_memory_clk_period_ps());
+
+ /* Pick a caslat override. */
+ popts->cas_latency_override = 0;
+ popts->cas_latency_override_value = 3;
+ if (popts->cas_latency_override) {
+ debug("using caslat override value = %u\n",
+ popts->cas_latency_override_value);
+ }
+
+ /* Decide whether to use the computed derated latency */
+ popts->use_derated_caslat = 0;
+
+ /* Choose an additive latency. */
+ popts->additive_latency_override = 0;
+ popts->additive_latency_override_value = 3;
+ if (popts->additive_latency_override) {
+ debug("using additive latency override value = %u\n",
+ popts->additive_latency_override_value);
+ }
+
+ /*
+ * 2T_EN setting
+ *
+ * Factors to consider for 2T_EN:
+ * - number of DIMMs installed
+ * - number of components, number of active ranks
+ * - how much time you want to spend playing around
+ */
+ popts->twoT_en = 0;
+ popts->threeT_en = 0;
+
+ /* for RDIMM, address parity enable */
+ popts->ap_en = 1;
+
+ /*
+ * BSTTOPRE precharge interval
+ *
+ * Set this to 0 for global auto precharge
+ *
+ * FIXME: Should this be configured in picoseconds?
+ * Why it should be in ps: better understanding of this
+ * relative to actual DRAM timing parameters such as tRAS.
+ * e.g. tRAS(min) = 40 ns
+ */
+ popts->bstopre = 0x100;
+
+ /* Minimum CKE pulse width -- tCKE(MIN) */
+ popts->tCKE_clock_pulse_width_ps
+ = mclk_to_picos(FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR);
+
+ /*
+ * Window for four activates -- tFAW
+ *
+ * FIXME: UM: applies only to DDR2/DDR3 with eight logical banks only
+ * FIXME: varies depending upon number of column addresses or data
+ * FIXME: width, was considering looking at pdimm->primary_sdram_width
+ */
+#if defined(CONFIG_FSL_DDR1)
+ popts->tFAW_window_four_activates_ps = mclk_to_picos(1);
+
+#elif defined(CONFIG_FSL_DDR2)
+ /*
+ * x4/x8; some datasheets have 35000
+ * x16 wide columns only? Use 50000?
+ */
+ popts->tFAW_window_four_activates_ps = 37500;
+
+#elif defined(CONFIG_FSL_DDR3)
+ popts->tFAW_window_four_activates_ps = pdimm[0].tFAW_ps;
+#endif
+ popts->zq_en = 0;
+ popts->wrlvl_en = 0;
+#if defined(CONFIG_FSL_DDR3)
+ /*
+ * due to ddr3 dimm is fly-by topology
+ * we suggest to enable write leveling to
+ * meet the tQDSS under different loading.
+ */
+ popts->wrlvl_en = 1;
+ popts->zq_en = 1;
+ popts->wrlvl_override = 0;
+#endif
+
+ /*
+ * Check interleaving configuration from environment.
+ * Please refer to doc/README.fsl-ddr for the detail.
+ *
+ * If memory controller interleaving is enabled, then the data
+ * bus widths must be programmed identically for all memory controllers.
+ *
+ * XXX: Attempt to set all controllers to the same chip select
+ * interleaving mode. It will do a best effort to get the
+ * requested ranks interleaved together such that the result
+ * should be a subset of the requested configuration.
+ */
+#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
+ if (!hwconfig_sub_f("fsl_ddr", "ctlr_intlv", buf))
+ goto done;
+
+ if (pdimm[0].n_ranks == 0) {
+ printf("There is no rank on CS0 for controller %d.\n", ctrl_num);
+ popts->memctl_interleaving = 0;
+ goto done;
+ }
+ popts->memctl_interleaving = 1;
+ /*
+ * test null first. if CONFIG_HWCONFIG is not defined
+ * hwconfig_arg_cmp returns non-zero
+ */
+ if (hwconfig_subarg_cmp_f("fsl_ddr", "ctlr_intlv",
+ "null", buf)) {
+ popts->memctl_interleaving = 0;
+ debug("memory controller interleaving disabled.\n");
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "cacheline", buf)) {
+ popts->memctl_interleaving_mode =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : FSL_DDR_CACHE_LINE_INTERLEAVING;
+ popts->memctl_interleaving =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : 1;
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "page", buf)) {
+ popts->memctl_interleaving_mode =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : FSL_DDR_PAGE_INTERLEAVING;
+ popts->memctl_interleaving =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : 1;
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "bank", buf)) {
+ popts->memctl_interleaving_mode =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : FSL_DDR_BANK_INTERLEAVING;
+ popts->memctl_interleaving =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : 1;
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "superbank", buf)) {
+ popts->memctl_interleaving_mode =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : FSL_DDR_SUPERBANK_INTERLEAVING;
+ popts->memctl_interleaving =
+ ((CONFIG_NUM_DDR_CONTROLLERS == 3) && ctrl_num == 2) ?
+ 0 : 1;
+#if (CONFIG_NUM_DDR_CONTROLLERS == 3)
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "3way_1KB", buf)) {
+ popts->memctl_interleaving_mode =
+ FSL_DDR_3WAY_1KB_INTERLEAVING;
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "3way_4KB", buf)) {
+ popts->memctl_interleaving_mode =
+ FSL_DDR_3WAY_4KB_INTERLEAVING;
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "3way_8KB", buf)) {
+ popts->memctl_interleaving_mode =
+ FSL_DDR_3WAY_8KB_INTERLEAVING;
+#elif (CONFIG_NUM_DDR_CONTROLLERS == 4)
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "4way_1KB", buf)) {
+ popts->memctl_interleaving_mode =
+ FSL_DDR_4WAY_1KB_INTERLEAVING;
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "4way_4KB", buf)) {
+ popts->memctl_interleaving_mode =
+ FSL_DDR_4WAY_4KB_INTERLEAVING;
+ } else if (hwconfig_subarg_cmp_f("fsl_ddr",
+ "ctlr_intlv",
+ "4way_8KB", buf)) {
+ popts->memctl_interleaving_mode =
+ FSL_DDR_4WAY_8KB_INTERLEAVING;
+#endif
+ } else {
+ popts->memctl_interleaving = 0;
+ printf("hwconfig has unrecognized parameter for ctlr_intlv.\n");
+ }
+done:
+#endif
+ if ((hwconfig_sub_f("fsl_ddr", "bank_intlv", buf)) &&
+ (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
+ /* test null first. if CONFIG_HWCONFIG is not defined,
+ * hwconfig_subarg_cmp_f returns non-zero */
+ if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
+ "null", buf))
+ debug("bank interleaving disabled.\n");
+ else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
+ "cs0_cs1", buf))
+ popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
+ else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
+ "cs2_cs3", buf))
+ popts->ba_intlv_ctl = FSL_DDR_CS2_CS3;
+ else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
+ "cs0_cs1_and_cs2_cs3", buf))
+ popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3;
+ else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
+ "cs0_cs1_cs2_cs3", buf))
+ popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;
+ else if (hwconfig_subarg_cmp_f("fsl_ddr", "bank_intlv",
+ "auto", buf))
+ popts->ba_intlv_ctl = auto_bank_intlv(pdimm);
+ else
+ printf("hwconfig has unrecognized parameter for bank_intlv.\n");
+ switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
+ case FSL_DDR_CS0_CS1_CS2_CS3:
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+ if (pdimm[0].n_ranks < 4) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not enough bank(chip-select) for "
+ "CS0+CS1+CS2+CS3 on controller %d, "
+ "interleaving disabled!\n", ctrl_num);
+ }
+#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+#ifdef CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE
+ if (pdimm[0].n_ranks == 4)
+ break;
+#endif
+ if ((pdimm[0].n_ranks < 2) && (pdimm[1].n_ranks < 2)) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not enough bank(chip-select) for "
+ "CS0+CS1+CS2+CS3 on controller %d, "
+ "interleaving disabled!\n", ctrl_num);
+ }
+ if (pdimm[0].capacity != pdimm[1].capacity) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not identical DIMM size for "
+ "CS0+CS1+CS2+CS3 on controller %d, "
+ "interleaving disabled!\n", ctrl_num);
+ }
+#endif
+ break;
+ case FSL_DDR_CS0_CS1:
+ if (pdimm[0].n_ranks < 2) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not enough bank(chip-select) for "
+ "CS0+CS1 on controller %d, "
+ "interleaving disabled!\n", ctrl_num);
+ }
+ break;
+ case FSL_DDR_CS2_CS3:
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+ if (pdimm[0].n_ranks < 4) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not enough bank(chip-select) for CS2+CS3 "
+ "on controller %d, interleaving disabled!\n", ctrl_num);
+ }
+#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+ if (pdimm[1].n_ranks < 2) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not enough bank(chip-select) for CS2+CS3 "
+ "on controller %d, interleaving disabled!\n", ctrl_num);
+ }
+#endif
+ break;
+ case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+#if (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
+ if (pdimm[0].n_ranks < 4) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not enough bank(CS) for CS0+CS1 and "
+ "CS2+CS3 on controller %d, "
+ "interleaving disabled!\n", ctrl_num);
+ }
+#elif (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
+ if ((pdimm[0].n_ranks < 2) || (pdimm[1].n_ranks < 2)) {
+ popts->ba_intlv_ctl = 0;
+ printf("Not enough bank(CS) for CS0+CS1 and "
+ "CS2+CS3 on controller %d, "
+ "interleaving disabled!\n", ctrl_num);
+ }
+#endif
+ break;
+ default:
+ popts->ba_intlv_ctl = 0;
+ break;
+ }
+ }
+
+ if (hwconfig_sub_f("fsl_ddr", "addr_hash", buf)) {
+ if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash", "null", buf))
+ popts->addr_hash = 0;
+ else if (hwconfig_subarg_cmp_f("fsl_ddr", "addr_hash",
+ "true", buf))
+ popts->addr_hash = 1;
+ }
+
+ if (pdimm[0].n_ranks == 4)
+ popts->quad_rank_present = 1;
+
+ ddr_freq = get_ddr_freq(0) / 1000000;
+ if (popts->registered_dimm_en) {
+ popts->rcw_override = 1;
+ popts->rcw_1 = 0x000a5a00;
+ if (ddr_freq <= 800)
+ popts->rcw_2 = 0x00000000;
+ else if (ddr_freq <= 1066)
+ popts->rcw_2 = 0x00100000;
+ else if (ddr_freq <= 1333)
+ popts->rcw_2 = 0x00200000;
+ else
+ popts->rcw_2 = 0x00300000;
+ }
+
+ fsl_ddr_board_options(popts, pdimm, ctrl_num);
+
+ return 0;
+}
+
+void check_interleaving_options(fsl_ddr_info_t *pinfo)
+{
+ int i, j, k, check_n_ranks, intlv_invalid = 0;
+ unsigned int check_intlv, check_n_row_addr, check_n_col_addr;
+ unsigned long long check_rank_density;
+ struct dimm_params_s *dimm;
+ /*
+ * Check if all controllers are configured for memory
+ * controller interleaving. Identical dimms are recommended. At least
+ * the size, row and col address should be checked.
+ */
+ j = 0;
+ check_n_ranks = pinfo->dimm_params[0][0].n_ranks;
+ check_rank_density = pinfo->dimm_params[0][0].rank_density;
+ check_n_row_addr = pinfo->dimm_params[0][0].n_row_addr;
+ check_n_col_addr = pinfo->dimm_params[0][0].n_col_addr;
+ check_intlv = pinfo->memctl_opts[0].memctl_interleaving_mode;
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
+ dimm = &pinfo->dimm_params[i][0];
+ if (!pinfo->memctl_opts[i].memctl_interleaving) {
+ continue;
+ } else if (((check_rank_density != dimm->rank_density) ||
+ (check_n_ranks != dimm->n_ranks) ||
+ (check_n_row_addr != dimm->n_row_addr) ||
+ (check_n_col_addr != dimm->n_col_addr) ||
+ (check_intlv !=
+ pinfo->memctl_opts[i].memctl_interleaving_mode))){
+ intlv_invalid = 1;
+ break;
+ } else {
+ j++;
+ }
+
+ }
+ if (intlv_invalid) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
+ pinfo->memctl_opts[i].memctl_interleaving = 0;
+ printf("Not all DIMMs are identical. "
+ "Memory controller interleaving disabled.\n");
+ } else {
+ switch (check_intlv) {
+ case FSL_DDR_CACHE_LINE_INTERLEAVING:
+ case FSL_DDR_PAGE_INTERLEAVING:
+ case FSL_DDR_BANK_INTERLEAVING:
+ case FSL_DDR_SUPERBANK_INTERLEAVING:
+ if (3 == CONFIG_NUM_DDR_CONTROLLERS)
+ k = 2;
+ else
+ k = CONFIG_NUM_DDR_CONTROLLERS;
+ break;
+ case FSL_DDR_3WAY_1KB_INTERLEAVING:
+ case FSL_DDR_3WAY_4KB_INTERLEAVING:
+ case FSL_DDR_3WAY_8KB_INTERLEAVING:
+ case FSL_DDR_4WAY_1KB_INTERLEAVING:
+ case FSL_DDR_4WAY_4KB_INTERLEAVING:
+ case FSL_DDR_4WAY_8KB_INTERLEAVING:
+ default:
+ k = CONFIG_NUM_DDR_CONTROLLERS;
+ break;
+ }
+ debug("%d of %d controllers are interleaving.\n", j, k);
+ if (j && (j != k)) {
+ for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++)
+ pinfo->memctl_opts[i].memctl_interleaving = 0;
+ printf("Not all controllers have compatible "
+ "interleaving mode. All disabled.\n");
+ }
+ }
+ debug("Checking interleaving options completed\n");
+}
+
+int fsl_use_spd(void)
+{
+ int use_spd = 0;
+
+#ifdef CONFIG_DDR_SPD
+ char buffer[HWCONFIG_BUFFER_SIZE];
+ char *buf = NULL;
+
+ /*
+ * Extract hwconfig from environment since we have not properly setup
+ * the environment but need it for ddr config params
+ */
+ if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
+ buf = buffer;
+
+ /* if hwconfig is not enabled, or "sdram" is not defined, use spd */
+ if (hwconfig_sub_f("fsl_ddr", "sdram", buf)) {
+ if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram", "spd", buf))
+ use_spd = 1;
+ else if (hwconfig_subarg_cmp_f("fsl_ddr", "sdram",
+ "fixed", buf))
+ use_spd = 0;
+ else
+ use_spd = 1;
+ } else
+ use_spd = 1;
+#endif
+
+ return use_spd;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
new file mode 100644
index 0000000..acfe1f0
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_law.h>
+#include <div64.h>
+
+#include "ddr.h"
+
+/* To avoid 64-bit full-divides, we factor this here */
+#define ULL_2E12 2000000000000ULL
+#define UL_5POW12 244140625UL
+#define UL_2POW13 (1UL << 13)
+
+#define ULL_8FS 0xFFFFFFFFULL
+
+/*
+ * Round up mclk_ps to nearest 1 ps in memory controller code
+ * if the error is 0.5ps or more.
+ *
+ * If an imprecise data rate is too high due to rounding error
+ * propagation, compute a suitably rounded mclk_ps to compute
+ * a working memory controller configuration.
+ */
+unsigned int get_memory_clk_period_ps(void)
+{
+ unsigned int data_rate = get_ddr_freq(0);
+ unsigned int result;
+
+ /* Round to nearest 10ps, being careful about 64-bit multiply/divide */
+ unsigned long long rem, mclk_ps = ULL_2E12;
+
+ /* Now perform the big divide, the result fits in 32-bits */
+ rem = do_div(mclk_ps, data_rate);
+ result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps;
+
+ return result;
+}
+
+/* Convert picoseconds into DRAM clock cycles (rounding up if needed). */
+unsigned int picos_to_mclk(unsigned int picos)
+{
+ unsigned long long clks, clks_rem;
+ unsigned long data_rate = get_ddr_freq(0);
+
+ /* Short circuit for zero picos */
+ if (!picos)
+ return 0;
+
+ /* First multiply the time by the data rate (32x32 => 64) */
+ clks = picos * (unsigned long long)data_rate;
+ /*
+ * Now divide by 5^12 and track the 32-bit remainder, then divide
+ * by 2*(2^12) using shifts (and updating the remainder).
+ */
+ clks_rem = do_div(clks, UL_5POW12);
+ clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12;
+ clks >>= 13;
+
+ /* If we had a remainder greater than the 1ps error, then round up */
+ if (clks_rem > data_rate)
+ clks++;
+
+ /* Clamp to the maximum representable value */
+ if (clks > ULL_8FS)
+ clks = ULL_8FS;
+ return (unsigned int) clks;
+}
+
+unsigned int mclk_to_picos(unsigned int mclk)
+{
+ return get_memory_clk_period_ps() * mclk;
+}
+
+void
+__fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
+ unsigned int law_memctl,
+ unsigned int ctrl_num)
+{
+ unsigned long long base = memctl_common_params->base_address;
+ unsigned long long size = memctl_common_params->total_mem;
+
+ /*
+ * If no DIMMs on this controller, do not proceed any further.
+ */
+ if (!memctl_common_params->ndimms_present) {
+ return;
+ }
+
+#if !defined(CONFIG_PHYS_64BIT)
+ if (base >= CONFIG_MAX_MEM_MAPPED)
+ return;
+ if ((base + size) >= CONFIG_MAX_MEM_MAPPED)
+ size = CONFIG_MAX_MEM_MAPPED - base;
+#endif
+ if (set_ddr_laws(base, size, law_memctl) < 0) {
+ printf("%s: ERROR (ctrl #%d, TRGT ID=%x)\n", __func__, ctrl_num,
+ law_memctl);
+ return ;
+ }
+ debug("setup ddr law base = 0x%llx, size 0x%llx, TRGT_ID 0x%x\n",
+ base, size, law_memctl);
+}
+
+__attribute__((weak, alias("__fsl_ddr_set_lawbar"))) void
+fsl_ddr_set_lawbar(const common_timing_params_t *memctl_common_params,
+ unsigned int memctl_interleaved,
+ unsigned int ctrl_num);
+
+void fsl_ddr_set_intl3r(const unsigned int granule_size)
+{
+#ifdef CONFIG_E6500
+ u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004);
+ *mcintl3r = 0x80000000 | (granule_size & 0x1f);
+ debug("Enable MCINTL3R with granule size 0x%x\n", granule_size);
+#endif
+}
+
+u32 fsl_ddr_get_intl3r(void)
+{
+ u32 val = 0;
+#ifdef CONFIG_E6500
+ u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004);
+ val = *mcintl3r;
+#endif
+ return val;
+}
+
+void board_add_ram_info(int use_default)
+{
+ ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR);
+
+#if defined(CONFIG_E6500) && (CONFIG_NUM_DDR_CONTROLLERS == 3)
+ u32 *mcintl3r = (void *) (CONFIG_SYS_IMMR + 0x18004);
+#endif
+#if (CONFIG_NUM_DDR_CONTROLLERS > 1)
+ uint32_t cs0_config = in_be32(&ddr->cs0_config);
+#endif
+ uint32_t sdram_cfg = in_be32(&ddr->sdram_cfg);
+ int cas_lat;
+
+#if CONFIG_NUM_DDR_CONTROLLERS >= 2
+ if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
+ ddr = (void __iomem *)CONFIG_SYS_MPC8xxx_DDR2_ADDR;
+ sdram_cfg = in_be32(&ddr->sdram_cfg);
+ }
+#endif
+#if CONFIG_NUM_DDR_CONTROLLERS >= 3
+ if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
+ ddr = (void __iomem *)CONFIG_SYS_MPC8xxx_DDR3_ADDR;
+ sdram_cfg = in_be32(&ddr->sdram_cfg);
+ }
+#endif
+ puts(" (DDR");
+ switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
+ SDRAM_CFG_SDRAM_TYPE_SHIFT) {
+ case SDRAM_TYPE_DDR1:
+ puts("1");
+ break;
+ case SDRAM_TYPE_DDR2:
+ puts("2");
+ break;
+ case SDRAM_TYPE_DDR3:
+ puts("3");
+ break;
+ default:
+ puts("?");
+ break;
+ }
+
+ if (sdram_cfg & SDRAM_CFG_32_BE)
+ puts(", 32-bit");
+ else if (sdram_cfg & SDRAM_CFG_16_BE)
+ puts(", 16-bit");
+ else
+ puts(", 64-bit");
+
+ /* Calculate CAS latency based on timing cfg values */
+ cas_lat = ((in_be32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1;
+ if ((in_be32(&ddr->timing_cfg_3) >> 12) & 1)
+ cas_lat += (8 << 1);
+ printf(", CL=%d", cas_lat >> 1);
+ if (cas_lat & 0x1)
+ puts(".5");
+
+ if (sdram_cfg & SDRAM_CFG_ECC_EN)
+ puts(", ECC on)");
+ else
+ puts(", ECC off)");
+
+#if (CONFIG_NUM_DDR_CONTROLLERS == 3)
+#ifdef CONFIG_E6500
+ if (*mcintl3r & 0x80000000) {
+ puts("\n");
+ puts(" DDR Controller Interleaving Mode: ");
+ switch (*mcintl3r & 0x1f) {
+ case FSL_DDR_3WAY_1KB_INTERLEAVING:
+ puts("3-way 1KB");
+ break;
+ case FSL_DDR_3WAY_4KB_INTERLEAVING:
+ puts("3-way 4KB");
+ break;
+ case FSL_DDR_3WAY_8KB_INTERLEAVING:
+ puts("3-way 8KB");
+ break;
+ default:
+ puts("3-way UNKNOWN");
+ break;
+ }
+ }
+#endif
+#endif
+#if (CONFIG_NUM_DDR_CONTROLLERS >= 2)
+ if (cs0_config & 0x20000000) {
+ puts("\n");
+ puts(" DDR Controller Interleaving Mode: ");
+
+ switch ((cs0_config >> 24) & 0xf) {
+ case FSL_DDR_CACHE_LINE_INTERLEAVING:
+ puts("cache line");
+ break;
+ case FSL_DDR_PAGE_INTERLEAVING:
+ puts("page");
+ break;
+ case FSL_DDR_BANK_INTERLEAVING:
+ puts("bank");
+ break;
+ case FSL_DDR_SUPERBANK_INTERLEAVING:
+ puts("super-bank");
+ break;
+ default:
+ puts("invalid");
+ break;
+ }
+ }
+#endif
+
+ if ((sdram_cfg >> 8) & 0x7f) {
+ puts("\n");
+ puts(" DDR Chip-Select Interleaving Mode: ");
+ switch(sdram_cfg >> 8 & 0x7f) {
+ case FSL_DDR_CS0_CS1_CS2_CS3:
+ puts("CS0+CS1+CS2+CS3");
+ break;
+ case FSL_DDR_CS0_CS1:
+ puts("CS0+CS1");
+ break;
+ case FSL_DDR_CS2_CS3:
+ puts("CS2+CS3");
+ break;
+ case FSL_DDR_CS0_CS1_AND_CS2_CS3:
+ puts("CS0+CS1 and CS2+CS3");
+ break;
+ default:
+ puts("invalid");
+ break;
+ }
+ }
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/fdt.c b/arch/powerpc/cpu/mpc8xxx/fdt.c
new file mode 100644
index 0000000..2db9045
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/fdt.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and
+ * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains
+ * cpu specific common code for 85xx/86xx processors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/mp.h>
+#include <asm/fsl_serdes.h>
+#include <phy.h>
+#include <hwconfig.h>
+
+#define FSL_MAX_NUM_USB_CTRLS 2
+
+#if defined(CONFIG_MP) && (defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx))
+static int ft_del_cpuhandle(void *blob, int cpuhandle)
+{
+ int off, ret = -FDT_ERR_NOTFOUND;
+
+ /* if we find a match, we'll delete at it which point the offsets are
+ * invalid so we start over from the beginning
+ */
+ off = fdt_node_offset_by_prop_value(blob, -1, "cpu-handle",
+ &cpuhandle, 4);
+ while (off != -FDT_ERR_NOTFOUND) {
+ fdt_delprop(blob, off, "cpu-handle");
+ ret = 1;
+ off = fdt_node_offset_by_prop_value(blob, -1, "cpu-handle",
+ &cpuhandle, 4);
+ }
+
+ return ret;
+}
+
+void ft_fixup_num_cores(void *blob) {
+ int off, num_cores, del_cores;
+
+ del_cores = 0;
+ num_cores = cpu_numcores();
+
+ off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
+ while (off != -FDT_ERR_NOTFOUND) {
+ u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
+ u32 phys_cpu_id = thread_to_core(*reg);
+
+ if (!is_core_valid(phys_cpu_id) || is_core_disabled(phys_cpu_id)) {
+ int ph = fdt_get_phandle(blob, off);
+
+ /* Delete the cpu node once there are no cpu handles */
+ if (-FDT_ERR_NOTFOUND == ft_del_cpuhandle(blob, ph)) {
+ fdt_del_node(blob, off);
+ del_cores++;
+ }
+ /* either we deleted some cpu handles or the cpu node
+ * so we reset the offset back to the start since we
+ * can't trust the offsets anymore
+ */
+ off = -1;
+ }
+ off = fdt_node_offset_by_prop_value(blob, off,
+ "device_type", "cpu", 4);
+ }
+ debug ("%x core system found\n", num_cores);
+ debug ("deleted %d extra core entry entries from device tree\n",
+ del_cores);
+}
+#endif /* defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) */
+
+#if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB)
+static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
+ const char *phy_type, int start_offset)
+{
+ const char *compat_dr = "fsl-usb2-dr";
+ const char *compat_mph = "fsl-usb2-mph";
+ const char *prop_mode = "dr_mode";
+ const char *prop_type = "phy_type";
+ const char *node_type = NULL;
+ int node_offset;
+ int err;
+
+ node_offset = fdt_node_offset_by_compatible(blob,
+ start_offset, compat_mph);
+ if (node_offset < 0) {
+ node_offset = fdt_node_offset_by_compatible(blob,
+ start_offset, compat_dr);
+ if (node_offset < 0) {
+ printf("WARNING: could not find compatible"
+ " node %s or %s: %s.\n", compat_mph,
+ compat_dr, fdt_strerror(node_offset));
+ return -1;
+ } else
+ node_type = compat_dr;
+ } else
+ node_type = compat_mph;
+
+ if (mode) {
+ err = fdt_setprop(blob, node_offset, prop_mode, mode,
+ strlen(mode) + 1);
+ if (err < 0)
+ printf("WARNING: could not set %s for %s: %s.\n",
+ prop_mode, node_type, fdt_strerror(err));
+ }
+
+ if (phy_type) {
+ err = fdt_setprop(blob, node_offset, prop_type, phy_type,
+ strlen(phy_type) + 1);
+ if (err < 0)
+ printf("WARNING: could not set %s for %s: %s.\n",
+ prop_type, node_type, fdt_strerror(err));
+ }
+
+ return node_offset;
+}
+
+void fdt_fixup_dr_usb(void *blob, bd_t *bd)
+{
+ const char *modes[] = { "host", "peripheral", "otg" };
+ const char *phys[] = { "ulpi", "utmi" };
+ const char *mode = NULL;
+ const char *phy_type = NULL;
+ const char *dr_mode_type = NULL;
+ const char *dr_phy_type = NULL;
+ char usb1_defined = 0;
+ int usb_mode_off = -1;
+ int usb_phy_off = -1;
+ char str[5];
+ int i, j;
+
+ for (i = 1; i <= FSL_MAX_NUM_USB_CTRLS; i++) {
+ int mode_idx = -1, phy_idx = -1;
+ snprintf(str, 5, "%s%d", "usb", i);
+ if (hwconfig(str)) {
+ for (j = 0; j < ARRAY_SIZE(modes); j++) {
+ if (hwconfig_subarg_cmp(str, "dr_mode",
+ modes[j])) {
+ mode_idx = j;
+ break;
+ }
+ }
+
+ for (j = 0; j < ARRAY_SIZE(phys); j++) {
+ if (hwconfig_subarg_cmp(str, "phy_type",
+ phys[j])) {
+ phy_idx = j;
+ break;
+ }
+ }
+
+ if (mode_idx < 0 || phy_idx < 0) {
+ puts("ERROR: wrong usb mode/phy defined!!\n");
+ return;
+ }
+
+ dr_mode_type = modes[mode_idx];
+ dr_phy_type = phys[phy_idx];
+
+ /* use usb_dr_mode and usb_phy_type if
+ usb1_defined = 0; these variables are to
+ be deprecated */
+ if (!strcmp(str, "usb1"))
+ usb1_defined = 1;
+
+ if (mode_idx < 0 && phy_idx < 0) {
+ printf("WARNING: invalid phy or mode\n");
+ return;
+ }
+ }
+
+ usb_mode_off = fdt_fixup_usb_mode_phy_type(blob,
+ dr_mode_type, NULL, usb_mode_off);
+
+ if (usb_mode_off < 0)
+ return;
+
+ usb_phy_off = fdt_fixup_usb_mode_phy_type(blob,
+ NULL, dr_phy_type, usb_phy_off);
+
+ if (usb_phy_off < 0)
+ return;
+ }
+
+ if (!usb1_defined) {
+ int usb_off = -1;
+ mode = getenv("usb_dr_mode");
+ phy_type = getenv("usb_phy_type");
+ if (mode || phy_type) {
+ printf("WARNING: usb_dr_mode and usb_phy_type "
+ "are to be deprecated soon. Use "
+ "hwconfig to set these values instead!!\n");
+ fdt_fixup_usb_mode_phy_type(blob, mode,
+ phy_type, usb_off);
+ }
+ }
+}
+#endif /* defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB) */
+
+/*
+ * update crypto node properties to a specified revision of the SEC
+ * called with sec_rev == 0 if not on an E processor
+ */
+#if CONFIG_SYS_FSL_SEC_COMPAT == 2 /* SEC 2.x/3.x */
+void fdt_fixup_crypto_node(void *blob, int sec_rev)
+{
+ static const struct sec_rev_prop {
+ u32 sec_rev;
+ u32 num_channels;
+ u32 channel_fifo_len;
+ u32 exec_units_mask;
+ u32 descriptor_types_mask;
+ } sec_rev_prop_list [] = {
+ { 0x0200, 4, 24, 0x07e, 0x01010ebf }, /* SEC 2.0 */
+ { 0x0201, 4, 24, 0x0fe, 0x012b0ebf }, /* SEC 2.1 */
+ { 0x0202, 1, 24, 0x04c, 0x0122003f }, /* SEC 2.2 */
+ { 0x0204, 4, 24, 0x07e, 0x012b0ebf }, /* SEC 2.4 */
+ { 0x0300, 4, 24, 0x9fe, 0x03ab0ebf }, /* SEC 3.0 */
+ { 0x0301, 4, 24, 0xbfe, 0x03ab0ebf }, /* SEC 3.1 */
+ { 0x0303, 4, 24, 0x97c, 0x03a30abf }, /* SEC 3.3 */
+ };
+ static char compat_strlist[ARRAY_SIZE(sec_rev_prop_list) *
+ sizeof("fsl,secX.Y")];
+ int crypto_node, sec_idx, err;
+ char *p;
+ u32 val;
+
+ /* locate crypto node based on lowest common compatible */
+ crypto_node = fdt_node_offset_by_compatible(blob, -1, "fsl,sec2.0");
+ if (crypto_node == -FDT_ERR_NOTFOUND)
+ return;
+
+ /* delete it if not on an E-processor */
+ if (crypto_node > 0 && !sec_rev) {
+ fdt_del_node(blob, crypto_node);
+ return;
+ }
+
+ /* else we got called for possible uprev */
+ for (sec_idx = 0; sec_idx < ARRAY_SIZE(sec_rev_prop_list); sec_idx++)
+ if (sec_rev_prop_list[sec_idx].sec_rev == sec_rev)
+ break;
+
+ if (sec_idx == ARRAY_SIZE(sec_rev_prop_list)) {
+ puts("warning: unknown SEC revision number\n");
+ return;
+ }
+
+ val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].num_channels);
+ err = fdt_setprop(blob, crypto_node, "fsl,num-channels", &val, 4);
+ if (err < 0)
+ printf("WARNING: could not set crypto property: %s\n",
+ fdt_strerror(err));
+
+ val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].descriptor_types_mask);
+ err = fdt_setprop(blob, crypto_node, "fsl,descriptor-types-mask", &val, 4);
+ if (err < 0)
+ printf("WARNING: could not set crypto property: %s\n",
+ fdt_strerror(err));
+
+ val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].exec_units_mask);
+ err = fdt_setprop(blob, crypto_node, "fsl,exec-units-mask", &val, 4);
+ if (err < 0)
+ printf("WARNING: could not set crypto property: %s\n",
+ fdt_strerror(err));
+
+ val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].channel_fifo_len);
+ err = fdt_setprop(blob, crypto_node, "fsl,channel-fifo-len", &val, 4);
+ if (err < 0)
+ printf("WARNING: could not set crypto property: %s\n",
+ fdt_strerror(err));
+
+ val = 0;
+ while (sec_idx >= 0) {
+ p = compat_strlist + val;
+ val += sprintf(p, "fsl,sec%d.%d",
+ (sec_rev_prop_list[sec_idx].sec_rev & 0xff00) >> 8,
+ sec_rev_prop_list[sec_idx].sec_rev & 0x00ff) + 1;
+ sec_idx--;
+ }
+ err = fdt_setprop(blob, crypto_node, "compatible", &compat_strlist, val);
+ if (err < 0)
+ printf("WARNING: could not set crypto property: %s\n",
+ fdt_strerror(err));
+}
+#elif CONFIG_SYS_FSL_SEC_COMPAT >= 4 /* SEC4 */
+static u8 caam_get_era(void)
+{
+ static const struct {
+ u16 ip_id;
+ u8 maj_rev;
+ u8 era;
+ } caam_eras[] = {
+ {0x0A10, 1, 1},
+ {0x0A10, 2, 2},
+ {0x0A12, 1, 3},
+ {0x0A14, 1, 3},
+ {0x0A14, 2, 4},
+ {0x0A16, 1, 4},
+ {0x0A10, 3, 4},
+ {0x0A11, 1, 4},
+ {0x0A18, 1, 4},
+ {0x0A11, 2, 5},
+ {0x0A12, 2, 5},
+ {0x0A13, 1, 5},
+ {0x0A1C, 1, 5}
+ };
+
+ ccsr_sec_t __iomem *sec = (void __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ u32 secvid_ms = in_be32(&sec->secvid_ms);
+ u32 ccbvid = in_be32(&sec->ccbvid);
+ u16 ip_id = (secvid_ms & SEC_SECVID_MS_IPID_MASK) >>
+ SEC_SECVID_MS_IPID_SHIFT;
+ u8 maj_rev = (secvid_ms & SEC_SECVID_MS_MAJ_REV_MASK) >>
+ SEC_SECVID_MS_MAJ_REV_SHIFT;
+ u8 era = (ccbvid & SEC_CCBVID_ERA_MASK) >> SEC_CCBVID_ERA_SHIFT;
+
+ int i;
+
+ if (era) /* This is '0' prior to CAAM ERA-6 */
+ return era;
+
+ for (i = 0; i < ARRAY_SIZE(caam_eras); i++)
+ if (caam_eras[i].ip_id == ip_id &&
+ caam_eras[i].maj_rev == maj_rev)
+ return caam_eras[i].era;
+
+ return 0;
+}
+
+static void fdt_fixup_crypto_era(void *blob, u32 era)
+{
+ int err;
+ int crypto_node;
+
+ crypto_node = fdt_path_offset(blob, "crypto");
+ if (crypto_node < 0) {
+ printf("WARNING: Missing crypto node\n");
+ return;
+ }
+
+ err = fdt_setprop(blob, crypto_node, "fsl,sec-era", &era,
+ sizeof(era));
+ if (err < 0) {
+ printf("ERROR: could not set fsl,sec-era property: %s\n",
+ fdt_strerror(err));
+ }
+}
+
+void fdt_fixup_crypto_node(void *blob, int sec_rev)
+{
+ u8 era;
+
+ if (!sec_rev) {
+ fdt_del_node_and_alias(blob, "crypto");
+ return;
+ }
+
+ /* Add SEC ERA information in compatible */
+ era = caam_get_era();
+ if (era) {
+ fdt_fixup_crypto_era(blob, era);
+ } else {
+ printf("WARNING: Unable to get ERA for CAAM rev: %d\n",
+ sec_rev);
+ }
+}
+#endif
+
+int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc)
+{
+ return fdt_setprop_string(blob, offset, "phy-connection-type",
+ phy_string_for_interface(phyc));
+}
+
+#ifdef CONFIG_SYS_SRIO
+static inline void ft_disable_srio_port(void *blob, int srio_off, int port)
+{
+ int off = fdt_node_offset_by_prop_value(blob, srio_off,
+ "cell-index", &port, 4);
+ if (off >= 0) {
+ off = fdt_setprop_string(blob, off, "status", "disabled");
+ if (off > 0)
+ printf("WARNING unable to set status for fsl,srio "
+ "port %d: %s\n", port, fdt_strerror(off));
+ }
+}
+
+static inline void ft_disable_rman(void *blob)
+{
+ int off = fdt_node_offset_by_compatible(blob, -1, "fsl,rman");
+ if (off >= 0) {
+ off = fdt_setprop_string(blob, off, "status", "disabled");
+ if (off > 0)
+ printf("WARNING unable to set status for fsl,rman %s\n",
+ fdt_strerror(off));
+ }
+}
+
+static inline void ft_disable_rmu(void *blob)
+{
+ int off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio-rmu");
+ if (off >= 0) {
+ off = fdt_setprop_string(blob, off, "status", "disabled");
+ if (off > 0)
+ printf("WARNING unable to set status for "
+ "fsl,srio-rmu %s\n", fdt_strerror(off));
+ }
+}
+
+void ft_srio_setup(void *blob)
+{
+ int srio1_used = 0, srio2_used = 0;
+ int srio_off;
+
+ /* search for srio node, if doesn't exist just return - nothing todo */
+ srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio");
+ if (srio_off < 0)
+ return ;
+
+#ifdef CONFIG_SRIO1
+ if (is_serdes_configured(SRIO1))
+ srio1_used = 1;
+#endif
+#ifdef CONFIG_SRIO2
+ if (is_serdes_configured(SRIO2))
+ srio2_used = 1;
+#endif
+
+ /* mark port1 disabled */
+ if (!srio1_used)
+ ft_disable_srio_port(blob, srio_off, 1);
+
+ /* mark port2 disabled */
+ if (!srio2_used)
+ ft_disable_srio_port(blob, srio_off, 2);
+
+ /* if both ports not used, disable controller, rmu and rman */
+ if (!srio1_used && !srio2_used) {
+ fdt_setprop_string(blob, srio_off, "status", "disabled");
+
+ ft_disable_rman(blob);
+ ft_disable_rmu(blob);
+ }
+}
+#endif
diff --git a/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c b/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
new file mode 100644
index 0000000..4e8a441
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/fsl_ifc.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/fsl_ifc.h>
+
+void print_ifc_regs(void)
+{
+ int i, j;
+
+ printf("IFC Controller Registers\n");
+ for (i = 0; i < CONFIG_SYS_FSL_IFC_BANK_COUNT; i++) {
+ printf("CSPR%d:0x%08X\tAMASK%d:0x%08X\tCSOR%d:0x%08X\n",
+ i, get_ifc_cspr(i), i, get_ifc_amask(i),
+ i, get_ifc_csor(i));
+ for (j = 0; j < 4; j++)
+ printf("IFC_FTIM%d:0x%08X\n", j, get_ifc_ftim(i, j));
+ }
+}
+
+void init_early_memctl_regs(void)
+{
+#if defined(CONFIG_SYS_CSPR0) && defined(CONFIG_SYS_CSOR0)
+ set_ifc_ftim(IFC_CS0, IFC_FTIM0, CONFIG_SYS_CS0_FTIM0);
+ set_ifc_ftim(IFC_CS0, IFC_FTIM1, CONFIG_SYS_CS0_FTIM1);
+ set_ifc_ftim(IFC_CS0, IFC_FTIM2, CONFIG_SYS_CS0_FTIM2);
+ set_ifc_ftim(IFC_CS0, IFC_FTIM3, CONFIG_SYS_CS0_FTIM3);
+
+#ifndef CONFIG_A003399_NOR_WORKAROUND
+#ifdef CONFIG_SYS_CSPR0_EXT
+ set_ifc_cspr_ext(IFC_CS0, CONFIG_SYS_CSPR0_EXT);
+#endif
+ set_ifc_cspr(IFC_CS0, CONFIG_SYS_CSPR0);
+ set_ifc_amask(IFC_CS0, CONFIG_SYS_AMASK0);
+ set_ifc_csor(IFC_CS0, CONFIG_SYS_CSOR0);
+#endif
+#endif
+
+#ifdef CONFIG_SYS_CSPR1_EXT
+ set_ifc_cspr_ext(IFC_CS1, CONFIG_SYS_CSPR1_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR1) && defined(CONFIG_SYS_CSOR1)
+ set_ifc_ftim(IFC_CS1, IFC_FTIM0, CONFIG_SYS_CS1_FTIM0);
+ set_ifc_ftim(IFC_CS1, IFC_FTIM1, CONFIG_SYS_CS1_FTIM1);
+ set_ifc_ftim(IFC_CS1, IFC_FTIM2, CONFIG_SYS_CS1_FTIM2);
+ set_ifc_ftim(IFC_CS1, IFC_FTIM3, CONFIG_SYS_CS1_FTIM3);
+
+ set_ifc_csor(IFC_CS1, CONFIG_SYS_CSOR1);
+ set_ifc_amask(IFC_CS1, CONFIG_SYS_AMASK1);
+ set_ifc_cspr(IFC_CS1, CONFIG_SYS_CSPR1);
+#endif
+
+#ifdef CONFIG_SYS_CSPR2_EXT
+ set_ifc_cspr_ext(IFC_CS2, CONFIG_SYS_CSPR2_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR2) && defined(CONFIG_SYS_CSOR2)
+ set_ifc_ftim(IFC_CS2, IFC_FTIM0, CONFIG_SYS_CS2_FTIM0);
+ set_ifc_ftim(IFC_CS2, IFC_FTIM1, CONFIG_SYS_CS2_FTIM1);
+ set_ifc_ftim(IFC_CS2, IFC_FTIM2, CONFIG_SYS_CS2_FTIM2);
+ set_ifc_ftim(IFC_CS2, IFC_FTIM3, CONFIG_SYS_CS2_FTIM3);
+
+ set_ifc_csor(IFC_CS2, CONFIG_SYS_CSOR2);
+ set_ifc_amask(IFC_CS2, CONFIG_SYS_AMASK2);
+ set_ifc_cspr(IFC_CS2, CONFIG_SYS_CSPR2);
+#endif
+
+#ifdef CONFIG_SYS_CSPR3_EXT
+ set_ifc_cspr_ext(IFC_CS3, CONFIG_SYS_CSPR3_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR3) && defined(CONFIG_SYS_CSOR3)
+ set_ifc_ftim(IFC_CS3, IFC_FTIM0, CONFIG_SYS_CS3_FTIM0);
+ set_ifc_ftim(IFC_CS3, IFC_FTIM1, CONFIG_SYS_CS3_FTIM1);
+ set_ifc_ftim(IFC_CS3, IFC_FTIM2, CONFIG_SYS_CS3_FTIM2);
+ set_ifc_ftim(IFC_CS3, IFC_FTIM3, CONFIG_SYS_CS3_FTIM3);
+
+ set_ifc_cspr(IFC_CS3, CONFIG_SYS_CSPR3);
+ set_ifc_amask(IFC_CS3, CONFIG_SYS_AMASK3);
+ set_ifc_csor(IFC_CS3, CONFIG_SYS_CSOR3);
+#endif
+
+#ifdef CONFIG_SYS_CSPR4_EXT
+ set_ifc_cspr_ext(IFC_CS4, CONFIG_SYS_CSPR4_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR4) && defined(CONFIG_SYS_CSOR4)
+ set_ifc_ftim(IFC_CS4, IFC_FTIM0, CONFIG_SYS_CS4_FTIM0);
+ set_ifc_ftim(IFC_CS4, IFC_FTIM1, CONFIG_SYS_CS4_FTIM1);
+ set_ifc_ftim(IFC_CS4, IFC_FTIM2, CONFIG_SYS_CS4_FTIM2);
+ set_ifc_ftim(IFC_CS4, IFC_FTIM3, CONFIG_SYS_CS4_FTIM3);
+
+ set_ifc_cspr(IFC_CS4, CONFIG_SYS_CSPR4);
+ set_ifc_amask(IFC_CS4, CONFIG_SYS_AMASK4);
+ set_ifc_csor(IFC_CS4, CONFIG_SYS_CSOR4);
+#endif
+
+#ifdef CONFIG_SYS_CSPR5_EXT
+ set_ifc_cspr_ext(IFC_CS5, CONFIG_SYS_CSPR5_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR5) && defined(CONFIG_SYS_CSOR5)
+ set_ifc_ftim(IFC_CS5, IFC_FTIM0, CONFIG_SYS_CS5_FTIM0);
+ set_ifc_ftim(IFC_CS5, IFC_FTIM1, CONFIG_SYS_CS5_FTIM1);
+ set_ifc_ftim(IFC_CS5, IFC_FTIM2, CONFIG_SYS_CS5_FTIM2);
+ set_ifc_ftim(IFC_CS5, IFC_FTIM3, CONFIG_SYS_CS5_FTIM3);
+
+ set_ifc_cspr(IFC_CS5, CONFIG_SYS_CSPR5);
+ set_ifc_amask(IFC_CS5, CONFIG_SYS_AMASK5);
+ set_ifc_csor(IFC_CS5, CONFIG_SYS_CSOR5);
+#endif
+
+#ifdef CONFIG_SYS_CSPR6_EXT
+ set_ifc_cspr_ext(IFC_CS6, CONFIG_SYS_CSPR6_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR6) && defined(CONFIG_SYS_CSOR6)
+ set_ifc_ftim(IFC_CS6, IFC_FTIM0, CONFIG_SYS_CS6_FTIM0);
+ set_ifc_ftim(IFC_CS6, IFC_FTIM1, CONFIG_SYS_CS6_FTIM1);
+ set_ifc_ftim(IFC_CS6, IFC_FTIM2, CONFIG_SYS_CS6_FTIM2);
+ set_ifc_ftim(IFC_CS6, IFC_FTIM3, CONFIG_SYS_CS6_FTIM3);
+
+ set_ifc_cspr(IFC_CS6, CONFIG_SYS_CSPR6);
+ set_ifc_amask(IFC_CS6, CONFIG_SYS_AMASK6);
+ set_ifc_csor(IFC_CS6, CONFIG_SYS_CSOR6);
+#endif
+
+#ifdef CONFIG_SYS_CSPR7_EXT
+ set_ifc_cspr_ext(IFC_CS7, CONFIG_SYS_CSPR7_EXT);
+#endif
+#if defined(CONFIG_SYS_CSPR7) && defined(CONFIG_SYS_CSOR7)
+ set_ifc_ftim(IFC_CS7, IFC_FTIM0, CONFIG_SYS_CS7_FTIM0);
+ set_ifc_ftim(IFC_CS7, IFC_FTIM1, CONFIG_SYS_CS7_FTIM1);
+ set_ifc_ftim(IFC_CS7, IFC_FTIM2, CONFIG_SYS_CS7_FTIM2);
+ set_ifc_ftim(IFC_CS7, IFC_FTIM3, CONFIG_SYS_CS7_FTIM3);
+
+ set_ifc_cspr(IFC_CS7, CONFIG_SYS_CSPR7);
+ set_ifc_amask(IFC_CS7, CONFIG_SYS_AMASK7);
+ set_ifc_csor(IFC_CS7, CONFIG_SYS_CSOR7);
+#endif
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/fsl_lbc.c b/arch/powerpc/cpu/mpc8xxx/fsl_lbc.c
new file mode 100644
index 0000000..c1fe579
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/fsl_lbc.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <asm/fsl_lbc.h>
+
+#ifdef CONFIG_MPC85xx
+/* Boards should provide their own version of this if they use lbc sdram */
+static void __lbc_sdram_init(void)
+{
+ /* Do nothing */
+}
+void lbc_sdram_init(void) __attribute__((weak, alias("__lbc_sdram_init")));
+#endif
+
+
+void print_lbc_regs(void)
+{
+ int i;
+
+ printf("\nLocal Bus Controller Registers\n");
+ for (i = 0; i < 8; i++) {
+ printf("BR%d\t0x%08X\tOR%d\t0x%08X\n",
+ i, get_lbc_br(i), i, get_lbc_or(i));
+ }
+ printf("LBCR\t0x%08X\tLCRR\t0x%08X\n",
+ get_lbc_lbcr(), get_lbc_lcrr());
+}
+
+void init_early_memctl_regs(void)
+{
+ uint init_br1 = 1;
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+ /* Set the local bus monitor timeout value to the maximum */
+ clrsetbits_be32(&(LBC_BASE_ADDR)->lbcr, LBCR_BMT|LBCR_BMTPS, 0xf);
+#endif
+
+#ifdef CONFIG_MPC85xx
+ /* if cs1 is already set via debugger, leave cs0/cs1 alone */
+ if (get_lbc_br(1) & BR_V)
+ init_br1 = 0;
+#endif
+
+ /*
+ * Map banks 0 (and maybe 1) to the FLASH banks 0 (and 1) at
+ * preliminary addresses - these have to be modified later
+ * when FLASH size has been determined
+ */
+#if defined(CONFIG_SYS_OR0_REMAP)
+ set_lbc_or(0, CONFIG_SYS_OR0_REMAP);
+#endif
+#if defined(CONFIG_SYS_OR1_REMAP)
+ set_lbc_or(1, CONFIG_SYS_OR1_REMAP);
+#endif
+ /* now restrict to preliminary range */
+ if (init_br1) {
+#if defined(CONFIG_SYS_BR0_PRELIM) && defined(CONFIG_SYS_OR0_PRELIM)
+ set_lbc_br(0, CONFIG_SYS_BR0_PRELIM);
+ set_lbc_or(0, CONFIG_SYS_OR0_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM)
+ set_lbc_or(1, CONFIG_SYS_OR1_PRELIM);
+ set_lbc_br(1, CONFIG_SYS_BR1_PRELIM);
+#endif
+ }
+
+#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM)
+ set_lbc_or(2, CONFIG_SYS_OR2_PRELIM);
+ set_lbc_br(2, CONFIG_SYS_BR2_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM)
+ set_lbc_or(3, CONFIG_SYS_OR3_PRELIM);
+ set_lbc_br(3, CONFIG_SYS_BR3_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM)
+ set_lbc_or(4, CONFIG_SYS_OR4_PRELIM);
+ set_lbc_br(4, CONFIG_SYS_BR4_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM)
+ set_lbc_or(5, CONFIG_SYS_OR5_PRELIM);
+ set_lbc_br(5, CONFIG_SYS_BR5_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM)
+ set_lbc_or(6, CONFIG_SYS_OR6_PRELIM);
+ set_lbc_br(6, CONFIG_SYS_BR6_PRELIM);
+#endif
+
+#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM)
+ set_lbc_or(7, CONFIG_SYS_OR7_PRELIM);
+ set_lbc_br(7, CONFIG_SYS_BR7_PRELIM);
+#endif
+}
+
+/*
+ * Configures a UPM. The function requires the respective MxMR to be set
+ * before calling this function. "size" is the number or entries, not a sizeof.
+ */
+void upmconfig(uint upm, uint *table, uint size)
+{
+ fsl_lbc_t *lbc = LBC_BASE_ADDR;
+ int i, mad, old_mad = 0;
+ u32 mask = (~MxMR_OP_MSK & ~MxMR_MAD_MSK);
+ u32 msel = BR_UPMx_TO_MSEL(upm);
+ u32 *mxmr = &lbc->mamr + upm;
+ volatile u8 *dummy = NULL;
+
+ if (upm < UPMA || upm > UPMC) {
+ printf("Error: %s() Bad UPM index %d\n", __func__, upm);
+ hang();
+ }
+
+ /*
+ * Find the address for the dummy write - scan all of the BRs until we
+ * find one matching the UPM and extract the base address bits from it.
+ */
+ for (i = 0; i < 8; i++) {
+ if ((get_lbc_br(i) & (BR_V | BR_MSEL)) == (BR_V | msel)) {
+ dummy = (volatile u8 *)(get_lbc_br(i) & BR_BA);
+ break;
+ }
+ }
+
+ if (!dummy) {
+ printf("Error: %s() No matching BR\n", __func__);
+ hang();
+ }
+
+ /* Program UPM using steps outlined by the reference manual */
+ for (i = 0; i < size; i++) {
+ out_be32(mxmr, (in_be32(mxmr) & mask) | MxMR_OP_WARR | i);
+ out_be32(&lbc->mdr, table[i]);
+ (void)in_be32(&lbc->mdr);
+ *dummy = 0;
+ do {
+ mad = in_be32(mxmr) & MxMR_MAD_MSK;
+ } while (mad <= old_mad && !(!mad && i == (size-1)));
+ old_mad = mad;
+ }
+
+ /* Return to normal operation */
+ out_be32(mxmr, (in_be32(mxmr) & mask) | MxMR_OP_NORM);
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/law.c b/arch/powerpc/cpu/mpc8xxx/law.c
new file mode 100644
index 0000000..6f9d568
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/law.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <linux/compiler.h>
+#include <asm/fsl_law.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define FSL_HW_NUM_LAWS CONFIG_SYS_FSL_NUM_LAWS
+
+#ifdef CONFIG_FSL_CORENET
+#define LAW_BASE (CONFIG_SYS_FSL_CORENET_CCM_ADDR)
+#define LAWAR_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawar)
+#define LAWBARH_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarh)
+#define LAWBARL_ADDR(x) (&((ccsr_local_t *)LAW_BASE)->law[x].lawbarl)
+#define LAWBAR_SHIFT 0
+#else
+#define LAW_BASE (CONFIG_SYS_IMMR + 0xc08)
+#define LAWAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x + 2)
+#define LAWBAR_ADDR(x) ((u32 *)LAW_BASE + 8 * x)
+#define LAWBAR_SHIFT 12
+#endif
+
+
+static inline phys_addr_t get_law_base_addr(int idx)
+{
+#ifdef CONFIG_FSL_CORENET
+ return (phys_addr_t)
+ ((u64)in_be32(LAWBARH_ADDR(idx)) << 32) |
+ in_be32(LAWBARL_ADDR(idx));
+#else
+ return (phys_addr_t)in_be32(LAWBAR_ADDR(idx)) << LAWBAR_SHIFT;
+#endif
+}
+
+static inline void set_law_base_addr(int idx, phys_addr_t addr)
+{
+#ifdef CONFIG_FSL_CORENET
+ out_be32(LAWBARL_ADDR(idx), addr & 0xffffffff);
+ out_be32(LAWBARH_ADDR(idx), (u64)addr >> 32);
+#else
+ out_be32(LAWBAR_ADDR(idx), addr >> LAWBAR_SHIFT);
+#endif
+}
+
+void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
+{
+ gd->arch.used_laws |= (1 << idx);
+
+ out_be32(LAWAR_ADDR(idx), 0);
+ set_law_base_addr(idx, addr);
+ out_be32(LAWAR_ADDR(idx), LAW_EN | ((u32)id << 20) | (u32)sz);
+
+ /* Read back so that we sync the writes */
+ in_be32(LAWAR_ADDR(idx));
+}
+
+void disable_law(u8 idx)
+{
+ gd->arch.used_laws &= ~(1 << idx);
+
+ out_be32(LAWAR_ADDR(idx), 0);
+ set_law_base_addr(idx, 0);
+
+ /* Read back so that we sync the writes */
+ in_be32(LAWAR_ADDR(idx));
+
+ return;
+}
+
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
+static int get_law_entry(u8 i, struct law_entry *e)
+{
+ u32 lawar;
+
+ lawar = in_be32(LAWAR_ADDR(i));
+
+ if (!(lawar & LAW_EN))
+ return 0;
+
+ e->addr = get_law_base_addr(i);
+ e->size = lawar & 0x3f;
+ e->trgt_id = (lawar >> 20) & 0xff;
+
+ return 1;
+}
+#endif
+
+int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
+{
+ u32 idx = ffz(gd->arch.used_laws);
+
+ if (idx >= FSL_HW_NUM_LAWS)
+ return -1;
+
+ set_law(idx, addr, sz, id);
+
+ return idx;
+}
+
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
+int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
+{
+ u32 idx;
+
+ /* we have no LAWs free */
+ if (gd->arch.used_laws == -1)
+ return -1;
+
+ /* grab the last free law */
+ idx = __ilog2(~(gd->arch.used_laws));
+
+ if (idx >= FSL_HW_NUM_LAWS)
+ return -1;
+
+ set_law(idx, addr, sz, id);
+
+ return idx;
+}
+
+struct law_entry find_law(phys_addr_t addr)
+{
+ struct law_entry entry;
+ int i;
+
+ entry.index = -1;
+ entry.addr = 0;
+ entry.size = 0;
+ entry.trgt_id = 0;
+
+ for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
+ u64 upper;
+
+ if (!get_law_entry(i, &entry))
+ continue;
+
+ upper = entry.addr + (2ull << entry.size);
+ if ((addr >= entry.addr) && (addr < upper)) {
+ entry.index = i;
+ break;
+ }
+ }
+
+ return entry;
+}
+
+void print_laws(void)
+{
+ int i;
+ u32 lawar;
+
+ printf("\nLocal Access Window Configuration\n");
+ for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
+ lawar = in_be32(LAWAR_ADDR(i));
+#ifdef CONFIG_FSL_CORENET
+ printf("LAWBARH%02d: 0x%08x LAWBARL%02d: 0x%08x",
+ i, in_be32(LAWBARH_ADDR(i)),
+ i, in_be32(LAWBARL_ADDR(i)));
+#else
+ printf("LAWBAR%02d: 0x%08x", i, in_be32(LAWBAR_ADDR(i)));
+#endif
+ printf(" LAWAR%02d: 0x%08x\n", i, lawar);
+ printf("\t(EN: %d TGT: 0x%02x SIZE: ",
+ (lawar & LAW_EN) ? 1 : 0, (lawar >> 20) & 0xff);
+ print_size(lawar_size(lawar), ")\n");
+ }
+
+ return;
+}
+
+/* use up to 2 LAWs for DDR, used the last available LAWs */
+int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
+{
+ u64 start_align, law_sz;
+ int law_sz_enc;
+
+ if (start == 0)
+ start_align = 1ull << (LAW_SIZE_32G + 1);
+ else
+ start_align = 1ull << (ffs64(start) - 1);
+ law_sz = min(start_align, sz);
+ law_sz_enc = __ilog2_u64(law_sz) - 1;
+
+ if (set_last_law(start, law_sz_enc, id) < 0)
+ return -1;
+
+ /* recalculate size based on what was actually covered by the law */
+ law_sz = 1ull << __ilog2_u64(law_sz);
+
+ /* do we still have anything to map */
+ sz = sz - law_sz;
+ if (sz) {
+ start += law_sz;
+
+ start_align = 1ull << (ffs64(start) - 1);
+ law_sz = min(start_align, sz);
+ law_sz_enc = __ilog2_u64(law_sz) - 1;
+
+ if (set_last_law(start, law_sz_enc, id) < 0)
+ return -1;
+ } else {
+ return 0;
+ }
+
+ /* do we still have anything to map */
+ sz = sz - law_sz;
+ if (sz)
+ return 1;
+
+ return 0;
+}
+#endif /* not SPL */
+
+void init_laws(void)
+{
+ int i;
+
+#if FSL_HW_NUM_LAWS < 32
+ gd->arch.used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1);
+#elif FSL_HW_NUM_LAWS == 32
+ gd->arch.used_laws = 0;
+#else
+#error FSL_HW_NUM_LAWS can not be greater than 32 w/o code changes
+#endif
+
+ /*
+ * Any LAWs that were set up before we booted assume they are meant to
+ * be around and mark them used.
+ */
+ for (i = 0; i < FSL_HW_NUM_LAWS; i++) {
+ u32 lawar = in_be32(LAWAR_ADDR(i));
+
+ if (lawar & LAW_EN)
+ gd->arch.used_laws |= (1 << i);
+ }
+
+#if (defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)) || \
+ (defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
+ /*
+ * in SPL boot we've already parsed the law_table and setup those LAWs
+ * so don't do it again.
+ */
+ return;
+#endif
+
+ for (i = 0; i < num_law_entries; i++) {
+ if (law_table[i].index == -1)
+ set_next_law(law_table[i].addr, law_table[i].size,
+ law_table[i].trgt_id);
+ else
+ set_law(law_table[i].index, law_table[i].addr,
+ law_table[i].size, law_table[i].trgt_id);
+ }
+
+#ifdef CONFIG_SRIO_PCIE_BOOT_SLAVE
+ /* check RCW to get which port is used for boot */
+ ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
+ u32 bootloc = in_be32(&gur->rcwsr[6]);
+ /*
+ * in SRIO or PCIE boot we need to set specail LAWs for
+ * SRIO or PCIE interfaces.
+ */
+ switch ((bootloc & FSL_CORENET_RCWSR6_BOOT_LOC) >> 23) {
+ case 0x0: /* boot from PCIE1 */
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_PCIE_1);
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_PCIE_1);
+ break;
+ case 0x1: /* boot from PCIE2 */
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_PCIE_2);
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_PCIE_2);
+ break;
+ case 0x2: /* boot from PCIE3 */
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_PCIE_3);
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_PCIE_3);
+ break;
+ case 0x8: /* boot from SRIO1 */
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_RIO_1);
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_RIO_1);
+ break;
+ case 0x9: /* boot from SRIO2 */
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_SLAVE_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_RIO_2);
+ set_next_law(CONFIG_SYS_SRIO_PCIE_BOOT_UCODE_ENV_ADDR_PHYS,
+ LAW_SIZE_1M,
+ LAW_TRGT_IF_RIO_2);
+ break;
+ default:
+ break;
+ }
+#endif
+
+ return ;
+}
diff --git a/arch/powerpc/cpu/mpc8xxx/srio.c b/arch/powerpc/cpu/mpc8xxx/srio.c
new file mode 100644
index 0000000..90d1065
--- /dev/null
+++ b/arch/powerpc/cpu/mpc8xxx/srio.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <config.h>
+#include <asm/fsl_law.h>
+#include <asm/fsl_serdes.h>
+#include <asm/fsl_srio.h>
+#include <asm/errno.h>
+
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
+#define SRIO_PORT_ACCEPT_ALL 0x10000001
+#define SRIO_IB_ATMU_AR 0x80f55000
+#define SRIO_OB_ATMU_AR_MAINT 0x80077000
+#define SRIO_OB_ATMU_AR_RW 0x80045000
+#define SRIO_LCSBA1CSR_OFFSET 0x5c
+#define SRIO_MAINT_WIN_SIZE 0x1000000 /* 16M */
+#define SRIO_RW_WIN_SIZE 0x100000 /* 1M */
+#define SRIO_LCSBA1CSR 0x60000000
+#endif
+
+#if defined(CONFIG_FSL_CORENET)
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ #define _DEVDISR_SRIO1 FSL_CORENET_DEVDISR3_SRIO1
+ #define _DEVDISR_SRIO2 FSL_CORENET_DEVDISR3_SRIO2
+#else
+ #define _DEVDISR_SRIO1 FSL_CORENET_DEVDISR_SRIO1
+ #define _DEVDISR_SRIO2 FSL_CORENET_DEVDISR_SRIO2
+#endif
+ #define _DEVDISR_RMU FSL_CORENET_DEVDISR_RMU
+ #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR
+#elif defined(CONFIG_MPC85xx)
+ #define _DEVDISR_SRIO1 MPC85xx_DEVDISR_SRIO
+ #define _DEVDISR_SRIO2 MPC85xx_DEVDISR_SRIO
+ #define _DEVDISR_RMU MPC85xx_DEVDISR_RMSG
+ #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR
+#elif defined(CONFIG_MPC86xx)
+ #define _DEVDISR_SRIO1 MPC86xx_DEVDISR_SRIO
+ #define _DEVDISR_SRIO2 MPC86xx_DEVDISR_SRIO
+ #define _DEVDISR_RMU MPC86xx_DEVDISR_RMSG
+ #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \
+ (&((immap_t *)CONFIG_SYS_IMMR)->im_gur)
+#else
+#error "No defines for DEVDISR_SRIO"
+#endif
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+/*
+ * Erratum A-004034
+ * Affects: SRIO
+ * Description: During port initialization, the SRIO port performs
+ * lane synchronization (detecting valid symbols on a lane) and
+ * lane alignment (coordinating multiple lanes to receive valid data
+ * across lanes). Internal errors in lane synchronization and lane
+ * alignment may cause failure to achieve link initialization at
+ * the configured port width.
+ * An SRIO port configured as a 4x port may see one of these scenarios:
+ * 1. One or more lanes fails to achieve lane synchronization. Depending
+ * on which lanes fail, this may result in downtraining from 4x to 1x
+ * on lane 0, 4x to 1x on lane R (redundant lane).
+ * 2. The link may fail to achieve lane alignment as a 4x, even though
+ * all 4 lanes achieve lane synchronization, and downtrain to a 1x.
+ * An SRIO port configured as a 1x port may fail to complete port
+ * initialization (PnESCSR[PU] never deasserts) because of scenario 1.
+ * Impact: SRIO port may downtrain to 1x, or may fail to complete
+ * link initialization. Once a port completes link initialization
+ * successfully, it will operate normally.
+ */
+static int srio_erratum_a004034(u8 port)
+{
+ serdes_corenet_t *srds_regs;
+ u32 conf_lane;
+ u32 init_lane;
+ int idx, first, last;
+ u32 i;
+ unsigned long long end_tick;
+ struct ccsr_rio *srio_regs = (void *)CONFIG_SYS_FSL_SRIO_ADDR;
+
+ srds_regs = (void *)(CONFIG_SYS_FSL_CORENET_SERDES_ADDR);
+ conf_lane = (in_be32((void *)&srds_regs->srdspccr0)
+ >> (12 - port * 4)) & 0x3;
+ init_lane = (in_be32((void *)&srio_regs->lp_serial
+ .port[port].pccsr) >> 27) & 0x7;
+
+ /*
+ * Start a counter set to ~2 ms after the SERDES reset is
+ * complete (SERDES SRDSBnRSTCTL[RST_DONE]=1 for n
+ * corresponding to the SERDES bank/PLL for the SRIO port).
+ */
+ if (in_be32((void *)&srds_regs->bank[0].rstctl)
+ & SRDS_RSTCTL_RSTDONE) {
+ /*
+ * Poll the port uninitialized status (SRIO PnESCSR[PO]) until
+ * PO=1 or the counter expires. If the counter expires, the
+ * port has failed initialization: go to recover steps. If PO=1
+ * and the desired port width is 1x, go to normal steps. If
+ * PO = 1 and the desired port width is 4x, go to recover steps.
+ */
+ end_tick = usec2ticks(2000) + get_ticks();
+ do {
+ if (in_be32((void *)&srio_regs->lp_serial
+ .port[port].pescsr) & 0x2) {
+ if (conf_lane == 0x1)
+ goto host_ok;
+ else {
+ if (init_lane == 0x2)
+ goto host_ok;
+ else
+ break;
+ }
+ }
+ } while (end_tick > get_ticks());
+
+ /* recover at most 3 times */
+ for (i = 0; i < 3; i++) {
+ /* Set SRIO PnCCSR[PD]=1 */
+ setbits_be32((void *)&srio_regs->lp_serial
+ .port[port].pccsr,
+ 0x800000);
+ /*
+ * Set SRIO PnPCR[OBDEN] on the host to
+ * enable the discarding of any pending packets.
+ */
+ setbits_be32((void *)&srio_regs->impl.port[port].pcr,
+ 0x04);
+ /* Wait 50 us */
+ udelay(50);
+ /* Run sync command */
+ isync();
+
+ if (port)
+ first = serdes_get_first_lane(SRIO2);
+ else
+ first = serdes_get_first_lane(SRIO1);
+ if (unlikely(first < 0))
+ return -ENODEV;
+ if (conf_lane == 0x1)
+ last = first;
+ else
+ last = first + 3;
+ /*
+ * Set SERDES BnGCRm0[RRST]=0 for each SRIO
+ * bank n and lane m.
+ */
+ for (idx = first; idx <= last; idx++)
+ clrbits_be32(&srds_regs->lane[idx].gcr0,
+ SRDS_GCR0_RRST);
+ /*
+ * Read SERDES BnGCRm0 for each SRIO
+ * bank n and lane m
+ */
+ for (idx = first; idx <= last; idx++)
+ in_be32(&srds_regs->lane[idx].gcr0);
+ /* Run sync command */
+ isync();
+ /* Wait >= 100 ns */
+ udelay(1);
+ /*
+ * Set SERDES BnGCRm0[RRST]=1 for each SRIO
+ * bank n and lane m.
+ */
+ for (idx = first; idx <= last; idx++)
+ setbits_be32(&srds_regs->lane[idx].gcr0,
+ SRDS_GCR0_RRST);
+ /*
+ * Read SERDES BnGCRm0 for each SRIO
+ * bank n and lane m
+ */
+ for (idx = first; idx <= last; idx++)
+ in_be32(&srds_regs->lane[idx].gcr0);
+ /* Run sync command */
+ isync();
+ /* Wait >= 300 ns */
+ udelay(1);
+
+ /* Write 1 to clear all bits in SRIO PnSLCSR */
+ out_be32((void *)&srio_regs->impl.port[port].slcsr,
+ 0xffffffff);
+ /* Clear SRIO PnPCR[OBDEN] on the host */
+ clrbits_be32((void *)&srio_regs->impl.port[port].pcr,
+ 0x04);
+ /* Set SRIO PnCCSR[PD]=0 */
+ clrbits_be32((void *)&srio_regs->lp_serial
+ .port[port].pccsr,
+ 0x800000);
+ /* Wait >= 24 ms */
+ udelay(24000);
+ /* Poll the state of the port again */
+ init_lane =
+ (in_be32((void *)&srio_regs->lp_serial
+ .port[port].pccsr) >> 27) & 0x7;
+ if (in_be32((void *)&srio_regs->lp_serial
+ .port[port].pescsr) & 0x2) {
+ if (conf_lane == 0x1)
+ goto host_ok;
+ else {
+ if (init_lane == 0x2)
+ goto host_ok;
+ }
+ }
+ if (i == 2)
+ return -ENODEV;
+ }
+ } else
+ return -ENODEV;
+
+host_ok:
+ /* Poll PnESCSR[OES] on the host until it is clear */
+ end_tick = usec2ticks(1000000) + get_ticks();
+ do {
+ if (!(in_be32((void *)&srio_regs->lp_serial.port[port].pescsr)
+ & 0x10000)) {
+ out_be32(((void *)&srio_regs->lp_serial
+ .port[port].pescsr), 0xffffffff);
+ out_be32(((void *)&srio_regs->phys_err
+ .port[port].edcsr), 0);
+ out_be32(((void *)&srio_regs->logical_err.ltledcsr), 0);
+ return 0;
+ }
+ } while (end_tick > get_ticks());
+
+ return -ENODEV;
+}
+#endif
+
+void srio_init(void)
+{
+ ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR;
+ int srio1_used = 0, srio2_used = 0;
+ u32 *devdisr;
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ devdisr = &gur->devdisr3;
+#else
+ devdisr = &gur->devdisr;
+#endif
+ if (is_serdes_configured(SRIO1)) {
+ set_next_law(CONFIG_SYS_SRIO1_MEM_PHYS,
+ law_size_bits(CONFIG_SYS_SRIO1_MEM_SIZE),
+ LAW_TRGT_IF_RIO_1);
+ srio1_used = 1;
+#ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+ if (srio_erratum_a004034(0) < 0)
+ printf("SRIO1: enabled but port error\n");
+ else
+#endif
+ printf("SRIO1: enabled\n");
+ } else {
+ printf("SRIO1: disabled\n");
+ }
+
+#ifdef CONFIG_SRIO2
+ if (is_serdes_configured(SRIO2)) {
+ set_next_law(CONFIG_SYS_SRIO2_MEM_PHYS,
+ law_size_bits(CONFIG_SYS_SRIO2_MEM_SIZE),
+ LAW_TRGT_IF_RIO_2);
+ srio2_used = 1;
+#ifdef CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+ if (srio_erratum_a004034(1) < 0)
+ printf("SRIO2: enabled but port error\n");
+ else
+#endif
+ printf("SRIO2: enabled\n");
+
+ } else {
+ printf("SRIO2: disabled\n");
+ }
+#endif
+
+#ifdef CONFIG_FSL_CORENET
+ /* On FSL_CORENET devices we can disable individual ports */
+ if (!srio1_used)
+ setbits_be32(devdisr, _DEVDISR_SRIO1);
+ if (!srio2_used)
+ setbits_be32(devdisr, _DEVDISR_SRIO2);
+#endif
+
+ /* neither port is used - disable everything */
+ if (!srio1_used && !srio2_used) {
+ setbits_be32(devdisr, _DEVDISR_SRIO1);
+ setbits_be32(devdisr, _DEVDISR_SRIO2);
+ setbits_be32(devdisr, _DEVDISR_RMU);
+ }
+}
+
+#ifdef CONFIG_SRIO_PCIE_BOOT_MASTER
+void srio_boot_master(int port)
+{
+ struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR;
+
+ /* set port accept-all */
+ out_be32((void *)&srio->impl.port[port - 1].ptaacr,
+ SRIO_PORT_ACCEPT_ALL);
+
+ debug("SRIOBOOT - MASTER: Master port [ %d ] for srio boot.\n", port);
+ /* configure inbound window for slave's u-boot image */
+ debug("SRIOBOOT - MASTER: Inbound window for slave's image; "
+ "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n",
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS,
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwtar,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwbar,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1 >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[0].riwar,
+ SRIO_IB_ATMU_AR
+ | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE));
+
+ /* configure inbound window for slave's u-boot image */
+ debug("SRIOBOOT - MASTER: Inbound window for slave's image; "
+ "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n",
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS,
+ (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwtar,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwbar,
+ CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2 >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[1].riwar,
+ SRIO_IB_ATMU_AR
+ | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE));
+
+ /* configure inbound window for slave's ucode and ENV */
+ debug("SRIOBOOT - MASTER: Inbound window for slave's ucode and ENV; "
+ "Local = 0x%llx, Srio = 0x%llx, Size = 0x%x\n",
+ (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS,
+ (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS,
+ CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwtar,
+ CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwbar,
+ CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1].inbw[2].riwar,
+ SRIO_IB_ATMU_AR
+ | atmu_size_mask(CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE));
+}
+
+void srio_boot_master_release_slave(int port)
+{
+ struct ccsr_rio *srio = (void *)CONFIG_SYS_FSL_SRIO_ADDR;
+ u32 escsr;
+ debug("SRIOBOOT - MASTER: "
+ "Check the port status and release slave core ...\n");
+
+ escsr = in_be32((void *)&srio->lp_serial.port[port - 1].pescsr);
+ if (escsr & 0x2) {
+ if (escsr & 0x10100) {
+ debug("SRIOBOOT - MASTER: Port [ %d ] is error.\n",
+ port);
+ } else {
+ debug("SRIOBOOT - MASTER: "
+ "Port [ %d ] is ready, now release slave's core ...\n",
+ port);
+ /*
+ * configure outbound window
+ * with maintenance attribute to set slave's LCSBA1CSR
+ */
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[1].rowtar, 0);
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[1].rowtear, 0);
+ if (port - 1)
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[1].rowbar,
+ CONFIG_SYS_SRIO2_MEM_PHYS >> 12);
+ else
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[1].rowbar,
+ CONFIG_SYS_SRIO1_MEM_PHYS >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[1].rowar,
+ SRIO_OB_ATMU_AR_MAINT
+ | atmu_size_mask(SRIO_MAINT_WIN_SIZE));
+
+ /*
+ * configure outbound window
+ * with R/W attribute to set slave's BRR
+ */
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[2].rowtar,
+ SRIO_LCSBA1CSR >> 9);
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[2].rowtear, 0);
+ if (port - 1)
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[2].rowbar,
+ (CONFIG_SYS_SRIO2_MEM_PHYS
+ + SRIO_MAINT_WIN_SIZE) >> 12);
+ else
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[2].rowbar,
+ (CONFIG_SYS_SRIO1_MEM_PHYS
+ + SRIO_MAINT_WIN_SIZE) >> 12);
+ out_be32((void *)&srio->atmu.port[port - 1]
+ .outbw[2].rowar,
+ SRIO_OB_ATMU_AR_RW
+ | atmu_size_mask(SRIO_RW_WIN_SIZE));
+
+ /*
+ * Set the LCSBA1CSR register in slave
+ * by the maint-outbound window
+ */
+ if (port - 1) {
+ out_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT
+ + SRIO_LCSBA1CSR_OFFSET,
+ SRIO_LCSBA1CSR);
+ while (in_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT
+ + SRIO_LCSBA1CSR_OFFSET)
+ != SRIO_LCSBA1CSR)
+ ;
+ /*
+ * And then set the BRR register
+ * to release slave core
+ */
+ out_be32((void *)CONFIG_SYS_SRIO2_MEM_VIRT
+ + SRIO_MAINT_WIN_SIZE
+ + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET,
+ CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK);
+ } else {
+ out_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT
+ + SRIO_LCSBA1CSR_OFFSET,
+ SRIO_LCSBA1CSR);
+ while (in_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT
+ + SRIO_LCSBA1CSR_OFFSET)
+ != SRIO_LCSBA1CSR)
+ ;
+ /*
+ * And then set the BRR register
+ * to release slave core
+ */
+ out_be32((void *)CONFIG_SYS_SRIO1_MEM_VIRT
+ + SRIO_MAINT_WIN_SIZE
+ + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET,
+ CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK);
+ }
+ debug("SRIOBOOT - MASTER: "
+ "Release slave successfully! Now the slave should start up!\n");
+ }
+ } else
+ debug("SRIOBOOT - MASTER: Port [ %d ] is not ready.\n", port);
+}
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c b/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c
new file mode 100644
index 0000000..48aa753
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c
@@ -0,0 +1,464 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/40x_spd_sdram.c
+ * This SPD SDRAM detection code supports IBM/AMCC PPC44x cpu with a
+ * SDRAM controller. Those are all current 405 PPC's.
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com
+ *
+ * Based on code by:
+ *
+ * Kenneth Johansson ,Ericsson AB.
+ * kenneth.johansson@etx.ericsson.se
+ *
+ * hacked up by bill hunter. fixed so we could run before
+ * serial_init and console_init. previous version avoided this by
+ * running out of cache memory during serial/console init, then running
+ * this code later.
+ *
+ * (C) Copyright 2002
+ * Jun Gu, Artesyn Technology, jung@artesyncp.com
+ * Support for AMCC 440 based on OpenBIOS draminit.c from IBM.
+ *
+ * (C) Copyright 2005
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <i2c.h>
+#include <asm/ppc4xx.h>
+
+#if defined(CONFIG_SPD_EEPROM) && !defined(CONFIG_440)
+
+/*
+ * Set default values
+ */
+#ifndef CONFIG_SYS_I2C_SPEED
+#define CONFIG_SYS_I2C_SPEED 50000
+#endif
+
+#define ONE_BILLION 1000000000
+
+#define SDRAM0_CFG_DCE 0x80000000
+#define SDRAM0_CFG_SRE 0x40000000
+#define SDRAM0_CFG_PME 0x20000000
+#define SDRAM0_CFG_MEMCHK 0x10000000
+#define SDRAM0_CFG_REGEN 0x08000000
+#define SDRAM0_CFG_ECCDD 0x00400000
+#define SDRAM0_CFG_EMDULR 0x00200000
+#define SDRAM0_CFG_DRW_SHIFT (31-6)
+#define SDRAM0_CFG_BRPF_SHIFT (31-8)
+
+#define SDRAM0_TR_CASL_SHIFT (31-8)
+#define SDRAM0_TR_PTA_SHIFT (31-13)
+#define SDRAM0_TR_CTP_SHIFT (31-15)
+#define SDRAM0_TR_LDF_SHIFT (31-17)
+#define SDRAM0_TR_RFTA_SHIFT (31-29)
+#define SDRAM0_TR_RCD_SHIFT (31-31)
+
+#define SDRAM0_RTR_SHIFT (31-15)
+#define SDRAM0_ECCCFG_SHIFT (31-11)
+
+/* SDRAM0_CFG enable macro */
+#define SDRAM0_CFG_BRPF(x) ( ( x & 0x3)<< SDRAM0_CFG_BRPF_SHIFT )
+
+#define SDRAM0_BXCR_SZ_MASK 0x000e0000
+#define SDRAM0_BXCR_AM_MASK 0x0000e000
+
+#define SDRAM0_BXCR_SZ_SHIFT (31-14)
+#define SDRAM0_BXCR_AM_SHIFT (31-18)
+
+#define SDRAM0_BXCR_SZ(x) ( (( x << SDRAM0_BXCR_SZ_SHIFT) & SDRAM0_BXCR_SZ_MASK) )
+#define SDRAM0_BXCR_AM(x) ( (( x << SDRAM0_BXCR_AM_SHIFT) & SDRAM0_BXCR_AM_MASK) )
+
+#ifdef CONFIG_SPDDRAM_SILENT
+# define SPD_ERR(x) do { return 0; } while (0)
+#else
+# define SPD_ERR(x) do { printf(x); return(0); } while (0)
+#endif
+
+#define sdram_HZ_to_ns(hertz) (1000000000/(hertz))
+
+/* function prototypes */
+int spd_read(uint addr);
+
+
+/*
+ * This function is reading data from the DIMM module EEPROM over the SPD bus
+ * and uses that to program the sdram controller.
+ *
+ * This works on boards that has the same schematics that the AMCC walnut has.
+ *
+ * Input: null for default I2C spd functions or a pointer to a custom function
+ * returning spd_data.
+ */
+
+long int spd_sdram(int(read_spd)(uint addr))
+{
+ int tmp,row,col;
+ int total_size,bank_size,bank_code;
+ int mode;
+ int bank_cnt;
+
+ int sdram0_pmit=0x07c00000;
+ int sdram0_b0cr;
+ int sdram0_b1cr = 0;
+#ifndef CONFIG_405EP /* not on PPC405EP */
+ int sdram0_b2cr = 0;
+ int sdram0_b3cr = 0;
+ int sdram0_besr0 = -1;
+ int sdram0_besr1 = -1;
+ int sdram0_eccesr = -1;
+ int sdram0_ecccfg;
+ int ecc_on;
+#endif
+
+ int sdram0_rtr=0;
+ int sdram0_tr=0;
+
+ int sdram0_cfg=0;
+
+ int t_rp;
+ int t_rcd;
+ int t_ras;
+ int t_rc;
+ int min_cas;
+
+ PPC4xx_SYS_INFO sys_info;
+ unsigned long bus_period_x_10;
+
+ /*
+ * get the board info
+ */
+ get_sys_info(&sys_info);
+ bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+
+ if (read_spd == 0){
+ read_spd=spd_read;
+ /*
+ * Make sure I2C controller is initialized
+ * before continuing.
+ */
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ }
+
+ /* Make shure we are using SDRAM */
+ if (read_spd(2) != 0x04) {
+ SPD_ERR("SDRAM - non SDRAM memory module found\n");
+ }
+
+ /* ------------------------------------------------------------------
+ * configure memory timing register
+ *
+ * data from DIMM:
+ * 27 IN Row Precharge Time ( t RP)
+ * 29 MIN RAS to CAS Delay ( t RCD)
+ * 127 Component and Clock Detail ,clk0-clk3, junction temp, CAS
+ * -------------------------------------------------------------------*/
+
+ /*
+ * first figure out which cas latency mode to use
+ * use the min supported mode
+ */
+
+ tmp = read_spd(127) & 0x6;
+ if (tmp == 0x02) { /* only cas = 2 supported */
+ min_cas = 2;
+/* t_ck = read_spd(9); */
+/* t_ac = read_spd(10); */
+ } else if (tmp == 0x04) { /* only cas = 3 supported */
+ min_cas = 3;
+/* t_ck = read_spd(9); */
+/* t_ac = read_spd(10); */
+ } else if (tmp == 0x06) { /* 2,3 supported, so use 2 */
+ min_cas = 2;
+/* t_ck = read_spd(23); */
+/* t_ac = read_spd(24); */
+ } else {
+ SPD_ERR("SDRAM - unsupported CAS latency \n");
+ }
+
+ /* get some timing values, t_rp,t_rcd,t_ras,t_rc
+ */
+ t_rp = read_spd(27);
+ t_rcd = read_spd(29);
+ t_ras = read_spd(30);
+ t_rc = t_ras + t_rp;
+
+ /* The following timing calcs subtract 1 before deviding.
+ * this has effect of using ceiling instead of floor rounding,
+ * and also subtracting 1 to convert number to reg value
+ */
+ /* set up CASL */
+ sdram0_tr = (min_cas - 1) << SDRAM0_TR_CASL_SHIFT;
+ /* set up PTA */
+ sdram0_tr |= ((((t_rp - 1) * 10)/bus_period_x_10) & 0x3) << SDRAM0_TR_PTA_SHIFT;
+ /* set up CTP */
+ tmp = (((t_rc - t_rcd - t_rp -1) * 10) / bus_period_x_10) & 0x3;
+ if (tmp < 1)
+ tmp = 1;
+ sdram0_tr |= tmp << SDRAM0_TR_CTP_SHIFT;
+ /* set LDF = 2 cycles, reg value = 1 */
+ sdram0_tr |= 1 << SDRAM0_TR_LDF_SHIFT;
+ /* set RFTA = t_rfc/bus_period, use t_rfc = t_rc */
+ tmp = (((t_rc - 1) * 10) / bus_period_x_10) - 3;
+ if (tmp < 0)
+ tmp = 0;
+ if (tmp > 6)
+ tmp = 6;
+ sdram0_tr |= tmp << SDRAM0_TR_RFTA_SHIFT;
+ /* set RCD = t_rcd/bus_period*/
+ sdram0_tr |= ((((t_rcd - 1) * 10) / bus_period_x_10) &0x3) << SDRAM0_TR_RCD_SHIFT ;
+
+
+ /*------------------------------------------------------------------
+ * configure RTR register
+ * -------------------------------------------------------------------*/
+ row = read_spd(3);
+ col = read_spd(4);
+ tmp = read_spd(12) & 0x7f ; /* refresh type less self refresh bit */
+ switch (tmp) {
+ case 0x00:
+ tmp = 15625;
+ break;
+ case 0x01:
+ tmp = 15625 / 4;
+ break;
+ case 0x02:
+ tmp = 15625 / 2;
+ break;
+ case 0x03:
+ tmp = 15625 * 2;
+ break;
+ case 0x04:
+ tmp = 15625 * 4;
+ break;
+ case 0x05:
+ tmp = 15625 * 8;
+ break;
+ default:
+ SPD_ERR("SDRAM - Bad refresh period \n");
+ }
+ /* convert from nsec to bus cycles */
+ tmp = (tmp * 10) / bus_period_x_10;
+ sdram0_rtr = (tmp & 0x3ff8) << SDRAM0_RTR_SHIFT;
+
+ /*------------------------------------------------------------------
+ * determine the number of banks used
+ * -------------------------------------------------------------------*/
+ /* byte 7:6 is module data width */
+ if (read_spd(7) != 0)
+ SPD_ERR("SDRAM - unsupported module width\n");
+ tmp = read_spd(6);
+ if (tmp < 32)
+ SPD_ERR("SDRAM - unsupported module width\n");
+ else if (tmp < 64)
+ bank_cnt = 1; /* one bank per sdram side */
+ else if (tmp < 73)
+ bank_cnt = 2; /* need two banks per side */
+ else if (tmp < 161)
+ bank_cnt = 4; /* need four banks per side */
+ else
+ SPD_ERR("SDRAM - unsupported module width\n");
+
+ /* byte 5 is the module row count (refered to as dimm "sides") */
+ tmp = read_spd(5);
+ if (tmp == 1)
+ ;
+ else if (tmp==2)
+ bank_cnt *= 2;
+ else if (tmp==4)
+ bank_cnt *= 4;
+ else
+ bank_cnt = 8; /* 8 is an error code */
+
+ if (bank_cnt > 4) /* we only have 4 banks to work with */
+ SPD_ERR("SDRAM - unsupported module rows for this width\n");
+
+#ifndef CONFIG_405EP /* not on PPC405EP */
+ /* now check for ECC ability of module. We only support ECC
+ * on 32 bit wide devices with 8 bit ECC.
+ */
+ if ((read_spd(11)==2) && (read_spd(6)==40) && (read_spd(14)==8)) {
+ sdram0_ecccfg = 0xf << SDRAM0_ECCCFG_SHIFT;
+ ecc_on = 1;
+ } else {
+ sdram0_ecccfg = 0;
+ ecc_on = 0;
+ }
+#endif
+
+ /*------------------------------------------------------------------
+ * calculate total size
+ * -------------------------------------------------------------------*/
+ /* calculate total size and do sanity check */
+ tmp = read_spd(31);
+ total_size = 1 << 22; /* total_size = 4MB */
+ /* now multiply 4M by the smallest device row density */
+ /* note that we don't support asymetric rows */
+ while (((tmp & 0x0001) == 0) && (tmp != 0)) {
+ total_size = total_size << 1;
+ tmp = tmp >> 1;
+ }
+ total_size *= read_spd(5); /* mult by module rows (dimm sides) */
+
+ /*------------------------------------------------------------------
+ * map rows * cols * banks to a mode
+ * -------------------------------------------------------------------*/
+
+ switch (row) {
+ case 11:
+ switch (col) {
+ case 8:
+ mode=4; /* mode 5 */
+ break;
+ case 9:
+ case 10:
+ mode=0; /* mode 1 */
+ break;
+ default:
+ SPD_ERR("SDRAM - unsupported mode\n");
+ }
+ break;
+ case 12:
+ switch (col) {
+ case 8:
+ mode=3; /* mode 4 */
+ break;
+ case 9:
+ case 10:
+ mode=1; /* mode 2 */
+ break;
+ default:
+ SPD_ERR("SDRAM - unsupported mode\n");
+ }
+ break;
+ case 13:
+ switch (col) {
+ case 8:
+ mode=5; /* mode 6 */
+ break;
+ case 9:
+ case 10:
+ if (read_spd(17) == 2)
+ mode = 6; /* mode 7 */
+ else
+ mode = 2; /* mode 3 */
+ break;
+ case 11:
+ mode = 2; /* mode 3 */
+ break;
+ default:
+ SPD_ERR("SDRAM - unsupported mode\n");
+ }
+ break;
+ default:
+ SPD_ERR("SDRAM - unsupported mode\n");
+ }
+
+ /*------------------------------------------------------------------
+ * using the calculated values, compute the bank
+ * config register values.
+ * -------------------------------------------------------------------*/
+
+ /* compute the size of each bank */
+ bank_size = total_size / bank_cnt;
+ /* convert bank size to bank size code for ppc4xx
+ by takeing log2(bank_size) - 22 */
+ tmp = bank_size; /* start with tmp = bank_size */
+ bank_code = 0; /* and bank_code = 0 */
+ while (tmp > 1) { /* this takes log2 of tmp */
+ bank_code++; /* and stores result in bank_code */
+ tmp = tmp >> 1;
+ } /* bank_code is now log2(bank_size) */
+ bank_code -= 22; /* subtract 22 to get the code */
+
+ tmp = SDRAM0_BXCR_SZ(bank_code) | SDRAM0_BXCR_AM(mode) | 1;
+ sdram0_b0cr = (bank_size * 0) | tmp;
+#ifndef CONFIG_405EP /* not on PPC405EP */
+ if (bank_cnt > 1)
+ sdram0_b2cr = (bank_size * 1) | tmp;
+ if (bank_cnt > 2)
+ sdram0_b1cr = (bank_size * 2) | tmp;
+ if (bank_cnt > 3)
+ sdram0_b3cr = (bank_size * 3) | tmp;
+#else
+ /* PPC405EP chip only supports two SDRAM banks */
+ if (bank_cnt > 1)
+ sdram0_b1cr = (bank_size * 1) | tmp;
+ if (bank_cnt > 2)
+ total_size = 2 * bank_size;
+#endif
+
+ /*
+ * enable sdram controller DCE=1
+ * enable burst read prefetch to 32 bytes BRPF=2
+ * leave other functions off
+ */
+
+ /*------------------------------------------------------------------
+ * now that we've done our calculations, we are ready to
+ * program all the registers.
+ * -------------------------------------------------------------------*/
+
+ /* disable memcontroller so updates work */
+ mtsdram(SDRAM0_CFG, 0);
+
+#ifndef CONFIG_405EP /* not on PPC405EP */
+ mtsdram(SDRAM0_BESR0, sdram0_besr0);
+ mtsdram(SDRAM0_BESR1, sdram0_besr1);
+ mtsdram(SDRAM0_ECCCFG, sdram0_ecccfg);
+ mtsdram(SDRAM0_ECCESR, sdram0_eccesr);
+#endif
+ mtsdram(SDRAM0_RTR, sdram0_rtr);
+ mtsdram(SDRAM0_PMIT, sdram0_pmit);
+ mtsdram(SDRAM0_B0CR, sdram0_b0cr);
+ mtsdram(SDRAM0_B1CR, sdram0_b1cr);
+#ifndef CONFIG_405EP /* not on PPC405EP */
+ mtsdram(SDRAM0_B2CR, sdram0_b2cr);
+ mtsdram(SDRAM0_B3CR, sdram0_b3cr);
+#endif
+ mtsdram(SDRAM0_TR, sdram0_tr);
+
+ /* SDRAM have a power on delay, 500 micro should do */
+ udelay(500);
+ sdram0_cfg = SDRAM0_CFG_DCE | SDRAM0_CFG_BRPF(1) | SDRAM0_CFG_ECCDD | SDRAM0_CFG_EMDULR;
+#ifndef CONFIG_405EP /* not on PPC405EP */
+ if (ecc_on)
+ sdram0_cfg |= SDRAM0_CFG_MEMCHK;
+#endif
+ mtsdram(SDRAM0_CFG, sdram0_cfg);
+
+ return (total_size);
+}
+
+int spd_read(uint addr)
+{
+ uchar data[2];
+
+ if (i2c_read(SPD_EEPROM_ADDRESS, addr, 1, data, 1) == 0)
+ return (int)data[0];
+ else
+ return 0;
+}
+
+#endif /* CONFIG_SPD_EEPROM */
diff --git a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c
new file mode 100644
index 0000000..161d274
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c
@@ -0,0 +1,1244 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/44x_spd_ddr.c
+ * This SPD DDR detection code supports IBM/AMCC PPC44x cpu with a
+ * DDR controller. Those are 440GP/GX/EP/GR.
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com
+ *
+ * Based on code by:
+ *
+ * Kenneth Johansson ,Ericsson AB.
+ * kenneth.johansson@etx.ericsson.se
+ *
+ * hacked up by bill hunter. fixed so we could run before
+ * serial_init and console_init. previous version avoided this by
+ * running out of cache memory during serial/console init, then running
+ * this code later.
+ *
+ * (C) Copyright 2002
+ * Jun Gu, Artesyn Technology, jung@artesyncp.com
+ * Support for AMCC 440 based on OpenBIOS draminit.c from IBM.
+ *
+ * (C) Copyright 2005-2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <asm/processor.h>
+#include <i2c.h>
+#include <asm/ppc4xx.h>
+#include <asm/mmu.h>
+
+#include "ecc.h"
+
+#if defined(CONFIG_SPD_EEPROM) && \
+ (defined(CONFIG_440GP) || defined(CONFIG_440GX) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR))
+
+/*
+ * Set default values
+ */
+#ifndef CONFIG_SYS_I2C_SPEED
+#define CONFIG_SYS_I2C_SPEED 50000
+#endif
+
+#define ONE_BILLION 1000000000
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang (void)
+{
+ hang ();
+}
+void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+
+/*-----------------------------------------------------------------------------+
+ | General Definition
+ +-----------------------------------------------------------------------------*/
+#define DEFAULT_SPD_ADDR1 0x53
+#define DEFAULT_SPD_ADDR2 0x52
+#define MAXBANKS 4 /* at most 4 dimm banks */
+#define MAX_SPD_BYTES 256
+#define NUMHALFCYCLES 4
+#define NUMMEMTESTS 8
+#define NUMMEMWORDS 8
+#define MAXBXCR 4
+
+/*
+ * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory
+ * region. Right now the cache should still be disabled in U-Boot because of the
+ * EMAC driver, that need it's buffer descriptor to be located in non cached
+ * memory.
+ *
+ * If at some time this restriction doesn't apply anymore, just define
+ * CONFIG_4xx_DCACHE in the board config file and this code should setup
+ * everything correctly.
+ */
+#ifdef CONFIG_4xx_DCACHE
+#define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */
+#else
+#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */
+#endif
+
+/* bank_parms is used to sort the bank sizes by descending order */
+struct bank_param {
+ unsigned long cr;
+ unsigned long bank_size_bytes;
+};
+
+typedef struct bank_param BANKPARMS;
+
+#ifdef CONFIG_SYS_SIMULATE_SPD_EEPROM
+extern const unsigned char cfg_simulate_spd_eeprom[128];
+#endif
+
+static unsigned char spd_read(uchar chip, uint addr);
+static void get_spd_info(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_mem_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_volt_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_cfg0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_cfg1(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_rtr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_tr0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_tr1(void);
+
+static unsigned long program_bxcr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+
+/*
+ * This function is reading data from the DIMM module EEPROM over the SPD bus
+ * and uses that to program the sdram controller.
+ *
+ * This works on boards that has the same schematics that the AMCC walnut has.
+ *
+ * BUG: Don't handle ECC memory
+ * BUG: A few values in the TR register is currently hardcoded
+ */
+long int spd_sdram(void) {
+ unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
+ unsigned long dimm_populated[sizeof(iic0_dimm_addr)];
+ unsigned long total_size;
+ unsigned long cfg0;
+ unsigned long mcsts;
+ unsigned long num_dimm_banks; /* on board dimm banks */
+
+ num_dimm_banks = sizeof(iic0_dimm_addr);
+
+ /*
+ * Make sure I2C controller is initialized
+ * before continuing.
+ */
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+ /*
+ * Read the SPD information using I2C interface. Check to see if the
+ * DIMM slots are populated.
+ */
+ get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * Check the memory type for the dimms plugged.
+ */
+ check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * Check the voltage type for the dimms plugged.
+ */
+ check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ /*
+ * Soft-reset SDRAM controller.
+ */
+ mtsdr(SDR0_SRST, SDR0_SRST_DMC);
+ mtsdr(SDR0_SRST, 0x00000000);
+#endif
+
+ /*
+ * program 440GP SDRAM controller options (SDRAM0_CFG0)
+ */
+ program_cfg0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program 440GP SDRAM controller options (SDRAM0_CFG1)
+ */
+ program_cfg1(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program SDRAM refresh register (SDRAM0_RTR)
+ */
+ program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program SDRAM Timing Register 0 (SDRAM0_TR0)
+ */
+ program_tr0(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*
+ * program the BxCR registers to find out total sdram installed
+ */
+ total_size = program_bxcr(dimm_populated, iic0_dimm_addr,
+ num_dimm_banks);
+
+#ifdef CONFIG_PROG_SDRAM_TLB /* this define should eventually be removed */
+ /* and program tlb entries for this size (dynamic) */
+ program_tlb(0, 0, total_size, MY_TLB_WORD2_I_ENABLE);
+#endif
+
+ /*
+ * program SDRAM Clock Timing Register (SDRAM0_CLKTR)
+ */
+ mtsdram(SDRAM0_CLKTR, 0x40000000);
+
+ /*
+ * delay to ensure 200 usec has elapsed
+ */
+ udelay(400);
+
+ /*
+ * enable the memory controller
+ */
+ mfsdram(SDRAM0_CFG0, cfg0);
+ mtsdram(SDRAM0_CFG0, cfg0 | SDRAM_CFG0_DCEN);
+
+ /*
+ * wait for SDRAM_CFG0_DC_EN to complete
+ */
+ while (1) {
+ mfsdram(SDRAM0_MCSTS, mcsts);
+ if ((mcsts & SDRAM_MCSTS_MRSC) != 0)
+ break;
+ }
+
+ /*
+ * program SDRAM Timing Register 1, adding some delays
+ */
+ program_tr1();
+
+#ifdef CONFIG_DDR_ECC
+ /*
+ * If ecc is enabled, initialize the parity bits.
+ */
+ ecc_init(CONFIG_SYS_SDRAM_BASE, total_size);
+#endif
+
+ return total_size;
+}
+
+static unsigned char spd_read(uchar chip, uint addr)
+{
+ unsigned char data[2];
+
+#ifdef CONFIG_SYS_SIMULATE_SPD_EEPROM
+ if (chip == CONFIG_SYS_SIMULATE_SPD_EEPROM) {
+ /*
+ * Onboard spd eeprom requested -> simulate values
+ */
+ return cfg_simulate_spd_eeprom[addr];
+ }
+#endif /* CONFIG_SYS_SIMULATE_SPD_EEPROM */
+
+ if (i2c_probe(chip) == 0) {
+ if (i2c_read(chip, addr, 1, data, 1) == 0) {
+ return data[0];
+ }
+ }
+
+ return 0;
+}
+
+static void get_spd_info(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long dimm_found;
+ unsigned char num_of_bytes;
+ unsigned char total_size;
+
+ dimm_found = false;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ num_of_bytes = 0;
+ total_size = 0;
+
+ num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
+ total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
+
+ if ((num_of_bytes != 0) && (total_size != 0)) {
+ dimm_populated[dimm_num] = true;
+ dimm_found = true;
+ debug("DIMM slot %lu: populated\n", dimm_num);
+ } else {
+ dimm_populated[dimm_num] = false;
+ debug("DIMM slot %lu: Not populated\n", dimm_num);
+ }
+ }
+
+ if (dimm_found == false) {
+ printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n");
+ spd_ddr_init_hang ();
+ }
+}
+
+static void check_mem_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned char dimm_type;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == true) {
+ dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);
+ switch (dimm_type) {
+ case 7:
+ debug("DIMM slot %lu: DDR SDRAM detected\n", dimm_num);
+ break;
+ default:
+ printf("ERROR: Unsupported DIMM detected in slot %lu.\n",
+ dimm_num);
+ printf("Only DDR SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ }
+ }
+ }
+}
+
+static void check_volt_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long voltage_type;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == true) {
+ voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
+ if (voltage_type != 0x04) {
+ printf("ERROR: DIMM %lu with unsupported voltage level.\n",
+ dimm_num);
+ spd_ddr_init_hang ();
+ } else {
+ debug("DIMM %lu voltage level supported.\n", dimm_num);
+ }
+ break;
+ }
+ }
+}
+
+static void program_cfg0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long cfg0;
+ unsigned long ecc_enabled;
+ unsigned char ecc;
+ unsigned char attributes;
+ unsigned long data_width;
+
+ /*
+ * get Memory Controller Options 0 data
+ */
+ mfsdram(SDRAM0_CFG0, cfg0);
+
+ /*
+ * clear bits
+ */
+ cfg0 &= ~(SDRAM_CFG0_DCEN | SDRAM_CFG0_MCHK_MASK |
+ SDRAM_CFG0_RDEN | SDRAM_CFG0_PMUD |
+ SDRAM_CFG0_DMWD_MASK |
+ SDRAM_CFG0_UIOS_MASK | SDRAM_CFG0_PDP);
+
+
+ /*
+ * FIXME: assume the DDR SDRAMs in both banks are the same
+ */
+ ecc_enabled = true;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == true) {
+ ecc = spd_read(iic0_dimm_addr[dimm_num], 11);
+ if (ecc != 0x02) {
+ ecc_enabled = false;
+ }
+
+ /*
+ * program Registered DIMM Enable
+ */
+ attributes = spd_read(iic0_dimm_addr[dimm_num], 21);
+ if ((attributes & 0x02) != 0x00) {
+ cfg0 |= SDRAM_CFG0_RDEN;
+ }
+
+ /*
+ * program DDR SDRAM Data Width
+ */
+ data_width =
+ (unsigned long)spd_read(iic0_dimm_addr[dimm_num],6) +
+ (((unsigned long)spd_read(iic0_dimm_addr[dimm_num],7)) << 8);
+ if (data_width == 64 || data_width == 72) {
+ cfg0 |= SDRAM_CFG0_DMWD_64;
+ } else if (data_width == 32 || data_width == 40) {
+ cfg0 |= SDRAM_CFG0_DMWD_32;
+ } else {
+ printf("WARNING: DIMM with datawidth of %lu bits.\n",
+ data_width);
+ printf("Only DIMMs with 32 or 64 bit datawidths supported.\n");
+ spd_ddr_init_hang ();
+ }
+ break;
+ }
+ }
+
+ /*
+ * program Memory Data Error Checking
+ */
+ if (ecc_enabled == true) {
+ cfg0 |= SDRAM_CFG0_MCHK_GEN;
+ } else {
+ cfg0 |= SDRAM_CFG0_MCHK_NON;
+ }
+
+ /*
+ * program Page Management Unit (0 == enabled)
+ */
+ cfg0 &= ~SDRAM_CFG0_PMUD;
+
+ /*
+ * program Memory Controller Options 0
+ * Note: DCEN must be enabled after all DDR SDRAM controller
+ * configuration registers get initialized.
+ */
+ mtsdram(SDRAM0_CFG0, cfg0);
+}
+
+static void program_cfg1(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long cfg1;
+ mfsdram(SDRAM0_CFG1, cfg1);
+
+ /*
+ * Self-refresh exit, disable PM
+ */
+ cfg1 &= ~(SDRAM_CFG1_SRE | SDRAM_CFG1_PMEN);
+
+ /*
+ * program Memory Controller Options 1
+ */
+ mtsdram(SDRAM0_CFG1, cfg1);
+}
+
+static void program_rtr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long bus_period_x_10;
+ unsigned long refresh_rate = 0;
+ unsigned char refresh_rate_type;
+ unsigned long refresh_interval;
+ unsigned long sdram_rtr;
+ PPC4xx_SYS_INFO sys_info;
+
+ /*
+ * get the board info
+ */
+ get_sys_info(&sys_info);
+ bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == true) {
+ refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12);
+ switch (refresh_rate_type) {
+ case 0x00:
+ refresh_rate = 15625;
+ break;
+ case 0x01:
+ refresh_rate = 15625/4;
+ break;
+ case 0x02:
+ refresh_rate = 15625/2;
+ break;
+ case 0x03:
+ refresh_rate = 15626*2;
+ break;
+ case 0x04:
+ refresh_rate = 15625*4;
+ break;
+ case 0x05:
+ refresh_rate = 15625*8;
+ break;
+ default:
+ printf("ERROR: DIMM %lu, unsupported refresh rate/type.\n",
+ dimm_num);
+ printf("Replace the DIMM module with a supported DIMM.\n");
+ break;
+ }
+
+ break;
+ }
+ }
+
+ refresh_interval = refresh_rate * 10 / bus_period_x_10;
+ sdram_rtr = (refresh_interval & 0x3ff8) << 16;
+
+ /*
+ * program Refresh Timer Register (SDRAM0_RTR)
+ */
+ mtsdram(SDRAM0_RTR, sdram_rtr);
+}
+
+static void program_tr0(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long tr0;
+ unsigned char wcsbc;
+ unsigned char t_rp_ns;
+ unsigned char t_rcd_ns;
+ unsigned char t_ras_ns;
+ unsigned long t_rp_clk;
+ unsigned long t_ras_rcd_clk;
+ unsigned long t_rcd_clk;
+ unsigned long t_rfc_clk;
+ unsigned long plb_check;
+ unsigned char cas_bit;
+ unsigned long cas_index;
+ unsigned char cas_2_0_available;
+ unsigned char cas_2_5_available;
+ unsigned char cas_3_0_available;
+ unsigned long cycle_time_ns_x_10[3];
+ unsigned long tcyc_3_0_ns_x_10;
+ unsigned long tcyc_2_5_ns_x_10;
+ unsigned long tcyc_2_0_ns_x_10;
+ unsigned long tcyc_reg;
+ unsigned long bus_period_x_10;
+ PPC4xx_SYS_INFO sys_info;
+ unsigned long residue;
+
+ /*
+ * get the board info
+ */
+ get_sys_info(&sys_info);
+ bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10);
+
+ /*
+ * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
+ */
+ mfsdram(SDRAM0_TR0, tr0);
+ tr0 &= ~(SDRAM_TR0_SDWR_MASK | SDRAM_TR0_SDWD_MASK |
+ SDRAM_TR0_SDCL_MASK | SDRAM_TR0_SDPA_MASK |
+ SDRAM_TR0_SDCP_MASK | SDRAM_TR0_SDLD_MASK |
+ SDRAM_TR0_SDRA_MASK | SDRAM_TR0_SDRD_MASK);
+
+ /*
+ * initialization
+ */
+ wcsbc = 0;
+ t_rp_ns = 0;
+ t_rcd_ns = 0;
+ t_ras_ns = 0;
+ cas_2_0_available = true;
+ cas_2_5_available = true;
+ cas_3_0_available = true;
+ tcyc_2_0_ns_x_10 = 0;
+ tcyc_2_5_ns_x_10 = 0;
+ tcyc_3_0_ns_x_10 = 0;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == true) {
+ wcsbc = spd_read(iic0_dimm_addr[dimm_num], 15);
+ t_rp_ns = spd_read(iic0_dimm_addr[dimm_num], 27) >> 2;
+ t_rcd_ns = spd_read(iic0_dimm_addr[dimm_num], 29) >> 2;
+ t_ras_ns = spd_read(iic0_dimm_addr[dimm_num], 30);
+ cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18);
+
+ for (cas_index = 0; cas_index < 3; cas_index++) {
+ switch (cas_index) {
+ case 0:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
+ break;
+ case 1:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23);
+ break;
+ default:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25);
+ break;
+ }
+
+ if ((tcyc_reg & 0x0F) >= 10) {
+ printf("ERROR: Tcyc incorrect for DIMM in slot %lu\n",
+ dimm_num);
+ spd_ddr_init_hang ();
+ }
+
+ cycle_time_ns_x_10[cas_index] =
+ (((tcyc_reg & 0xF0) >> 4) * 10) + (tcyc_reg & 0x0F);
+ }
+
+ cas_index = 0;
+
+ if ((cas_bit & 0x80) != 0) {
+ cas_index += 3;
+ } else if ((cas_bit & 0x40) != 0) {
+ cas_index += 2;
+ } else if ((cas_bit & 0x20) != 0) {
+ cas_index += 1;
+ }
+
+ if (((cas_bit & 0x10) != 0) && (cas_index < 3)) {
+ tcyc_3_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
+ cas_index++;
+ } else {
+ if (cas_index != 0) {
+ cas_index++;
+ }
+ cas_3_0_available = false;
+ }
+
+ if (((cas_bit & 0x08) != 0) || (cas_index < 3)) {
+ tcyc_2_5_ns_x_10 = cycle_time_ns_x_10[cas_index];
+ cas_index++;
+ } else {
+ if (cas_index != 0) {
+ cas_index++;
+ }
+ cas_2_5_available = false;
+ }
+
+ if (((cas_bit & 0x04) != 0) || (cas_index < 3)) {
+ tcyc_2_0_ns_x_10 = cycle_time_ns_x_10[cas_index];
+ cas_index++;
+ } else {
+ if (cas_index != 0) {
+ cas_index++;
+ }
+ cas_2_0_available = false;
+ }
+
+ break;
+ }
+ }
+
+ /*
+ * Program SD_WR and SD_WCSBC fields
+ */
+ tr0 |= SDRAM_TR0_SDWR_2_CLK; /* Write Recovery: 2 CLK */
+ switch (wcsbc) {
+ case 0:
+ tr0 |= SDRAM_TR0_SDWD_0_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDWD_1_CLK;
+ break;
+ }
+
+ /*
+ * Program SD_CASL field
+ */
+ if ((cas_2_0_available == true) &&
+ (bus_period_x_10 >= tcyc_2_0_ns_x_10)) {
+ tr0 |= SDRAM_TR0_SDCL_2_0_CLK;
+ } else if ((cas_2_5_available == true) &&
+ (bus_period_x_10 >= tcyc_2_5_ns_x_10)) {
+ tr0 |= SDRAM_TR0_SDCL_2_5_CLK;
+ } else if ((cas_3_0_available == true) &&
+ (bus_period_x_10 >= tcyc_3_0_ns_x_10)) {
+ tr0 |= SDRAM_TR0_SDCL_3_0_CLK;
+ } else {
+ printf("ERROR: No supported CAS latency with the installed DIMMs.\n");
+ printf("Only CAS latencies of 2.0, 2.5, and 3.0 are supported.\n");
+ printf("Make sure the PLB speed is within the supported range.\n");
+ spd_ddr_init_hang ();
+ }
+
+ /*
+ * Calculate Trp in clock cycles and round up if necessary
+ * Program SD_PTA field
+ */
+ t_rp_clk = sys_info.freqPLB * t_rp_ns / ONE_BILLION;
+ plb_check = ONE_BILLION * t_rp_clk / t_rp_ns;
+ if (sys_info.freqPLB != plb_check) {
+ t_rp_clk++;
+ }
+ switch ((unsigned long)t_rp_clk) {
+ case 0:
+ case 1:
+ case 2:
+ tr0 |= SDRAM_TR0_SDPA_2_CLK;
+ break;
+ case 3:
+ tr0 |= SDRAM_TR0_SDPA_3_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDPA_4_CLK;
+ break;
+ }
+
+ /*
+ * Program SD_CTP field
+ */
+ t_ras_rcd_clk = sys_info.freqPLB * (t_ras_ns - t_rcd_ns) / ONE_BILLION;
+ plb_check = ONE_BILLION * t_ras_rcd_clk / (t_ras_ns - t_rcd_ns);
+ if (sys_info.freqPLB != plb_check) {
+ t_ras_rcd_clk++;
+ }
+ switch (t_ras_rcd_clk) {
+ case 0:
+ case 1:
+ case 2:
+ tr0 |= SDRAM_TR0_SDCP_2_CLK;
+ break;
+ case 3:
+ tr0 |= SDRAM_TR0_SDCP_3_CLK;
+ break;
+ case 4:
+ tr0 |= SDRAM_TR0_SDCP_4_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDCP_5_CLK;
+ break;
+ }
+
+ /*
+ * Program SD_LDF field
+ */
+ tr0 |= SDRAM_TR0_SDLD_2_CLK;
+
+ /*
+ * Program SD_RFTA field
+ * FIXME tRFC hardcoded as 75 nanoseconds
+ */
+ t_rfc_clk = sys_info.freqPLB / (ONE_BILLION / 75);
+ residue = sys_info.freqPLB % (ONE_BILLION / 75);
+ if (residue >= (ONE_BILLION / 150)) {
+ t_rfc_clk++;
+ }
+ switch (t_rfc_clk) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ tr0 |= SDRAM_TR0_SDRA_6_CLK;
+ break;
+ case 7:
+ tr0 |= SDRAM_TR0_SDRA_7_CLK;
+ break;
+ case 8:
+ tr0 |= SDRAM_TR0_SDRA_8_CLK;
+ break;
+ case 9:
+ tr0 |= SDRAM_TR0_SDRA_9_CLK;
+ break;
+ case 10:
+ tr0 |= SDRAM_TR0_SDRA_10_CLK;
+ break;
+ case 11:
+ tr0 |= SDRAM_TR0_SDRA_11_CLK;
+ break;
+ case 12:
+ tr0 |= SDRAM_TR0_SDRA_12_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDRA_13_CLK;
+ break;
+ }
+
+ /*
+ * Program SD_RCD field
+ */
+ t_rcd_clk = sys_info.freqPLB * t_rcd_ns / ONE_BILLION;
+ plb_check = ONE_BILLION * t_rcd_clk / t_rcd_ns;
+ if (sys_info.freqPLB != plb_check) {
+ t_rcd_clk++;
+ }
+ switch (t_rcd_clk) {
+ case 0:
+ case 1:
+ case 2:
+ tr0 |= SDRAM_TR0_SDRD_2_CLK;
+ break;
+ case 3:
+ tr0 |= SDRAM_TR0_SDRD_3_CLK;
+ break;
+ default:
+ tr0 |= SDRAM_TR0_SDRD_4_CLK;
+ break;
+ }
+
+ debug("tr0: %lx\n", tr0);
+ mtsdram(SDRAM0_TR0, tr0);
+}
+
+static int short_mem_test(void)
+{
+ unsigned long i, j;
+ unsigned long bxcr_num;
+ unsigned long *membase;
+ const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = {
+ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55}};
+
+ for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) {
+ mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (bxcr_num << 2));
+ if ((mfdcr(SDRAM0_CFGDATA) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) {
+ /* Bank is enabled */
+ membase = (unsigned long*)
+ (mfdcr(SDRAM0_CFGDATA) & SDRAM_BXCR_SDBA_MASK);
+
+ /*
+ * Run the short memory test
+ */
+ for (i = 0; i < NUMMEMTESTS; i++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ /* printf("bank enabled base:%x\n", &membase[j]); */
+ membase[j] = test[i][j];
+ ppcDcbf((unsigned long)&(membase[j]));
+ }
+
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (membase[j] != test[i][j]) {
+ ppcDcbf((unsigned long)&(membase[j]));
+ return 0;
+ }
+ ppcDcbf((unsigned long)&(membase[j]));
+ }
+
+ if (j < NUMMEMWORDS)
+ return 0;
+ }
+
+ /*
+ * see if the rdclt value passed
+ */
+ if (i < NUMMEMTESTS)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void program_tr1(void)
+{
+ unsigned long tr0;
+ unsigned long tr1;
+ unsigned long cfg0;
+ unsigned long ecc_temp;
+ unsigned long dlycal;
+ unsigned long dly_val;
+ unsigned long k;
+ unsigned long max_pass_length;
+ unsigned long current_pass_length;
+ unsigned long current_fail_length;
+ unsigned long current_start;
+ unsigned long rdclt;
+ unsigned long rdclt_offset;
+ long max_start;
+ long max_end;
+ long rdclt_average;
+ unsigned char window_found;
+ unsigned char fail_found;
+ unsigned char pass_found;
+ PPC4xx_SYS_INFO sys_info;
+
+ /*
+ * get the board info
+ */
+ get_sys_info(&sys_info);
+
+ /*
+ * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits
+ */
+ mfsdram(SDRAM0_TR1, tr1);
+ tr1 &= ~(SDRAM_TR1_RDSS_MASK | SDRAM_TR1_RDSL_MASK |
+ SDRAM_TR1_RDCD_MASK | SDRAM_TR1_RDCT_MASK);
+
+ mfsdram(SDRAM0_TR0, tr0);
+ if (((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) &&
+ (sys_info.freqPLB > 100000000)) {
+ tr1 |= SDRAM_TR1_RDSS_TR2;
+ tr1 |= SDRAM_TR1_RDSL_STAGE3;
+ tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
+ } else {
+ tr1 |= SDRAM_TR1_RDSS_TR1;
+ tr1 |= SDRAM_TR1_RDSL_STAGE2;
+ tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
+ }
+
+ /*
+ * save CFG0 ECC setting to a temporary variable and turn ECC off
+ */
+ mfsdram(SDRAM0_CFG0, cfg0);
+ ecc_temp = cfg0 & SDRAM_CFG0_MCHK_MASK;
+ mtsdram(SDRAM0_CFG0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_NON);
+
+ /*
+ * get the delay line calibration register value
+ */
+ mfsdram(SDRAM0_DLYCAL, dlycal);
+ dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2;
+
+ max_pass_length = 0;
+ max_start = 0;
+ max_end = 0;
+ current_pass_length = 0;
+ current_fail_length = 0;
+ current_start = 0;
+ rdclt_offset = 0;
+ window_found = false;
+ fail_found = false;
+ pass_found = false;
+ debug("Starting memory test ");
+
+ for (k = 0; k < NUMHALFCYCLES; k++) {
+ for (rdclt = 0; rdclt < dly_val; rdclt++) {
+ /*
+ * Set the timing reg for the test.
+ */
+ mtsdram(SDRAM0_TR1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt)));
+
+ if (short_mem_test()) {
+ if (fail_found == true) {
+ pass_found = true;
+ if (current_pass_length == 0) {
+ current_start = rdclt_offset + rdclt;
+ }
+
+ current_fail_length = 0;
+ current_pass_length++;
+
+ if (current_pass_length > max_pass_length) {
+ max_pass_length = current_pass_length;
+ max_start = current_start;
+ max_end = rdclt_offset + rdclt;
+ }
+ }
+ } else {
+ current_pass_length = 0;
+ current_fail_length++;
+
+ if (current_fail_length >= (dly_val>>2)) {
+ if (fail_found == false) {
+ fail_found = true;
+ } else if (pass_found == true) {
+ window_found = true;
+ break;
+ }
+ }
+ }
+ }
+ debug(".");
+
+ if (window_found == true)
+ break;
+
+ tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
+ rdclt_offset += dly_val;
+ }
+ debug("\n");
+
+ /*
+ * make sure we find the window
+ */
+ if (window_found == false) {
+ printf("ERROR: Cannot determine a common read delay.\n");
+ spd_ddr_init_hang ();
+ }
+
+ /*
+ * restore the orignal ECC setting
+ */
+ mtsdram(SDRAM0_CFG0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | ecc_temp);
+
+ /*
+ * set the SDRAM TR1 RDCD value
+ */
+ tr1 &= ~SDRAM_TR1_RDCD_MASK;
+ if ((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) {
+ tr1 |= SDRAM_TR1_RDCD_RCD_1_2;
+ } else {
+ tr1 |= SDRAM_TR1_RDCD_RCD_0_0;
+ }
+
+ /*
+ * set the SDRAM TR1 RDCLT value
+ */
+ tr1 &= ~SDRAM_TR1_RDCT_MASK;
+ while (max_end >= (dly_val << 1)) {
+ max_end -= (dly_val << 1);
+ max_start -= (dly_val << 1);
+ }
+
+ rdclt_average = ((max_start + max_end) >> 1);
+
+ if (rdclt_average < 0) {
+ rdclt_average = 0;
+ }
+
+ if (rdclt_average >= dly_val) {
+ rdclt_average -= dly_val;
+ tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK;
+ }
+ tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average);
+
+ debug("tr1: %lx\n", tr1);
+
+ /*
+ * program SDRAM Timing Register 1 TR1
+ */
+ mtsdram(SDRAM0_TR1, tr1);
+}
+
+static unsigned long program_bxcr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long bank_base_addr;
+ unsigned long cr;
+ unsigned long i;
+ unsigned long j;
+ unsigned long temp;
+ unsigned char num_row_addr;
+ unsigned char num_col_addr;
+ unsigned char num_banks;
+ unsigned char bank_size_id;
+ unsigned long ctrl_bank_num[MAXBANKS];
+ unsigned long bx_cr_num;
+ unsigned long largest_size_index;
+ unsigned long largest_size;
+ unsigned long current_size_index;
+ BANKPARMS bank_parms[MAXBXCR];
+ unsigned long sorted_bank_num[MAXBXCR]; /* DDR Controller bank number table (sorted by size) */
+ unsigned long sorted_bank_size[MAXBXCR]; /* DDR Controller bank size table (sorted by size)*/
+
+ /*
+ * Set the BxCR regs. First, wipe out the bank config registers.
+ */
+ for (bx_cr_num = 0; bx_cr_num < MAXBXCR; bx_cr_num++) {
+ mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (bx_cr_num << 2));
+ mtdcr(SDRAM0_CFGDATA, 0x00000000);
+ bank_parms[bx_cr_num].bank_size_bytes = 0;
+ }
+
+#ifdef CONFIG_BAMBOO
+ /*
+ * This next section is hardware dependent and must be programmed
+ * to match the hardware. For bamboo, the following holds...
+ * 1. SDRAM0_B0CR: Bank 0 of dimm 0 ctrl_bank_num : 0 (soldered onboard)
+ * 2. SDRAM0_B1CR: Bank 0 of dimm 1 ctrl_bank_num : 1
+ * 3. SDRAM0_B2CR: Bank 1 of dimm 1 ctrl_bank_num : 1
+ * 4. SDRAM0_B3CR: Bank 0 of dimm 2 ctrl_bank_num : 3
+ * ctrl_bank_num corresponds to the first usable DDR controller bank number by DIMM
+ */
+ ctrl_bank_num[0] = 0;
+ ctrl_bank_num[1] = 1;
+ ctrl_bank_num[2] = 3;
+#else
+ /*
+ * Ocotea, Ebony and the other IBM/AMCC eval boards have
+ * 2 DIMM slots with each max 2 banks
+ */
+ ctrl_bank_num[0] = 0;
+ ctrl_bank_num[1] = 2;
+#endif
+
+ /*
+ * reset the bank_base address
+ */
+ bank_base_addr = CONFIG_SYS_SDRAM_BASE;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == true) {
+ num_row_addr = spd_read(iic0_dimm_addr[dimm_num], 3);
+ num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4);
+ num_banks = spd_read(iic0_dimm_addr[dimm_num], 5);
+ bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31);
+ debug("DIMM%ld: row=%d col=%d banks=%d\n", dimm_num,
+ num_row_addr, num_col_addr, num_banks);
+
+ /*
+ * Set the SDRAM0_BxCR regs
+ */
+ cr = 0;
+ switch (bank_size_id) {
+ case 0x02:
+ cr |= SDRAM_BXCR_SDSZ_8;
+ break;
+ case 0x04:
+ cr |= SDRAM_BXCR_SDSZ_16;
+ break;
+ case 0x08:
+ cr |= SDRAM_BXCR_SDSZ_32;
+ break;
+ case 0x10:
+ cr |= SDRAM_BXCR_SDSZ_64;
+ break;
+ case 0x20:
+ cr |= SDRAM_BXCR_SDSZ_128;
+ break;
+ case 0x40:
+ cr |= SDRAM_BXCR_SDSZ_256;
+ break;
+ case 0x80:
+ cr |= SDRAM_BXCR_SDSZ_512;
+ break;
+ default:
+ printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
+ dimm_num);
+ printf("ERROR: Unsupported value for the banksize: %d.\n",
+ bank_size_id);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ }
+
+ switch (num_col_addr) {
+ case 0x08:
+ cr |= SDRAM_BXCR_SDAM_1;
+ break;
+ case 0x09:
+ cr |= SDRAM_BXCR_SDAM_2;
+ break;
+ case 0x0A:
+ cr |= SDRAM_BXCR_SDAM_3;
+ break;
+ case 0x0B:
+ cr |= SDRAM_BXCR_SDAM_4;
+ break;
+ default:
+ printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n",
+ dimm_num);
+ printf("ERROR: Unsupported value for number of "
+ "column addresses: %d.\n", num_col_addr);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ }
+
+ /*
+ * enable the bank
+ */
+ cr |= SDRAM_BXCR_SDBE;
+
+ for (i = 0; i < num_banks; i++) {
+ bank_parms[ctrl_bank_num[dimm_num]+i].bank_size_bytes =
+ (4 << 20) * bank_size_id;
+ bank_parms[ctrl_bank_num[dimm_num]+i].cr = cr;
+ debug("DIMM%ld-bank %ld (SDRAM0_B%ldCR): "
+ "bank_size_bytes=%ld\n",
+ dimm_num, i,
+ ctrl_bank_num[dimm_num] + i,
+ bank_parms[ctrl_bank_num[dimm_num] + i].bank_size_bytes);
+ }
+ }
+ }
+
+ /* Initialize sort tables */
+ for (i = 0; i < MAXBXCR; i++) {
+ sorted_bank_num[i] = i;
+ sorted_bank_size[i] = bank_parms[i].bank_size_bytes;
+ }
+
+ for (i = 0; i < MAXBXCR-1; i++) {
+ largest_size = sorted_bank_size[i];
+ largest_size_index = 255;
+
+ /* Find the largest remaining value */
+ for (j = i + 1; j < MAXBXCR; j++) {
+ if (sorted_bank_size[j] > largest_size) {
+ /* Save largest remaining value and its index */
+ largest_size = sorted_bank_size[j];
+ largest_size_index = j;
+ }
+ }
+
+ if (largest_size_index != 255) {
+ /* Swap the current and largest values */
+ current_size_index = sorted_bank_num[largest_size_index];
+ sorted_bank_size[largest_size_index] = sorted_bank_size[i];
+ sorted_bank_size[i] = largest_size;
+ sorted_bank_num[largest_size_index] = sorted_bank_num[i];
+ sorted_bank_num[i] = current_size_index;
+ }
+ }
+
+ /* Set the SDRAM0_BxCR regs thanks to sort tables */
+ for (bx_cr_num = 0, bank_base_addr = 0; bx_cr_num < MAXBXCR; bx_cr_num++) {
+ if (bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes) {
+ mtdcr(SDRAM0_CFGADDR, SDRAM0_B0CR + (sorted_bank_num[bx_cr_num] << 2));
+ temp = mfdcr(SDRAM0_CFGDATA) & ~(SDRAM_BXCR_SDBA_MASK | SDRAM_BXCR_SDSZ_MASK |
+ SDRAM_BXCR_SDAM_MASK | SDRAM_BXCR_SDBE);
+ temp = temp | (bank_base_addr & SDRAM_BXCR_SDBA_MASK) |
+ bank_parms[sorted_bank_num[bx_cr_num]].cr;
+ mtdcr(SDRAM0_CFGDATA, temp);
+ bank_base_addr += bank_parms[sorted_bank_num[bx_cr_num]].bank_size_bytes;
+ debug("SDRAM0_B%ldCR=0x%08lx\n",
+ sorted_bank_num[bx_cr_num], temp);
+ }
+ }
+
+ return(bank_base_addr);
+}
+#endif /* CONFIG_SPD_EEPROM */
diff --git a/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
new file mode 100644
index 0000000..def7ebf
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
@@ -0,0 +1,3167 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/44x_spd_ddr2.c
+ * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
+ * DDR2 controller (non Denali Core). Those currently are:
+ *
+ * 405: 405EX(r)
+ * 440/460: 440SP/440SPe/460EX/460GT
+ *
+ * Copyright (c) 2008 Nuovation System Designs, LLC
+ * Grant Erickson <gerickson@nuovations.com>
+
+ * (C) Copyright 2007-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * COPYRIGHT AMCC CORPORATION 2004
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <command.h>
+#include <asm/ppc4xx.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+
+#include "ecc.h"
+
+#define PPC4xx_IBM_DDR2_DUMP_REGISTER(mnemonic) \
+ do { \
+ u32 data; \
+ mfsdram(SDRAM_##mnemonic, data); \
+ printf("%20s[%02x] = 0x%08X\n", \
+ "SDRAM_" #mnemonic, SDRAM_##mnemonic, data); \
+ } while (0)
+
+#define PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(mnemonic) \
+ do { \
+ u32 data; \
+ data = mfdcr(SDRAM_##mnemonic); \
+ printf("%20s[%02x] = 0x%08X\n", \
+ "SDRAM_" #mnemonic, SDRAM_##mnemonic, data); \
+ } while (0)
+
+#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
+static void update_rdcc(void)
+{
+ u32 val;
+
+ /*
+ * Complete RDSS configuration as mentioned on page 7 of the AMCC
+ * PowerPC440SP/SPe DDR2 application note:
+ * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning"
+ *
+ * Or item #10 "10. Complete RDSS configuration" in chapter
+ * "22.2.9 SDRAM Initialization" of AMCC PPC460EX/EXr/GT users
+ * manual.
+ */
+ mfsdram(SDRAM_RTSR, val);
+ if ((val & SDRAM_RTSR_TRK1SM_MASK) == SDRAM_RTSR_TRK1SM_ATPLS1) {
+ mfsdram(SDRAM_RDCC, val);
+ if ((val & SDRAM_RDCC_RDSS_MASK) != SDRAM_RDCC_RDSS_T4) {
+ val += 0x40000000;
+ mtsdram(SDRAM_RDCC, val);
+ }
+ }
+}
+#endif
+
+#if defined(CONFIG_440)
+/*
+ * This DDR2 setup code can dynamically setup the TLB entries for the DDR2
+ * memory region. Right now the cache should still be disabled in U-Boot
+ * because of the EMAC driver, that need its buffer descriptor to be located
+ * in non cached memory.
+ *
+ * If at some time this restriction doesn't apply anymore, just define
+ * CONFIG_4xx_DCACHE in the board config file and this code should setup
+ * everything correctly.
+ */
+#ifdef CONFIG_4xx_DCACHE
+/* enable caching on SDRAM */
+#define MY_TLB_WORD2_I_ENABLE 0
+#else
+/* disable caching on SDRAM */
+#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE
+#endif /* CONFIG_4xx_DCACHE */
+
+void dcbz_area(u32 start_address, u32 num_bytes);
+#endif /* CONFIG_440 */
+
+#define MAXRANKS 4
+#define MAXBXCF 4
+
+#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
+
+#if !defined(CONFIG_NAND_SPL)
+/*-----------------------------------------------------------------------------+
+ * sdram_memsize
+ *-----------------------------------------------------------------------------*/
+phys_size_t sdram_memsize(void)
+{
+ phys_size_t mem_size;
+ unsigned long mcopt2;
+ unsigned long mcstat;
+ unsigned long mb0cf;
+ unsigned long sdsz;
+ unsigned long i;
+
+ mem_size = 0;
+
+ mfsdram(SDRAM_MCOPT2, mcopt2);
+ mfsdram(SDRAM_MCSTAT, mcstat);
+
+ /* DDR controller must be enabled and not in self-refresh. */
+ /* Otherwise memsize is zero. */
+ if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+ && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+ && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+ == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
+ for (i = 0; i < MAXBXCF; i++) {
+ mfsdram(SDRAM_MB0CF + (i << 2), mb0cf);
+ /* Banks enabled */
+ if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+#if defined(CONFIG_440)
+ sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK;
+#else
+ sdsz = mb0cf & SDRAM_RXBAS_SDSZ_MASK;
+#endif
+ switch(sdsz) {
+ case SDRAM_RXBAS_SDSZ_8:
+ mem_size+=8;
+ break;
+ case SDRAM_RXBAS_SDSZ_16:
+ mem_size+=16;
+ break;
+ case SDRAM_RXBAS_SDSZ_32:
+ mem_size+=32;
+ break;
+ case SDRAM_RXBAS_SDSZ_64:
+ mem_size+=64;
+ break;
+ case SDRAM_RXBAS_SDSZ_128:
+ mem_size+=128;
+ break;
+ case SDRAM_RXBAS_SDSZ_256:
+ mem_size+=256;
+ break;
+ case SDRAM_RXBAS_SDSZ_512:
+ mem_size+=512;
+ break;
+ case SDRAM_RXBAS_SDSZ_1024:
+ mem_size+=1024;
+ break;
+ case SDRAM_RXBAS_SDSZ_2048:
+ mem_size+=2048;
+ break;
+ case SDRAM_RXBAS_SDSZ_4096:
+ mem_size+=4096;
+ break;
+ default:
+ printf("WARNING: Unsupported bank size (SDSZ=0x%lx)!\n"
+ , sdsz);
+ mem_size=0;
+ break;
+ }
+ }
+ }
+ }
+
+ return mem_size << 20;
+}
+
+/*-----------------------------------------------------------------------------+
+ * is_ecc_enabled
+ *-----------------------------------------------------------------------------*/
+static unsigned long is_ecc_enabled(void)
+{
+ unsigned long val;
+
+ mfsdram(SDRAM_MCOPT1, val);
+
+ return SDRAM_MCOPT1_MCHK_CHK_DECODE(val);
+}
+
+/*-----------------------------------------------------------------------------+
+ * board_add_ram_info
+ *-----------------------------------------------------------------------------*/
+void board_add_ram_info(int use_default)
+{
+ PPC4xx_SYS_INFO board_cfg;
+ u32 val;
+
+ if (is_ecc_enabled())
+ puts(" (ECC");
+ else
+ puts(" (ECC not");
+
+ get_sys_info(&board_cfg);
+
+#if defined(CONFIG_405EX)
+ val = board_cfg.freqPLB;
+#else
+ mfsdr(SDR0_DDR0, val);
+ val = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(val), 1);
+#endif
+ printf(" enabled, %d MHz", (val * 2) / 1000000);
+
+ mfsdram(SDRAM_MMODE, val);
+ val = (val & SDRAM_MMODE_DCL_MASK) >> 4;
+ printf(", CL%d)", val);
+}
+#endif /* !CONFIG_NAND_SPL */
+
+#if defined(CONFIG_SPD_EEPROM)
+
+/*-----------------------------------------------------------------------------+
+ * Defines
+ *-----------------------------------------------------------------------------*/
+#define SDRAM_DDR1 1
+#define SDRAM_DDR2 2
+#define SDRAM_NONE 0
+
+#define MAXDIMMS 2
+#define MAX_SPD_BYTES 256 /* Max number of bytes on the DIMM's SPD EEPROM */
+
+#define ONE_BILLION 1000000000
+
+#define CMD_NOP (7 << 19)
+#define CMD_PRECHARGE (2 << 19)
+#define CMD_REFRESH (1 << 19)
+#define CMD_EMR (0 << 19)
+#define CMD_READ (5 << 19)
+#define CMD_WRITE (4 << 19)
+
+#define SELECT_MR (0 << 16)
+#define SELECT_EMR (1 << 16)
+#define SELECT_EMR2 (2 << 16)
+#define SELECT_EMR3 (3 << 16)
+
+/* MR */
+#define DLL_RESET 0x00000100
+
+#define WRITE_RECOV_2 (1 << 9)
+#define WRITE_RECOV_3 (2 << 9)
+#define WRITE_RECOV_4 (3 << 9)
+#define WRITE_RECOV_5 (4 << 9)
+#define WRITE_RECOV_6 (5 << 9)
+
+#define BURST_LEN_4 0x00000002
+
+/* EMR */
+#define ODT_0_OHM 0x00000000
+#define ODT_50_OHM 0x00000044
+#define ODT_75_OHM 0x00000004
+#define ODT_150_OHM 0x00000040
+
+#define ODS_FULL 0x00000000
+#define ODS_REDUCED 0x00000002
+#define OCD_CALIB_DEF 0x00000380
+
+/* defines for ODT (On Die Termination) of the 440SP(e) DDR2 controller */
+#define ODT_EB0R (0x80000000 >> 8)
+#define ODT_EB0W (0x80000000 >> 7)
+#define CALC_ODT_R(n) (ODT_EB0R << (n << 1))
+#define CALC_ODT_W(n) (ODT_EB0W << (n << 1))
+#define CALC_ODT_RW(n) (CALC_ODT_R(n) | CALC_ODT_W(n))
+
+/* Defines for the Read Cycle Delay test */
+#define NUMMEMTESTS 8
+#define NUMMEMWORDS 8
+#define NUMLOOPS 64 /* memory test loops */
+
+/*
+ * Newer PPC's like 440SPe, 460EX/GT can be equipped with more than 2GB of SDRAM.
+ * To support such configurations, we "only" map the first 2GB via the TLB's. We
+ * need some free virtual address space for the remaining peripherals like, SoC
+ * devices, FLASH etc.
+ *
+ * Note that ECC is currently not supported on configurations with more than 2GB
+ * SDRAM. This is because we only map the first 2GB on such systems, and therefore
+ * the ECC parity byte of the remaining area can't be written.
+ */
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang (void)
+{
+ hang ();
+}
+void spd_ddr_init_hang (void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+
+/*
+ * To provide an interface for board specific config values in this common
+ * DDR setup code, we implement he "weak" default functions here. They return
+ * the default value back to the caller.
+ *
+ * Please see include/configs/yucca.h for an example fora board specific
+ * implementation.
+ */
+u32 __ddr_wrdtr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
+
+u32 __ddr_clktr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
+
+
+/* Private Structure Definitions */
+
+/* enum only to ease code for cas latency setting */
+typedef enum ddr_cas_id {
+ DDR_CAS_2 = 20,
+ DDR_CAS_2_5 = 25,
+ DDR_CAS_3 = 30,
+ DDR_CAS_4 = 40,
+ DDR_CAS_5 = 50
+} ddr_cas_id_t;
+
+/*-----------------------------------------------------------------------------+
+ * Prototypes
+ *-----------------------------------------------------------------------------*/
+static void get_spd_info(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_mem_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_frequency(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_rank_number(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void check_voltage_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_memory_queue(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_codt(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_mode(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks,
+ ddr_cas_id_t *selected_cas,
+ int *write_recovery);
+static void program_tr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_rtr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_bxcf(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_copt1(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+static void program_initplr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks,
+ ddr_cas_id_t selected_cas,
+ int write_recovery);
+#ifdef CONFIG_DDR_ECC
+static void program_ecc(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks,
+ unsigned long tlb_word2_i_value);
+#endif
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+static void program_DQS_calibration(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks);
+#ifdef HARD_CODED_DQS /* calibration test with hardvalues */
+static void test(void);
+#else
+static void DQS_calibration_process(void);
+#endif
+#endif
+
+static unsigned char spd_read(uchar chip, uint addr)
+{
+ unsigned char data[2];
+
+ if (i2c_probe(chip) == 0)
+ if (i2c_read(chip, addr, 1, data, 1) == 0)
+ return data[0];
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------+
+ * initdram. Initializes the 440SP Memory Queue and DDR SDRAM controller.
+ * Note: This routine runs from flash with a stack set up in the chip's
+ * sram space. It is important that the routine does not require .sbss, .bss or
+ * .data sections. It also cannot call routines that require these sections.
+ *-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ * Function: initdram
+ * Description: Configures SDRAM memory banks for DDR operation.
+ * Auto Memory Configuration option reads the DDR SDRAM EEPROMs
+ * via the IIC bus and then configures the DDR SDRAM memory
+ * banks appropriately. If Auto Memory Configuration is
+ * not used, it is assumed that no DIMM is plugged
+ *-----------------------------------------------------------------------------*/
+phys_size_t initdram(int board_type)
+{
+ unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
+ unsigned long dimm_populated[MAXDIMMS] = {SDRAM_NONE, SDRAM_NONE};
+ unsigned long num_dimm_banks; /* on board dimm banks */
+ unsigned long val;
+ ddr_cas_id_t selected_cas = DDR_CAS_5; /* preset to silence compiler */
+ int write_recovery;
+ phys_size_t dram_size = 0;
+
+ num_dimm_banks = sizeof(iic0_dimm_addr);
+
+ /*------------------------------------------------------------------
+ * Reset the DDR-SDRAM controller.
+ *-----------------------------------------------------------------*/
+ mtsdr(SDR0_SRST, SDR0_SRST0_DMC);
+ mtsdr(SDR0_SRST, 0x00000000);
+
+ /*
+ * Make sure I2C controller is initialized
+ * before continuing.
+ */
+
+ /* switch to correct I2C bus */
+ I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM);
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+ /*------------------------------------------------------------------
+ * Clear out the serial presence detect buffers.
+ * Perform IIC reads from the dimm. Fill in the spds.
+ * Check to see if the dimm slots are populated
+ *-----------------------------------------------------------------*/
+ get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Check the memory type for the dimms plugged.
+ *-----------------------------------------------------------------*/
+ check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Check the frequency supported for the dimms plugged.
+ *-----------------------------------------------------------------*/
+ check_frequency(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Check the total rank number.
+ *-----------------------------------------------------------------*/
+ check_rank_number(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Check the voltage type for the dimms plugged.
+ *-----------------------------------------------------------------*/
+ check_voltage_type(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Program SDRAM controller options 2 register
+ * Except Enabling of the memory controller.
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_MCOPT2, val);
+ mtsdram(SDRAM_MCOPT2,
+ (val &
+ ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_PMEN_MASK |
+ SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_XSRP_MASK |
+ SDRAM_MCOPT2_ISIE_MASK))
+ | (SDRAM_MCOPT2_SREN_ENTER | SDRAM_MCOPT2_PMEN_DISABLE |
+ SDRAM_MCOPT2_IPTR_IDLE | SDRAM_MCOPT2_XSRP_ALLOW |
+ SDRAM_MCOPT2_ISIE_ENABLE));
+
+ /*------------------------------------------------------------------
+ * Program SDRAM controller options 1 register
+ * Note: Does not enable the memory controller.
+ *-----------------------------------------------------------------*/
+ program_copt1(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Controller On Die Termination Register
+ *-----------------------------------------------------------------*/
+ program_codt(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Program SDRAM refresh register.
+ *-----------------------------------------------------------------*/
+ program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Program SDRAM mode register.
+ *-----------------------------------------------------------------*/
+ program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks,
+ &selected_cas, &write_recovery);
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Write Data/DM/DQS Clock Timing Reg
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_WRDTR, val);
+ mtsdram(SDRAM_WRDTR, (val & ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
+ ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV));
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Clock Timing Register
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_CLKTR, val);
+ mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) |
+ ddr_clktr(SDRAM_CLKTR_CLKP_0_DEG));
+
+ /*------------------------------------------------------------------
+ * Program the BxCF registers.
+ *-----------------------------------------------------------------*/
+ program_bxcf(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Program SDRAM timing registers.
+ *-----------------------------------------------------------------*/
+ program_tr(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Set the Extended Mode register
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_MEMODE, val);
+ mtsdram(SDRAM_MEMODE,
+ (val & ~(SDRAM_MEMODE_DIC_MASK | SDRAM_MEMODE_DLL_MASK |
+ SDRAM_MEMODE_RTT_MASK | SDRAM_MEMODE_DQS_MASK)) |
+ (SDRAM_MEMODE_DIC_NORMAL | SDRAM_MEMODE_DLL_ENABLE
+ | SDRAM_MEMODE_RTT_150OHM | SDRAM_MEMODE_DQS_ENABLE));
+
+ /*------------------------------------------------------------------
+ * Program Initialization preload registers.
+ *-----------------------------------------------------------------*/
+ program_initplr(dimm_populated, iic0_dimm_addr, num_dimm_banks,
+ selected_cas, write_recovery);
+
+ /*------------------------------------------------------------------
+ * Delay to ensure 200usec have elapsed since reset.
+ *-----------------------------------------------------------------*/
+ udelay(400);
+
+ /*------------------------------------------------------------------
+ * Set the memory queue core base addr.
+ *-----------------------------------------------------------------*/
+ program_memory_queue(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Program SDRAM controller options 2 register
+ * Enable the memory controller.
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_MCOPT2, val);
+ mtsdram(SDRAM_MCOPT2,
+ (val & ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_DCEN_MASK |
+ SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_ISIE_MASK)) |
+ SDRAM_MCOPT2_IPTR_EXECUTE);
+
+ /*------------------------------------------------------------------
+ * Wait for IPTR_EXECUTE init sequence to complete.
+ *-----------------------------------------------------------------*/
+ do {
+ mfsdram(SDRAM_MCSTAT, val);
+ } while ((val & SDRAM_MCSTAT_MIC_MASK) == SDRAM_MCSTAT_MIC_NOTCOMP);
+
+ /* enable the controller only after init sequence completes */
+ mfsdram(SDRAM_MCOPT2, val);
+ mtsdram(SDRAM_MCOPT2, (val | SDRAM_MCOPT2_DCEN_ENABLE));
+
+ /* Make sure delay-line calibration is done before proceeding */
+ do {
+ mfsdram(SDRAM_DLCR, val);
+ } while (!(val & SDRAM_DLCR_DLCS_COMPLETE));
+
+ /* get installed memory size */
+ dram_size = sdram_memsize();
+
+ /*
+ * Limit size to 2GB
+ */
+ if (dram_size > CONFIG_MAX_MEM_MAPPED)
+ dram_size = CONFIG_MAX_MEM_MAPPED;
+
+ /* and program tlb entries for this size (dynamic) */
+
+ /*
+ * Program TLB entries with caches enabled, for best performace
+ * while auto-calibrating and ECC generation
+ */
+ program_tlb(0, 0, dram_size, 0);
+
+ /*------------------------------------------------------------------
+ * DQS calibration.
+ *-----------------------------------------------------------------*/
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+ DQS_autocalibration();
+#else
+ program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+#endif
+ /*
+ * Now complete RDSS configuration as mentioned on page 7 of the AMCC
+ * PowerPC440SP/SPe DDR2 application note:
+ * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning"
+ */
+ update_rdcc();
+
+#ifdef CONFIG_DDR_ECC
+ /*------------------------------------------------------------------
+ * If ecc is enabled, initialize the parity bits.
+ *-----------------------------------------------------------------*/
+ program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks, 0);
+#endif
+
+ /*
+ * Flush the dcache before removing the TLB with caches
+ * enabled. Otherwise this might lead to problems later on,
+ * e.g. while booting Linux (as seen on ICON-440SPe).
+ */
+ flush_dcache();
+
+ /*
+ * Now after initialization (auto-calibration and ECC generation)
+ * remove the TLB entries with caches enabled and program again with
+ * desired cache functionality
+ */
+ remove_tlb(0, dram_size);
+ program_tlb(0, 0, dram_size, MY_TLB_WORD2_I_ENABLE);
+
+ ppc4xx_ibm_ddr2_register_dump();
+
+ /*
+ * Clear potential errors resulting from auto-calibration.
+ * If not done, then we could get an interrupt later on when
+ * exceptions are enabled.
+ */
+ set_mcsr(get_mcsr());
+
+ return sdram_memsize();
+}
+
+static void get_spd_info(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long dimm_found;
+ unsigned char num_of_bytes;
+ unsigned char total_size;
+
+ dimm_found = false;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ num_of_bytes = 0;
+ total_size = 0;
+
+ num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
+ debug("\nspd_read(0x%x) returned %d\n",
+ iic0_dimm_addr[dimm_num], num_of_bytes);
+ total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
+ debug("spd_read(0x%x) returned %d\n",
+ iic0_dimm_addr[dimm_num], total_size);
+
+ if ((num_of_bytes != 0) && (total_size != 0)) {
+ dimm_populated[dimm_num] = true;
+ dimm_found = true;
+ debug("DIMM slot %lu: populated\n", dimm_num);
+ } else {
+ dimm_populated[dimm_num] = false;
+ debug("DIMM slot %lu: Not populated\n", dimm_num);
+ }
+ }
+
+ if (dimm_found == false) {
+ printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n");
+ spd_ddr_init_hang ();
+ }
+}
+
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies that they
+ * really are DDR specific DIMMs.
+ *-----------------------------------------------------------------*/
+static void check_mem_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long dimm_type;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] == true) {
+ dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2);
+ switch (dimm_type) {
+ case 1:
+ printf("ERROR: Standard Fast Page Mode DRAM DIMM detected in "
+ "slot %d.\n", (unsigned int)dimm_num);
+ printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ case 2:
+ printf("ERROR: EDO DIMM detected in slot %d.\n",
+ (unsigned int)dimm_num);
+ printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ case 3:
+ printf("ERROR: Pipelined Nibble DIMM detected in slot %d.\n",
+ (unsigned int)dimm_num);
+ printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ case 4:
+ printf("ERROR: SDRAM DIMM detected in slot %d.\n",
+ (unsigned int)dimm_num);
+ printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ case 5:
+ printf("ERROR: Multiplexed ROM DIMM detected in slot %d.\n",
+ (unsigned int)dimm_num);
+ printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ case 6:
+ printf("ERROR: SGRAM DIMM detected in slot %d.\n",
+ (unsigned int)dimm_num);
+ printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ case 7:
+ debug("DIMM slot %lu: DDR1 SDRAM detected\n", dimm_num);
+ dimm_populated[dimm_num] = SDRAM_DDR1;
+ break;
+ case 8:
+ debug("DIMM slot %lu: DDR2 SDRAM detected\n", dimm_num);
+ dimm_populated[dimm_num] = SDRAM_DDR2;
+ break;
+ default:
+ printf("ERROR: Unknown DIMM detected in slot %d.\n",
+ (unsigned int)dimm_num);
+ printf("Only DDR1 and DDR2 SDRAM DIMMs are supported.\n");
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ }
+ }
+ }
+ for (dimm_num = 1; dimm_num < num_dimm_banks; dimm_num++) {
+ if ((dimm_populated[dimm_num-1] != SDRAM_NONE)
+ && (dimm_populated[dimm_num] != SDRAM_NONE)
+ && (dimm_populated[dimm_num-1] != dimm_populated[dimm_num])) {
+ printf("ERROR: DIMM's DDR1 and DDR2 type can not be mixed.\n");
+ spd_ddr_init_hang ();
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies that
+ * frequency previously calculated is supported.
+ *-----------------------------------------------------------------*/
+static void check_frequency(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long tcyc_reg;
+ unsigned long cycle_time;
+ unsigned long calc_cycle_time;
+ unsigned long sdram_freq;
+ unsigned long sdr_ddrpll;
+ PPC4xx_SYS_INFO board_cfg;
+
+ /*------------------------------------------------------------------
+ * Get the board configuration info.
+ *-----------------------------------------------------------------*/
+ get_sys_info(&board_cfg);
+
+ mfsdr(SDR0_DDR0, sdr_ddrpll);
+ sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+
+ /*
+ * calc_cycle_time is calculated from DDR frequency set by board/chip
+ * and is expressed in multiple of 10 picoseconds
+ * to match the way DIMM cycle time is calculated below.
+ */
+ calc_cycle_time = MULDIV64(ONE_BILLION, 100, sdram_freq);
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
+ /*
+ * Byte 9, Cycle time for CAS Latency=X, is split into two nibbles:
+ * the higher order nibble (bits 4-7) designates the cycle time
+ * to a granularity of 1ns;
+ * the value presented by the lower order nibble (bits 0-3)
+ * has a granularity of .1ns and is added to the value designated
+ * by the higher nibble. In addition, four lines of the lower order
+ * nibble are assigned to support +.25,+.33, +.66 and +.75.
+ */
+ /* Convert from hex to decimal */
+ if ((tcyc_reg & 0x0F) == 0x0D)
+ cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 75;
+ else if ((tcyc_reg & 0x0F) == 0x0C)
+ cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 66;
+ else if ((tcyc_reg & 0x0F) == 0x0B)
+ cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 33;
+ else if ((tcyc_reg & 0x0F) == 0x0A)
+ cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 25;
+ else
+ cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) +
+ ((tcyc_reg & 0x0F)*10);
+ debug("cycle_time=%lu [10 picoseconds]\n", cycle_time);
+
+ if (cycle_time > (calc_cycle_time + 10)) {
+ /*
+ * the provided sdram cycle_time is too small
+ * for the available DIMM cycle_time.
+ * The additionnal 100ps is here to accept a small incertainty.
+ */
+ printf("ERROR: DRAM DIMM detected with cycle_time %d ps in "
+ "slot %d \n while calculated cycle time is %d ps.\n",
+ (unsigned int)(cycle_time*10),
+ (unsigned int)dimm_num,
+ (unsigned int)(calc_cycle_time*10));
+ printf("Replace the DIMM, or change DDR frequency via "
+ "strapping bits.\n\n");
+ spd_ddr_init_hang ();
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies two
+ * ranks/banks maximum are availables.
+ *-----------------------------------------------------------------*/
+static void check_rank_number(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long dimm_rank;
+ unsigned long total_rank = 0;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ dimm_rank = spd_read(iic0_dimm_addr[dimm_num], 5);
+ if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08)
+ dimm_rank = (dimm_rank & 0x0F) +1;
+ else
+ dimm_rank = dimm_rank & 0x0F;
+
+
+ if (dimm_rank > MAXRANKS) {
+ printf("ERROR: DRAM DIMM detected with %lu ranks in "
+ "slot %lu is not supported.\n", dimm_rank, dimm_num);
+ printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ } else
+ total_rank += dimm_rank;
+ }
+ if (total_rank > MAXRANKS) {
+ printf("ERROR: DRAM DIMM detected with a total of %d ranks "
+ "for all slots.\n", (unsigned int)total_rank);
+ printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS);
+ printf("Remove one of the DIMM modules.\n\n");
+ spd_ddr_init_hang ();
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ * only support 2.5V modules.
+ * This routine verifies this.
+ *-----------------------------------------------------------------*/
+static void check_voltage_type(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long voltage_type;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
+ switch (voltage_type) {
+ case 0x00:
+ printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+ printf("This DIMM is 5.0 Volt/TTL.\n");
+ printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+ (unsigned int)dimm_num);
+ spd_ddr_init_hang ();
+ break;
+ case 0x01:
+ printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+ printf("This DIMM is LVTTL.\n");
+ printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+ (unsigned int)dimm_num);
+ spd_ddr_init_hang ();
+ break;
+ case 0x02:
+ printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+ printf("This DIMM is 1.5 Volt.\n");
+ printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+ (unsigned int)dimm_num);
+ spd_ddr_init_hang ();
+ break;
+ case 0x03:
+ printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+ printf("This DIMM is 3.3 Volt/TTL.\n");
+ printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+ (unsigned int)dimm_num);
+ spd_ddr_init_hang ();
+ break;
+ case 0x04:
+ /* 2.5 Voltage only for DDR1 */
+ break;
+ case 0x05:
+ /* 1.8 Voltage only for DDR2 */
+ break;
+ default:
+ printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n");
+ printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n",
+ (unsigned int)dimm_num);
+ spd_ddr_init_hang ();
+ break;
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_copt1.
+ *-----------------------------------------------------------------------------*/
+static void program_copt1(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long mcopt1;
+ unsigned long ecc_enabled;
+ unsigned long ecc = 0;
+ unsigned long data_width = 0;
+ unsigned long dimm_32bit;
+ unsigned long dimm_64bit;
+ unsigned long registered = 0;
+ unsigned long attribute = 0;
+ unsigned long buf0, buf1; /* TODO: code to be changed for IOP1.6 to support 4 DIMMs */
+ unsigned long bankcount;
+ unsigned long val;
+
+#ifdef CONFIG_DDR_ECC
+ ecc_enabled = true;
+#else
+ ecc_enabled = false;
+#endif
+ dimm_32bit = false;
+ dimm_64bit = false;
+ buf0 = false;
+ buf1 = false;
+
+ /*------------------------------------------------------------------
+ * Set memory controller options reg 1, SDRAM_MCOPT1.
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_MCOPT1, val);
+ mcopt1 = val & ~(SDRAM_MCOPT1_MCHK_MASK | SDRAM_MCOPT1_RDEN_MASK |
+ SDRAM_MCOPT1_PMU_MASK | SDRAM_MCOPT1_DMWD_MASK |
+ SDRAM_MCOPT1_UIOS_MASK | SDRAM_MCOPT1_BCNT_MASK |
+ SDRAM_MCOPT1_DDR_TYPE_MASK | SDRAM_MCOPT1_RWOO_MASK |
+ SDRAM_MCOPT1_WOOO_MASK | SDRAM_MCOPT1_DCOO_MASK |
+ SDRAM_MCOPT1_DREF_MASK);
+
+ mcopt1 |= SDRAM_MCOPT1_QDEP;
+ mcopt1 |= SDRAM_MCOPT1_PMU_OPEN;
+ mcopt1 |= SDRAM_MCOPT1_RWOO_DISABLED;
+ mcopt1 |= SDRAM_MCOPT1_WOOO_DISABLED;
+ mcopt1 |= SDRAM_MCOPT1_DCOO_DISABLED;
+ mcopt1 |= SDRAM_MCOPT1_DREF_NORMAL;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ /* test ecc support */
+ ecc = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 11);
+ if (ecc != 0x02) /* ecc not supported */
+ ecc_enabled = false;
+
+ /* test bank count */
+ bankcount = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 17);
+ if (bankcount == 0x04) /* bank count = 4 */
+ mcopt1 |= SDRAM_MCOPT1_4_BANKS;
+ else /* bank count = 8 */
+ mcopt1 |= SDRAM_MCOPT1_8_BANKS;
+
+ /* test for buffered/unbuffered, registered, differential clocks */
+ registered = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 20);
+ attribute = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 21);
+
+ /* TODO: code to be changed for IOP1.6 to support 4 DIMMs */
+ if (dimm_num == 0) {
+ if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */
+ mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE;
+ if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */
+ mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE;
+ if (registered == 1) { /* DDR2 always buffered */
+ /* TODO: what about above comments ? */
+ mcopt1 |= SDRAM_MCOPT1_RDEN;
+ buf0 = true;
+ } else {
+ /* TODO: the mask 0x02 doesn't match Samsung def for byte 21. */
+ if ((attribute & 0x02) == 0x00) {
+ /* buffered not supported */
+ buf0 = false;
+ } else {
+ mcopt1 |= SDRAM_MCOPT1_RDEN;
+ buf0 = true;
+ }
+ }
+ }
+ else if (dimm_num == 1) {
+ if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */
+ mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE;
+ if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */
+ mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE;
+ if (registered == 1) {
+ /* DDR2 always buffered */
+ mcopt1 |= SDRAM_MCOPT1_RDEN;
+ buf1 = true;
+ } else {
+ if ((attribute & 0x02) == 0x00) {
+ /* buffered not supported */
+ buf1 = false;
+ } else {
+ mcopt1 |= SDRAM_MCOPT1_RDEN;
+ buf1 = true;
+ }
+ }
+ }
+
+ /* Note that for DDR2 the byte 7 is reserved, but OK to keep code as is. */
+ data_width = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 6) +
+ (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 7)) << 8);
+
+ switch (data_width) {
+ case 72:
+ case 64:
+ dimm_64bit = true;
+ break;
+ case 40:
+ case 32:
+ dimm_32bit = true;
+ break;
+ default:
+ printf("WARNING: Detected a DIMM with a data width of %lu bits.\n",
+ data_width);
+ printf("Only DIMMs with 32 or 64 bit DDR-SDRAM widths are supported.\n");
+ break;
+ }
+ }
+ }
+
+ /* verify matching properties */
+ if ((dimm_populated[0] != SDRAM_NONE) && (dimm_populated[1] != SDRAM_NONE)) {
+ if (buf0 != buf1) {
+ printf("ERROR: DIMM's buffered/unbuffered, registered, clocking don't match.\n");
+ spd_ddr_init_hang ();
+ }
+ }
+
+ if ((dimm_64bit == true) && (dimm_32bit == true)) {
+ printf("ERROR: Cannot mix 32 bit and 64 bit DDR-SDRAM DIMMs together.\n");
+ spd_ddr_init_hang ();
+ } else if ((dimm_64bit == true) && (dimm_32bit == false)) {
+ mcopt1 |= SDRAM_MCOPT1_DMWD_64;
+ } else if ((dimm_64bit == false) && (dimm_32bit == true)) {
+ mcopt1 |= SDRAM_MCOPT1_DMWD_32;
+ } else {
+ printf("ERROR: Please install only 32 or 64 bit DDR-SDRAM DIMMs.\n\n");
+ spd_ddr_init_hang ();
+ }
+
+ if (ecc_enabled == true)
+ mcopt1 |= SDRAM_MCOPT1_MCHK_GEN;
+ else
+ mcopt1 |= SDRAM_MCOPT1_MCHK_NON;
+
+ mtsdram(SDRAM_MCOPT1, mcopt1);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_codt.
+ *-----------------------------------------------------------------------------*/
+static void program_codt(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long codt;
+ unsigned long modt0 = 0;
+ unsigned long modt1 = 0;
+ unsigned long modt2 = 0;
+ unsigned long modt3 = 0;
+ unsigned char dimm_num;
+ unsigned char dimm_rank;
+ unsigned char total_rank = 0;
+ unsigned char total_dimm = 0;
+ unsigned char dimm_type = 0;
+ unsigned char firstSlot = 0;
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Controller On Die Termination Register
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_CODT, codt);
+ codt &= ~(SDRAM_CODT_DQS_SINGLE_END | SDRAM_CODT_CKSE_SINGLE_END);
+ codt |= SDRAM_CODT_IO_NMODE;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ dimm_rank = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 5);
+ if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) {
+ dimm_rank = (dimm_rank & 0x0F) + 1;
+ dimm_type = SDRAM_DDR2;
+ } else {
+ dimm_rank = dimm_rank & 0x0F;
+ dimm_type = SDRAM_DDR1;
+ }
+
+ total_rank += dimm_rank;
+ total_dimm++;
+ if ((dimm_num == 0) && (total_dimm == 1))
+ firstSlot = true;
+ else
+ firstSlot = false;
+ }
+ }
+ if (dimm_type == SDRAM_DDR2) {
+ codt |= SDRAM_CODT_DQS_1_8_V_DDR2;
+ if ((total_dimm == 1) && (firstSlot == true)) {
+ if (total_rank == 1) { /* PUUU */
+ codt |= CALC_ODT_R(0);
+ modt0 = CALC_ODT_W(0);
+ modt1 = 0x00000000;
+ modt2 = 0x00000000;
+ modt3 = 0x00000000;
+ }
+ if (total_rank == 2) { /* PPUU */
+ codt |= CALC_ODT_R(0) | CALC_ODT_R(1);
+ modt0 = CALC_ODT_W(0) | CALC_ODT_W(1);
+ modt1 = 0x00000000;
+ modt2 = 0x00000000;
+ modt3 = 0x00000000;
+ }
+ } else if ((total_dimm == 1) && (firstSlot != true)) {
+ if (total_rank == 1) { /* UUPU */
+ codt |= CALC_ODT_R(2);
+ modt0 = 0x00000000;
+ modt1 = 0x00000000;
+ modt2 = CALC_ODT_W(2);
+ modt3 = 0x00000000;
+ }
+ if (total_rank == 2) { /* UUPP */
+ codt |= CALC_ODT_R(2) | CALC_ODT_R(3);
+ modt0 = 0x00000000;
+ modt1 = 0x00000000;
+ modt2 = CALC_ODT_W(2) | CALC_ODT_W(3);
+ modt3 = 0x00000000;
+ }
+ }
+ if (total_dimm == 2) {
+ if (total_rank == 2) { /* PUPU */
+ codt |= CALC_ODT_R(0) | CALC_ODT_R(2);
+ modt0 = CALC_ODT_RW(2);
+ modt1 = 0x00000000;
+ modt2 = CALC_ODT_RW(0);
+ modt3 = 0x00000000;
+ }
+ if (total_rank == 4) { /* PPPP */
+ codt |= CALC_ODT_R(0) | CALC_ODT_R(1) |
+ CALC_ODT_R(2) | CALC_ODT_R(3);
+ modt0 = CALC_ODT_RW(2) | CALC_ODT_RW(3);
+ modt1 = 0x00000000;
+ modt2 = CALC_ODT_RW(0) | CALC_ODT_RW(1);
+ modt3 = 0x00000000;
+ }
+ }
+ } else {
+ codt |= SDRAM_CODT_DQS_2_5_V_DDR1;
+ modt0 = 0x00000000;
+ modt1 = 0x00000000;
+ modt2 = 0x00000000;
+ modt3 = 0x00000000;
+
+ if (total_dimm == 1) {
+ if (total_rank == 1)
+ codt |= 0x00800000;
+ if (total_rank == 2)
+ codt |= 0x02800000;
+ }
+ if (total_dimm == 2) {
+ if (total_rank == 2)
+ codt |= 0x08800000;
+ if (total_rank == 4)
+ codt |= 0x2a800000;
+ }
+ }
+
+ debug("nb of dimm %d\n", total_dimm);
+ debug("nb of rank %d\n", total_rank);
+ if (total_dimm == 1)
+ debug("dimm in slot %d\n", firstSlot);
+
+ mtsdram(SDRAM_CODT, codt);
+ mtsdram(SDRAM_MODT0, modt0);
+ mtsdram(SDRAM_MODT1, modt1);
+ mtsdram(SDRAM_MODT2, modt2);
+ mtsdram(SDRAM_MODT3, modt3);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_initplr.
+ *-----------------------------------------------------------------------------*/
+static void program_initplr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks,
+ ddr_cas_id_t selected_cas,
+ int write_recovery)
+{
+ u32 cas = 0;
+ u32 odt = 0;
+ u32 ods = 0;
+ u32 mr;
+ u32 wr;
+ u32 emr;
+ u32 emr2;
+ u32 emr3;
+ int dimm_num;
+ int total_dimm = 0;
+
+ /******************************************************
+ ** Assumption: if more than one DIMM, all DIMMs are the same
+ ** as already checked in check_memory_type
+ ******************************************************/
+
+ if ((dimm_populated[0] == SDRAM_DDR1) || (dimm_populated[1] == SDRAM_DDR1)) {
+ mtsdram(SDRAM_INITPLR0, 0x81B80000);
+ mtsdram(SDRAM_INITPLR1, 0x81900400);
+ mtsdram(SDRAM_INITPLR2, 0x81810000);
+ mtsdram(SDRAM_INITPLR3, 0xff800162);
+ mtsdram(SDRAM_INITPLR4, 0x81900400);
+ mtsdram(SDRAM_INITPLR5, 0x86080000);
+ mtsdram(SDRAM_INITPLR6, 0x86080000);
+ mtsdram(SDRAM_INITPLR7, 0x81000062);
+ } else if ((dimm_populated[0] == SDRAM_DDR2) || (dimm_populated[1] == SDRAM_DDR2)) {
+ switch (selected_cas) {
+ case DDR_CAS_3:
+ cas = 3 << 4;
+ break;
+ case DDR_CAS_4:
+ cas = 4 << 4;
+ break;
+ case DDR_CAS_5:
+ cas = 5 << 4;
+ break;
+ default:
+ printf("ERROR: ucode error on selected_cas value %d", selected_cas);
+ spd_ddr_init_hang ();
+ break;
+ }
+
+#if 0
+ /*
+ * ToDo - Still a problem with the write recovery:
+ * On the Corsair CM2X512-5400C4 module, setting write recovery
+ * in the INITPLR reg to the value calculated in program_mode()
+ * results in not correctly working DDR2 memory (crash after
+ * relocation).
+ *
+ * So for now, set the write recovery to 3. This seems to work
+ * on the Corair module too.
+ *
+ * 2007-03-01, sr
+ */
+ switch (write_recovery) {
+ case 3:
+ wr = WRITE_RECOV_3;
+ break;
+ case 4:
+ wr = WRITE_RECOV_4;
+ break;
+ case 5:
+ wr = WRITE_RECOV_5;
+ break;
+ case 6:
+ wr = WRITE_RECOV_6;
+ break;
+ default:
+ printf("ERROR: write recovery not support (%d)", write_recovery);
+ spd_ddr_init_hang ();
+ break;
+ }
+#else
+ wr = WRITE_RECOV_3; /* test-only, see description above */
+#endif
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++)
+ if (dimm_populated[dimm_num] != SDRAM_NONE)
+ total_dimm++;
+ if (total_dimm == 1) {
+ odt = ODT_150_OHM;
+ ods = ODS_FULL;
+ } else if (total_dimm == 2) {
+ odt = ODT_75_OHM;
+ ods = ODS_REDUCED;
+ } else {
+ printf("ERROR: Unsupported number of DIMM's (%d)", total_dimm);
+ spd_ddr_init_hang ();
+ }
+
+ mr = CMD_EMR | SELECT_MR | BURST_LEN_4 | wr | cas;
+ emr = CMD_EMR | SELECT_EMR | odt | ods;
+ emr2 = CMD_EMR | SELECT_EMR2;
+ emr3 = CMD_EMR | SELECT_EMR3;
+ /* NOP - Wait 106 MemClk cycles */
+ mtsdram(SDRAM_INITPLR0, SDRAM_INITPLR_ENABLE | CMD_NOP |
+ SDRAM_INITPLR_IMWT_ENCODE(106));
+ udelay(1000);
+ /* precharge 4 MemClk cycles */
+ mtsdram(SDRAM_INITPLR1, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE |
+ SDRAM_INITPLR_IMWT_ENCODE(4));
+ /* EMR2 - Wait tMRD (2 MemClk cycles) */
+ mtsdram(SDRAM_INITPLR2, SDRAM_INITPLR_ENABLE | emr2 |
+ SDRAM_INITPLR_IMWT_ENCODE(2));
+ /* EMR3 - Wait tMRD (2 MemClk cycles) */
+ mtsdram(SDRAM_INITPLR3, SDRAM_INITPLR_ENABLE | emr3 |
+ SDRAM_INITPLR_IMWT_ENCODE(2));
+ /* EMR DLL ENABLE - Wait tMRD (2 MemClk cycles) */
+ mtsdram(SDRAM_INITPLR4, SDRAM_INITPLR_ENABLE | emr |
+ SDRAM_INITPLR_IMWT_ENCODE(2));
+ /* MR w/ DLL reset - 200 cycle wait for DLL reset */
+ mtsdram(SDRAM_INITPLR5, SDRAM_INITPLR_ENABLE | mr | DLL_RESET |
+ SDRAM_INITPLR_IMWT_ENCODE(200));
+ udelay(1000);
+ /* precharge 4 MemClk cycles */
+ mtsdram(SDRAM_INITPLR6, SDRAM_INITPLR_ENABLE | CMD_PRECHARGE |
+ SDRAM_INITPLR_IMWT_ENCODE(4));
+ /* Refresh 25 MemClk cycles */
+ mtsdram(SDRAM_INITPLR7, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+ SDRAM_INITPLR_IMWT_ENCODE(25));
+ /* Refresh 25 MemClk cycles */
+ mtsdram(SDRAM_INITPLR8, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+ SDRAM_INITPLR_IMWT_ENCODE(25));
+ /* Refresh 25 MemClk cycles */
+ mtsdram(SDRAM_INITPLR9, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+ SDRAM_INITPLR_IMWT_ENCODE(25));
+ /* Refresh 25 MemClk cycles */
+ mtsdram(SDRAM_INITPLR10, SDRAM_INITPLR_ENABLE | CMD_REFRESH |
+ SDRAM_INITPLR_IMWT_ENCODE(25));
+ /* MR w/o DLL reset - Wait tMRD (2 MemClk cycles) */
+ mtsdram(SDRAM_INITPLR11, SDRAM_INITPLR_ENABLE | mr |
+ SDRAM_INITPLR_IMWT_ENCODE(2));
+ /* EMR OCD Default - Wait tMRD (2 MemClk cycles) */
+ mtsdram(SDRAM_INITPLR12, SDRAM_INITPLR_ENABLE | OCD_CALIB_DEF |
+ SDRAM_INITPLR_IMWT_ENCODE(2) | emr);
+ /* EMR OCD Exit */
+ mtsdram(SDRAM_INITPLR13, SDRAM_INITPLR_ENABLE | emr |
+ SDRAM_INITPLR_IMWT_ENCODE(2));
+ } else {
+ printf("ERROR: ucode error as unknown DDR type in program_initplr");
+ spd_ddr_init_hang ();
+ }
+}
+
+/*------------------------------------------------------------------
+ * This routine programs the SDRAM_MMODE register.
+ * the selected_cas is an output parameter, that will be passed
+ * by caller to call the above program_initplr( )
+ *-----------------------------------------------------------------*/
+static void program_mode(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks,
+ ddr_cas_id_t *selected_cas,
+ int *write_recovery)
+{
+ unsigned long dimm_num;
+ unsigned long sdram_ddr1;
+ unsigned long t_wr_ns;
+ unsigned long t_wr_clk;
+ unsigned long cas_bit;
+ unsigned long cas_index;
+ unsigned long sdram_freq;
+ unsigned long ddr_check;
+ unsigned long mmode;
+ unsigned long tcyc_reg;
+ unsigned long cycle_2_0_clk;
+ unsigned long cycle_2_5_clk;
+ unsigned long cycle_3_0_clk;
+ unsigned long cycle_4_0_clk;
+ unsigned long cycle_5_0_clk;
+ unsigned long max_2_0_tcyc_ns_x_100;
+ unsigned long max_2_5_tcyc_ns_x_100;
+ unsigned long max_3_0_tcyc_ns_x_100;
+ unsigned long max_4_0_tcyc_ns_x_100;
+ unsigned long max_5_0_tcyc_ns_x_100;
+ unsigned long cycle_time_ns_x_100[3];
+ PPC4xx_SYS_INFO board_cfg;
+ unsigned char cas_2_0_available;
+ unsigned char cas_2_5_available;
+ unsigned char cas_3_0_available;
+ unsigned char cas_4_0_available;
+ unsigned char cas_5_0_available;
+ unsigned long sdr_ddrpll;
+
+ /*------------------------------------------------------------------
+ * Get the board configuration info.
+ *-----------------------------------------------------------------*/
+ get_sys_info(&board_cfg);
+
+ mfsdr(SDR0_DDR0, sdr_ddrpll);
+ sdram_freq = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(sdr_ddrpll), 1);
+ debug("sdram_freq=%lu\n", sdram_freq);
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ t_wr_ns = 0;
+ cas_2_0_available = true;
+ cas_2_5_available = true;
+ cas_3_0_available = true;
+ cas_4_0_available = true;
+ cas_5_0_available = true;
+ max_2_0_tcyc_ns_x_100 = 10;
+ max_2_5_tcyc_ns_x_100 = 10;
+ max_3_0_tcyc_ns_x_100 = 10;
+ max_4_0_tcyc_ns_x_100 = 10;
+ max_5_0_tcyc_ns_x_100 = 10;
+ sdram_ddr1 = true;
+
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ if (dimm_populated[dimm_num] == SDRAM_DDR1)
+ sdram_ddr1 = true;
+ else
+ sdram_ddr1 = false;
+
+ cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18);
+ debug("cas_bit[SPD byte 18]=%02lx\n", cas_bit);
+
+ /* For a particular DIMM, grab the three CAS values it supports */
+ for (cas_index = 0; cas_index < 3; cas_index++) {
+ switch (cas_index) {
+ case 0:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9);
+ break;
+ case 1:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23);
+ break;
+ default:
+ tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25);
+ break;
+ }
+
+ if ((tcyc_reg & 0x0F) >= 10) {
+ if ((tcyc_reg & 0x0F) == 0x0D) {
+ /* Convert from hex to decimal */
+ cycle_time_ns_x_100[cas_index] =
+ (((tcyc_reg & 0xF0) >> 4) * 100) + 75;
+ } else {
+ printf("ERROR: SPD reported Tcyc is incorrect for DIMM "
+ "in slot %d\n", (unsigned int)dimm_num);
+ spd_ddr_init_hang ();
+ }
+ } else {
+ /* Convert from hex to decimal */
+ cycle_time_ns_x_100[cas_index] =
+ (((tcyc_reg & 0xF0) >> 4) * 100) +
+ ((tcyc_reg & 0x0F)*10);
+ }
+ debug("cas_index=%lu: cycle_time_ns_x_100=%lu\n", cas_index,
+ cycle_time_ns_x_100[cas_index]);
+ }
+
+ /* The rest of this routine determines if CAS 2.0, 2.5, 3.0, 4.0 and 5.0 are */
+ /* supported for a particular DIMM. */
+ cas_index = 0;
+
+ if (sdram_ddr1) {
+ /*
+ * DDR devices use the following bitmask for CAS latency:
+ * Bit 7 6 5 4 3 2 1 0
+ * TBD 4.0 3.5 3.0 2.5 2.0 1.5 1.0
+ */
+ if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
+ cas_index++;
+ } else {
+ if (cas_index != 0)
+ cas_index++;
+ cas_4_0_available = false;
+ }
+
+ if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
+ cas_index++;
+ } else {
+ if (cas_index != 0)
+ cas_index++;
+ cas_3_0_available = false;
+ }
+
+ if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
+ cas_index++;
+ } else {
+ if (cas_index != 0)
+ cas_index++;
+ cas_2_5_available = false;
+ }
+
+ if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
+ cas_index++;
+ } else {
+ if (cas_index != 0)
+ cas_index++;
+ cas_2_0_available = false;
+ }
+ } else {
+ /*
+ * DDR2 devices use the following bitmask for CAS latency:
+ * Bit 7 6 5 4 3 2 1 0
+ * TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD
+ */
+ if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
+ cas_index++;
+ } else {
+ if (cas_index != 0)
+ cas_index++;
+ cas_5_0_available = false;
+ }
+
+ if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
+ cas_index++;
+ } else {
+ if (cas_index != 0)
+ cas_index++;
+ cas_4_0_available = false;
+ }
+
+ if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) &&
+ (cycle_time_ns_x_100[cas_index] != 0)) {
+ max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100,
+ cycle_time_ns_x_100[cas_index]);
+ cas_index++;
+ } else {
+ if (cas_index != 0)
+ cas_index++;
+ cas_3_0_available = false;
+ }
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM mode, SDRAM_MMODE
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_MMODE, mmode);
+ mmode = mmode & ~(SDRAM_MMODE_WR_MASK | SDRAM_MMODE_DCL_MASK);
+
+ /* add 10 here because of rounding problems */
+ cycle_2_0_clk = MULDIV64(ONE_BILLION, 100, max_2_0_tcyc_ns_x_100) + 10;
+ cycle_2_5_clk = MULDIV64(ONE_BILLION, 100, max_2_5_tcyc_ns_x_100) + 10;
+ cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100) + 10;
+ cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100) + 10;
+ cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100) + 10;
+ debug("cycle_3_0_clk=%lu\n", cycle_3_0_clk);
+ debug("cycle_4_0_clk=%lu\n", cycle_4_0_clk);
+ debug("cycle_5_0_clk=%lu\n", cycle_5_0_clk);
+
+ if (sdram_ddr1 == true) { /* DDR1 */
+ if ((cas_2_0_available == true) &&
+ (sdram_freq <= cycle_2_0_clk)) {
+ mmode |= SDRAM_MMODE_DCL_DDR1_2_0_CLK;
+ *selected_cas = DDR_CAS_2;
+ } else if ((cas_2_5_available == true) &&
+ (sdram_freq <= cycle_2_5_clk)) {
+ mmode |= SDRAM_MMODE_DCL_DDR1_2_5_CLK;
+ *selected_cas = DDR_CAS_2_5;
+ } else if ((cas_3_0_available == true) &&
+ (sdram_freq <= cycle_3_0_clk)) {
+ mmode |= SDRAM_MMODE_DCL_DDR1_3_0_CLK;
+ *selected_cas = DDR_CAS_3;
+ } else {
+ printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n");
+ printf("Only DIMMs DDR1 with CAS latencies of 2.0, 2.5, and 3.0 are supported.\n");
+ printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n");
+ spd_ddr_init_hang ();
+ }
+ } else { /* DDR2 */
+ debug("cas_3_0_available=%d\n", cas_3_0_available);
+ debug("cas_4_0_available=%d\n", cas_4_0_available);
+ debug("cas_5_0_available=%d\n", cas_5_0_available);
+ if ((cas_3_0_available == true) &&
+ (sdram_freq <= cycle_3_0_clk)) {
+ mmode |= SDRAM_MMODE_DCL_DDR2_3_0_CLK;
+ *selected_cas = DDR_CAS_3;
+ } else if ((cas_4_0_available == true) &&
+ (sdram_freq <= cycle_4_0_clk)) {
+ mmode |= SDRAM_MMODE_DCL_DDR2_4_0_CLK;
+ *selected_cas = DDR_CAS_4;
+ } else if ((cas_5_0_available == true) &&
+ (sdram_freq <= cycle_5_0_clk)) {
+ mmode |= SDRAM_MMODE_DCL_DDR2_5_0_CLK;
+ *selected_cas = DDR_CAS_5;
+ } else {
+ printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n");
+ printf("Only DIMMs DDR2 with CAS latencies of 3.0, 4.0, and 5.0 are supported.\n");
+ printf("Make sure the PLB speed is within the supported range of the DIMMs.\n");
+ printf("cas3=%d cas4=%d cas5=%d\n",
+ cas_3_0_available, cas_4_0_available, cas_5_0_available);
+ printf("sdram_freq=%lu cycle3=%lu cycle4=%lu cycle5=%lu\n\n",
+ sdram_freq, cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk);
+ spd_ddr_init_hang ();
+ }
+ }
+
+ if (sdram_ddr1 == true)
+ mmode |= SDRAM_MMODE_WR_DDR1;
+ else {
+
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_populated[dimm_num] != SDRAM_NONE)
+ t_wr_ns = max(t_wr_ns,
+ spd_read(iic0_dimm_addr[dimm_num], 36) >> 2);
+ }
+
+ /*
+ * convert from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_wr_clk = MULDIV64(sdram_freq, t_wr_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_wr_clk, t_wr_ns);
+ if (sdram_freq != ddr_check)
+ t_wr_clk++;
+
+ switch (t_wr_clk) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ mmode |= SDRAM_MMODE_WR_DDR2_3_CYC;
+ break;
+ case 4:
+ mmode |= SDRAM_MMODE_WR_DDR2_4_CYC;
+ break;
+ case 5:
+ mmode |= SDRAM_MMODE_WR_DDR2_5_CYC;
+ break;
+ default:
+ mmode |= SDRAM_MMODE_WR_DDR2_6_CYC;
+ break;
+ }
+ *write_recovery = t_wr_clk;
+ }
+
+ debug("CAS latency = %d\n", *selected_cas);
+ debug("Write recovery = %d\n", *write_recovery);
+
+ mtsdram(SDRAM_MMODE, mmode);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_rtr.
+ *-----------------------------------------------------------------------------*/
+static void program_rtr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ PPC4xx_SYS_INFO board_cfg;
+ unsigned long max_refresh_rate;
+ unsigned long dimm_num;
+ unsigned long refresh_rate_type;
+ unsigned long refresh_rate;
+ unsigned long rint;
+ unsigned long sdram_freq;
+ unsigned long sdr_ddrpll;
+ unsigned long val;
+
+ /*------------------------------------------------------------------
+ * Get the board configuration info.
+ *-----------------------------------------------------------------*/
+ get_sys_info(&board_cfg);
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Refresh Timing Register, SDRAM_RTR
+ *-----------------------------------------------------------------*/
+ mfsdr(SDR0_DDR0, sdr_ddrpll);
+ sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+
+ max_refresh_rate = 0;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+
+ refresh_rate_type = spd_read(iic0_dimm_addr[dimm_num], 12);
+ refresh_rate_type &= 0x7F;
+ switch (refresh_rate_type) {
+ case 0:
+ refresh_rate = 15625;
+ break;
+ case 1:
+ refresh_rate = 3906;
+ break;
+ case 2:
+ refresh_rate = 7812;
+ break;
+ case 3:
+ refresh_rate = 31250;
+ break;
+ case 4:
+ refresh_rate = 62500;
+ break;
+ case 5:
+ refresh_rate = 125000;
+ break;
+ default:
+ refresh_rate = 0;
+ printf("ERROR: DIMM %d unsupported refresh rate/type.\n",
+ (unsigned int)dimm_num);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ break;
+ }
+
+ max_refresh_rate = max(max_refresh_rate, refresh_rate);
+ }
+ }
+
+ rint = MULDIV64(sdram_freq, max_refresh_rate, ONE_BILLION);
+ mfsdram(SDRAM_RTR, val);
+ mtsdram(SDRAM_RTR, (val & ~SDRAM_RTR_RINT_MASK) |
+ (SDRAM_RTR_RINT_ENCODE(rint)));
+}
+
+/*------------------------------------------------------------------
+ * This routine programs the SDRAM_TRx registers.
+ *-----------------------------------------------------------------*/
+static void program_tr(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long sdram_ddr1;
+ unsigned long t_rp_ns;
+ unsigned long t_rcd_ns;
+ unsigned long t_rrd_ns;
+ unsigned long t_ras_ns;
+ unsigned long t_rc_ns;
+ unsigned long t_rfc_ns;
+ unsigned long t_wpc_ns;
+ unsigned long t_wtr_ns;
+ unsigned long t_rpc_ns;
+ unsigned long t_rp_clk;
+ unsigned long t_rcd_clk;
+ unsigned long t_rrd_clk;
+ unsigned long t_ras_clk;
+ unsigned long t_rc_clk;
+ unsigned long t_rfc_clk;
+ unsigned long t_wpc_clk;
+ unsigned long t_wtr_clk;
+ unsigned long t_rpc_clk;
+ unsigned long sdtr1, sdtr2, sdtr3;
+ unsigned long ddr_check;
+ unsigned long sdram_freq;
+ unsigned long sdr_ddrpll;
+
+ PPC4xx_SYS_INFO board_cfg;
+
+ /*------------------------------------------------------------------
+ * Get the board configuration info.
+ *-----------------------------------------------------------------*/
+ get_sys_info(&board_cfg);
+
+ mfsdr(SDR0_DDR0, sdr_ddrpll);
+ sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ t_rp_ns = 0;
+ t_rrd_ns = 0;
+ t_rcd_ns = 0;
+ t_ras_ns = 0;
+ t_rc_ns = 0;
+ t_rfc_ns = 0;
+ t_wpc_ns = 0;
+ t_wtr_ns = 0;
+ t_rpc_ns = 0;
+ sdram_ddr1 = true;
+
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ if (dimm_populated[dimm_num] == SDRAM_DDR2)
+ sdram_ddr1 = true;
+ else
+ sdram_ddr1 = false;
+
+ t_rcd_ns = max(t_rcd_ns, spd_read(iic0_dimm_addr[dimm_num], 29) >> 2);
+ t_rrd_ns = max(t_rrd_ns, spd_read(iic0_dimm_addr[dimm_num], 28) >> 2);
+ t_rp_ns = max(t_rp_ns, spd_read(iic0_dimm_addr[dimm_num], 27) >> 2);
+ t_ras_ns = max(t_ras_ns, spd_read(iic0_dimm_addr[dimm_num], 30));
+ t_rc_ns = max(t_rc_ns, spd_read(iic0_dimm_addr[dimm_num], 41));
+ t_rfc_ns = max(t_rfc_ns, spd_read(iic0_dimm_addr[dimm_num], 42));
+ }
+ }
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Timing Reg 1, SDRAM_TR1
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_SDTR1, sdtr1);
+ sdtr1 &= ~(SDRAM_SDTR1_LDOF_MASK | SDRAM_SDTR1_RTW_MASK |
+ SDRAM_SDTR1_WTWO_MASK | SDRAM_SDTR1_RTRO_MASK);
+
+ /* default values */
+ sdtr1 |= SDRAM_SDTR1_LDOF_2_CLK;
+ sdtr1 |= SDRAM_SDTR1_RTW_2_CLK;
+
+ /* normal operations */
+ sdtr1 |= SDRAM_SDTR1_WTWO_0_CLK;
+ sdtr1 |= SDRAM_SDTR1_RTRO_1_CLK;
+
+ mtsdram(SDRAM_SDTR1, sdtr1);
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Timing Reg 2, SDRAM_TR2
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_SDTR2, sdtr2);
+ sdtr2 &= ~(SDRAM_SDTR2_RCD_MASK | SDRAM_SDTR2_WTR_MASK |
+ SDRAM_SDTR2_XSNR_MASK | SDRAM_SDTR2_WPC_MASK |
+ SDRAM_SDTR2_RPC_MASK | SDRAM_SDTR2_RP_MASK |
+ SDRAM_SDTR2_RRD_MASK);
+
+ /*
+ * convert t_rcd from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_rcd_clk = MULDIV64(sdram_freq, t_rcd_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_rcd_clk, t_rcd_ns);
+ if (sdram_freq != ddr_check)
+ t_rcd_clk++;
+
+ switch (t_rcd_clk) {
+ case 0:
+ case 1:
+ sdtr2 |= SDRAM_SDTR2_RCD_1_CLK;
+ break;
+ case 2:
+ sdtr2 |= SDRAM_SDTR2_RCD_2_CLK;
+ break;
+ case 3:
+ sdtr2 |= SDRAM_SDTR2_RCD_3_CLK;
+ break;
+ case 4:
+ sdtr2 |= SDRAM_SDTR2_RCD_4_CLK;
+ break;
+ default:
+ sdtr2 |= SDRAM_SDTR2_RCD_5_CLK;
+ break;
+ }
+
+ if (sdram_ddr1 == true) { /* DDR1 */
+ if (sdram_freq < 200000000) {
+ sdtr2 |= SDRAM_SDTR2_WTR_1_CLK;
+ sdtr2 |= SDRAM_SDTR2_WPC_2_CLK;
+ sdtr2 |= SDRAM_SDTR2_RPC_2_CLK;
+ } else {
+ sdtr2 |= SDRAM_SDTR2_WTR_2_CLK;
+ sdtr2 |= SDRAM_SDTR2_WPC_3_CLK;
+ sdtr2 |= SDRAM_SDTR2_RPC_2_CLK;
+ }
+ } else { /* DDR2 */
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ t_wpc_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 36) >> 2);
+ t_wtr_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 37) >> 2);
+ t_rpc_ns = max(t_rpc_ns, spd_read(iic0_dimm_addr[dimm_num], 38) >> 2);
+ }
+ }
+
+ /*
+ * convert from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_wpc_clk = MULDIV64(sdram_freq, t_wpc_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_wpc_clk, t_wpc_ns);
+ if (sdram_freq != ddr_check)
+ t_wpc_clk++;
+
+ switch (t_wpc_clk) {
+ case 0:
+ case 1:
+ case 2:
+ sdtr2 |= SDRAM_SDTR2_WPC_2_CLK;
+ break;
+ case 3:
+ sdtr2 |= SDRAM_SDTR2_WPC_3_CLK;
+ break;
+ case 4:
+ sdtr2 |= SDRAM_SDTR2_WPC_4_CLK;
+ break;
+ case 5:
+ sdtr2 |= SDRAM_SDTR2_WPC_5_CLK;
+ break;
+ default:
+ sdtr2 |= SDRAM_SDTR2_WPC_6_CLK;
+ break;
+ }
+
+ /*
+ * convert from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_wtr_clk = MULDIV64(sdram_freq, t_wtr_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_wtr_clk, t_wtr_ns);
+ if (sdram_freq != ddr_check)
+ t_wtr_clk++;
+
+ switch (t_wtr_clk) {
+ case 0:
+ case 1:
+ sdtr2 |= SDRAM_SDTR2_WTR_1_CLK;
+ break;
+ case 2:
+ sdtr2 |= SDRAM_SDTR2_WTR_2_CLK;
+ break;
+ case 3:
+ sdtr2 |= SDRAM_SDTR2_WTR_3_CLK;
+ break;
+ default:
+ sdtr2 |= SDRAM_SDTR2_WTR_4_CLK;
+ break;
+ }
+
+ /*
+ * convert from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_rpc_clk = MULDIV64(sdram_freq, t_rpc_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_rpc_clk, t_rpc_ns);
+ if (sdram_freq != ddr_check)
+ t_rpc_clk++;
+
+ switch (t_rpc_clk) {
+ case 0:
+ case 1:
+ case 2:
+ sdtr2 |= SDRAM_SDTR2_RPC_2_CLK;
+ break;
+ case 3:
+ sdtr2 |= SDRAM_SDTR2_RPC_3_CLK;
+ break;
+ default:
+ sdtr2 |= SDRAM_SDTR2_RPC_4_CLK;
+ break;
+ }
+ }
+
+ /* default value */
+ sdtr2 |= SDRAM_SDTR2_XSNR_16_CLK;
+
+ /*
+ * convert t_rrd from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_rrd_clk = MULDIV64(sdram_freq, t_rrd_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_rrd_clk, t_rrd_ns);
+ if (sdram_freq != ddr_check)
+ t_rrd_clk++;
+
+ if (t_rrd_clk == 3)
+ sdtr2 |= SDRAM_SDTR2_RRD_3_CLK;
+ else
+ sdtr2 |= SDRAM_SDTR2_RRD_2_CLK;
+
+ /*
+ * convert t_rp from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_rp_clk = MULDIV64(sdram_freq, t_rp_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_rp_clk, t_rp_ns);
+ if (sdram_freq != ddr_check)
+ t_rp_clk++;
+
+ switch (t_rp_clk) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ sdtr2 |= SDRAM_SDTR2_RP_3_CLK;
+ break;
+ case 4:
+ sdtr2 |= SDRAM_SDTR2_RP_4_CLK;
+ break;
+ case 5:
+ sdtr2 |= SDRAM_SDTR2_RP_5_CLK;
+ break;
+ case 6:
+ sdtr2 |= SDRAM_SDTR2_RP_6_CLK;
+ break;
+ default:
+ sdtr2 |= SDRAM_SDTR2_RP_7_CLK;
+ break;
+ }
+
+ mtsdram(SDRAM_SDTR2, sdtr2);
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM Timing Reg 3, SDRAM_TR3
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_SDTR3, sdtr3);
+ sdtr3 &= ~(SDRAM_SDTR3_RAS_MASK | SDRAM_SDTR3_RC_MASK |
+ SDRAM_SDTR3_XCS_MASK | SDRAM_SDTR3_RFC_MASK);
+
+ /*
+ * convert t_ras from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_ras_clk = MULDIV64(sdram_freq, t_ras_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_ras_clk, t_ras_ns);
+ if (sdram_freq != ddr_check)
+ t_ras_clk++;
+
+ sdtr3 |= SDRAM_SDTR3_RAS_ENCODE(t_ras_clk);
+
+ /*
+ * convert t_rc from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_rc_clk = MULDIV64(sdram_freq, t_rc_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_rc_clk, t_rc_ns);
+ if (sdram_freq != ddr_check)
+ t_rc_clk++;
+
+ sdtr3 |= SDRAM_SDTR3_RC_ENCODE(t_rc_clk);
+
+ /* default xcs value */
+ sdtr3 |= SDRAM_SDTR3_XCS;
+
+ /*
+ * convert t_rfc from nanoseconds to ddr clocks
+ * round up if necessary
+ */
+ t_rfc_clk = MULDIV64(sdram_freq, t_rfc_ns, ONE_BILLION);
+ ddr_check = MULDIV64(ONE_BILLION, t_rfc_clk, t_rfc_ns);
+ if (sdram_freq != ddr_check)
+ t_rfc_clk++;
+
+ sdtr3 |= SDRAM_SDTR3_RFC_ENCODE(t_rfc_clk);
+
+ mtsdram(SDRAM_SDTR3, sdtr3);
+}
+
+/*-----------------------------------------------------------------------------+
+ * program_bxcf.
+ *-----------------------------------------------------------------------------*/
+static void program_bxcf(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long num_col_addr;
+ unsigned long num_ranks;
+ unsigned long num_banks;
+ unsigned long mode;
+ unsigned long ind_rank;
+ unsigned long ind;
+ unsigned long ind_bank;
+ unsigned long bank_0_populated;
+
+ /*------------------------------------------------------------------
+ * Set the BxCF regs. First, wipe out the bank config registers.
+ *-----------------------------------------------------------------*/
+ mtsdram(SDRAM_MB0CF, 0x00000000);
+ mtsdram(SDRAM_MB1CF, 0x00000000);
+ mtsdram(SDRAM_MB2CF, 0x00000000);
+ mtsdram(SDRAM_MB3CF, 0x00000000);
+
+ mode = SDRAM_BXCF_M_BE_ENABLE;
+
+ bank_0_populated = 0;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4);
+ num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5);
+ if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08)
+ num_ranks = (num_ranks & 0x0F) +1;
+ else
+ num_ranks = num_ranks & 0x0F;
+
+ num_banks = spd_read(iic0_dimm_addr[dimm_num], 17);
+
+ for (ind_bank = 0; ind_bank < 2; ind_bank++) {
+ if (num_banks == 4)
+ ind = 0;
+ else
+ ind = 5 << 8;
+ switch (num_col_addr) {
+ case 0x08:
+ mode |= (SDRAM_BXCF_M_AM_0 + ind);
+ break;
+ case 0x09:
+ mode |= (SDRAM_BXCF_M_AM_1 + ind);
+ break;
+ case 0x0A:
+ mode |= (SDRAM_BXCF_M_AM_2 + ind);
+ break;
+ case 0x0B:
+ mode |= (SDRAM_BXCF_M_AM_3 + ind);
+ break;
+ case 0x0C:
+ mode |= (SDRAM_BXCF_M_AM_4 + ind);
+ break;
+ default:
+ printf("DDR-SDRAM: DIMM %d BxCF configuration.\n",
+ (unsigned int)dimm_num);
+ printf("ERROR: Unsupported value for number of "
+ "column addresses: %d.\n", (unsigned int)num_col_addr);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ }
+ }
+
+ if ((dimm_populated[dimm_num] != SDRAM_NONE)&& (dimm_num ==1))
+ bank_0_populated = 1;
+
+ for (ind_rank = 0; ind_rank < num_ranks; ind_rank++) {
+ mtsdram(SDRAM_MB0CF +
+ ((dimm_num + bank_0_populated + ind_rank) << 2),
+ mode);
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ * program memory queue.
+ *-----------------------------------------------------------------*/
+static void program_memory_queue(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ phys_size_t rank_base_addr;
+ unsigned long rank_reg;
+ phys_size_t rank_size_bytes;
+ unsigned long rank_size_id;
+ unsigned long num_ranks;
+ unsigned long baseadd_size;
+ unsigned long i;
+ unsigned long bank_0_populated = 0;
+ phys_size_t total_size = 0;
+
+ /*------------------------------------------------------------------
+ * Reset the rank_base_address.
+ *-----------------------------------------------------------------*/
+ rank_reg = SDRAM_R0BAS;
+
+ rank_base_addr = 0x00000000;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_populated[dimm_num] != SDRAM_NONE) {
+ num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5);
+ if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08)
+ num_ranks = (num_ranks & 0x0F) + 1;
+ else
+ num_ranks = num_ranks & 0x0F;
+
+ rank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31);
+
+ /*------------------------------------------------------------------
+ * Set the sizes
+ *-----------------------------------------------------------------*/
+ baseadd_size = 0;
+ switch (rank_size_id) {
+ case 0x01:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_1024;
+ total_size = 1024;
+ break;
+ case 0x02:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_2048;
+ total_size = 2048;
+ break;
+ case 0x04:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_4096;
+ total_size = 4096;
+ break;
+ case 0x08:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_32;
+ total_size = 32;
+ break;
+ case 0x10:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_64;
+ total_size = 64;
+ break;
+ case 0x20:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_128;
+ total_size = 128;
+ break;
+ case 0x40:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_256;
+ total_size = 256;
+ break;
+ case 0x80:
+ baseadd_size |= SDRAM_RXBAS_SDSZ_512;
+ total_size = 512;
+ break;
+ default:
+ printf("DDR-SDRAM: DIMM %d memory queue configuration.\n",
+ (unsigned int)dimm_num);
+ printf("ERROR: Unsupported value for the banksize: %d.\n",
+ (unsigned int)rank_size_id);
+ printf("Replace the DIMM module with a supported DIMM.\n\n");
+ spd_ddr_init_hang ();
+ }
+ rank_size_bytes = total_size << 20;
+
+ if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1))
+ bank_0_populated = 1;
+
+ for (i = 0; i < num_ranks; i++) {
+ mtdcr_any(rank_reg+i+dimm_num+bank_0_populated,
+ (SDRAM_RXBAS_SDBA_ENCODE(rank_base_addr) |
+ baseadd_size));
+ rank_base_addr += rank_size_bytes;
+ }
+ }
+ }
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX)
+ /*
+ * Enable high bandwidth access
+ * This is currently not used, but with this setup
+ * it is possible to use it later on in e.g. the Linux
+ * EMAC driver for performance gain.
+ */
+ mtdcr(SDRAM_PLBADDULL, 0x00000000); /* MQ0_BAUL */
+ mtdcr(SDRAM_PLBADDUHB, 0x00000008); /* MQ0_BAUH */
+
+ /*
+ * Set optimal value for Memory Queue HB/LL Configuration registers
+ */
+ mtdcr(SDRAM_CONF1HB, (mfdcr(SDRAM_CONF1HB) & ~SDRAM_CONF1HB_MASK) |
+ SDRAM_CONF1HB_AAFR | SDRAM_CONF1HB_RPEN | SDRAM_CONF1HB_RFTE |
+ SDRAM_CONF1HB_RPLM | SDRAM_CONF1HB_WRCL);
+ mtdcr(SDRAM_CONF1LL, (mfdcr(SDRAM_CONF1LL) & ~SDRAM_CONF1LL_MASK) |
+ SDRAM_CONF1LL_AAFR | SDRAM_CONF1LL_RPEN | SDRAM_CONF1LL_RFTE |
+ SDRAM_CONF1LL_RPLM);
+ mtdcr(SDRAM_CONFPATHB, mfdcr(SDRAM_CONFPATHB) | SDRAM_CONFPATHB_TPEN);
+#endif
+}
+
+#ifdef CONFIG_DDR_ECC
+/*-----------------------------------------------------------------------------+
+ * program_ecc.
+ *-----------------------------------------------------------------------------*/
+static void program_ecc(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks,
+ unsigned long tlb_word2_i_value)
+{
+ unsigned long dimm_num;
+ unsigned long ecc;
+
+ ecc = 0;
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_populated[dimm_num] != SDRAM_NONE)
+ ecc = max(ecc, spd_read(iic0_dimm_addr[dimm_num], 11));
+ }
+ if (ecc == 0)
+ return;
+
+ do_program_ecc(tlb_word2_i_value);
+}
+#endif
+
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+/*-----------------------------------------------------------------------------+
+ * program_DQS_calibration.
+ *-----------------------------------------------------------------------------*/
+static void program_DQS_calibration(unsigned long *dimm_populated,
+ unsigned char *iic0_dimm_addr,
+ unsigned long num_dimm_banks)
+{
+ unsigned long val;
+
+#ifdef HARD_CODED_DQS /* calibration test with hardvalues */
+ mtsdram(SDRAM_RQDC, 0x80000037);
+ mtsdram(SDRAM_RDCC, 0x40000000);
+ mtsdram(SDRAM_RFDC, 0x000001DF);
+
+ test();
+#else
+ /*------------------------------------------------------------------
+ * Program RDCC register
+ * Read sample cycle auto-update enable
+ *-----------------------------------------------------------------*/
+
+ mfsdram(SDRAM_RDCC, val);
+ mtsdram(SDRAM_RDCC,
+ (val & ~(SDRAM_RDCC_RDSS_MASK | SDRAM_RDCC_RSAE_MASK))
+ | SDRAM_RDCC_RSAE_ENABLE);
+
+ /*------------------------------------------------------------------
+ * Program RQDC register
+ * Internal DQS delay mechanism enable
+ *-----------------------------------------------------------------*/
+ mtsdram(SDRAM_RQDC, (SDRAM_RQDC_RQDE_ENABLE|SDRAM_RQDC_RQFD_ENCODE(0x38)));
+
+ /*------------------------------------------------------------------
+ * Program RFDC register
+ * Set Feedback Fractional Oversample
+ * Auto-detect read sample cycle enable
+ * Set RFOS to 1/4 of memclk cycle (0x3f)
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_RFDC, val);
+ mtsdram(SDRAM_RFDC,
+ (val & ~(SDRAM_RFDC_ARSE_MASK | SDRAM_RFDC_RFOS_MASK |
+ SDRAM_RFDC_RFFD_MASK))
+ | (SDRAM_RFDC_ARSE_ENABLE | SDRAM_RFDC_RFOS_ENCODE(0x3f) |
+ SDRAM_RFDC_RFFD_ENCODE(0)));
+
+ DQS_calibration_process();
+#endif
+}
+
+static int short_mem_test(void)
+{
+ u32 *membase;
+ u32 bxcr_num;
+ u32 bxcf;
+ int i;
+ int j;
+ phys_size_t base_addr;
+ u32 test[NUMMEMTESTS][NUMMEMWORDS] = {
+ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} };
+ int l;
+
+ for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+ mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf);
+
+ /* Banks enabled */
+ if ((bxcf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+ /* Bank is enabled */
+
+ /*
+ * Only run test on accessable memory (below 2GB)
+ */
+ base_addr = SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num));
+ if (base_addr >= CONFIG_MAX_MEM_MAPPED)
+ continue;
+
+ /*------------------------------------------------------------------
+ * Run the short memory test.
+ *-----------------------------------------------------------------*/
+ membase = (u32 *)(u32)base_addr;
+
+ for (i = 0; i < NUMMEMTESTS; i++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ membase[j] = test[i][j];
+ ppcDcbf((u32)&(membase[j]));
+ }
+ sync();
+ for (l=0; l<NUMLOOPS; l++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (membase[j] != test[i][j]) {
+ ppcDcbf((u32)&(membase[j]));
+ return 0;
+ }
+ ppcDcbf((u32)&(membase[j]));
+ }
+ sync();
+ }
+ }
+ } /* if bank enabled */
+ } /* for bxcf_num */
+
+ return 1;
+}
+
+#ifndef HARD_CODED_DQS
+/*-----------------------------------------------------------------------------+
+ * DQS_calibration_process.
+ *-----------------------------------------------------------------------------*/
+static void DQS_calibration_process(void)
+{
+ unsigned long rfdc_reg;
+ unsigned long rffd;
+ unsigned long val;
+ long rffd_average;
+ long max_start;
+ unsigned long dlycal;
+ unsigned long dly_val;
+ unsigned long max_pass_length;
+ unsigned long current_pass_length;
+ unsigned long current_fail_length;
+ unsigned long current_start;
+ long max_end;
+ unsigned char fail_found;
+ unsigned char pass_found;
+#if !defined(CONFIG_DDR_RQDC_FIXED)
+ int window_found;
+ u32 rqdc_reg;
+ u32 rqfd;
+ u32 rqfd_start;
+ u32 rqfd_average;
+ int loopi = 0;
+ char str[] = "Auto calibration -";
+ char slash[] = "\\|/-\\|/-";
+
+ /*------------------------------------------------------------------
+ * Test to determine the best read clock delay tuning bits.
+ *
+ * Before the DDR controller can be used, the read clock delay needs to be
+ * set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
+ * This value cannot be hardcoded into the program because it changes
+ * depending on the board's setup and environment.
+ * To do this, all delay values are tested to see if they
+ * work or not. By doing this, you get groups of fails with groups of
+ * passing values. The idea is to find the start and end of a passing
+ * window and take the center of it to use as the read clock delay.
+ *
+ * A failure has to be seen first so that when we hit a pass, we know
+ * that it is truely the start of the window. If we get passing values
+ * to start off with, we don't know if we are at the start of the window.
+ *
+ * The code assumes that a failure will always be found.
+ * If a failure is not found, there is no easy way to get the middle
+ * of the passing window. I guess we can pretty much pick any value
+ * but some values will be better than others. Since the lowest speed
+ * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
+ * from experimentation it is safe to say you will always have a failure.
+ *-----------------------------------------------------------------*/
+
+ /* first fix RQDC[RQFD] to an average of 80 degre phase shift to find RFDC[RFFD] */
+ rqfd_start = 64; /* test-only: don't know if this is the _best_ start value */
+
+ puts(str);
+
+calibration_loop:
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+ SDRAM_RQDC_RQFD_ENCODE(rqfd_start));
+#else /* CONFIG_DDR_RQDC_FIXED */
+ /*
+ * On Katmai the complete auto-calibration somehow doesn't seem to
+ * produce the best results, meaning optimal values for RQFD/RFFD.
+ * This was discovered by GDA using a high bandwidth scope,
+ * analyzing the DDR2 signals. GDA provided a fixed value for RQFD,
+ * so now on Katmai "only" RFFD is auto-calibrated.
+ */
+ mtsdram(SDRAM_RQDC, CONFIG_DDR_RQDC_FIXED);
+#endif /* CONFIG_DDR_RQDC_FIXED */
+
+ max_start = 0;
+
+ max_pass_length = 0;
+ max_start = 0;
+ max_end = 0;
+ current_pass_length = 0;
+ current_fail_length = 0;
+ current_start = 0;
+ fail_found = false;
+ pass_found = false;
+
+ /*
+ * get the delay line calibration register value
+ */
+ mfsdram(SDRAM_DLCR, dlycal);
+ dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2;
+
+ for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+
+ /*------------------------------------------------------------------
+ * Set the timing reg for the test.
+ *-----------------------------------------------------------------*/
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+ /*------------------------------------------------------------------
+ * See if the rffd value passed.
+ *-----------------------------------------------------------------*/
+ if (short_mem_test()) {
+ if (fail_found == true) {
+ pass_found = true;
+ if (current_pass_length == 0)
+ current_start = rffd;
+
+ current_fail_length = 0;
+ current_pass_length++;
+
+ if (current_pass_length > max_pass_length) {
+ max_pass_length = current_pass_length;
+ max_start = current_start;
+ max_end = rffd;
+ }
+ }
+ } else {
+ current_pass_length = 0;
+ current_fail_length++;
+
+ if (current_fail_length >= (dly_val >> 2)) {
+ if (fail_found == false)
+ fail_found = true;
+ else if (pass_found == true)
+ break;
+ }
+ }
+ } /* for rffd */
+
+ /*------------------------------------------------------------------
+ * Set the average RFFD value
+ *-----------------------------------------------------------------*/
+ rffd_average = ((max_start + max_end) >> 1);
+
+ if (rffd_average < 0)
+ rffd_average = 0;
+
+ if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+ rffd_average = SDRAM_RFDC_RFFD_MAX;
+ /* now fix RFDC[RFFD] found and find RQDC[RQFD] */
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+
+#if !defined(CONFIG_DDR_RQDC_FIXED)
+ max_pass_length = 0;
+ max_start = 0;
+ max_end = 0;
+ current_pass_length = 0;
+ current_fail_length = 0;
+ current_start = 0;
+ window_found = false;
+ fail_found = false;
+ pass_found = false;
+
+ for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+
+ /*------------------------------------------------------------------
+ * Set the timing reg for the test.
+ *-----------------------------------------------------------------*/
+ mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+ /*------------------------------------------------------------------
+ * See if the rffd value passed.
+ *-----------------------------------------------------------------*/
+ if (short_mem_test()) {
+ if (fail_found == true) {
+ pass_found = true;
+ if (current_pass_length == 0)
+ current_start = rqfd;
+
+ current_fail_length = 0;
+ current_pass_length++;
+
+ if (current_pass_length > max_pass_length) {
+ max_pass_length = current_pass_length;
+ max_start = current_start;
+ max_end = rqfd;
+ }
+ }
+ } else {
+ current_pass_length = 0;
+ current_fail_length++;
+
+ if (fail_found == false) {
+ fail_found = true;
+ } else if (pass_found == true) {
+ window_found = true;
+ break;
+ }
+ }
+ }
+
+ rqfd_average = ((max_start + max_end) >> 1);
+
+ /*------------------------------------------------------------------
+ * Make sure we found the valid read passing window. Halt if not
+ *-----------------------------------------------------------------*/
+ if (window_found == false) {
+ if (rqfd_start < SDRAM_RQDC_RQFD_MAX) {
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+
+ /* try again from with a different RQFD start value */
+ rqfd_start++;
+ goto calibration_loop;
+ }
+
+ printf("\nERROR: Cannot determine a common read delay for the "
+ "DIMM(s) installed.\n");
+ debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__);
+ ppc4xx_ibm_ddr2_register_dump();
+ spd_ddr_init_hang ();
+ }
+
+ if (rqfd_average < 0)
+ rqfd_average = 0;
+
+ if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+ rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+ mtsdram(SDRAM_RQDC,
+ (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+ SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+ blank_string(strlen(str));
+#endif /* CONFIG_DDR_RQDC_FIXED */
+
+ mfsdram(SDRAM_DLCR, val);
+ debug("%s[%d] DLCR: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+ mfsdram(SDRAM_RQDC, val);
+ debug("%s[%d] RQDC: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+ mfsdram(SDRAM_RFDC, val);
+ debug("%s[%d] RFDC: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+ mfsdram(SDRAM_RDCC, val);
+ debug("%s[%d] RDCC: 0x%08lX\n", __FUNCTION__, __LINE__, val);
+}
+#else /* calibration test with hardvalues */
+/*-----------------------------------------------------------------------------+
+ * DQS_calibration_process.
+ *-----------------------------------------------------------------------------*/
+static void test(void)
+{
+ unsigned long dimm_num;
+ unsigned long ecc_temp;
+ unsigned long i, j;
+ unsigned long *membase;
+ unsigned long bxcf[MAXRANKS];
+ unsigned long val;
+ char window_found;
+ char begin_found[MAXDIMMS];
+ char end_found[MAXDIMMS];
+ char search_end[MAXDIMMS];
+ unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = {
+ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} };
+
+ /*------------------------------------------------------------------
+ * Test to determine the best read clock delay tuning bits.
+ *
+ * Before the DDR controller can be used, the read clock delay needs to be
+ * set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
+ * This value cannot be hardcoded into the program because it changes
+ * depending on the board's setup and environment.
+ * To do this, all delay values are tested to see if they
+ * work or not. By doing this, you get groups of fails with groups of
+ * passing values. The idea is to find the start and end of a passing
+ * window and take the center of it to use as the read clock delay.
+ *
+ * A failure has to be seen first so that when we hit a pass, we know
+ * that it is truely the start of the window. If we get passing values
+ * to start off with, we don't know if we are at the start of the window.
+ *
+ * The code assumes that a failure will always be found.
+ * If a failure is not found, there is no easy way to get the middle
+ * of the passing window. I guess we can pretty much pick any value
+ * but some values will be better than others. Since the lowest speed
+ * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
+ * from experimentation it is safe to say you will always have a failure.
+ *-----------------------------------------------------------------*/
+ mfsdram(SDRAM_MCOPT1, ecc_temp);
+ ecc_temp &= SDRAM_MCOPT1_MCHK_MASK;
+ mfsdram(SDRAM_MCOPT1, val);
+ mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) |
+ SDRAM_MCOPT1_MCHK_NON);
+
+ window_found = false;
+ begin_found[0] = false;
+ end_found[0] = false;
+ search_end[0] = false;
+ begin_found[1] = false;
+ end_found[1] = false;
+ search_end[1] = false;
+
+ for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) {
+ mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf[bxcr_num]);
+
+ /* Banks enabled */
+ if ((bxcf[dimm_num] & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
+
+ /* Bank is enabled */
+ membase =
+ (unsigned long*)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+dimm_num)));
+
+ /*------------------------------------------------------------------
+ * Run the short memory test.
+ *-----------------------------------------------------------------*/
+ for (i = 0; i < NUMMEMTESTS; i++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ membase[j] = test[i][j];
+ ppcDcbf((u32)&(membase[j]));
+ }
+ sync();
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (membase[j] != test[i][j]) {
+ ppcDcbf((u32)&(membase[j]));
+ break;
+ }
+ ppcDcbf((u32)&(membase[j]));
+ }
+ sync();
+ if (j < NUMMEMWORDS)
+ break;
+ }
+
+ /*------------------------------------------------------------------
+ * See if the rffd value passed.
+ *-----------------------------------------------------------------*/
+ if (i < NUMMEMTESTS) {
+ if ((end_found[dimm_num] == false) &&
+ (search_end[dimm_num] == true)) {
+ end_found[dimm_num] = true;
+ }
+ if ((end_found[0] == true) &&
+ (end_found[1] == true))
+ break;
+ } else {
+ if (begin_found[dimm_num] == false) {
+ begin_found[dimm_num] = true;
+ search_end[dimm_num] = true;
+ }
+ }
+ } else {
+ begin_found[dimm_num] = true;
+ end_found[dimm_num] = true;
+ }
+ }
+
+ if ((begin_found[0] == true) && (begin_found[1] == true))
+ window_found = true;
+
+ /*------------------------------------------------------------------
+ * Make sure we found the valid read passing window. Halt if not
+ *-----------------------------------------------------------------*/
+ if (window_found == false) {
+ printf("ERROR: Cannot determine a common read delay for the "
+ "DIMM(s) installed.\n");
+ spd_ddr_init_hang ();
+ }
+
+ /*------------------------------------------------------------------
+ * Restore the ECC variable to what it originally was
+ *-----------------------------------------------------------------*/
+ mtsdram(SDRAM_MCOPT1,
+ (ppcMfdcr_sdram(SDRAM_MCOPT1) & ~SDRAM_MCOPT1_MCHK_MASK)
+ | ecc_temp);
+}
+#endif /* !HARD_CODED_DQS */
+#endif /* !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) */
+
+#else /* CONFIG_SPD_EEPROM */
+
+/*-----------------------------------------------------------------------------
+ * Function: initdram
+ * Description: Configures the PPC4xx IBM DDR1/DDR2 SDRAM memory controller.
+ * The configuration is performed using static, compile-
+ * time parameters.
+ * Configures the PPC405EX(r) and PPC460EX/GT
+ *---------------------------------------------------------------------------*/
+phys_size_t initdram(int board_type)
+{
+ /*
+ * Only run this SDRAM init code once. For NAND booting
+ * targets like Kilauea, we call initdram() early from the
+ * 4k NAND booting image (CONFIG_NAND_SPL) from nand_boot().
+ * Later on the NAND U-Boot image runs (CONFIG_NAND_U_BOOT)
+ * which calls initdram() again. This time the controller
+ * mustn't be reconfigured again since we're already running
+ * from SDRAM.
+ */
+#if !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL)
+ unsigned long val;
+
+#if defined(CONFIG_440)
+ mtdcr(SDRAM_R0BAS, CONFIG_SYS_SDRAM_R0BAS);
+ mtdcr(SDRAM_R1BAS, CONFIG_SYS_SDRAM_R1BAS);
+ mtdcr(SDRAM_R2BAS, CONFIG_SYS_SDRAM_R2BAS);
+ mtdcr(SDRAM_R3BAS, CONFIG_SYS_SDRAM_R3BAS);
+ mtdcr(SDRAM_PLBADDULL, CONFIG_SYS_SDRAM_PLBADDULL); /* MQ0_BAUL */
+ mtdcr(SDRAM_PLBADDUHB, CONFIG_SYS_SDRAM_PLBADDUHB); /* MQ0_BAUH */
+ mtdcr(SDRAM_CONF1LL, CONFIG_SYS_SDRAM_CONF1LL);
+ mtdcr(SDRAM_CONF1HB, CONFIG_SYS_SDRAM_CONF1HB);
+ mtdcr(SDRAM_CONFPATHB, CONFIG_SYS_SDRAM_CONFPATHB);
+#endif
+
+ /* Set Memory Bank Configuration Registers */
+
+ mtsdram(SDRAM_MB0CF, CONFIG_SYS_SDRAM0_MB0CF);
+ mtsdram(SDRAM_MB1CF, CONFIG_SYS_SDRAM0_MB1CF);
+ mtsdram(SDRAM_MB2CF, CONFIG_SYS_SDRAM0_MB2CF);
+ mtsdram(SDRAM_MB3CF, CONFIG_SYS_SDRAM0_MB3CF);
+
+ /* Set Memory Clock Timing Register */
+
+ mtsdram(SDRAM_CLKTR, CONFIG_SYS_SDRAM0_CLKTR);
+
+ /* Set Refresh Time Register */
+
+ mtsdram(SDRAM_RTR, CONFIG_SYS_SDRAM0_RTR);
+
+ /* Set SDRAM Timing Registers */
+
+ mtsdram(SDRAM_SDTR1, CONFIG_SYS_SDRAM0_SDTR1);
+ mtsdram(SDRAM_SDTR2, CONFIG_SYS_SDRAM0_SDTR2);
+ mtsdram(SDRAM_SDTR3, CONFIG_SYS_SDRAM0_SDTR3);
+
+ /* Set Mode and Extended Mode Registers */
+
+ mtsdram(SDRAM_MMODE, CONFIG_SYS_SDRAM0_MMODE);
+ mtsdram(SDRAM_MEMODE, CONFIG_SYS_SDRAM0_MEMODE);
+
+ /* Set Memory Controller Options 1 Register */
+
+ mtsdram(SDRAM_MCOPT1, CONFIG_SYS_SDRAM0_MCOPT1);
+
+ /* Set Manual Initialization Control Registers */
+
+ mtsdram(SDRAM_INITPLR0, CONFIG_SYS_SDRAM0_INITPLR0);
+ mtsdram(SDRAM_INITPLR1, CONFIG_SYS_SDRAM0_INITPLR1);
+ mtsdram(SDRAM_INITPLR2, CONFIG_SYS_SDRAM0_INITPLR2);
+ mtsdram(SDRAM_INITPLR3, CONFIG_SYS_SDRAM0_INITPLR3);
+ mtsdram(SDRAM_INITPLR4, CONFIG_SYS_SDRAM0_INITPLR4);
+ mtsdram(SDRAM_INITPLR5, CONFIG_SYS_SDRAM0_INITPLR5);
+ mtsdram(SDRAM_INITPLR6, CONFIG_SYS_SDRAM0_INITPLR6);
+ mtsdram(SDRAM_INITPLR7, CONFIG_SYS_SDRAM0_INITPLR7);
+ mtsdram(SDRAM_INITPLR8, CONFIG_SYS_SDRAM0_INITPLR8);
+ mtsdram(SDRAM_INITPLR9, CONFIG_SYS_SDRAM0_INITPLR9);
+ mtsdram(SDRAM_INITPLR10, CONFIG_SYS_SDRAM0_INITPLR10);
+ mtsdram(SDRAM_INITPLR11, CONFIG_SYS_SDRAM0_INITPLR11);
+ mtsdram(SDRAM_INITPLR12, CONFIG_SYS_SDRAM0_INITPLR12);
+ mtsdram(SDRAM_INITPLR13, CONFIG_SYS_SDRAM0_INITPLR13);
+ mtsdram(SDRAM_INITPLR14, CONFIG_SYS_SDRAM0_INITPLR14);
+ mtsdram(SDRAM_INITPLR15, CONFIG_SYS_SDRAM0_INITPLR15);
+
+ /* Set On-Die Termination Registers */
+
+ mtsdram(SDRAM_CODT, CONFIG_SYS_SDRAM0_CODT);
+ mtsdram(SDRAM_MODT0, CONFIG_SYS_SDRAM0_MODT0);
+ mtsdram(SDRAM_MODT1, CONFIG_SYS_SDRAM0_MODT1);
+
+ /* Set Write Timing Register */
+
+ mtsdram(SDRAM_WRDTR, CONFIG_SYS_SDRAM0_WRDTR);
+
+ /*
+ * Start Initialization by SDRAM0_MCOPT2[SREN] = 0 and
+ * SDRAM0_MCOPT2[IPTR] = 1
+ */
+
+ mtsdram(SDRAM_MCOPT2, (SDRAM_MCOPT2_SREN_EXIT |
+ SDRAM_MCOPT2_IPTR_EXECUTE));
+
+ /*
+ * Poll SDRAM0_MCSTAT[MIC] for assertion to indicate the
+ * completion of initialization.
+ */
+
+ do {
+ mfsdram(SDRAM_MCSTAT, val);
+ } while ((val & SDRAM_MCSTAT_MIC_MASK) != SDRAM_MCSTAT_MIC_COMP);
+
+ /* Set Delay Control Registers */
+
+ mtsdram(SDRAM_DLCR, CONFIG_SYS_SDRAM0_DLCR);
+
+#if !defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+ mtsdram(SDRAM_RDCC, CONFIG_SYS_SDRAM0_RDCC);
+ mtsdram(SDRAM_RQDC, CONFIG_SYS_SDRAM0_RQDC);
+ mtsdram(SDRAM_RFDC, CONFIG_SYS_SDRAM0_RFDC);
+#endif /* !CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
+ /*
+ * Enable Controller by SDRAM0_MCOPT2[DCEN] = 1:
+ */
+
+ mfsdram(SDRAM_MCOPT2, val);
+ mtsdram(SDRAM_MCOPT2, val | SDRAM_MCOPT2_DCEN_ENABLE);
+
+#if defined(CONFIG_440)
+ /*
+ * Program TLB entries with caches enabled, for best performace
+ * while auto-calibrating and ECC generation
+ */
+ program_tlb(0, 0, (CONFIG_SYS_MBYTES_SDRAM << 20), 0);
+#endif
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+ /*------------------------------------------------------------------
+ | DQS calibration.
+ +-----------------------------------------------------------------*/
+ DQS_autocalibration();
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
+#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
+ /*
+ * Now complete RDSS configuration as mentioned on page 7 of the AMCC
+ * PowerPC440SP/SPe DDR2 application note:
+ * "DDR1/DDR2 Initialization Sequence and Dynamic Tuning"
+ */
+ update_rdcc();
+
+#if defined(CONFIG_DDR_ECC)
+ do_program_ecc(0);
+#endif /* defined(CONFIG_DDR_ECC) */
+
+#if defined(CONFIG_440)
+ /*
+ * Now after initialization (auto-calibration and ECC generation)
+ * remove the TLB entries with caches enabled and program again with
+ * desired cache functionality
+ */
+ remove_tlb(0, (CONFIG_SYS_MBYTES_SDRAM << 20));
+ program_tlb(0, 0, (CONFIG_SYS_MBYTES_SDRAM << 20), MY_TLB_WORD2_I_ENABLE);
+#endif
+
+ ppc4xx_ibm_ddr2_register_dump();
+
+#if defined(CONFIG_PPC4xx_DDR_AUTOCALIBRATION)
+ /*
+ * Clear potential errors resulting from auto-calibration.
+ * If not done, then we could get an interrupt later on when
+ * exceptions are enabled.
+ */
+ set_mcsr(get_mcsr());
+#endif /* CONFIG_PPC4xx_DDR_AUTOCALIBRATION */
+
+#endif /* !defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
+
+ return (CONFIG_SYS_MBYTES_SDRAM << 20);
+}
+#endif /* CONFIG_SPD_EEPROM */
+
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#if defined(CONFIG_440)
+u32 mfdcr_any(u32 dcr)
+{
+ u32 val;
+
+ switch (dcr) {
+ case SDRAM_R0BAS + 0:
+ val = mfdcr(SDRAM_R0BAS + 0);
+ break;
+ case SDRAM_R0BAS + 1:
+ val = mfdcr(SDRAM_R0BAS + 1);
+ break;
+ case SDRAM_R0BAS + 2:
+ val = mfdcr(SDRAM_R0BAS + 2);
+ break;
+ case SDRAM_R0BAS + 3:
+ val = mfdcr(SDRAM_R0BAS + 3);
+ break;
+ default:
+ printf("DCR %d not defined in case statement!!!\n", dcr);
+ val = 0; /* just to satisfy the compiler */
+ }
+
+ return val;
+}
+
+void mtdcr_any(u32 dcr, u32 val)
+{
+ switch (dcr) {
+ case SDRAM_R0BAS + 0:
+ mtdcr(SDRAM_R0BAS + 0, val);
+ break;
+ case SDRAM_R0BAS + 1:
+ mtdcr(SDRAM_R0BAS + 1, val);
+ break;
+ case SDRAM_R0BAS + 2:
+ mtdcr(SDRAM_R0BAS + 2, val);
+ break;
+ case SDRAM_R0BAS + 3:
+ mtdcr(SDRAM_R0BAS + 3, val);
+ break;
+ default:
+ printf("DCR %d not defined in case statement!!!\n", dcr);
+ }
+}
+#endif /* defined(CONFIG_440) */
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
+
+inline void ppc4xx_ibm_ddr2_register_dump(void)
+{
+#if defined(DEBUG)
+ printf("\nPPC4xx IBM DDR2 Register Dump:\n");
+
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
+ PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R0BAS);
+ PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R1BAS);
+ PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R2BAS);
+ PPC4xx_IBM_DDR2_DUMP_MQ_REGISTER(R3BAS);
+#endif /* (defined(CONFIG_440SP) || ... */
+#if defined(CONFIG_405EX)
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(BESR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARL);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(BEARH);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(WMIRQ);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(PLBOPT);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(PUABA);
+#endif /* defined(CONFIG_405EX) */
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB0CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB1CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB2CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MB3CF);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MCSTAT);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MCOPT2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT0);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MODT3);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(CODT);
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(VVPR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(OPARS);
+ /*
+ * OPART is only used as a trigger register.
+ *
+ * No data is contained in this register, and reading or writing
+ * to is can cause bad things to happen (hangs). Just skip it and
+ * report "N/A".
+ */
+ printf("%20s = N/A\n", "SDRAM_OPART");
+#endif /* defined(CONFIG_440SP) || ... */
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RTR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR0);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR3);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR4);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR5);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR6);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR7);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR8);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR9);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR10);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR11);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR12);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR13);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR14);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(INITPLR15);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RQDC);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RFDC);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RDCC);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(DLCR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(CLKTR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(WRDTR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR1);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR2);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(SDTR3);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MMODE);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(MEMODE);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(ECCES);
+#if (defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT))
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(CID);
+#endif /* defined(CONFIG_440SP) || ... */
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RID);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(FCSR);
+ PPC4xx_IBM_DDR2_DUMP_REGISTER(RTSR);
+#endif /* defined(DEBUG) */
+}
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c b/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
new file mode 100644
index 0000000..3c87bfb
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
@@ -0,0 +1,1256 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
+ * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
+ * DDR2 controller (non Denali Core). Those currently are:
+ *
+ * 405: 405EX
+ * 440/460: 440SP/440SPe/460EX/460GT/460SX
+ *
+ * (C) Copyright 2008 Applied Micro Circuits Corporation
+ * Adam Graham <agraham@amcc.com>
+ *
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * COPYRIGHT AMCC CORPORATION 2004
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#undef DEBUG
+
+#include <common.h>
+#include <asm/ppc4xx.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#include "ecc.h"
+
+/*
+ * Only compile the DDR auto-calibration code for NOR boot and
+ * not for NAND boot (NAND SPL and NAND U-Boot - NUB)
+ */
+#if !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+
+#define MAXBXCF 4
+#define SDRAM_RXBAS_SHIFT_1M 20
+
+#if defined(CONFIG_SYS_DECREMENT_PATTERNS)
+#define NUMMEMTESTS 24
+#else
+#define NUMMEMTESTS 8
+#endif /* CONFIG_SYS_DECREMENT_PATTERNS */
+#define NUMLOOPS 1 /* configure as you deem approporiate */
+#define NUMMEMWORDS 16
+
+#define SDRAM_RDCC_RDSS_VAL(n) SDRAM_RDCC_RDSS_DECODE(ddr_rdss_opt(n))
+
+/* Private Structure Definitions */
+
+struct autocal_regs {
+ u32 rffd;
+ u32 rqfd;
+};
+
+struct ddrautocal {
+ u32 rffd;
+ u32 rffd_min;
+ u32 rffd_max;
+ u32 rffd_size;
+ u32 rqfd;
+ u32 rqfd_size;
+ u32 rdcc;
+ u32 flags;
+};
+
+struct sdram_timing_clks {
+ u32 wrdtr;
+ u32 clktr;
+ u32 rdcc;
+ u32 flags;
+};
+
+struct autocal_clks {
+ struct sdram_timing_clks clocks;
+ struct ddrautocal autocal;
+};
+
+/*--------------------------------------------------------------------------+
+ * Prototypes
+ *--------------------------------------------------------------------------*/
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+static u32 DQS_calibration_methodA(struct ddrautocal *);
+static u32 program_DQS_calibration_methodA(struct ddrautocal *);
+#else
+static u32 DQS_calibration_methodB(struct ddrautocal *);
+static u32 program_DQS_calibration_methodB(struct ddrautocal *);
+#endif
+static int short_mem_test(u32 *);
+
+/*
+ * To provide an interface for board specific config values in this common
+ * DDR setup code, we implement he "weak" default functions here. They return
+ * the default value back to the caller.
+ *
+ * Please see include/configs/yucca.h for an example fora board specific
+ * implementation.
+ */
+
+#if !defined(CONFIG_SPD_EEPROM)
+u32 __ddr_wrdtr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
+
+u32 __ddr_clktr(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang(void)
+{
+ hang();
+}
+void
+spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang")));
+#endif /* defined(CONFIG_SPD_EEPROM) */
+
+struct sdram_timing *__ddr_scan_option(struct sdram_timing *default_val)
+{
+ return default_val;
+}
+struct sdram_timing *ddr_scan_option(struct sdram_timing *)
+ __attribute__((weak, alias("__ddr_scan_option")));
+
+u32 __ddr_rdss_opt(u32 default_val)
+{
+ return default_val;
+}
+u32 ddr_rdss_opt(ulong) __attribute__((weak, alias("__ddr_rdss_opt")));
+
+
+static u32 *get_membase(int bxcr_num)
+{
+ u32 *membase;
+
+#if defined(SDRAM_R0BAS)
+ /* BAS from Memory Queue rank reg. */
+ membase =
+ (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
+#else
+ {
+ ulong bxcf;
+
+ /* BAS from SDRAM_MBxCF mem rank reg. */
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+ membase = (u32 *)((bxcf & 0xfff80000) << 3);
+ }
+#endif
+
+ return membase;
+}
+
+static inline void ecc_clear_status_reg(void)
+{
+ mtsdram(SDRAM_ECCES, 0xffffffff);
+#if defined(SDRAM_R0BAS)
+ mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
+#endif
+}
+
+/*
+ * Reset and relock memory DLL after SDRAM_CLKTR change
+ */
+static inline void relock_memory_DLL(void)
+{
+ u32 reg;
+
+ mtsdram(SDRAM_MCOPT2, SDRAM_MCOPT2_IPTR_EXECUTE);
+
+ do {
+ mfsdram(SDRAM_MCSTAT, reg);
+ } while (!(reg & SDRAM_MCSTAT_MIC_COMP));
+
+ mfsdram(SDRAM_MCOPT2, reg);
+ mtsdram(SDRAM_MCOPT2, reg | SDRAM_MCOPT2_DCEN_ENABLE);
+}
+
+static int ecc_check_status_reg(void)
+{
+ u32 ecc_status;
+
+ /*
+ * Compare suceeded, now check
+ * if got ecc error. If got an
+ * ecc error, then don't count
+ * this as a passing value
+ */
+ mfsdram(SDRAM_ECCES, ecc_status);
+ if (ecc_status != 0x00000000) {
+ /* clear on error */
+ ecc_clear_status_reg();
+ /* ecc check failure */
+ return 0;
+ }
+ ecc_clear_status_reg();
+ sync();
+
+ return 1;
+}
+
+/* return 1 if passes, 0 if fail */
+static int short_mem_test(u32 *base_address)
+{
+ int i, j, l;
+ u32 ecc_mode = 0;
+
+ ulong test[NUMMEMTESTS][NUMMEMWORDS] = {
+ /* 0 */ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
+ /* 1 */ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
+ /* 2 */ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
+ /* 3 */ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
+ /* 4 */ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
+ /* 5 */ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
+ /* 6 */ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
+ /* 7 */ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55},
+
+#if defined(CONFIG_SYS_DECREMENT_PATTERNS)
+ /* 8 */ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
+ /* 9 */ {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+ 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+ 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
+ 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe},
+ /* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+ 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+ 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
+ 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd},
+ /* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+ 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+ 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
+ 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc},
+ /* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+ 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+ 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
+ 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb},
+ /* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa,
+ 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
+ 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
+ 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa},
+ /* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+ 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+ 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
+ 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9},
+ /* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+ 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+ 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
+ 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8},
+ /* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+ 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+ 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
+ 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7},
+ /* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+ 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+ 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
+ 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7},
+ /* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+ 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+ 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
+ 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5},
+ /* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+ 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+ 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
+ 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4},
+ /* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+ 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+ 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
+ 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3},
+ /* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+ 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+ 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
+ 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2},
+ /* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+ 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+ 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
+ 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1},
+ /* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+ 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+ 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
+ 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0},
+#endif /* CONFIG_SYS_DECREMENT_PATTERNS */
+ };
+
+ mfsdram(SDRAM_MCOPT1, ecc_mode);
+ if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) ==
+ SDRAM_MCOPT1_MCHK_CHK_REP) {
+ ecc_clear_status_reg();
+ sync();
+ ecc_mode = 1;
+ } else {
+ ecc_mode = 0;
+ }
+
+ /*
+ * Run the short memory test.
+ */
+ for (i = 0; i < NUMMEMTESTS; i++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ base_address[j] = test[i][j];
+ ppcDcbf((ulong)&(base_address[j]));
+ }
+ sync();
+ iobarrier_rw();
+ for (l = 0; l < NUMLOOPS; l++) {
+ for (j = 0; j < NUMMEMWORDS; j++) {
+ if (base_address[j] != test[i][j]) {
+ ppcDcbf((u32)&(base_address[j]));
+ return 0;
+ } else {
+ if (ecc_mode) {
+ if (!ecc_check_status_reg())
+ return 0;
+ }
+ }
+ ppcDcbf((u32)&(base_address[j]));
+ } /* for (j = 0; j < NUMMEMWORDS; j++) */
+ sync();
+ iobarrier_rw();
+ } /* for (l=0; l<NUMLOOPS; l++) */
+ }
+
+ return 1;
+}
+
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+/*-----------------------------------------------------------------------------+
+| program_DQS_calibration_methodA.
++-----------------------------------------------------------------------------*/
+static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal)
+{
+ u32 pass_result = 0;
+
+#ifdef DEBUG
+ ulong temp;
+
+ mfsdram(SDRAM_RDCC, temp);
+ debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
+#endif
+
+ pass_result = DQS_calibration_methodA(ddrcal);
+
+ return pass_result;
+}
+
+/*
+ * DQS_calibration_methodA()
+ *
+ * Autocalibration Method A
+ *
+ * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
+ * ARRAY [Entire FDBK Range] FDBK_Valid_Window; initialized to all zeros
+ * MEMWRITE(addr, expected_data);
+ * for (i = 0; i < Entire DQS Range; i++) { RQDC.RQFD
+ * for (j = 0; j < Entire FDBK Range; j++) { RFDC.RFFD
+ * MEMREAD(addr, actual_data);
+ * if (actual_data == expected_data) {
+ * DQS_Valid_Window[i] = 1; RQDC.RQFD
+ * FDBK_Valid_Window[i][j] = 1; RFDC.RFFD
+ * }
+ * }
+ * }
+ */
+static u32 DQS_calibration_methodA(struct ddrautocal *cal)
+{
+ ulong rfdc_reg;
+ ulong rffd;
+
+ ulong rqdc_reg;
+ ulong rqfd;
+
+ u32 *membase;
+ ulong bxcf;
+ int rqfd_average;
+ int bxcr_num;
+ int rffd_average;
+ int pass;
+ u32 passed = 0;
+
+ int in_window;
+ struct autocal_regs curr_win_min;
+ struct autocal_regs curr_win_max;
+ struct autocal_regs best_win_min;
+ struct autocal_regs best_win_max;
+ struct autocal_regs loop_win_min;
+ struct autocal_regs loop_win_max;
+
+#ifdef DEBUG
+ ulong temp;
+#endif
+ ulong rdcc;
+
+ char slash[] = "\\|/-\\|/-";
+ int loopi = 0;
+
+ /* start */
+ in_window = 0;
+
+ memset(&curr_win_min, 0, sizeof(curr_win_min));
+ memset(&curr_win_max, 0, sizeof(curr_win_max));
+ memset(&best_win_min, 0, sizeof(best_win_min));
+ memset(&best_win_max, 0, sizeof(best_win_max));
+ memset(&loop_win_min, 0, sizeof(loop_win_min));
+ memset(&loop_win_max, 0, sizeof(loop_win_max));
+
+ rdcc = 0;
+
+ /*
+ * Program RDCC register
+ * Read sample cycle auto-update enable
+ */
+ mtsdram(SDRAM_RDCC,
+ ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RDCC, temp);
+ debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);
+ mfsdram(SDRAM_RTSR, temp);
+ debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);
+ mfsdram(SDRAM_FCSR, temp);
+ debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RQDC register
+ * Internal DQS delay mechanism enable
+ */
+ mtsdram(SDRAM_RQDC,
+ SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RQDC, temp);
+ debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RFDC register
+ * Set Feedback Fractional Oversample
+ * Auto-detect read sample cycle enable
+ */
+ mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
+ SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RFDC, temp);
+ debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);
+#endif
+
+ putc(' ');
+ for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+ mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+
+ curr_win_min.rffd = 0;
+ curr_win_max.rffd = 0;
+ in_window = 0;
+
+ for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+ mtsdram(SDRAM_RFDC,
+ rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+ for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+ /* Banks enabled */
+ if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+ /* Bank is enabled */
+ membase = get_membase(bxcr_num);
+ pass = short_mem_test(membase);
+ } /* if bank enabled */
+ } /* for bxcr_num */
+
+ /* If this value passed update RFFD windows */
+ if (pass && !in_window) { /* at the start of window */
+ in_window = 1;
+ curr_win_min.rffd = curr_win_max.rffd = rffd;
+ curr_win_min.rqfd = curr_win_max.rqfd = rqfd;
+ mfsdram(SDRAM_RDCC, rdcc); /*record this value*/
+ } else if (!pass && in_window) { /* at end of window */
+ in_window = 0;
+ } else if (pass && in_window) { /* within the window */
+ curr_win_max.rffd = rffd;
+ curr_win_max.rqfd = rqfd;
+ }
+ /* else if (!pass && !in_window)
+ skip - no pass, not currently in a window */
+
+ if (in_window) {
+ if ((curr_win_max.rffd - curr_win_min.rffd) >
+ (best_win_max.rffd - best_win_min.rffd)) {
+ best_win_min.rffd = curr_win_min.rffd;
+ best_win_max.rffd = curr_win_max.rffd;
+
+ best_win_min.rqfd = curr_win_min.rqfd;
+ best_win_max.rqfd = curr_win_max.rqfd;
+ cal->rdcc = rdcc;
+ }
+ passed = 1;
+ }
+ } /* RFDC.RFFD */
+
+ /*
+ * save-off the best window results of the RFDC.RFFD
+ * for this RQDC.RQFD setting
+ */
+ /*
+ * if (just ended RFDC.RFDC loop pass window) >
+ * (prior RFDC.RFFD loop pass window)
+ */
+ if ((best_win_max.rffd - best_win_min.rffd) >
+ (loop_win_max.rffd - loop_win_min.rffd)) {
+ loop_win_min.rffd = best_win_min.rffd;
+ loop_win_max.rffd = best_win_max.rffd;
+ loop_win_min.rqfd = rqfd;
+ loop_win_max.rqfd = rqfd;
+ debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "
+ "RFFD.min 0x%08x, RFFD.max 0x%08x\n",
+ loop_win_min.rqfd, loop_win_max.rqfd,
+ loop_win_min.rffd, loop_win_max.rffd);
+ }
+ } /* RQDC.RQFD */
+
+ putc('\b');
+
+ debug("\n");
+
+ if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&
+ (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&
+ (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {
+ passed = 0;
+ }
+
+ /*
+ * Need to program RQDC before RFDC.
+ */
+ debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);
+ debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);
+ rqfd_average = loop_win_max.rqfd;
+
+ if (rqfd_average < 0)
+ rqfd_average = 0;
+
+ if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+ rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+ debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);
+ mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+ SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+ debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);
+ debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);
+ rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);
+
+ if (rffd_average < 0)
+ rffd_average = 0;
+
+ if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+ rffd_average = SDRAM_RFDC_RFFD_MAX;
+
+ debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+
+ /* if something passed, then return the size of the largest window */
+ if (passed != 0) {
+ passed = loop_win_max.rffd - loop_win_min.rffd;
+ cal->rqfd = rqfd_average;
+ cal->rffd = rffd_average;
+ cal->rffd_min = loop_win_min.rffd;
+ cal->rffd_max = loop_win_max.rffd;
+ }
+
+ return (u32)passed;
+}
+
+#else /* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */
+
+/*-----------------------------------------------------------------------------+
+| program_DQS_calibration_methodB.
++-----------------------------------------------------------------------------*/
+static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
+{
+ u32 pass_result = 0;
+
+#ifdef DEBUG
+ ulong temp;
+#endif
+
+ /*
+ * Program RDCC register
+ * Read sample cycle auto-update enable
+ */
+ mtsdram(SDRAM_RDCC,
+ ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RDCC, temp);
+ debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RQDC register
+ * Internal DQS delay mechanism enable
+ */
+ mtsdram(SDRAM_RQDC,
+#if defined(CONFIG_DDR_RQDC_START_VAL)
+ SDRAM_RQDC_RQDE_ENABLE |
+ SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));
+#else
+ SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));
+#endif
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RQDC, temp);
+ debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);
+#endif
+
+ /*
+ * Program RFDC register
+ * Set Feedback Fractional Oversample
+ * Auto-detect read sample cycle enable
+ */
+ mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
+ SDRAM_RFDC_RFOS_ENCODE(0) |
+ SDRAM_RFDC_RFFD_ENCODE(0));
+
+#ifdef DEBUG
+ mfsdram(SDRAM_RFDC, temp);
+ debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);
+#endif
+
+ pass_result = DQS_calibration_methodB(ddrcal);
+
+ return pass_result;
+}
+
+/*
+ * DQS_calibration_methodB()
+ *
+ * Autocalibration Method B
+ *
+ * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
+ * ARRAY [Entire Feedback Range] FDBK_Valid_Window; initialized to all zeros
+ * MEMWRITE(addr, expected_data);
+ * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38).
+ *
+ * for (j = 0; j < Entire Feedback Range; j++) {
+ * MEMREAD(addr, actual_data);
+ * if (actual_data == expected_data) {
+ * FDBK_Valid_Window[j] = 1;
+ * }
+ * }
+ *
+ * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window.
+ *
+ * for (i = 0; i < Entire DQS Range; i++) {
+ * MEMREAD(addr, actual_data);
+ * if (actual_data == expected_data) {
+ * DQS_Valid_Window[i] = 1;
+ * }
+ * }
+ *
+ * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window.
+ */
+/*-----------------------------------------------------------------------------+
+| DQS_calibration_methodB.
++-----------------------------------------------------------------------------*/
+static u32 DQS_calibration_methodB(struct ddrautocal *cal)
+{
+ ulong rfdc_reg;
+#ifndef CONFIG_DDR_RFDC_FIXED
+ ulong rffd;
+#endif
+
+ ulong rqdc_reg;
+ ulong rqfd;
+
+ ulong rdcc;
+
+ u32 *membase;
+ ulong bxcf;
+ int rqfd_average;
+ int bxcr_num;
+ int rffd_average;
+ int pass;
+ uint passed = 0;
+
+ int in_window;
+ u32 curr_win_min, curr_win_max;
+ u32 best_win_min, best_win_max;
+ u32 size = 0;
+
+ /*------------------------------------------------------------------
+ | Test to determine the best read clock delay tuning bits.
+ |
+ | Before the DDR controller can be used, the read clock delay needs to
+ | be set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
+ | This value cannot be hardcoded into the program because it changes
+ | depending on the board's setup and environment.
+ | To do this, all delay values are tested to see if they
+ | work or not. By doing this, you get groups of fails with groups of
+ | passing values. The idea is to find the start and end of a passing
+ | window and take the center of it to use as the read clock delay.
+ |
+ | A failure has to be seen first so that when we hit a pass, we know
+ | that it is truely the start of the window. If we get passing values
+ | to start off with, we don't know if we are at the start of the window
+ |
+ | The code assumes that a failure will always be found.
+ | If a failure is not found, there is no easy way to get the middle
+ | of the passing window. I guess we can pretty much pick any value
+ | but some values will be better than others. Since the lowest speed
+ | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
+ | from experimentation it is safe to say you will always have a failure
+ +-----------------------------------------------------------------*/
+
+ debug("\n\n");
+
+#if defined(CONFIG_DDR_RFDC_FIXED)
+ mtsdram(SDRAM_RFDC, CONFIG_DDR_RFDC_FIXED);
+ size = 512;
+ rffd_average = CONFIG_DDR_RFDC_FIXED & SDRAM_RFDC_RFFD_MASK;
+ mfsdram(SDRAM_RDCC, rdcc); /* record this value */
+ cal->rdcc = rdcc;
+#else /* CONFIG_DDR_RFDC_FIXED */
+ in_window = 0;
+ rdcc = 0;
+
+ curr_win_min = curr_win_max = 0;
+ best_win_min = best_win_max = 0;
+ for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
+
+ pass = 1;
+ for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+ /* Banks enabled */
+ if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+ /* Bank is enabled */
+ membase = get_membase(bxcr_num);
+ pass &= short_mem_test(membase);
+ } /* if bank enabled */
+ } /* for bxcf_num */
+
+ /* If this value passed */
+ if (pass && !in_window) { /* start of passing window */
+ in_window = 1;
+ curr_win_min = curr_win_max = rffd;
+ mfsdram(SDRAM_RDCC, rdcc); /* record this value */
+ } else if (!pass && in_window) { /* end passing window */
+ in_window = 0;
+ } else if (pass && in_window) { /* within the passing window */
+ curr_win_max = rffd;
+ }
+
+ if (in_window) {
+ if ((curr_win_max - curr_win_min) >
+ (best_win_max - best_win_min)) {
+ best_win_min = curr_win_min;
+ best_win_max = curr_win_max;
+ cal->rdcc = rdcc;
+ }
+ passed = 1;
+ }
+ } /* for rffd */
+
+ if ((best_win_min == 0) && (best_win_max == 0))
+ passed = 0;
+ else
+ size = best_win_max - best_win_min;
+
+ debug("RFFD Min: 0x%x\n", best_win_min);
+ debug("RFFD Max: 0x%x\n", best_win_max);
+ rffd_average = ((best_win_min + best_win_max) / 2);
+
+ cal->rffd_min = best_win_min;
+ cal->rffd_max = best_win_max;
+
+ if (rffd_average < 0)
+ rffd_average = 0;
+
+ if (rffd_average > SDRAM_RFDC_RFFD_MAX)
+ rffd_average = SDRAM_RFDC_RFFD_MAX;
+
+ mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
+#endif /* CONFIG_DDR_RFDC_FIXED */
+
+ in_window = 0;
+
+ curr_win_min = curr_win_max = 0;
+ best_win_min = best_win_max = 0;
+ for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+ mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
+
+ pass = 1;
+ for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
+
+ mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
+
+ /* Banks enabled */
+ if (bxcf & SDRAM_BXCF_M_BE_MASK) {
+ /* Bank is enabled */
+ membase = get_membase(bxcr_num);
+ pass &= short_mem_test(membase);
+ } /* if bank enabled */
+ } /* for bxcf_num */
+
+ /* If this value passed */
+ if (pass && !in_window) {
+ in_window = 1;
+ curr_win_min = curr_win_max = rqfd;
+ } else if (!pass && in_window) {
+ in_window = 0;
+ } else if (pass && in_window) {
+ curr_win_max = rqfd;
+ }
+
+ if (in_window) {
+ if ((curr_win_max - curr_win_min) >
+ (best_win_max - best_win_min)) {
+ best_win_min = curr_win_min;
+ best_win_max = curr_win_max;
+ }
+ passed = 1;
+ }
+ } /* for rqfd */
+
+ if ((best_win_min == 0) && (best_win_max == 0))
+ passed = 0;
+
+ debug("RQFD Min: 0x%x\n", best_win_min);
+ debug("RQFD Max: 0x%x\n", best_win_max);
+ rqfd_average = ((best_win_min + best_win_max) / 2);
+
+ if (rqfd_average < 0)
+ rqfd_average = 0;
+
+ if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
+ rqfd_average = SDRAM_RQDC_RQFD_MAX;
+
+ mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
+ SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+
+ /*
+ * Need to program RQDC before RFDC. The value is read above.
+ * That is the reason why auto cal not work.
+ * See, comments below.
+ */
+ mtsdram(SDRAM_RQDC, rqdc_reg);
+ mtsdram(SDRAM_RFDC, rfdc_reg);
+
+ debug("RQDC: 0x%08lX\n", rqdc_reg);
+ debug("RFDC: 0x%08lX\n", rfdc_reg);
+
+ /* if something passed, then return the size of the largest window */
+ if (passed != 0) {
+ passed = size;
+ cal->rqfd = rqfd_average;
+ cal->rffd = rffd_average;
+ }
+
+ return (uint)passed;
+}
+#endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */
+
+/*
+ * Default table for DDR auto-calibration of all
+ * possible WRDTR and CLKTR values.
+ * Table format is:
+ * {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]}
+ *
+ * Table is terminated with {-1, -1} value pair.
+ *
+ * Board vendors can specify their own board specific subset of
+ * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value
+ * pairs via a board defined ddr_scan_option() function.
+ */
+static struct sdram_timing full_scan_options[] = {
+ {0, 0}, {0, 1}, {0, 2}, {0, 3},
+ {1, 0}, {1, 1}, {1, 2}, {1, 3},
+ {2, 0}, {2, 1}, {2, 2}, {2, 3},
+ {3, 0}, {3, 1}, {3, 2}, {3, 3},
+ {4, 0}, {4, 1}, {4, 2}, {4, 3},
+ {5, 0}, {5, 1}, {5, 2}, {5, 3},
+ {6, 0}, {6, 1}, {6, 2}, {6, 3},
+ {-1, -1}
+};
+
+/*---------------------------------------------------------------------------+
+| DQS_calibration.
++----------------------------------------------------------------------------*/
+u32 DQS_autocalibration(void)
+{
+ u32 wdtr;
+ u32 clkp;
+ u32 result = 0;
+ u32 best_result = 0;
+ u32 best_rdcc;
+ struct ddrautocal ddrcal;
+ struct autocal_clks tcal;
+ ulong rfdc_reg;
+ ulong rqdc_reg;
+ u32 val;
+ int verbose_lvl = 0;
+ char *str;
+ char slash[] = "\\|/-\\|/-";
+ int loopi = 0;
+ struct sdram_timing *scan_list;
+
+#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
+ int i;
+ char tmp[64]; /* long enough for environment variables */
+#endif
+
+ memset(&tcal, 0, sizeof(tcal));
+
+ scan_list = ddr_scan_option(full_scan_options);
+
+ mfsdram(SDRAM_MCOPT1, val);
+ if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP)
+ str = "ECC Auto calibration -";
+ else
+ str = "Auto calibration -";
+
+ puts(str);
+
+#if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
+ i = getenv_f("autocalib", tmp, sizeof(tmp));
+ if (i < 0)
+ strcpy(tmp, CONFIG_AUTOCALIB);
+
+ if (strcmp(tmp, "final") == 0) {
+ /* display the final autocalibration results only */
+ verbose_lvl = 1;
+ } else if (strcmp(tmp, "loop") == 0) {
+ /* display summary autocalibration info per iteration */
+ verbose_lvl = 2;
+ } else if (strcmp(tmp, "display") == 0) {
+ /* display full debug autocalibration window info. */
+ verbose_lvl = 3;
+ }
+#endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */
+
+ best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30);
+
+ while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) {
+ wdtr = scan_list->wrdtr;
+ clkp = scan_list->clktr;
+
+ mfsdram(SDRAM_WRDTR, val);
+ val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK);
+ mtsdram(SDRAM_WRDTR, (val |
+ ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25))));
+
+ mtsdram(SDRAM_CLKTR, clkp << 30);
+
+ relock_memory_DLL();
+
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+
+#ifdef DEBUG
+ debug("\n");
+ debug("*** --------------\n");
+ mfsdram(SDRAM_WRDTR, val);
+ debug("*** SDRAM_WRDTR set to 0x%08x\n", val);
+ mfsdram(SDRAM_CLKTR, val);
+ debug("*** SDRAM_CLKTR set to 0x%08x\n", val);
+#endif
+
+ debug("\n");
+ if (verbose_lvl > 2) {
+ printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr);
+ printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp);
+ }
+
+ memset(&ddrcal, 0, sizeof(ddrcal));
+
+ /*
+ * DQS calibration.
+ */
+ /*
+ * program_DQS_calibration_method[A|B]() returns 0 if no
+ * passing RFDC.[RFFD] window is found or returns the size
+ * of the best passing window; in the case of a found passing
+ * window, the ddrcal will contain the values of the best
+ * window RQDC.[RQFD] and RFDC.[RFFD].
+ */
+
+ /*
+ * Call PPC4xx SDRAM DDR autocalibration methodA or methodB.
+ * Default is methodB.
+ * Defined the autocalibration method in the board specific
+ * header file.
+ * Please see include/configs/kilauea.h for an example for
+ * a board specific implementation.
+ */
+#if defined(CONFIG_PPC4xx_DDR_METHOD_A)
+ result = program_DQS_calibration_methodA(&ddrcal);
+#else
+ result = program_DQS_calibration_methodB(&ddrcal);
+#endif
+
+ sync();
+
+ /*
+ * Clear potential errors resulting from auto-calibration.
+ * If not done, then we could get an interrupt later on when
+ * exceptions are enabled.
+ */
+ set_mcsr(get_mcsr());
+
+ val = ddrcal.rdcc; /* RDCC from the best passing window */
+
+ udelay(100);
+
+ if (verbose_lvl > 1) {
+ char *tstr;
+ switch ((val >> 30)) {
+ case 0:
+ if (result != 0)
+ tstr = "T1";
+ else
+ tstr = "N/A";
+ break;
+ case 1:
+ tstr = "T2";
+ break;
+ case 2:
+ tstr = "T3";
+ break;
+ case 3:
+ tstr = "T4";
+ break;
+ default:
+ tstr = "unknown";
+ break;
+ }
+ printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), "
+ "max-min(0x%04x)(0x%04x), RDCC: %s\n",
+ wdtr, clkp, result, best_result,
+ ddrcal.rffd_min, ddrcal.rffd_max, tstr);
+ }
+
+ /*
+ * The DQS calibration "result" is either "0"
+ * if no passing window was found, or is the
+ * size of the RFFD passing window.
+ */
+ /*
+ * want the lowest Read Sample Cycle Select
+ */
+ val = SDRAM_RDCC_RDSS_DECODE(val);
+ debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
+ val, best_rdcc);
+
+ if ((result != 0) &&
+ (val >= SDRAM_RDCC_RDSS_VAL(SDRAM_RDCC_RDSS_T2))) {
+ if (((result == best_result) && (val < best_rdcc)) ||
+ ((result > best_result) && (val <= best_rdcc))) {
+ tcal.autocal.flags = 1;
+ debug("*** (%d)(%d) result passed window "
+ "size: 0x%08x, rqfd = 0x%08x, "
+ "rffd = 0x%08x, rdcc = 0x%08x\n",
+ wdtr, clkp, result, ddrcal.rqfd,
+ ddrcal.rffd, ddrcal.rdcc);
+
+ /*
+ * Save the SDRAM_WRDTR and SDRAM_CLKTR
+ * settings for the largest returned
+ * RFFD passing window size.
+ */
+ best_rdcc = val;
+ tcal.clocks.wrdtr = wdtr;
+ tcal.clocks.clktr = clkp;
+ tcal.clocks.rdcc = SDRAM_RDCC_RDSS_ENCODE(val);
+ tcal.autocal.rqfd = ddrcal.rqfd;
+ tcal.autocal.rffd = ddrcal.rffd;
+ best_result = result;
+
+ if (verbose_lvl > 2) {
+ printf("** (%d)(%d) "
+ "best result: 0x%04x\n",
+ wdtr, clkp,
+ best_result);
+ printf("** (%d)(%d) "
+ "best WRDTR: 0x%04x\n",
+ wdtr, clkp,
+ tcal.clocks.wrdtr);
+ printf("** (%d)(%d) "
+ "best CLKTR: 0x%04x\n",
+ wdtr, clkp,
+ tcal.clocks.clktr);
+ printf("** (%d)(%d) "
+ "best RQDC: 0x%04x\n",
+ wdtr, clkp,
+ tcal.autocal.rqfd);
+ printf("** (%d)(%d) "
+ "best RFDC: 0x%04x\n",
+ wdtr, clkp,
+ tcal.autocal.rffd);
+ printf("** (%d)(%d) "
+ "best RDCC: 0x%08x\n",
+ wdtr, clkp,
+ (u32)tcal.clocks.rdcc);
+ mfsdram(SDRAM_RTSR, val);
+ printf("** (%d)(%d) best "
+ "loop RTSR: 0x%08x\n",
+ wdtr, clkp, val);
+ mfsdram(SDRAM_FCSR, val);
+ printf("** (%d)(%d) best "
+ "loop FCSR: 0x%08x\n",
+ wdtr, clkp, val);
+ }
+ }
+ } /* if ((result != 0) && (val >= (ddr_rdss_opt()))) */
+ scan_list++;
+ } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */
+
+ if (tcal.autocal.flags == 1) {
+ if (verbose_lvl > 0) {
+ printf("*** --------------\n");
+ printf("*** best_result window size: %d\n",
+ best_result);
+ printf("*** best_result WRDTR: 0x%04x\n",
+ tcal.clocks.wrdtr);
+ printf("*** best_result CLKTR: 0x%04x\n",
+ tcal.clocks.clktr);
+ printf("*** best_result RQFD: 0x%04x\n",
+ tcal.autocal.rqfd);
+ printf("*** best_result RFFD: 0x%04x\n",
+ tcal.autocal.rffd);
+ printf("*** best_result RDCC: 0x%04x\n",
+ tcal.clocks.rdcc);
+ printf("*** --------------\n");
+ printf("\n");
+ }
+
+ /*
+ * if got best passing result window, then lock in the
+ * best CLKTR, WRDTR, RQFD, and RFFD values
+ */
+ mfsdram(SDRAM_WRDTR, val);
+ mtsdram(SDRAM_WRDTR, (val &
+ ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
+ ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC |
+ (tcal.clocks.wrdtr << 25)));
+
+ mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30);
+
+ relock_memory_DLL();
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
+ mtsdram(SDRAM_RQDC, rqdc_reg |
+ SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd));
+
+ mfsdram(SDRAM_RQDC, rqdc_reg);
+ debug("*** best_result: read value SDRAM_RQDC 0x%08lx\n",
+ rqdc_reg);
+
+#if defined(CONFIG_DDR_RFDC_FIXED)
+ mtsdram(SDRAM_RFDC, CONFIG_DDR_RFDC_FIXED);
+#else /* CONFIG_DDR_RFDC_FIXED */
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
+ mtsdram(SDRAM_RFDC, rfdc_reg |
+ SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd));
+#endif /* CONFIG_DDR_RFDC_FIXED */
+
+ mfsdram(SDRAM_RFDC, rfdc_reg);
+ debug("*** best_result: read value SDRAM_RFDC 0x%08lx\n",
+ rfdc_reg);
+ mfsdram(SDRAM_RDCC, val);
+ debug("*** SDRAM_RDCC 0x%08x\n", val);
+ } else {
+ /*
+ * no valid windows were found
+ */
+ printf("DQS memory calibration window can not be determined, "
+ "terminating u-boot.\n");
+ ppc4xx_ibm_ddr2_register_dump();
+ spd_ddr_init_hang();
+ }
+
+ blank_string(strlen(str));
+
+ return 0;
+}
+#else /* defined(CONFIG_NAND_U_BOOT) || defined(CONFIG_NAND_SPL) */
+u32 DQS_autocalibration(void)
+{
+ return 0;
+}
+#endif /* !defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) */
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pci.c b/arch/powerpc/cpu/ppc4xx/4xx_pci.c
new file mode 100644
index 0000000..2ca355b
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_pci.c
@@ -0,0 +1,885 @@
+/*-----------------------------------------------------------------------------+
+ * This source code is dual-licensed. You may use it under the terms of
+ * the GNU General Public license version 2, or under the license below.
+ *
+ * This source code has been made available to you by IBM on an AS-IS
+ * basis. Anyone receiving this source is licensed under IBM
+ * copyrights to use it in any way he or she deems fit, including
+ * copying it, modifying it, compiling it, and redistributing it either
+ * with or without modifications. No license under IBM patents or
+ * patent applications is to be implied by the copyright license.
+ *
+ * Any user of this software should understand that IBM cannot provide
+ * technical support for this software and will not be responsible for
+ * any consequences resulting from the use of this software.
+ *
+ * Any person who transfers this source code or any derivative work
+ * must include the IBM copyright notice, this paragraph, and the
+ * preceding two paragraphs in the transferred software.
+ *
+ * COPYRIGHT I B M CORPORATION 1995
+ * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
+ *-----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+ *
+ * File Name: 405gp_pci.c
+ *
+ * Function: Initialization code for the 405GP PCI Configuration regs.
+ *
+ * Author: Mark Game
+ *
+ * Change Activity-
+ *
+ * Date Description of Change BY
+ * --------- --------------------- ---
+ * 09-Sep-98 Created MCG
+ * 02-Nov-98 Removed External arbiter selected message JWB
+ * 27-Nov-98 Zero out PTMBAR2 and disable in PTM2MS JWB
+ * 04-Jan-99 Zero out other unused PMM and PTM regs. Change bus scan MCG
+ * from (0 to n) to (1 to n).
+ * 17-May-99 Port to Walnut JWB
+ * 17-Jun-99 Updated for VGA support JWB
+ * 21-Jun-99 Updated to allow SRAM region to be a target from PCI bus JWB
+ * 19-Jul-99 Updated for 405GP pass 1 errata #26 (Low PCI subsequent MCG
+ * target latency timer values are not supported).
+ * Should be fixed in pass 2.
+ * 09-Sep-99 Removed use of PTM2 since the SRAM region no longer needs JWB
+ * to be a PCI target. Zero out PTMBAR2 and disable in PTM2MS.
+ * 10-Dec-99 Updated PCI_Write_CFG_Reg for pass2 errata #6 JWB
+ * 11-Jan-00 Ensure PMMxMAs disabled before setting PMMxLAs. This is not
+ * really required after a reset since PMMxMAs are already
+ * disabled but is a good practice nonetheless. JWB
+ * 12-Jun-01 stefan.roese@esd-electronics.com
+ * - PCI host/adapter handling reworked
+ * 09-Jul-01 stefan.roese@esd-electronics.com
+ * - PCI host now configures from device 0 (not 1) to max_dev,
+ * (host configures itself)
+ * - On CPCI-405 pci base address and size is generated from
+ * SDRAM and FLASH size (CFG regs not used anymore)
+ * - Some minor changes for CPCI-405-A (adapter version)
+ * 14-Sep-01 stefan.roese@esd-electronics.com
+ * - CONFIG_PCI_SCAN_SHOW added to print pci devices upon startup
+ * 28-Sep-01 stefan.roese@esd-electronics.com
+ * - Changed pci master configuration for linux compatibility
+ * (no need for bios_fixup() anymore)
+ * 26-Feb-02 stefan.roese@esd-electronics.com
+ * - Bug fixed in pci configuration (Andrew May)
+ * - Removed pci class code init for CPCI405 board
+ * 15-May-02 stefan.roese@esd-electronics.com
+ * - New vga device handling
+ * 29-May-02 stefan.roese@esd-electronics.com
+ * - PCI class code init added (if defined)
+ *----------------------------------------------------------------------------*/
+
+#include <common.h>
+#include <command.h>
+#include <asm/4xx_pci.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#ifdef CONFIG_PCI
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
+
+#if defined(CONFIG_PMC405)
+ushort pmc405_pci_subsys_deviceid(void);
+#endif
+
+/*#define DEBUG*/
+
+/*
+ * Board-specific pci initialization
+ * Platform code can reimplement pci_pre_init() if needed
+ */
+int __pci_pre_init(struct pci_controller *hose)
+{
+#if defined(CONFIG_405EP)
+ /*
+ * Enable the internal PCI arbiter by default.
+ *
+ * On 405EP CPUs the internal arbiter can be controlled
+ * by the I2C strapping EEPROM. If you want to do so
+ * or if you want to disable the arbiter pci_pre_init()
+ * must be reimplemented without enabling the arbiter.
+ * The arbiter is enabled in this place because of
+ * compatibility reasons.
+ */
+ mtdcr(CPC0_PCI, mfdcr(CPC0_PCI) | CPC0_PCI_ARBIT_EN);
+#endif /* CONFIG_405EP */
+
+ return 1;
+}
+int pci_pre_init(struct pci_controller *hose)
+ __attribute__((weak, alias("__pci_pre_init")));
+
+int __is_pci_host(struct pci_controller *hose)
+{
+#if defined(CONFIG_405GP)
+ if (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN)
+ return 1;
+#elif defined (CONFIG_405EP)
+ if (mfdcr(CPC0_PCI) & CPC0_PCI_ARBIT_EN)
+ return 1;
+#endif
+ return 0;
+}
+int is_pci_host(struct pci_controller *hose) __attribute__((weak, alias("__is_pci_host")));
+
+/*-----------------------------------------------------------------------------+
+ * pci_init. Initializes the 405GP PCI Configuration regs.
+ *-----------------------------------------------------------------------------*/
+void pci_405gp_init(struct pci_controller *hose)
+{
+ int i, reg_num = 0;
+ bd_t *bd = gd->bd;
+
+ unsigned short temp_short;
+ unsigned long ptmpcila[2] = {CONFIG_SYS_PCI_PTM1PCI, CONFIG_SYS_PCI_PTM2PCI};
+#if defined(CONFIG_PCI_4xx_PTM_OVERWRITE)
+ char *ptmla_str, *ptmms_str;
+#endif
+ unsigned long ptmla[2] = {CONFIG_SYS_PCI_PTM1LA, CONFIG_SYS_PCI_PTM2LA};
+ unsigned long ptmms[2] = {CONFIG_SYS_PCI_PTM1MS, CONFIG_SYS_PCI_PTM2MS};
+#if defined(CONFIG_PIP405) || defined (CONFIG_MIP405)
+ unsigned long pmmla[3] = {0x80000000, 0xA0000000, 0};
+ unsigned long pmmma[3] = {0xE0000001, 0xE0000001, 0};
+ unsigned long pmmpcila[3] = {0x80000000, 0x00000000, 0};
+ unsigned long pmmpciha[3] = {0x00000000, 0x00000000, 0};
+#else
+ unsigned long pmmla[3] = {0x80000000, 0,0};
+ unsigned long pmmma[3] = {0xC0000001, 0,0};
+ unsigned long pmmpcila[3] = {0x80000000, 0,0};
+ unsigned long pmmpciha[3] = {0x00000000, 0,0};
+#endif
+#ifdef CONFIG_PCI_PNP
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+ char *s;
+#endif
+#endif
+
+#if defined(CONFIG_PCI_4xx_PTM_OVERWRITE)
+ ptmla_str = getenv("ptm1la");
+ ptmms_str = getenv("ptm1ms");
+ if(NULL != ptmla_str && NULL != ptmms_str ) {
+ ptmla[0] = simple_strtoul (ptmla_str, NULL, 16);
+ ptmms[0] = simple_strtoul (ptmms_str, NULL, 16);
+ }
+
+ ptmla_str = getenv("ptm2la");
+ ptmms_str = getenv("ptm2ms");
+ if(NULL != ptmla_str && NULL != ptmms_str ) {
+ ptmla[1] = simple_strtoul (ptmla_str, NULL, 16);
+ ptmms[1] = simple_strtoul (ptmms_str, NULL, 16);
+ }
+#endif
+
+ /*
+ * Register the hose
+ */
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ /* ISA/PCI I/O space */
+ pci_set_region(hose->regions + reg_num++,
+ MIN_PCI_PCI_IOADDR,
+ MIN_PLB_PCI_IOADDR,
+ 0x10000,
+ PCI_REGION_IO);
+
+ /* PCI I/O space */
+ pci_set_region(hose->regions + reg_num++,
+ 0x00800000,
+ 0xe8800000,
+ 0x03800000,
+ PCI_REGION_IO);
+
+ reg_num = 2;
+
+ /* Memory spaces */
+ for (i=0; i<2; i++)
+ if (ptmms[i] & 1)
+ {
+ if (!i) hose->pci_fb = hose->regions + reg_num;
+
+ pci_set_region(hose->regions + reg_num++,
+ ptmpcila[i], ptmla[i],
+ ~(ptmms[i] & 0xfffff000) + 1,
+ PCI_REGION_MEM |
+ PCI_REGION_SYS_MEMORY);
+ }
+
+ /* PCI memory spaces */
+ for (i=0; i<3; i++)
+ if (pmmma[i] & 1)
+ {
+ pci_set_region(hose->regions + reg_num++,
+ pmmpcila[i], pmmla[i],
+ ~(pmmma[i] & 0xfffff000) + 1,
+ PCI_REGION_MEM);
+ }
+
+ hose->region_count = reg_num;
+
+ pci_setup_indirect(hose,
+ PCICFGADR,
+ PCICFGDATA);
+
+ if (hose->pci_fb)
+ pciauto_region_init(hose->pci_fb);
+
+ /* Let board change/modify hose & do initial checks */
+ if (pci_pre_init(hose) == 0) {
+ printf("PCI: Board-specific initialization failed.\n");
+ printf("PCI: Configuration aborted.\n");
+ return;
+ }
+
+ pci_register_hose(hose);
+
+ /*--------------------------------------------------------------------------+
+ * 405GP PCI Master configuration.
+ * Map one 512 MB range of PLB/processor addresses to PCI memory space.
+ * PLB address 0x80000000-0xBFFFFFFF ==> PCI address 0x80000000-0xBFFFFFFF
+ * Use byte reversed out routines to handle endianess.
+ *--------------------------------------------------------------------------*/
+ out32r(PMM0MA, (pmmma[0]&~0x1)); /* disable, configure PMMxLA, PMMxPCILA first */
+ out32r(PMM0LA, pmmla[0]);
+ out32r(PMM0PCILA, pmmpcila[0]);
+ out32r(PMM0PCIHA, pmmpciha[0]);
+ out32r(PMM0MA, pmmma[0]);
+
+ /*--------------------------------------------------------------------------+
+ * PMM1 is not used. Initialize them to zero.
+ *--------------------------------------------------------------------------*/
+ out32r(PMM1MA, (pmmma[1]&~0x1));
+ out32r(PMM1LA, pmmla[1]);
+ out32r(PMM1PCILA, pmmpcila[1]);
+ out32r(PMM1PCIHA, pmmpciha[1]);
+ out32r(PMM1MA, pmmma[1]);
+
+ /*--------------------------------------------------------------------------+
+ * PMM2 is not used. Initialize them to zero.
+ *--------------------------------------------------------------------------*/
+ out32r(PMM2MA, (pmmma[2]&~0x1));
+ out32r(PMM2LA, pmmla[2]);
+ out32r(PMM2PCILA, pmmpcila[2]);
+ out32r(PMM2PCIHA, pmmpciha[2]);
+ out32r(PMM2MA, pmmma[2]);
+
+ /*--------------------------------------------------------------------------+
+ * 405GP PCI Target configuration. (PTM1)
+ * Note: PTM1MS is hardwire enabled but we set the enable bit anyway.
+ *--------------------------------------------------------------------------*/
+ out32r(PTM1LA, ptmla[0]); /* insert address */
+ out32r(PTM1MS, ptmms[0]); /* insert size, enable bit is 1 */
+ pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_1, ptmpcila[0]);
+
+ /*--------------------------------------------------------------------------+
+ * 405GP PCI Target configuration. (PTM2)
+ *--------------------------------------------------------------------------*/
+ out32r(PTM2LA, ptmla[1]); /* insert address */
+ pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, ptmpcila[1]);
+
+ if (ptmms[1] == 0)
+ {
+ out32r(PTM2MS, 0x00000001); /* set enable bit */
+ pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, 0x00000000);
+ out32r(PTM2MS, 0x00000000); /* disable */
+ }
+ else
+ {
+ out32r(PTM2MS, ptmms[1]); /* insert size, enable bit is 1 */
+ }
+
+ /*
+ * Insert Subsystem Vendor and Device ID
+ */
+ pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_VENDOR_ID, CONFIG_SYS_PCI_SUBSYS_VENDORID);
+#ifdef CONFIG_CPCI405
+ if (is_pci_host(hose))
+ pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID);
+ else
+ pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID2);
+#else
+ pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_DEVICEID);
+#endif
+
+ /*
+ * Insert Class-code
+ */
+#ifdef CONFIG_SYS_PCI_CLASSCODE
+ pci_write_config_word(PCIDEVID_405GP, PCI_CLASS_SUB_CODE, CONFIG_SYS_PCI_CLASSCODE);
+#endif /* CONFIG_SYS_PCI_CLASSCODE */
+
+ /*--------------------------------------------------------------------------+
+ * If PCI speed = 66MHz, set 66MHz capable bit.
+ *--------------------------------------------------------------------------*/
+ if (bd->bi_pci_busfreq >= 66000000) {
+ pci_read_config_word(PCIDEVID_405GP, PCI_STATUS, &temp_short);
+ pci_write_config_word(PCIDEVID_405GP,PCI_STATUS,(temp_short|PCI_STATUS_66MHZ));
+ }
+
+#if (CONFIG_PCI_HOST != PCI_HOST_ADAPTER)
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+ if (is_pci_host(hose) ||
+ (((s = getenv("pciscan")) != NULL) && (strcmp(s, "yes") == 0)))
+#endif
+ {
+ /*--------------------------------------------------------------------------+
+ * Write the 405GP PCI Configuration regs.
+ * Enable 405GP to be a master on the PCI bus (PMM).
+ * Enable 405GP to act as a PCI memory target (PTM).
+ *--------------------------------------------------------------------------*/
+ pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &temp_short);
+ pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND, temp_short |
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+ }
+#endif
+
+#if defined(CONFIG_405EP)
+ /*
+ * on ppc405ep vendor/device id is not set
+ * The user manual says 0x1014 (IBM) / 0x0156 (405GP!)
+ * are the correct values.
+ */
+ pci_write_config_word(PCIDEVID_405GP, PCI_VENDOR_ID, PCI_VENDOR_ID_IBM);
+ pci_write_config_word(PCIDEVID_405GP,
+ PCI_DEVICE_ID, PCI_DEVICE_ID_IBM_405GP);
+#endif
+
+ /*
+ * Set HCE bit (Host Configuration Enabled)
+ */
+ pci_read_config_word(PCIDEVID_405GP, PCIBRDGOPT2, &temp_short);
+ pci_write_config_word(PCIDEVID_405GP, PCIBRDGOPT2, (temp_short | 0x0001));
+
+#ifdef CONFIG_PCI_PNP
+ /*--------------------------------------------------------------------------+
+ * Scan the PCI bus and configure devices found.
+ *--------------------------------------------------------------------------*/
+#if (CONFIG_PCI_HOST == PCI_HOST_AUTO)
+ if (is_pci_host(hose) ||
+ (((s = getenv("pciscan")) != NULL) && (strcmp(s, "yes") == 0)))
+#endif
+ {
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+ hose->last_busno = pci_hose_scan(hose);
+ }
+#endif /* CONFIG_PCI_PNP */
+
+}
+
+/*
+ * drivers/pci/pci.c skips every host bridge but the 405GP since it could
+ * be set as an Adapter.
+ *
+ * I (Andrew May) don't know what we should do here, but I don't want
+ * the auto setup of a PCI device disabling what is done pci_405gp_init
+ * as has happened before.
+ */
+void pci_405gp_setup_bridge(struct pci_controller *hose, pci_dev_t dev,
+ struct pci_config_table *entry)
+{
+#ifdef DEBUG
+ printf("405gp_setup_bridge\n");
+#endif
+}
+
+/*
+ *
+ */
+
+void pci_405gp_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
+{
+ unsigned char int_line = 0xff;
+
+ /*
+ * Write pci interrupt line register (cpci405 specific)
+ */
+ switch (PCI_DEV(dev) & 0x03)
+ {
+ case 0:
+ int_line = 27 + 2;
+ break;
+ case 1:
+ int_line = 27 + 3;
+ break;
+ case 2:
+ int_line = 27 + 0;
+ break;
+ case 3:
+ int_line = 27 + 1;
+ break;
+ }
+
+ pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
+}
+
+void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev,
+ struct pci_config_table *entry)
+{
+ unsigned int cmdstat = 0;
+
+ pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_prefetch, hose->pci_io);
+
+ /* always enable io space on vga boards */
+ pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat);
+ cmdstat |= PCI_COMMAND_IO;
+ pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat);
+}
+
+#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405)) && !(defined (CONFIG_SC3))
+
+/*
+ *As is these functs get called out of flash Not a horrible
+ *thing, but something to keep in mind. (no statics?)
+ */
+static struct pci_config_table pci_405gp_config_table[] = {
+/*if VendID is 0 it terminates the table search (ie Walnut)*/
+#ifdef CONFIG_SYS_PCI_SUBSYS_VENDORID
+ {CONFIG_SYS_PCI_SUBSYS_VENDORID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_bridge},
+#endif
+ {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga},
+
+ {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga},
+
+ { }
+};
+
+static struct pci_controller hose = {
+ fixup_irq: pci_405gp_fixup_irq,
+ config_table: pci_405gp_config_table,
+};
+
+void pci_init_board(void)
+{
+ /*we want the ptrs to RAM not flash (ie don't use init list)*/
+ hose.fixup_irq = pci_405gp_fixup_irq;
+ hose.config_table = pci_405gp_config_table;
+ pci_405gp_init(&hose);
+}
+
+#endif
+
+#endif /* CONFIG_405GP */
+
+/*-----------------------------------------------------------------------------+
+ * CONFIG_440
+ *-----------------------------------------------------------------------------*/
+#if defined(CONFIG_440)
+
+#if defined(CONFIG_SYS_PCI_MASTER_INIT) || defined(CONFIG_SYS_PCI_TARGET_INIT)
+static struct pci_controller ppc440_hose = {0};
+#endif
+
+/*
+ * This routine is called to determine if a pci scan should be
+ * performed. With various hardware environments (especially cPCI and
+ * PPMC) it's insufficient to depend on the state of the arbiter enable
+ * bit in the strap register, or generic host/adapter assumptions.
+ *
+ * Rather than hard-code a bad assumption in the general 440 code, the
+ * 440 pci code requires the board to decide at runtime.
+ *
+ * Return 0 for adapter mode, non-zero for host (monarch) mode.
+ *
+ * Weak default implementation: "Normal" boards implement the PCI
+ * host functionality. This can be overridden for PCI adapter boards.
+ */
+int __is_pci_host(struct pci_controller *hose)
+{
+ return 1;
+}
+int is_pci_host(struct pci_controller *hose)
+ __attribute__((weak, alias("__is_pci_host")));
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRX)
+
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+/*
+ * pci_target_init
+ *
+ * The bootstrap configuration provides default settings for the pci
+ * inbound map (PIM). But the bootstrap config choices are limited and
+ * may not be sufficient for a given board.
+ */
+void __pci_target_init(struct pci_controller *hose)
+{
+ /*
+ * Set up Direct MMIO registers
+ */
+
+ /*
+ * PowerPC440 EP PCI Master configuration.
+ * Map one 1Gig range of PLB/processor addresses to PCI memory space.
+ * PLB address 0xA0000000-0xDFFFFFFF ==> PCI address 0xA0000000-0xDFFFFFFF
+ * Use byte reversed out routines to handle endianess.
+ * Make this region non-prefetchable.
+ */
+ /* PMM0 Mask/Attribute - disabled b4 setting */
+ out_le32((void *)PCIL0_PMM0MA, 0x00000000);
+ /* PMM0 Local Address */
+ out_le32((void *)PCIL0_PMM0LA, CONFIG_SYS_PCI_MEMBASE);
+ /* PMM0 PCI Low Address */
+ out_le32((void *)PCIL0_PMM0PCILA, CONFIG_SYS_PCI_MEMBASE);
+ /* PMM0 PCI High Address */
+ out_le32((void *)PCIL0_PMM0PCIHA, 0x00000000);
+ /* 512M + No prefetching, and enable region */
+ out_le32((void *)PCIL0_PMM0MA, 0xE0000001);
+
+ /* PMM1 Mask/Attribute - disabled b4 setting */
+ out_le32((void *)PCIL0_PMM1MA, 0x00000000);
+ /* PMM1 Local Address */
+ out_le32((void *)PCIL0_PMM1LA, CONFIG_SYS_PCI_MEMBASE2);
+ /* PMM1 PCI Low Address */
+ out_le32((void *)PCIL0_PMM1PCILA, CONFIG_SYS_PCI_MEMBASE2);
+ /* PMM1 PCI High Address */
+ out_le32((void *)PCIL0_PMM1PCIHA, 0x00000000);
+ /* 512M + No prefetching, and enable region */
+ out_le32((void *)PCIL0_PMM1MA, 0xE0000001);
+
+ out_le32((void *)PCIL0_PTM1MS, 0x00000001); /* Memory Size/Attribute */
+ out_le32((void *)PCIL0_PTM1LA, 0); /* Local Addr. Reg */
+ out_le32((void *)PCIL0_PTM2MS, 0); /* Memory Size/Attribute */
+ out_le32((void *)PCIL0_PTM2LA, 0); /* Local Addr. Reg */
+
+ /*
+ * Set up Configuration registers
+ */
+
+ /* Program the board's subsystem id/vendor id */
+ pci_write_config_word(0, PCI_SUBSYSTEM_VENDOR_ID,
+ CONFIG_SYS_PCI_SUBSYS_VENDORID);
+ pci_write_config_word(0, PCI_SUBSYSTEM_ID, CONFIG_SYS_PCI_SUBSYS_ID);
+
+ /* Configure command register as bus master */
+ pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER);
+
+ /* 240nS PCI clock */
+ pci_write_config_word(0, PCI_LATENCY_TIMER, 1);
+
+ /* No error reporting */
+ pci_write_config_word(0, PCI_ERREN, 0);
+
+ pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101);
+}
+#endif /* CONFIG_SYS_PCI_TARGET_INIT */
+
+/*
+ * pci_pre_init
+ *
+ * This routine is called just prior to registering the hose and gives
+ * the board the opportunity to check things. Returning a value of zero
+ * indicates that things are bad & PCI initialization should be aborted.
+ *
+ * Different boards may wish to customize the pci controller structure
+ * (add regions, override default access routines, etc) or perform
+ * certain pre-initialization actions.
+ *
+ */
+int __pci_pre_init(struct pci_controller *hose)
+{
+ u32 reg;
+
+ /*
+ * Set priority for all PLB3 devices to 0.
+ * Set PLB3 arbiter to fair mode.
+ */
+ mfsdr(SDR0_AMP1, reg);
+ mtsdr(SDR0_AMP1, (reg & 0x000000FF) | 0x0000FF00);
+ reg = mfdcr(PLB3A0_ACR);
+ mtdcr(PLB3A0_ACR, reg | 0x80000000);
+
+ /*
+ * Set priority for all PLB4 devices to 0.
+ */
+ mfsdr(SDR0_AMP0, reg);
+ mtsdr(SDR0_AMP0, (reg & 0x000000FF) | 0x0000FF00);
+ reg = mfdcr(PLB4A0_ACR) | 0xa0000000;
+ mtdcr(PLB4A0_ACR, reg);
+
+ /*
+ * Set Nebula PLB4 arbiter to fair mode.
+ */
+ /* Segment0 */
+ reg = (mfdcr(PLB4A0_ACR) & ~PLB4Ax_ACR_PPM_MASK) | PLB4Ax_ACR_PPM_FAIR;
+ reg = (reg & ~PLB4Ax_ACR_HBU_MASK) | PLB4Ax_ACR_HBU_ENABLED;
+ reg = (reg & ~PLB4Ax_ACR_RDP_MASK) | PLB4Ax_ACR_RDP_4DEEP;
+ reg = (reg & ~PLB4Ax_ACR_WRP_MASK) | PLB4Ax_ACR_WRP_2DEEP;
+ mtdcr(PLB4A0_ACR, reg);
+
+ /* Segment1 */
+ reg = (mfdcr(PLB4A1_ACR) & ~PLB4Ax_ACR_PPM_MASK) | PLB4Ax_ACR_PPM_FAIR;
+ reg = (reg & ~PLB4Ax_ACR_HBU_MASK) | PLB4Ax_ACR_HBU_ENABLED;
+ reg = (reg & ~PLB4Ax_ACR_RDP_MASK) | PLB4Ax_ACR_RDP_4DEEP;
+ reg = (reg & ~PLB4Ax_ACR_WRP_MASK) | PLB4Ax_ACR_WRP_2DEEP;
+ mtdcr(PLB4A1_ACR, reg);
+
+#if defined(CONFIG_SYS_PCI_BOARD_FIXUP_IRQ)
+ hose->fixup_irq = board_pci_fixup_irq;
+#endif
+
+ return 1;
+}
+
+#else /* defined(CONFIG_440EP) ... */
+
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+void __pci_target_init(struct pci_controller * hose)
+{
+ /*
+ * Disable everything
+ */
+ out_le32((void *)PCIL0_PIM0SA, 0); /* disable */
+ out_le32((void *)PCIL0_PIM1SA, 0); /* disable */
+ out_le32((void *)PCIL0_PIM2SA, 0); /* disable */
+ out_le32((void *)PCIL0_EROMBA, 0); /* disable expansion rom */
+
+ /*
+ * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440
+ * strapping options do not support sizes such as 128/256 MB.
+ */
+ out_le32((void *)PCIL0_PIM0LAL, CONFIG_SYS_SDRAM_BASE);
+ out_le32((void *)PCIL0_PIM0LAH, 0);
+ out_le32((void *)PCIL0_PIM0SA, ~(gd->ram_size - 1) | 1);
+ out_le32((void *)PCIL0_BAR0, 0);
+
+ /*
+ * Program the board's subsystem id/vendor id
+ */
+ out_le16((void *)PCIL0_SBSYSVID, CONFIG_SYS_PCI_SUBSYS_VENDORID);
+ out_le16((void *)PCIL0_SBSYSID, CONFIG_SYS_PCI_SUBSYS_DEVICEID);
+
+ out_le16((void *)PCIL0_CMD, in_le16((void *)PCIL0_CMD) |
+ PCI_COMMAND_MEMORY);
+}
+#endif /* CONFIG_SYS_PCI_TARGET_INIT */
+
+int __pci_pre_init(struct pci_controller *hose)
+{
+ /*
+ * This board is always configured as the host & requires the
+ * PCI arbiter to be enabled.
+ */
+ if (!pci_arbiter_enabled()) {
+ printf("PCI: PCI Arbiter disabled!\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+#endif /* defined(CONFIG_440EP) ... */
+
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+void pci_target_init(struct pci_controller * hose)
+ __attribute__((weak, alias("__pci_target_init")));
+#endif /* CONFIG_SYS_PCI_TARGET_INIT */
+
+int pci_pre_init(struct pci_controller *hose)
+ __attribute__((weak, alias("__pci_pre_init")));
+
+#if defined(CONFIG_SYS_PCI_MASTER_INIT)
+void __pci_master_init(struct pci_controller *hose)
+{
+ u16 reg;
+
+ /*
+ * Write the PowerPC440 EP PCI Configuration regs.
+ * Enable PowerPC440 EP to be a master on the PCI bus (PMM).
+ * Enable PowerPC440 EP to act as a PCI memory target (PTM).
+ */
+ pci_read_config_word(0, PCI_COMMAND, &reg);
+ pci_write_config_word(0, PCI_COMMAND, reg |
+ PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+}
+void pci_master_init(struct pci_controller *hose)
+ __attribute__((weak, alias("__pci_master_init")));
+#endif /* CONFIG_SYS_PCI_MASTER_INIT */
+
+#if defined(CONFIG_SYS_PCI_MASTER_INIT) || defined(CONFIG_SYS_PCI_TARGET_INIT)
+static int pci_440_init (struct pci_controller *hose)
+{
+ int reg_num = 0;
+
+#ifndef CONFIG_DISABLE_PISE_TEST
+ /*--------------------------------------------------------------------------+
+ * The PCI initialization sequence enable bit must be set ... if not abort
+ * pci setup since updating the bit requires chip reset.
+ *--------------------------------------------------------------------------*/
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+ unsigned long strap;
+
+ mfsdr(SDR0_SDSTP1,strap);
+ if ((strap & SDR0_SDSTP1_PISE_MASK) == 0) {
+ printf("PCI: SDR0_STRP1[PISE] not set.\n");
+ printf("PCI: Configuration aborted.\n");
+ return -1;
+ }
+#elif defined(CONFIG_440GP)
+ unsigned long strap;
+
+ strap = mfdcr(CPC0_STRP1);
+ if ((strap & CPC0_STRP1_PISE_MASK) == 0) {
+ printf("PCI: CPC0_STRP1[PISE] not set.\n");
+ printf("PCI: Configuration aborted.\n");
+ return -1;
+ }
+#endif
+#endif /* CONFIG_DISABLE_PISE_TEST */
+
+ /*--------------------------------------------------------------------------+
+ * PCI controller init
+ *--------------------------------------------------------------------------*/
+ hose->first_busno = 0;
+ hose->last_busno = 0;
+
+ /* PCI I/O space */
+ pci_set_region(hose->regions + reg_num++,
+ 0x00000000,
+ PCIL0_IOBASE,
+ 0x10000,
+ PCI_REGION_IO);
+
+ /* PCI memory space */
+ pci_set_region(hose->regions + reg_num++,
+ CONFIG_SYS_PCI_TARGBASE,
+ CONFIG_SYS_PCI_MEMBASE,
+#ifdef CONFIG_SYS_PCI_MEMSIZE
+ CONFIG_SYS_PCI_MEMSIZE,
+#else
+ 0x10000000,
+#endif
+ PCI_REGION_MEM );
+
+#if defined(CONFIG_PCI_SYS_MEM_BUS) && defined(CONFIG_PCI_SYS_MEM_PHYS) && \
+ defined(CONFIG_PCI_SYS_MEM_SIZE)
+ /* System memory space */
+ pci_set_region(hose->regions + reg_num++,
+ CONFIG_PCI_SYS_MEM_BUS,
+ CONFIG_PCI_SYS_MEM_PHYS,
+ CONFIG_PCI_SYS_MEM_SIZE,
+ PCI_REGION_MEM | PCI_REGION_SYS_MEMORY );
+#endif
+
+ hose->region_count = reg_num;
+
+ pci_setup_indirect(hose, PCIL0_CFGADR, PCIL0_CFGDATA);
+
+ /* Let board change/modify hose & do initial checks */
+ if (pci_pre_init(hose) == 0) {
+ printf("PCI: Board-specific initialization failed.\n");
+ printf("PCI: Configuration aborted.\n");
+ return -1;
+ }
+
+ pci_register_hose( hose );
+
+ /*--------------------------------------------------------------------------+
+ * PCI target init
+ *--------------------------------------------------------------------------*/
+#if defined(CONFIG_SYS_PCI_TARGET_INIT)
+ pci_target_init(hose); /* Let board setup pci target */
+#else
+ out16r( PCIL0_SBSYSVID, CONFIG_SYS_PCI_SUBSYS_VENDORID );
+ out16r( PCIL0_SBSYSID, CONFIG_SYS_PCI_SUBSYS_ID );
+ out16r( PCIL0_CLS, 0x00060000 ); /* Bridge, host bridge */
+#endif
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ out32r( PCIL0_BRDGOPT1, 0x04000060 ); /* PLB Rq pri highest */
+ out32r( PCIL0_BRDGOPT2, in32(PCIL0_BRDGOPT2) | 0x83 ); /* Enable host config, clear Timeout, ensure int src1 */
+#elif defined(PCIL0_BRDGOPT1)
+ out32r( PCIL0_BRDGOPT1, 0x10000060 ); /* PLB Rq pri highest */
+ out32r( PCIL0_BRDGOPT2, in32(PCIL0_BRDGOPT2) | 1 ); /* Enable host config */
+#endif
+
+ /*--------------------------------------------------------------------------+
+ * PCI master init: default is one 256MB region for PCI memory:
+ * 0x3_00000000 - 0x3_0FFFFFFF ==> CONFIG_SYS_PCI_MEMBASE
+ *--------------------------------------------------------------------------*/
+#if defined(CONFIG_SYS_PCI_MASTER_INIT)
+ pci_master_init(hose); /* Let board setup pci master */
+#else
+ out32r( PCIL0_POM0SA, 0 ); /* disable */
+ out32r( PCIL0_POM1SA, 0 ); /* disable */
+ out32r( PCIL0_POM2SA, 0 ); /* disable */
+#if defined(CONFIG_440SPE)
+ out32r( PCIL0_POM0LAL, 0x10000000 );
+ out32r( PCIL0_POM0LAH, 0x0000000c );
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ out32r( PCIL0_POM0LAL, 0x20000000 );
+ out32r( PCIL0_POM0LAH, 0x0000000c );
+#else
+ out32r( PCIL0_POM0LAL, 0x00000000 );
+ out32r( PCIL0_POM0LAH, 0x00000003 );
+#endif
+ out32r( PCIL0_POM0PCIAL, CONFIG_SYS_PCI_MEMBASE );
+ out32r( PCIL0_POM0PCIAH, 0x00000000 );
+ out32r( PCIL0_POM0SA, 0xf0000001 ); /* 256MB, enabled */
+ out32r( PCIL0_STS, in32r( PCIL0_STS ) & ~0x0000fff8 );
+#endif
+
+ /*--------------------------------------------------------------------------+
+ * PCI host configuration -- we don't make any assumptions here ... the
+ * _board_must_indicate_ what to do -- there's just too many runtime
+ * scenarios in environments like cPCI, PPMC, etc. to make a determination
+ * based on hard-coded values or state of arbiter enable.
+ *--------------------------------------------------------------------------*/
+ if (is_pci_host(hose)) {
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) && \
+ !defined(CONFIG_440EPX) && !defined(CONFIG_440GRX)
+ out16r( PCIL0_CMD, in16r( PCIL0_CMD ) | PCI_COMMAND_MASTER);
+#endif
+ hose->last_busno = pci_hose_scan(hose);
+ }
+ return hose->last_busno;
+}
+#endif
+
+void pci_init_board(void)
+{
+ int busno = 0;
+
+ /*
+ * Only init PCI when either master or target functionality
+ * is selected.
+ */
+#if defined(CONFIG_SYS_PCI_MASTER_INIT) || defined(CONFIG_SYS_PCI_TARGET_INIT)
+ busno = pci_440_init(&ppc440_hose);
+ if (busno < 0)
+ return;
+#endif
+#if (defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
+ !defined(CONFIG_PCI_DISABLE_PCIE)
+ pcie_setup_hoses(busno + 1);
+#endif
+}
+
+#endif /* CONFIG_440 */
+
+#if defined(CONFIG_405EX)
+void pci_init_board(void)
+{
+#ifdef CONFIG_PCI_SCAN_SHOW
+ printf("PCI: Bus Dev VenId DevId Class Int\n");
+#endif
+ pcie_setup_hoses(0);
+}
+#endif /* CONFIG_405EX */
+
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_pcie.c b/arch/powerpc/cpu/ppc4xx/4xx_pcie.c
new file mode 100644
index 0000000..43b972f
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_pcie.c
@@ -0,0 +1,1292 @@
+/*
+ * (C) Copyright 2006 - 2008
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <pci.h>
+#include <asm/ppc4xx.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+#if (defined(CONFIG_440SPE) || defined(CONFIG_405EX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)) && \
+ defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_PCIE)
+
+#include <asm/4xx_pcie.h>
+
+enum {
+ PTYPE_ENDPOINT = 0x0,
+ PTYPE_LEGACY_ENDPOINT = 0x1,
+ PTYPE_ROOT_PORT = 0x4,
+
+ LNKW_X1 = 0x1,
+ LNKW_X4 = 0x4,
+ LNKW_X8 = 0x8
+};
+
+static struct pci_controller pcie_hose[CONFIG_SYS_PCIE_NR_PORTS];
+
+/*
+ * Per default, all cards are present, so we need to check if the
+ * link comes up.
+ */
+int __board_pcie_card_present(int port)
+{
+ return 1;
+}
+int board_pcie_card_present(int port)
+ __attribute__((weak, alias("__board_pcie_card_present")));
+
+/*
+ * Some boards have runtime detection of the first and last PCIe
+ * slot used, so let's provide weak default functions for the
+ * common version.
+ */
+int __board_pcie_first(void)
+{
+ return 0;
+}
+int board_pcie_first(void)
+ __attribute__((weak, alias("__board_pcie_first")));
+
+int __board_pcie_last(void)
+{
+ return CONFIG_SYS_PCIE_NR_PORTS - 1;
+}
+int board_pcie_last(void)
+ __attribute__((weak, alias("__board_pcie_last")));
+
+void __board_pcie_setup_port(int port, int rootpoint)
+{
+ /* noting in this weak default implementation */
+}
+void board_pcie_setup_port(int port, int rootpoint)
+ __attribute__((weak, alias("__board_pcie_setup_port")));
+
+void pcie_setup_hoses(int busno)
+{
+ struct pci_controller *hose;
+ int i, bus;
+ int ret = 0;
+ char *env;
+ unsigned int delay;
+ int first = board_pcie_first();
+ int last = board_pcie_last();
+
+ /*
+ * Assume we're called after the PCI(X) hose(s) are initialized,
+ * which takes bus ID 0... and therefore start numbering PCIe's
+ * from the next number.
+ */
+ bus = busno;
+
+ for (i = first; i <= last; i++) {
+ /*
+ * Some boards (e.g. Katmai) can detects via hardware
+ * if a PCIe card is plugged, so let's check this.
+ */
+ if (!board_pcie_card_present(i))
+ continue;
+
+ if (is_end_point(i)) {
+ board_pcie_setup_port(i, 0);
+ ret = ppc4xx_init_pcie_endport(i);
+ } else {
+ board_pcie_setup_port(i, 1);
+ ret = ppc4xx_init_pcie_rootport(i);
+ }
+ if (ret == -ENODEV)
+ continue;
+ if (ret) {
+ printf("PCIE%d: initialization as %s failed\n", i,
+ is_end_point(i) ? "endpoint" : "root-complex");
+ continue;
+ }
+
+ hose = &pcie_hose[i];
+ hose->first_busno = bus;
+ hose->last_busno = bus;
+ hose->current_busno = bus;
+
+ /* setup mem resource */
+ pci_set_region(hose->regions + 0,
+ CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE,
+ CONFIG_SYS_PCIE_MEMBASE + i * CONFIG_SYS_PCIE_MEMSIZE,
+ CONFIG_SYS_PCIE_MEMSIZE,
+ PCI_REGION_MEM);
+ hose->region_count = 1;
+ pci_register_hose(hose);
+
+ if (is_end_point(i)) {
+ ppc4xx_setup_pcie_endpoint(hose, i);
+ /*
+ * Reson for no scanning is endpoint can not generate
+ * upstream configuration accesses.
+ */
+ } else {
+ ppc4xx_setup_pcie_rootpoint(hose, i);
+ env = getenv ("pciscandelay");
+ if (env != NULL) {
+ delay = simple_strtoul(env, NULL, 10);
+ if (delay > 5)
+ printf("Warning, expect noticable delay before "
+ "PCIe scan due to 'pciscandelay' value!\n");
+ mdelay(delay * 1000);
+ }
+
+ /*
+ * Config access can only go down stream
+ */
+ hose->last_busno = pci_hose_scan(hose);
+ bus = hose->last_busno + 1;
+ }
+ }
+}
+
+static int validate_endpoint(struct pci_controller *hose)
+{
+ if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE0_CFGBASE)
+ return (is_end_point(0));
+ else if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE1_CFGBASE)
+ return (is_end_point(1));
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ else if (hose->cfg_data == (u8 *)CONFIG_SYS_PCIE2_CFGBASE)
+ return (is_end_point(2));
+#endif
+
+ return 0;
+}
+
+static u8* pcie_get_base(struct pci_controller *hose, unsigned int devfn)
+{
+ u8 *base = (u8*)hose->cfg_data;
+
+ /* use local configuration space for the first bus */
+ if (PCI_BUS(devfn) == 0) {
+ if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE0_CFGBASE)
+ base = (u8*)CONFIG_SYS_PCIE0_XCFGBASE;
+ if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE1_CFGBASE)
+ base = (u8*)CONFIG_SYS_PCIE1_XCFGBASE;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ if (hose->cfg_data == (u8*)CONFIG_SYS_PCIE2_CFGBASE)
+ base = (u8*)CONFIG_SYS_PCIE2_XCFGBASE;
+#endif
+ }
+
+ return base;
+}
+
+static void pcie_dmer_disable(void)
+{
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) | GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) | GPL_DMER_MASK_DISA);
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) | GPL_DMER_MASK_DISA);
+#endif
+}
+
+static void pcie_dmer_enable(void)
+{
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE0_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) & ~GPL_DMER_MASK_DISA);
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE1_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) & ~GPL_DMER_MASK_DISA);
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE2_BASE),
+ mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) & ~GPL_DMER_MASK_DISA);
+#endif
+}
+
+static int pcie_read_config(struct pci_controller *hose, unsigned int devfn,
+ int offset, int len, u32 *val) {
+
+ *val = 0;
+
+ if (validate_endpoint(hose))
+ return 0; /* No upstream config access */
+
+ /*
+ * Bus numbers are relative to hose->first_busno
+ */
+ devfn -= PCI_BDF(hose->first_busno, 0, 0);
+
+ /*
+ * NOTICE: configuration space ranges are currenlty mapped only for
+ * the first 16 buses, so such limit must be imposed. In case more
+ * buses are required the TLB settings in board/amcc/<board>/init.S
+ * need to be altered accordingly (one bus takes 1 MB of memory space).
+ */
+ if (PCI_BUS(devfn) >= 16)
+ return 0;
+
+ /*
+ * Only single device/single function is supported for the primary and
+ * secondary buses of the 440SPe host bridge.
+ */
+ if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
+ ((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
+ return 0;
+
+ pcie_get_base(hose, devfn);
+ offset += devfn << 4;
+
+ /*
+ * Reading from configuration space of non-existing device can
+ * generate transaction errors. For the read duration we suppress
+ * assertion of machine check exceptions to avoid those.
+ */
+ pcie_dmer_disable ();
+
+ debug("%s: cfg_data=%p offset=%08x\n", __func__,
+ hose->cfg_data, offset);
+ switch (len) {
+ case 1:
+ *val = in_8(hose->cfg_data + offset);
+ break;
+ case 2:
+ *val = in_le16((u16 *)(hose->cfg_data + offset));
+ break;
+ default:
+ *val = in_le32((u32*)(hose->cfg_data + offset));
+ break;
+ }
+
+ pcie_dmer_enable ();
+
+ return 0;
+}
+
+static int pcie_write_config(struct pci_controller *hose, unsigned int devfn,
+ int offset, int len, u32 val) {
+
+ if (validate_endpoint(hose))
+ return 0; /* No upstream config access */
+
+ /*
+ * Bus numbers are relative to hose->first_busno
+ */
+ devfn -= PCI_BDF(hose->first_busno, 0, 0);
+
+ /*
+ * Same constraints as in pcie_read_config().
+ */
+ if (PCI_BUS(devfn) >= 16)
+ return 0;
+
+ if ((!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 0))) &&
+ ((PCI_BUS(devfn) == 0) || (PCI_BUS(devfn) == 1)))
+ return 0;
+
+ pcie_get_base(hose, devfn);
+ offset += devfn << 4;
+
+ /*
+ * Suppress MCK exceptions, similar to pcie_read_config()
+ */
+ pcie_dmer_disable ();
+
+ switch (len) {
+ case 1:
+ out_8(hose->cfg_data + offset, val);
+ break;
+ case 2:
+ out_le16((u16 *)(hose->cfg_data + offset), val);
+ break;
+ default:
+ out_le32((u32 *)(hose->cfg_data + offset), val);
+ break;
+ }
+
+ pcie_dmer_enable ();
+
+ return 0;
+}
+
+int pcie_read_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 *val)
+{
+ u32 v;
+ int rv;
+
+ rv = pcie_read_config(hose, dev, offset, 1, &v);
+ *val = (u8)v;
+ return rv;
+}
+
+int pcie_read_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 *val)
+{
+ u32 v;
+ int rv;
+
+ rv = pcie_read_config(hose, dev, offset, 2, &v);
+ *val = (u16)v;
+ return rv;
+}
+
+int pcie_read_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 *val)
+{
+ u32 v;
+ int rv;
+
+ rv = pcie_read_config(hose, dev, offset, 3, &v);
+ *val = (u32)v;
+ return rv;
+}
+
+int pcie_write_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 val)
+{
+ return pcie_write_config(hose,(u32)dev,offset,1,val);
+}
+
+int pcie_write_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 val)
+{
+ return pcie_write_config(hose,(u32)dev,offset,2,(u32 )val);
+}
+
+int pcie_write_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 val)
+{
+ return pcie_write_config(hose,(u32)dev,offset,3,(u32 )val);
+}
+
+#if defined(CONFIG_440SPE)
+static void ppc4xx_setup_utl(u32 port) {
+
+ volatile void *utl_base = NULL;
+
+ /*
+ * Map UTL registers
+ */
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x20000000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+ break;
+
+ case 1:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x20001000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+ break;
+
+ case 2:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x20002000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+ break;
+ }
+ utl_base = (unsigned int *)(CONFIG_SYS_PCIE_BASE + 0x1000 * port);
+
+ /*
+ * Set buffer allocations and then assert VRB and TXE.
+ */
+ out_be32(utl_base + PEUTL_OUTTR, 0x08000000);
+ out_be32(utl_base + PEUTL_INTR, 0x02000000);
+ out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000);
+ out_be32(utl_base + PEUTL_PBBSZ, 0x53000000);
+ out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000);
+ out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000);
+ out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+ out_be32(utl_base + PEUTL_PCTL, 0x80800066);
+}
+
+static int check_error(void)
+{
+ u32 valPE0, valPE1, valPE2;
+ int err = 0;
+
+ /* SDR0_PEGPLLLCT1 reset */
+ if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000))
+ printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0);
+
+ valPE0 = SDR_READ(PESDR0_RCSSET);
+ valPE1 = SDR_READ(PESDR1_RCSSET);
+ valPE2 = SDR_READ(PESDR2_RCSSET);
+
+ /* SDR0_PExRCSSET rstgu */
+ if (!(valPE0 & 0x01000000) ||
+ !(valPE1 & 0x01000000) ||
+ !(valPE2 & 0x01000000)) {
+ printf("PCIE: SDR0_PExRCSSET rstgu error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstdl */
+ if (!(valPE0 & 0x00010000) ||
+ !(valPE1 & 0x00010000) ||
+ !(valPE2 & 0x00010000)) {
+ printf("PCIE: SDR0_PExRCSSET rstdl error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstpyn */
+ if ((valPE0 & 0x00001000) ||
+ (valPE1 & 0x00001000) ||
+ (valPE2 & 0x00001000)) {
+ printf("PCIE: SDR0_PExRCSSET rstpyn error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET hldplb */
+ if ((valPE0 & 0x10000000) ||
+ (valPE1 & 0x10000000) ||
+ (valPE2 & 0x10000000)) {
+ printf("PCIE: SDR0_PExRCSSET hldplb error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rdy */
+ if ((valPE0 & 0x00100000) ||
+ (valPE1 & 0x00100000) ||
+ (valPE2 & 0x00100000)) {
+ printf("PCIE: SDR0_PExRCSSET rdy error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET shutdown */
+ if ((valPE0 & 0x00000100) ||
+ (valPE1 & 0x00000100) ||
+ (valPE2 & 0x00000100)) {
+ printf("PCIE: SDR0_PExRCSSET shutdown error\n");
+ err = -1;
+ }
+ return err;
+}
+
+/*
+ * Initialize PCI Express core
+ */
+int ppc4xx_init_pcie(void)
+{
+ int time_out = 20;
+
+ /* Set PLL clock receiver to LVPECL */
+ SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
+
+ if (check_error()) {
+ printf("ERROR: failed to set PCIe reference clock receiver --"
+ "PESDR0_PLLLCT1 = 0x%08x\n", SDR_READ(PESDR0_PLLLCT1));
+
+ return -1;
+ }
+
+ /* Did resistance calibration work? */
+ if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) {
+ printf("ERROR: PCIe resistance calibration failed --"
+ "PESDR0_PLLLCT2 = 0x%08x\n", SDR_READ(PESDR0_PLLLCT2));
+
+ return -1;
+ }
+ /* De-assert reset of PCIe PLL, wait for lock */
+ SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
+ udelay(300); /* 300 uS is maximum time lock should take */
+
+ while (time_out) {
+ if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) {
+ time_out--;
+ udelay(20); /* Wait 20 uS more if needed */
+ } else
+ break;
+ }
+ if (!time_out) {
+ printf("ERROR: PCIe PLL VCO output not locked to ref clock --"
+ "PESDR0_PLLLCTS=0x%08x\n", SDR_READ(PESDR0_PLLLCT3));
+
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+static void ppc4xx_setup_utl(u32 port)
+{
+ volatile void *utl_base = NULL;
+
+ /*
+ * Map UTL registers at 0x0801_n000 (4K 0xfff mask) PEGPLn_REGMSK
+ */
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE0), U64_TO_U32_HIGH(CONFIG_SYS_PCIE0_UTLBASE));
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE0), U64_TO_U32_LOW(CONFIG_SYS_PCIE0_UTLBASE));
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* BAM 11100000=4KB */
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);
+ break;
+
+ case 1:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE1), U64_TO_U32_HIGH(CONFIG_SYS_PCIE0_UTLBASE));
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE1), U64_TO_U32_LOW(CONFIG_SYS_PCIE0_UTLBASE)
+ + 0x1000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* BAM 11100000=4KB */
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);
+ break;
+ }
+ utl_base = (unsigned int *)(CONFIG_SYS_PCIE_BASE + 0x1000 * port);
+
+ /*
+ * Set buffer allocations and then assert VRB and TXE.
+ */
+ out_be32(utl_base + PEUTL_PBCTL, 0x0800000c); /* PLBME, CRRE */
+ out_be32(utl_base + PEUTL_OUTTR, 0x08000000);
+ out_be32(utl_base + PEUTL_INTR, 0x02000000);
+ out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000); /* OPD = 512 Bytes */
+ out_be32(utl_base + PEUTL_PBBSZ, 0x00000000); /* Max 512 Bytes */
+ out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000);
+ out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000); /* IPD = 512 Bytes */
+ out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+ out_be32(utl_base + PEUTL_PCTL, 0x80800066); /* VRB,TXE,timeout=default */
+}
+
+/*
+ * TODO: double check PCI express SDR based on the latest user manual
+ * Some registers specified here no longer exist.. has to be
+ * updated based on the final EAS spec.
+ */
+static int check_error(void)
+{
+ u32 valPE0, valPE1;
+ int err = 0;
+
+ valPE0 = SDR_READ(SDRN_PESDR_RCSSET(0));
+ valPE1 = SDR_READ(SDRN_PESDR_RCSSET(1));
+
+ /* SDR0_PExRCSSET rstgu */
+ if (!(valPE0 & PESDRx_RCSSET_RSTGU) || !(valPE1 & PESDRx_RCSSET_RSTGU)) {
+ printf("PCIE: SDR0_PExRCSSET rstgu error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstdl */
+ if (!(valPE0 & PESDRx_RCSSET_RSTDL) || !(valPE1 & PESDRx_RCSSET_RSTDL)) {
+ printf("PCIE: SDR0_PExRCSSET rstdl error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rstpyn */
+ if ((valPE0 & PESDRx_RCSSET_RSTPYN) || (valPE1 & PESDRx_RCSSET_RSTPYN)) {
+ printf("PCIE: SDR0_PExRCSSET rstpyn error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET hldplb */
+ if ((valPE0 & PESDRx_RCSSET_HLDPLB) || (valPE1 & PESDRx_RCSSET_HLDPLB)) {
+ printf("PCIE: SDR0_PExRCSSET hldplb error\n");
+ err = -1;
+ }
+
+ /* SDR0_PExRCSSET rdy */
+ if ((valPE0 & PESDRx_RCSSET_RDY) || (valPE1 & PESDRx_RCSSET_RDY)) {
+ printf("PCIE: SDR0_PExRCSSET rdy error\n");
+ err = -1;
+ }
+
+ return err;
+}
+
+/*
+ * Initialize PCI Express core as described in User Manual
+ * TODO: double check PE SDR PLL Register with the updated user manual.
+ */
+int ppc4xx_init_pcie(void)
+{
+ if (check_error())
+ return -1;
+
+ return 0;
+}
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_405EX)
+static void ppc4xx_setup_utl(u32 port)
+{
+ u32 utl_base;
+
+ /*
+ * Map UTL registers at 0xef4f_n000 (4K 0xfff mask) PEGPLn_REGMSK
+ */
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x00000000);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE0), CONFIG_SYS_PCIE0_UTLBASE);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); /* 4k region, valid */
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0);
+ break;
+
+ case 1:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x00000000);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE1), CONFIG_SYS_PCIE1_UTLBASE);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); /* 4k region, valid */
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0);
+
+ break;
+ }
+ utl_base = (port==0) ? CONFIG_SYS_PCIE0_UTLBASE : CONFIG_SYS_PCIE1_UTLBASE;
+
+ /*
+ * Set buffer allocations and then assert VRB and TXE.
+ */
+ out_be32((u32 *)(utl_base + PEUTL_OUTTR), 0x02000000);
+ out_be32((u32 *)(utl_base + PEUTL_INTR), 0x02000000);
+ out_be32((u32 *)(utl_base + PEUTL_OPDBSZ), 0x04000000);
+ out_be32((u32 *)(utl_base + PEUTL_PBBSZ), 0x21000000);
+ out_be32((u32 *)(utl_base + PEUTL_IPHBSZ), 0x02000000);
+ out_be32((u32 *)(utl_base + PEUTL_IPDBSZ), 0x04000000);
+ out_be32((u32 *)(utl_base + PEUTL_RCIRQEN), 0x00f00000);
+ out_be32((u32 *)(utl_base + PEUTL_PCTL), 0x80800066);
+
+ out_be32((u32 *)(utl_base + PEUTL_PBCTL), 0x0800000c);
+ out_be32((u32 *)(utl_base + PEUTL_RCSTA),
+ in_be32((u32 *)(utl_base + PEUTL_RCSTA)) | 0x000040000);
+}
+
+int ppc4xx_init_pcie(void)
+{
+ /*
+ * Nothing to do on 405EX
+ */
+ return 0;
+}
+#endif /* CONFIG_405EX */
+
+/*
+ * Board-specific pcie initialization
+ * Platform code can reimplement ppc4xx_init_pcie_port_hw() if needed
+ */
+
+/*
+ * Initialize various parts of the PCI Express core for our port:
+ *
+ * - Set as a root port and enable max width
+ * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4).
+ * - Set up UTL configuration.
+ * - Increase SERDES drive strength to levels suggested by AMCC.
+ * - De-assert RSTPYN, RSTDL and RSTGU.
+ *
+ * NOTICE for 440SPE revB chip: PESDRn_UTLSET2 is not set - we leave it
+ * with default setting 0x11310000. The register has new fields,
+ * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core
+ * hang.
+ */
+#if defined(CONFIG_440SPE)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+ u32 val = 1 << 24;
+ u32 utlset1;
+
+ if (rootport) {
+ val = PTYPE_ROOT_PORT << 20;
+ utlset1 = 0x21222222;
+ } else {
+ val = PTYPE_LEGACY_ENDPOINT << 20;
+ utlset1 = 0x20222222;
+ }
+
+ if (port == 0)
+ val |= LNKW_X8 << 12;
+ else
+ val |= LNKW_X4 << 12;
+
+ SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+ SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);
+ if (!ppc440spe_revB())
+ SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x11000000);
+ SDR_WRITE(SDRN_PESDR_HSSL0SET1(port), 0x35000000);
+ SDR_WRITE(SDRN_PESDR_HSSL1SET1(port), 0x35000000);
+ SDR_WRITE(SDRN_PESDR_HSSL2SET1(port), 0x35000000);
+ SDR_WRITE(SDRN_PESDR_HSSL3SET1(port), 0x35000000);
+ if (port == 0) {
+ SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
+ }
+ SDR_WRITE(SDRN_PESDR_RCSSET(port), (SDR_READ(SDRN_PESDR_RCSSET(port)) &
+ ~(1 << 24 | 1 << 16)) | 1 << 12);
+
+ return 0;
+}
+#endif /* CONFIG_440SPE */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+ u32 val;
+ u32 utlset1;
+
+ if (rootport)
+ val = PTYPE_ROOT_PORT << 20;
+ else
+ val = PTYPE_LEGACY_ENDPOINT << 20;
+
+ if (port == 0) {
+ val |= LNKW_X1 << 12;
+ utlset1 = 0x20000000;
+ } else {
+ val |= LNKW_X4 << 12;
+ utlset1 = 0x20101101;
+ }
+
+ SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+ SDR_WRITE(SDRN_PESDR_UTLSET1(port), utlset1);
+ SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01210000);
+
+ switch (port) {
+ case 0:
+ SDR_WRITE(PESDR0_L0CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR0_L0DRV, 0x00000130);
+ SDR_WRITE(PESDR0_L0CLK, 0x00000006);
+
+ SDR_WRITE(PESDR0_PHY_CTL_RST,0x10000000);
+ break;
+
+ case 1:
+ SDR_WRITE(PESDR1_L0CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L1CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L2CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L3CDRCTL, 0x00003230);
+ SDR_WRITE(PESDR1_L0DRV, 0x00000130);
+ SDR_WRITE(PESDR1_L1DRV, 0x00000130);
+ SDR_WRITE(PESDR1_L2DRV, 0x00000130);
+ SDR_WRITE(PESDR1_L3DRV, 0x00000130);
+ SDR_WRITE(PESDR1_L0CLK, 0x00000006);
+ SDR_WRITE(PESDR1_L1CLK, 0x00000006);
+ SDR_WRITE(PESDR1_L2CLK, 0x00000006);
+ SDR_WRITE(PESDR1_L3CLK, 0x00000006);
+
+ SDR_WRITE(PESDR1_PHY_CTL_RST,0x10000000);
+ break;
+ }
+
+ SDR_WRITE(SDRN_PESDR_RCSSET(port), SDR_READ(SDRN_PESDR_RCSSET(port)) |
+ (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
+
+ /* Poll for PHY reset */
+ switch (port) {
+ case 0:
+ while (!(SDR_READ(PESDR0_RSTSTA) & 0x1))
+ udelay(10);
+ break;
+ case 1:
+ while (!(SDR_READ(PESDR1_RSTSTA) & 0x1))
+ udelay(10);
+ break;
+ }
+
+ SDR_WRITE(SDRN_PESDR_RCSSET(port),
+ (SDR_READ(SDRN_PESDR_RCSSET(port)) &
+ ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
+ PESDRx_RCSSET_RSTPYN);
+
+ return 0;
+}
+#endif /* CONFIG_440SPE */
+
+#if defined(CONFIG_405EX)
+int __ppc4xx_init_pcie_port_hw(int port, int rootport)
+{
+ u32 val;
+
+ if (rootport)
+ val = 0x00401000;
+ else
+ val = 0x00101000;
+
+ SDR_WRITE(SDRN_PESDR_DLPSET(port), val);
+ SDR_WRITE(SDRN_PESDR_UTLSET1(port), 0x00000000);
+ SDR_WRITE(SDRN_PESDR_UTLSET2(port), 0x01010000);
+ SDR_WRITE(SDRN_PESDR_PHYSET1(port), 0x720F0000);
+ SDR_WRITE(SDRN_PESDR_PHYSET2(port), 0x70600003);
+
+ /* Assert the PE0_PHY reset */
+ SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01010000);
+ udelay(1000);
+
+ /* deassert the PE0_hotreset */
+ if (is_end_point(port))
+ SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01111000);
+ else
+ SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x01101000);
+
+ /* poll for phy !reset */
+ while (!(SDR_READ(SDRN_PESDR_PHYSTA(port)) & 0x00001000))
+ ;
+
+ /* deassert the PE0_gpl_utl_reset */
+ SDR_WRITE(SDRN_PESDR_RCSSET(port), 0x00101000);
+
+ if (port == 0)
+ mtdcr(DCRN_PEGPL_CFG(PCIE0), 0x10000000); /* guarded on */
+ else
+ mtdcr(DCRN_PEGPL_CFG(PCIE1), 0x10000000); /* guarded on */
+
+ return 0;
+}
+#endif /* CONFIG_405EX */
+
+int ppc4xx_init_pcie_port_hw(int port, int rootport)
+__attribute__((weak, alias("__ppc4xx_init_pcie_port_hw")));
+
+/*
+ * We map PCI Express configuration access into the 512MB regions
+ *
+ * NOTICE: revB is very strict about PLB real addressess and ranges to
+ * be mapped for config space; it seems to only work with d_nnnn_nnnn
+ * range (hangs the core upon config transaction attempts when set
+ * otherwise) while revA uses c_nnnn_nnnn.
+ *
+ * For 440SPe revA:
+ * PCIE0: 0xc_4000_0000
+ * PCIE1: 0xc_8000_0000
+ * PCIE2: 0xc_c000_0000
+ *
+ * For 440SPe revB:
+ * PCIE0: 0xd_0000_0000
+ * PCIE1: 0xd_2000_0000
+ * PCIE2: 0xd_4000_0000
+ *
+ * For 405EX:
+ * PCIE0: 0xa000_0000
+ * PCIE1: 0xc000_0000
+ *
+ * For 460EX/GT:
+ * PCIE0: 0xd_0000_0000
+ * PCIE1: 0xd_2000_0000
+ */
+static inline u64 ppc4xx_get_cfgaddr(int port)
+{
+#if defined(CONFIG_405EX)
+ if (port == 0)
+ return (u64)CONFIG_SYS_PCIE0_CFGBASE;
+ else
+ return (u64)CONFIG_SYS_PCIE1_CFGBASE;
+#endif
+#if defined(CONFIG_440SPE)
+ if (ppc440spe_revB()) {
+ switch (port) {
+ default: /* to satisfy compiler */
+ case 0:
+ return 0x0000000d00000000ULL;
+ case 1:
+ return 0x0000000d20000000ULL;
+ case 2:
+ return 0x0000000d40000000ULL;
+ }
+ } else {
+ switch (port) {
+ default: /* to satisfy compiler */
+ case 0:
+ return 0x0000000c40000000ULL;
+ case 1:
+ return 0x0000000c80000000ULL;
+ case 2:
+ return 0x0000000cc0000000ULL;
+ }
+ }
+#endif
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ if (port == 0)
+ return 0x0000000d00000000ULL;
+ else
+ return 0x0000000d20000000ULL;
+#endif
+}
+
+/*
+ * 4xx boards as endpoint and root point setup
+ * and
+ * testing inbound and out bound windows
+ *
+ * 4xx boards can be plugged into another 4xx boards or you can get PCI-E
+ * cable which can be used to setup loop back from one port to another port.
+ * Please rememeber that unless there is a endpoint plugged in to root port it
+ * will not initialize. It is the same in case of endpoint , unless there is
+ * root port attached it will not initialize.
+ *
+ * In this release of software all the PCI-E ports are configured as either
+ * endpoint or rootpoint.In future we will have support for selective ports
+ * setup as endpoint and root point in single board.
+ *
+ * Once your board came up as root point , you can verify by reading
+ * /proc/bus/pci/devices. Where you can see the configuration registers
+ * of endpoint device attached to the port.
+ *
+ * Enpoint cofiguration can be verified by connecting 4xx board to any
+ * host or another 4xx board. Then try to scan the device. In case of
+ * linux use "lspci" or appripriate os command.
+ *
+ * How do I verify the inbound and out bound windows ? (4xx to 4xx)
+ * in this configuration inbound and outbound windows are setup to access
+ * sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address
+ * is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000,
+ * This is waere your POM(PLB out bound memory window) mapped. then
+ * read the data from other 4xx board's u-boot prompt at address
+ * 0x9000 0000(SRAM). Data should match.
+ * In case of inbound , write data to u-boot command prompt at 0xb000 0000
+ * which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check
+ * data at 0x9000 0000(SRAM).Data should match.
+ */
+int ppc4xx_init_pcie_port(int port, int rootport)
+{
+ static int core_init;
+ volatile u32 val = 0;
+ int attempts;
+ u64 addr;
+ u32 low, high;
+
+ if (!core_init) {
+ if (ppc4xx_init_pcie())
+ return -1;
+ ++core_init;
+ }
+
+ /*
+ * Initialize various parts of the PCI Express core for our port
+ */
+ ppc4xx_init_pcie_port_hw(port, rootport);
+
+ /*
+ * Notice: the following delay has critical impact on device
+ * initialization - if too short (<50ms) the link doesn't get up.
+ */
+ mdelay(100);
+
+ val = SDR_READ(SDRN_PESDR_RCSSTS(port));
+ if (val & (1 << 20)) {
+ printf("PCIE%d: PGRST failed %08x\n", port, val);
+ return -1;
+ }
+
+ /*
+ * Verify link is up
+ */
+ val = SDR_READ(SDRN_PESDR_LOOP(port));
+ if (!(val & 0x00001000)) {
+ printf("PCIE%d: link is not up.\n", port);
+ return -ENODEV;
+ }
+
+ /*
+ * Setup UTL registers - but only on revA!
+ * We use default settings for revB chip.
+ */
+ if (!ppc440spe_revB())
+ ppc4xx_setup_utl(port);
+
+ /*
+ * We map PCI Express configuration access into the 512MB regions
+ */
+ addr = ppc4xx_get_cfgaddr(port);
+ low = U64_TO_U32_LOW(addr);
+ high = U64_TO_U32_HIGH(addr);
+
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), high);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), low);
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
+ break;
+ case 1:
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), high);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), low);
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
+ break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ case 2:
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), high);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), low);
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
+ break;
+#endif
+ }
+
+ /*
+ * Check for VC0 active and assert RDY.
+ */
+ attempts = 10;
+ while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 16))) {
+ if (!(attempts--)) {
+ printf("PCIE%d: VC0 not active\n", port);
+ return -1;
+ }
+ mdelay(1000);
+ }
+ SDR_WRITE(SDRN_PESDR_RCSSET(port),
+ SDR_READ(SDRN_PESDR_RCSSET(port)) | 1 << 20);
+ mdelay(100);
+
+ return 0;
+}
+
+int ppc4xx_init_pcie_rootport(int port)
+{
+ return ppc4xx_init_pcie_port(port, 1);
+}
+
+int ppc4xx_init_pcie_endport(int port)
+{
+ return ppc4xx_init_pcie_port(port, 0);
+}
+
+void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port)
+{
+ volatile void *mbase = NULL;
+
+ pci_set_ops(hose,
+ pcie_read_config_byte,
+ pcie_read_config_word,
+ pcie_read_config_dword,
+ pcie_write_config_byte,
+ pcie_write_config_word,
+ pcie_write_config_dword);
+
+ switch (port) {
+ case 0:
+ mbase = (u32 *)CONFIG_SYS_PCIE0_XCFGBASE;
+ hose->cfg_data = (u8 *)CONFIG_SYS_PCIE0_CFGBASE;
+ break;
+ case 1:
+ mbase = (u32 *)CONFIG_SYS_PCIE1_XCFGBASE;
+ hose->cfg_data = (u8 *)CONFIG_SYS_PCIE1_CFGBASE;
+ break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ case 2:
+ mbase = (u32 *)CONFIG_SYS_PCIE2_XCFGBASE;
+ hose->cfg_data = (u8 *)CONFIG_SYS_PCIE2_CFGBASE;
+ break;
+#endif
+ }
+
+ /*
+ * Set bus numbers on our root port
+ */
+ out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0);
+ out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1);
+ out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1);
+
+ /*
+ * Set up outbound translation to hose->mem_space from PLB
+ * addresses at an offset of 0xd_0000_0000. We set the low
+ * bits of the mask to 11 to turn off splitting into 8
+ * subregions and to enable the outbound translation.
+ */
+ out_le32(mbase + PECFG_POM0LAH, 0x00000000);
+ out_le32(mbase + PECFG_POM0LAL, CONFIG_SYS_PCIE_MEMBASE +
+ port * CONFIG_SYS_PCIE_MEMSIZE);
+ debug("PECFG_POM0LA=%08x.%08x\n", in_le32(mbase + PECFG_POM0LAH),
+ in_le32(mbase + PECFG_POM0LAL));
+
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CONFIG_SYS_PCIE_ADDR_HIGH);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CONFIG_SYS_PCIE_MEMBASE +
+ port * CONFIG_SYS_PCIE_MEMSIZE);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+ ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+ debug("0:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",
+ mfdcr(DCRN_PEGPL_OMR1BAH(PCIE0)),
+ mfdcr(DCRN_PEGPL_OMR1BAL(PCIE0)),
+ mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE0)),
+ mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE0)));
+ break;
+ case 1:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CONFIG_SYS_PCIE_ADDR_HIGH);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CONFIG_SYS_PCIE_MEMBASE +
+ port * CONFIG_SYS_PCIE_MEMSIZE);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+ ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+ debug("1:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",
+ mfdcr(DCRN_PEGPL_OMR1BAH(PCIE1)),
+ mfdcr(DCRN_PEGPL_OMR1BAL(PCIE1)),
+ mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE1)),
+ mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE1)));
+ break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ case 2:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CONFIG_SYS_PCIE_ADDR_HIGH);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CONFIG_SYS_PCIE_MEMBASE +
+ port * CONFIG_SYS_PCIE_MEMSIZE);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+ ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+ debug("2:PEGPL_OMR1BA=%08x.%08x MSK=%08x.%08x\n",
+ mfdcr(DCRN_PEGPL_OMR1BAH(PCIE2)),
+ mfdcr(DCRN_PEGPL_OMR1BAL(PCIE2)),
+ mfdcr(DCRN_PEGPL_OMR1MSKH(PCIE2)),
+ mfdcr(DCRN_PEGPL_OMR1MSKL(PCIE2)));
+ break;
+#endif
+ }
+
+ /* Set up 4GB inbound memory window at 0 */
+ out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+ out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+ out_le32(mbase + PECFG_BAR0HMPA, 0x7ffffff);
+ out_le32(mbase + PECFG_BAR0LMPA, 0);
+
+ out_le32(mbase + PECFG_PIM01SAH, 0xffff0000);
+ out_le32(mbase + PECFG_PIM01SAL, 0x00000000);
+ out_le32(mbase + PECFG_PIM0LAL, 0);
+ out_le32(mbase + PECFG_PIM0LAH, 0);
+ out_le32(mbase + PECFG_PIM1LAL, 0x00000000);
+ out_le32(mbase + PECFG_PIM1LAH, 0x00000004);
+ out_le32(mbase + PECFG_PIMEN, 0x1);
+
+ /* Enable I/O, Mem, and Busmaster cycles */
+ out_le16((u16 *)(mbase + PCI_COMMAND),
+ in_le16((u16 *)(mbase + PCI_COMMAND)) |
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+ /* Set Device and Vendor Id */
+ out_le16(mbase + 0x200, 0xaaa0 + port);
+ out_le16(mbase + 0x202, 0xbed0 + port);
+
+ /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
+ out_le32(mbase + 0x208, 0x06040001);
+
+ printf("PCIE%d: successfully set as root-complex\n", port);
+}
+
+int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port)
+{
+ volatile void *mbase = NULL;
+ int attempts = 0;
+
+ pci_set_ops(hose,
+ pcie_read_config_byte,
+ pcie_read_config_word,
+ pcie_read_config_dword,
+ pcie_write_config_byte,
+ pcie_write_config_word,
+ pcie_write_config_dword);
+
+ switch (port) {
+ case 0:
+ mbase = (u32 *)CONFIG_SYS_PCIE0_XCFGBASE;
+ hose->cfg_data = (u8 *)CONFIG_SYS_PCIE0_CFGBASE;
+ break;
+ case 1:
+ mbase = (u32 *)CONFIG_SYS_PCIE1_XCFGBASE;
+ hose->cfg_data = (u8 *)CONFIG_SYS_PCIE1_CFGBASE;
+ break;
+#if defined(CONFIG_SYS_PCIE2_CFGBASE)
+ case 2:
+ mbase = (u32 *)CONFIG_SYS_PCIE2_XCFGBASE;
+ hose->cfg_data = (u8 *)CONFIG_SYS_PCIE2_CFGBASE;
+ break;
+#endif
+ }
+
+ /*
+ * Set up outbound translation to hose->mem_space from PLB
+ * addresses at an offset of 0xd_0000_0000. We set the low
+ * bits of the mask to 11 to turn off splitting into 8
+ * subregions and to enable the outbound translation.
+ */
+ out_le32(mbase + PECFG_POM0LAH, 0x00001ff8);
+ out_le32(mbase + PECFG_POM0LAL, 0x00001000);
+
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), CONFIG_SYS_PCIE_ADDR_HIGH);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CONFIG_SYS_PCIE_MEMBASE +
+ port * CONFIG_SYS_PCIE_MEMSIZE);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+ ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+ break;
+ case 1:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), CONFIG_SYS_PCIE_ADDR_HIGH);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), CONFIG_SYS_PCIE_MEMBASE +
+ port * CONFIG_SYS_PCIE_MEMSIZE);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+ ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+ break;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ case 2:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), CONFIG_SYS_PCIE_ADDR_HIGH);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), CONFIG_SYS_PCIE_MEMBASE +
+ port * CONFIG_SYS_PCIE_MEMSIZE);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+ ~(CONFIG_SYS_PCIE_MEMSIZE - 1) | 3);
+ break;
+#endif
+ }
+
+ /* Set up 64MB inbound memory window at 0 */
+ out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+ out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+
+ out_le32(mbase + PECFG_PIM01SAH, 0xffffffff);
+ out_le32(mbase + PECFG_PIM01SAL, 0xfc000000);
+
+ /* Setup BAR0 */
+ out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffff);
+ out_le32(mbase + PECFG_BAR0LMPA, 0xfc000000 | PCI_BASE_ADDRESS_MEM_TYPE_64);
+
+ /* Disable BAR1 & BAR2 */
+ out_le32(mbase + PECFG_BAR1MPA, 0);
+ out_le32(mbase + PECFG_BAR2HMPA, 0);
+ out_le32(mbase + PECFG_BAR2LMPA, 0);
+
+ out_le32(mbase + PECFG_PIM0LAL, U64_TO_U32_LOW(CONFIG_SYS_PCIE_INBOUND_BASE));
+ out_le32(mbase + PECFG_PIM0LAH, U64_TO_U32_HIGH(CONFIG_SYS_PCIE_INBOUND_BASE));
+ out_le32(mbase + PECFG_PIMEN, 0x1);
+
+ /* Enable I/O, Mem, and Busmaster cycles */
+ out_le16((u16 *)(mbase + PCI_COMMAND),
+ in_le16((u16 *)(mbase + PCI_COMMAND)) |
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ out_le16(mbase + 0x200, 0xcaad); /* Setting vendor ID */
+ out_le16(mbase + 0x202, 0xfeed); /* Setting device ID */
+
+ /* Set Class Code to Processor/PPC */
+ out_le32(mbase + 0x208, 0x0b200001);
+
+ attempts = 10;
+ while(!(SDR_READ(SDRN_PESDR_RCSSTS(port)) & (1 << 8))) {
+ if (!(attempts--)) {
+ printf("PCIE%d: BME not active\n", port);
+ return -1;
+ }
+ mdelay(1000);
+ }
+
+ printf("PCIE%d: successfully set as endpoint\n", port);
+
+ return 0;
+}
+#endif /* CONFIG_440SPE && CONFIG_PCI */
diff --git a/arch/powerpc/cpu/ppc4xx/4xx_uart.c b/arch/powerpc/cpu/ppc4xx/4xx_uart.c
new file mode 100644
index 0000000..2ab185f
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/4xx_uart.c
@@ -0,0 +1,307 @@
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This source code is dual-licensed. You may use it under the terms of the
+ * GNU General Public License version 2, or under the license below.
+ *
+ * This source code has been made available to you by IBM on an AS-IS
+ * basis. Anyone receiving this source is licensed under IBM
+ * copyrights to use it in any way he or she deems fit, including
+ * copying it, modifying it, compiling it, and redistributing it either
+ * with or without modifications. No license under IBM patents or
+ * patent applications is to be implied by the copyright license.
+ *
+ * Any user of this software should understand that IBM cannot provide
+ * technical support for this software and will not be responsible for
+ * any consequences resulting from the use of this software.
+ *
+ * Any person who transfers this source code or any derivative work
+ * must include the IBM copyright notice, this paragraph, and the
+ * preceding two paragraphs in the transferred software.
+ *
+ * COPYRIGHT I B M CORPORATION 1995
+ * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
+ */
+
+#include <common.h>
+#include <commproc.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <watchdog.h>
+#include <asm/ppc4xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+ defined(CONFIG_405EX) || defined(CONFIG_440)
+
+#if defined(CONFIG_440)
+
+#if defined(CONFIG_440GP)
+#define CR0_MASK 0x3fff0000
+#define CR0_EXTCLK_ENA 0x00600000
+#define CR0_UDIV_POS 16
+#define UDIV_SUBTRACT 1
+#define UART0_SDR CPC0_CR0
+#define MFREG(a, d) d = mfdcr(a)
+#define MTREG(a, d) mtdcr(a, d)
+#else /* #if defined(CONFIG_440GP) */
+/* all other 440 PPC's access clock divider via sdr register */
+#define CR0_MASK 0xdfffffff
+#define CR0_EXTCLK_ENA 0x00800000
+#define CR0_UDIV_POS 0
+#define UDIV_SUBTRACT 0
+#define UART0_SDR SDR0_UART0
+#define UART1_SDR SDR0_UART1
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART2_SDR SDR0_UART2
+#endif
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define UART3_SDR SDR0_UART3
+#endif
+#define MFREG(a, d) mfsdr(a, d)
+#define MTREG(a, d) mtsdr(a, d)
+#endif /* #if defined(CONFIG_440GP) */
+#elif defined(CONFIG_405EP) || defined(CONFIG_405EZ)
+#define UCR0_MASK 0x0000007f
+#define UCR1_MASK 0x00007f00
+#define UCR0_UDIV_POS 0
+#define UCR1_UDIV_POS 8
+#define UDIV_MAX 127
+#elif defined(CONFIG_405EX)
+#define MFREG(a, d) mfsdr(a, d)
+#define MTREG(a, d) mtsdr(a, d)
+#define CR0_MASK 0x000000ff
+#define CR0_EXTCLK_ENA 0x00800000
+#define CR0_UDIV_POS 0
+#define UDIV_SUBTRACT 0
+#define UART0_SDR SDR0_UART0
+#define UART1_SDR SDR0_UART1
+#else /* CONFIG_405GP || CONFIG_405CR */
+#define CR0_MASK 0x00001fff
+#define CR0_EXTCLK_ENA 0x000000c0
+#define CR0_UDIV_POS 1
+#define UDIV_MAX 32
+#endif
+
+#if defined(CONFIG_405EP) && defined(CONFIG_SYS_EXT_SERIAL_CLOCK)
+#error "External serial clock not supported on AMCC PPC405EP!"
+#endif
+
+#if (defined(CONFIG_405EX) || defined(CONFIG_405EZ) || \
+ defined(CONFIG_440)) && !defined(CONFIG_SYS_EXT_SERIAL_CLOCK)
+/*
+ * For some SoC's, the cpu clock is on divider chain A, UART on
+ * divider chain B ... so cpu clock is irrelevant. Get the
+ * "optimized" values that are subject to the 1/2 opb clock
+ * constraint.
+ */
+static u16 serial_bdiv(int baudrate, u32 *udiv)
+{
+ sys_info_t sysinfo;
+ u32 div; /* total divisor udiv * bdiv */
+ u32 umin; /* minimum udiv */
+ u16 diff; /* smallest diff */
+ u16 idiff; /* current diff */
+ u16 ibdiv; /* current bdiv */
+ u32 i;
+ u32 est; /* current estimate */
+ u32 max;
+#if defined(CONFIG_405EZ)
+ u32 cpr_pllc;
+ u32 plloutb;
+ u32 reg;
+#endif
+
+ get_sys_info(&sysinfo);
+
+#if defined(CONFIG_405EZ)
+ /* check the pll feedback source */
+ mfcpr(CPR0_PLLC, cpr_pllc);
+ plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
+ sysinfo.pllFwdDivB : sysinfo.pllFwdDiv) *
+ sysinfo.pllFbkDiv) / sysinfo.pllFwdDivB);
+ div = plloutb / (16 * baudrate); /* total divisor */
+ umin = (plloutb / get_OPB_freq()) << 1; /* 2 x OPB divisor */
+ max = 256; /* highest possible */
+#else /* 405EZ */
+ div = sysinfo.freqPLB / (16 * baudrate); /* total divisor */
+ umin = sysinfo.pllOpbDiv << 1; /* 2 x OPB divisor */
+ max = 32; /* highest possible */
+#endif /* 405EZ */
+
+ *udiv = diff = max;
+
+ /*
+ * i is the test udiv value -- start with the largest
+ * possible (max) to minimize serial clock and constrain
+ * search to umin.
+ */
+ for (i = max; i > umin; i--) {
+ ibdiv = div / i;
+ est = i * ibdiv;
+ idiff = (est > div) ? (est - div) : (div - est);
+ if (idiff == 0) {
+ *udiv = i;
+ break; /* can't do better */
+ } else if (idiff < diff) {
+ *udiv = i; /* best so far */
+ diff = idiff; /* update lowest diff*/
+ }
+ }
+
+#if defined(CONFIG_405EZ)
+ mfcpr(CPR0_PERD0, reg);
+ reg &= ~0x0000ffff;
+ reg |= ((*udiv - 0) << 8) | (*udiv - 0);
+ mtcpr(CPR0_PERD0, reg);
+#endif
+
+ return div / *udiv;
+}
+#endif /* #if (defined(CONFIG_405EP) ... */
+
+/*
+ * This function returns the UART clock used by the common
+ * NS16550 driver. Additionally the SoC internal divisors for
+ * optimal UART baudrate are configured.
+ */
+int get_serial_clock(void)
+{
+ u32 clk;
+ u32 udiv;
+#if !defined(CONFIG_405EZ)
+ u32 reg;
+#endif
+#if !defined(CONFIG_SYS_EXT_SERIAL_CLOCK)
+ PPC4xx_SYS_INFO sys_info;
+#endif
+
+ /*
+ * Programming of the internal divisors is SoC specific.
+ * Let's handle this in some #ifdef's for the SoC's.
+ */
+
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP)
+ reg = mfdcr(CPC0_CR0) & ~CR0_MASK;
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+ clk = CONFIG_SYS_EXT_SERIAL_CLOCK;
+ udiv = 1;
+ reg |= CR0_EXTCLK_ENA;
+#else /* CONFIG_SYS_EXT_SERIAL_CLOCK */
+ clk = gd->cpu_clk;
+#ifdef CONFIG_SYS_405_UART_ERRATA_59
+ udiv = 31; /* Errata 59: stuck at 31 */
+#else /* CONFIG_SYS_405_UART_ERRATA_59 */
+ {
+ u32 tmp = CONFIG_SYS_BASE_BAUD * 16;
+
+ udiv = (clk + tmp / 2) / tmp;
+ }
+ if (udiv > UDIV_MAX) /* max. n bits for udiv */
+ udiv = UDIV_MAX;
+#endif /* CONFIG_SYS_405_UART_ERRATA_59 */
+#endif /* CONFIG_SYS_EXT_SERIAL_CLOCK */
+ reg |= (udiv - 1) << CR0_UDIV_POS; /* set the UART divisor */
+ mtdcr (CPC0_CR0, reg);
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+ clk = CONFIG_SYS_EXT_SERIAL_CLOCK;
+#else
+ clk = CONFIG_SYS_BASE_BAUD * 16;
+#endif
+#endif /* CONFIG_405CR */
+
+#if defined(CONFIG_405EP)
+ {
+ u32 tmp = CONFIG_SYS_BASE_BAUD * 16;
+
+ reg = mfdcr(CPC0_UCR) & ~(UCR0_MASK | UCR1_MASK);
+ clk = gd->cpu_clk;
+ udiv = (clk + tmp / 2) / tmp;
+ if (udiv > UDIV_MAX) /* max. n bits for udiv */
+ udiv = UDIV_MAX;
+ }
+ reg |= udiv << UCR0_UDIV_POS; /* set the UART divisor */
+ reg |= udiv << UCR1_UDIV_POS; /* set the UART divisor */
+ mtdcr(CPC0_UCR, reg);
+ clk = CONFIG_SYS_BASE_BAUD * 16;
+#endif /* CONFIG_405EP */
+
+#if defined(CONFIG_405EX) || defined(CONFIG_440)
+ MFREG(UART0_SDR, reg);
+ reg &= ~CR0_MASK;
+
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+ reg |= CR0_EXTCLK_ENA;
+ udiv = 1;
+ clk = CONFIG_SYS_EXT_SERIAL_CLOCK;
+#else /* CONFIG_SYS_EXT_SERIAL_CLOCK */
+ clk = gd->baudrate * serial_bdiv(gd->baudrate, &udiv) * 16;
+#endif /* CONFIG_SYS_EXT_SERIAL_CLOCK */
+
+ reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS; /* set the UART divisor */
+
+ /*
+ * Configure input clock to baudrate generator for all
+ * available serial ports here
+ */
+ MTREG(UART0_SDR, reg);
+#if defined(UART1_SDR)
+ MTREG(UART1_SDR, reg);
+#endif
+#if defined(UART2_SDR)
+ MTREG(UART2_SDR, reg);
+#endif
+#if defined(UART3_SDR)
+ MTREG(UART3_SDR, reg);
+#endif
+#endif /* CONFIG_405EX ... */
+
+#if defined(CONFIG_405EZ)
+ clk = gd->baudrate * serial_bdiv(gd->baudrate, &udiv) * 16;
+#endif /* CONFIG_405EZ */
+
+ /*
+ * Correct UART frequency in bd-info struct now that
+ * the UART divisor is available
+ */
+#ifdef CONFIG_SYS_EXT_SERIAL_CLOCK
+ gd->arch.uart_clk = CONFIG_SYS_EXT_SERIAL_CLOCK;
+#else
+ get_sys_info(&sys_info);
+ gd->arch.uart_clk = sys_info.freqUART / udiv;
+#endif
+
+ return clk;
+}
+#endif /* CONFIG_405GP || CONFIG_405CR */
diff --git a/arch/powerpc/cpu/ppc4xx/Makefile b/arch/powerpc/cpu/ppc4xx/Makefile
new file mode 100644
index 0000000..e301dc6
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/Makefile
@@ -0,0 +1,91 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+START := resetvec.o
+START += start.o
+
+SOBJS := cache.o
+SOBJS += dcr.o
+SOBJS += kgdb.o
+
+COBJS := 40x_spd_sdram.o
+
+ifndef CONFIG_NAND_SPL
+ifndef CONFIG_NAND_U_BOOT
+COBJS += 44x_spd_ddr.o
+endif
+endif
+COBJS-$(CONFIG_SDRAM_PPC4xx_IBM_DDR2) += 44x_spd_ddr2.o
+COBJS-$(CONFIG_PPC4xx_DDR_AUTOCALIBRATION) += 4xx_ibm_ddr2_autocalib.o
+COBJS += 4xx_pci.o
+COBJS += 4xx_pcie.o
+COBJS += bedbug_405.o
+COBJS-$(CONFIG_CMD_CHIP_CONFIG) += cmd_chip_config.o
+COBJS += cpu.o
+COBJS += cpu_init.o
+COBJS += denali_data_eye.o
+COBJS += denali_spd_ddr2.o
+COBJS += ecc.o
+COBJS-$(CONFIG_CMD_ECCTEST) += cmd_ecctest.o
+COBJS += fdt.o
+COBJS += interrupts.o
+COBJS-$(CONFIG_CMD_REGINFO) += reginfo.o
+COBJS += sdram.o
+COBJS += speed.o
+COBJS += tlb.o
+COBJS += traps.o
+COBJS += usb.o
+COBJS += usb_ohci.o
+COBJS-$(CONFIG_XILINX_440) += xilinx_irq.o
+ifndef CONFIG_XILINX_440
+COBJS += 4xx_uart.o
+COBJS += gpio.o
+COBJS += miiphy.o
+COBJS += uic.o
+endif
+
+ifdef CONFIG_SPL_BUILD
+COBJS-y += spl_boot.o
+endif
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS) $(COBJS-y))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/cpu/ppc4xx/bedbug_405.c b/arch/powerpc/cpu/ppc4xx/bedbug_405.c
new file mode 100644
index 0000000..e1500cc
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/bedbug_405.c
@@ -0,0 +1,308 @@
+/*
+ * Bedbug Functions specific to the PPC405 chip
+ */
+
+#include <common.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <bedbug/type.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+
+#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_4xx)
+
+#define MAX_BREAK_POINTS 4
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug405_init __P ((void));
+void bedbug405_do_break __P ((cmd_tbl_t *, int, int, char * const []));
+void bedbug405_break_isr __P ((struct pt_regs *));
+int bedbug405_find_empty __P ((void));
+int bedbug405_set __P ((int, unsigned long));
+int bedbug405_clear __P ((int));
+
+
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the AMCC PPC405. Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug405_init (void)
+{
+ int i;
+
+ /* -------------------------------------------------- */
+
+ bug_ctx.hw_debug_enabled = 0;
+ bug_ctx.stopped = 0;
+ bug_ctx.current_bp = 0;
+ bug_ctx.regs = NULL;
+
+ bug_ctx.do_break = bedbug405_do_break;
+ bug_ctx.break_isr = bedbug405_break_isr;
+ bug_ctx.find_empty = bedbug405_find_empty;
+ bug_ctx.set = bedbug405_set;
+ bug_ctx.clear = bedbug405_clear;
+
+ for (i = 1; i <= MAX_BREAK_POINTS; ++i)
+ (*bug_ctx.clear) (i);
+
+ puts ("BEDBUG:ready\n");
+ return;
+} /* bedbug_init_breakpoints */
+
+
+
+/* ======================================================================
+ * Set/clear/show one of the hardware breakpoints for the 405. The "off"
+ * string will disable a specific breakpoint. The "show" string will
+ * display the current breakpoints. Otherwise an address will set a
+ * breakpoint at that address. Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug405_do_break (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ long addr = 0; /* Address to break at */
+ int which_bp; /* Breakpoint number */
+
+ /* -------------------------------------------------- */
+
+ if (argc < 2) {
+ cmd_usage(cmdtp);
+ return;
+ }
+
+ /* Turn off a breakpoint */
+
+ if (strcmp (argv[1], "off") == 0) {
+ if (bug_ctx.hw_debug_enabled == 0) {
+ printf ("No breakpoints enabled\n");
+ return;
+ }
+
+ which_bp = simple_strtoul (argv[2], NULL, 10);
+
+ if (bug_ctx.clear)
+ (*bug_ctx.clear) (which_bp);
+
+ printf ("Breakpoint %d removed\n", which_bp);
+ return;
+ }
+
+ /* Show a list of breakpoints */
+
+ if (strcmp (argv[1], "show") == 0) {
+ for (which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp) {
+
+ switch (which_bp) {
+ case 1:
+ addr = GET_IAC1 ();
+ break;
+ case 2:
+ addr = GET_IAC2 ();
+ break;
+ case 3:
+ addr = GET_IAC3 ();
+ break;
+ case 4:
+ addr = GET_IAC4 ();
+ break;
+ }
+
+ printf ("Breakpoint [%d]: ", which_bp);
+ if (addr == 0)
+ printf ("NOT SET\n");
+ else
+ disppc ((unsigned char *) addr, 0, 1, bedbug_puts,
+ F_RADHEX);
+ }
+ return;
+ }
+
+ /* Set a breakpoint at the address */
+
+ if (!isdigit (argv[1][0])) {
+ cmd_usage(cmdtp);
+ return;
+ }
+
+ addr = simple_strtoul (argv[1], NULL, 16) & 0xfffffffc;
+
+ if ((bug_ctx.set) && (which_bp = (*bug_ctx.set) (0, addr)) > 0) {
+ printf ("Breakpoint [%d]: ", which_bp);
+ disppc ((unsigned char *) addr, 0, 1, bedbug_puts, F_RADHEX);
+ }
+
+ return;
+} /* bedbug405_do_break */
+
+
+
+/* ======================================================================
+ * Handle a breakpoint. First determine which breakpoint was hit by
+ * looking at the DeBug Status Register (DBSR), clear the breakpoint
+ * and enter a mini main loop. Stay in the loop until the stopped flag
+ * in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug405_break_isr (struct pt_regs *regs)
+{
+ unsigned long dbsr_val; /* Value of the DBSR */
+ unsigned long addr = 0; /* Address stopped at */
+
+ /* -------------------------------------------------- */
+
+ dbsr_val = GET_DBSR ();
+
+ if (dbsr_val & DBSR_IA1) {
+ bug_ctx.current_bp = 1;
+ addr = GET_IAC1 ();
+ SET_DBSR (DBSR_IA1); /* Write a 1 to clear */
+ } else if (dbsr_val & DBSR_IA2) {
+ bug_ctx.current_bp = 2;
+ addr = GET_IAC2 ();
+ SET_DBSR (DBSR_IA2); /* Write a 1 to clear */
+ } else if (dbsr_val & DBSR_IA3) {
+ bug_ctx.current_bp = 3;
+ addr = GET_IAC3 ();
+ SET_DBSR (DBSR_IA3); /* Write a 1 to clear */
+ } else if (dbsr_val & DBSR_IA4) {
+ bug_ctx.current_bp = 4;
+ addr = GET_IAC4 ();
+ SET_DBSR (DBSR_IA4); /* Write a 1 to clear */
+ }
+
+ bedbug_main_loop (addr, regs);
+ return;
+} /* bedbug405_break_isr */
+
+
+
+/* ======================================================================
+ * Look through all of the hardware breakpoints available to see if one
+ * is unused.
+ * ====================================================================== */
+
+int bedbug405_find_empty (void)
+{
+ /* -------------------------------------------------- */
+
+ if (GET_IAC1 () == 0)
+ return 1;
+
+ if (GET_IAC2 () == 0)
+ return 2;
+
+ if (GET_IAC3 () == 0)
+ return 3;
+
+ if (GET_IAC4 () == 0)
+ return 4;
+
+ return 0;
+} /* bedbug405_find_empty */
+
+
+
+/* ======================================================================
+ * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint. If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0. Set the break
+ * address in the appropriate IACx register and enable proper address
+ * beakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_set (int which_bp, unsigned long addr)
+{
+ /* -------------------------------------------------- */
+
+ /* Only look if which_bp == 0, else use which_bp */
+ if ((bug_ctx.find_empty) && (!which_bp) &&
+ (which_bp = (*bug_ctx.find_empty) ()) == 0) {
+ printf ("All breakpoints in use\n");
+ return 0;
+ }
+
+ if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
+ printf ("Invalid break point # %d\n", which_bp);
+ return 0;
+ }
+
+ if (!bug_ctx.hw_debug_enabled) {
+ SET_MSR (GET_MSR () | 0x200); /* set MSR[ DE ] */
+ SET_DBCR0 (GET_DBCR0 () | DBCR0_IDM);
+ bug_ctx.hw_debug_enabled = 1;
+ }
+
+ switch (which_bp) {
+ case 1:
+ SET_IAC1 (addr);
+ SET_DBCR0 (GET_DBCR0 () | DBCR0_IA1);
+ break;
+
+ case 2:
+ SET_IAC2 (addr);
+ SET_DBCR0 (GET_DBCR0 () | DBCR0_IA2);
+ break;
+
+ case 3:
+ SET_IAC3 (addr);
+ SET_DBCR0 (GET_DBCR0 () | DBCR0_IA3);
+ break;
+
+ case 4:
+ SET_IAC4 (addr);
+ SET_DBCR0 (GET_DBCR0 () | DBCR0_IA4);
+ break;
+ }
+
+ return which_bp;
+} /* bedbug405_set */
+
+
+
+/* ======================================================================
+ * Disable a specific breakoint by setting the appropriate IACx register
+ * to zero and claring the instruction address breakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_clear (int which_bp)
+{
+ /* -------------------------------------------------- */
+
+ if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
+ printf ("Invalid break point # (%d)\n", which_bp);
+ return -1;
+ }
+
+ switch (which_bp) {
+ case 1:
+ SET_IAC1 (0);
+ SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA1);
+ break;
+
+ case 2:
+ SET_IAC2 (0);
+ SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA2);
+ break;
+
+ case 3:
+ SET_IAC3 (0);
+ SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA3);
+ break;
+
+ case 4:
+ SET_IAC4 (0);
+ SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA4);
+ break;
+ }
+
+ return 0;
+} /* bedbug405_clear */
+
+
+/* ====================================================================== */
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/cache.S b/arch/powerpc/cpu/ppc4xx/cache.S
new file mode 100644
index 0000000..757d7da
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cache.S
@@ -0,0 +1,235 @@
+/*
+ * This file contains miscellaneous low-level functions.
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <config.h>
+#include <config.h>
+#include <asm/ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/*
+ * Flush instruction cache.
+ */
+_GLOBAL(invalidate_icache)
+ iccci r0,r0
+ isync
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,L1_CACHE_BYTES
+ bdnz 2b
+ sync /* additional sync needed on g4 */
+ isync
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory.
+ * Does not invalidate the corresponding cache lines (especially for
+ * any corresponding instruction cache).
+ *
+ * clean_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(clean_dcache_range)
+ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+
+1: dcbst 0,r3
+ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory and invalidate them.
+ * Does not invalidate the corresponding instruction cache blocks.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+
+1: dcbf 0,r3
+ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ blr
+
+/*
+ * Like above, but invalidate the D-cache. This is used by the 8xx
+ * to invalidate the cache so the PPC core doesn't get stale data
+ * from the CPM (no cache snooping here :-).
+ *
+ * invalidate_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_dcache_range)
+ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+
+1: dcbi 0,r3
+ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbi's to get to ram */
+ blr
+
+/*
+ * 40x cores have 8K or 16K dcache and 32 byte line size.
+ * 44x has a 32K dcache and 32 byte line size.
+ * 8xx has 1, 2, 4, 8K variants.
+ * For now, cover the worst case of the 44x.
+ * Must be called with external interrupts disabled.
+ */
+#define CACHE_NWAYS 64
+#define CACHE_NLINES 32
+
+_GLOBAL(flush_dcache)
+ li r4,(2 * CACHE_NWAYS * CACHE_NLINES)
+ mtctr r4
+ lis r5,0
+1: lwz r3,0(r5) /* Load one word from every line */
+ addi r5,r5,L1_CACHE_BYTES
+ bdnz 1b
+ sync
+ blr
+
+_GLOBAL(invalidate_dcache)
+ addi r6,0,0x0000 /* clear GPR 6 */
+ /* Do loop for # of dcache congruence classes. */
+ lis r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@ha /* TBS for large sized cache */
+ ori r7,r7,(CONFIG_SYS_DCACHE_SIZE / L1_CACHE_BYTES / 2)@l
+ /* NOTE: dccci invalidates both */
+ mtctr r7 /* ways in the D cache */
+..dcloop:
+ dccci 0,r6 /* invalidate line */
+ addi r6,r6,L1_CACHE_BYTES /* bump to next line */
+ bdnz ..dcloop
+ sync
+ blr
+
+/*
+ * Cache functions.
+ *
+ * NOTE: currently the 440s run with dcache _disabled_ once relocated to DRAM,
+ * although for some cache-ralated calls stubs have to be provided to satisfy
+ * symbols resolution.
+ * Icache-related functions are used in POST framework.
+ *
+ */
+#ifdef CONFIG_440
+
+ .globl dcache_disable
+ .globl dcache_enable
+ .globl icache_disable
+ .globl icache_enable
+dcache_disable:
+dcache_enable:
+icache_disable:
+icache_enable:
+ blr
+
+ .globl dcache_status
+ .globl icache_status
+dcache_status:
+icache_status:
+ mr r3, 0
+ blr
+
+#else /* CONFIG_440 */
+
+ .globl icache_enable
+icache_enable:
+ mflr r8
+ bl invalidate_icache
+ mtlr r8
+ isync
+ addis r3,r0, 0xc000 /* set bit 0 */
+ mticcr r3
+ blr
+
+ .globl icache_disable
+icache_disable:
+ addis r3,r0, 0x0000 /* clear bit 0 */
+ mticcr r3
+ isync
+ blr
+
+ .globl icache_status
+icache_status:
+ mficcr r3
+ srwi r3, r3, 31 /* >>31 => select bit 0 */
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+ mflr r8
+ bl invalidate_dcache
+ mtlr r8
+ isync
+ addis r3,r0, 0x8000 /* set bit 0 */
+ mtdccr r3
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ mflr r8
+ bl flush_dcache
+ mtlr r8
+ addis r3,r0, 0x0000 /* clear bit 0 */
+ mtdccr r3
+ blr
+
+ .globl dcache_status
+dcache_status:
+ mfdccr r3
+ srwi r3, r3, 31 /* >>31 => select bit 0 */
+ blr
+
+#endif /* CONFIG_440 */
diff --git a/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c b/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c
new file mode 100644
index 0000000..72c5aec
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cmd_chip_config.c
@@ -0,0 +1,148 @@
+/*
+ * (C) Copyright 2008-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2009
+ * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <i2c.h>
+#include <asm/ppc4xx_config.h>
+#include <asm/io.h>
+
+static void print_configs(int cur_config_nr)
+{
+ int i;
+
+ for (i = 0; i < ppc4xx_config_count; i++) {
+ printf("%-16s - %s", ppc4xx_config_val[i].label,
+ ppc4xx_config_val[i].description);
+ if (i == cur_config_nr)
+ printf(" ***");
+ printf("\n");
+ }
+
+}
+
+static int do_chip_config(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int i;
+ int ret;
+ int cur_config_nr = -1;
+ u8 cur_config[CONFIG_4xx_CONFIG_BLOCKSIZE];
+
+ /*
+ * First switch to correct I2C bus. This is I2C bus 0
+ * for all currently available 4xx derivats.
+ */
+ I2C_SET_BUS(0);
+
+#ifdef CONFIG_CMD_EEPROM
+ ret = eeprom_read(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+ CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+ cur_config, CONFIG_4xx_CONFIG_BLOCKSIZE);
+#else
+ ret = i2c_read(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+ CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+ 1, cur_config, CONFIG_4xx_CONFIG_BLOCKSIZE);
+#endif
+ if (ret) {
+ printf("Error reading EEPROM at addr 0x%x\n",
+ CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+ return -1;
+ }
+
+ /*
+ * Search the current configuration
+ */
+ for (i = 0; i < ppc4xx_config_count; i++) {
+ if (memcmp(cur_config, ppc4xx_config_val[i].val,
+ CONFIG_4xx_CONFIG_BLOCKSIZE) == 0)
+ cur_config_nr = i;
+ }
+
+ if (cur_config_nr == -1) {
+ printf("Warning: The I2C bootstrap values don't match any"
+ " of the available options!\n");
+ printf("I2C bootstrap EEPROM values are (I2C address 0x%02x):\n",
+ CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+ for (i = 0; i < CONFIG_4xx_CONFIG_BLOCKSIZE; i++) {
+ printf("%02x ", cur_config[i]);
+ }
+ printf("\n");
+ }
+
+ if (argc < 2) {
+ printf("Available configurations (I2C address 0x%02x):\n",
+ CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+ print_configs(cur_config_nr);
+ return 0;
+ }
+
+ for (i = 0; i < ppc4xx_config_count; i++) {
+ /*
+ * Search for configuration name/label
+ */
+ if (strcmp(argv[1], ppc4xx_config_val[i].label) == 0) {
+ printf("Using configuration:\n%-16s - %s\n",
+ ppc4xx_config_val[i].label,
+ ppc4xx_config_val[i].description);
+
+#ifdef CONFIG_CMD_EEPROM
+ ret = eeprom_write(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+ CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+ ppc4xx_config_val[i].val,
+ CONFIG_4xx_CONFIG_BLOCKSIZE);
+#else
+ ret = i2c_write(CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+ CONFIG_4xx_CONFIG_I2C_EEPROM_OFFSET,
+ 1, ppc4xx_config_val[i].val,
+ CONFIG_4xx_CONFIG_BLOCKSIZE);
+#endif
+ udelay(CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS * 1000);
+ if (ret) {
+ printf("Error updating EEPROM at addr 0x%x\n",
+ CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR);
+ return -1;
+ }
+
+ printf("done (dump via 'i2c md %x 0.1 %x')\n",
+ CONFIG_4xx_CONFIG_I2C_EEPROM_ADDR,
+ CONFIG_4xx_CONFIG_BLOCKSIZE);
+ printf("Reset the board for the changes to"
+ " take effect\n");
+ return 0;
+ }
+ }
+
+ printf("Configuration %s not found!\n", argv[1]);
+ print_configs(cur_config_nr);
+ return -1;
+}
+
+U_BOOT_CMD(
+ chip_config, 2, 0, do_chip_config,
+ "program the I2C bootstrap EEPROM",
+ "[config-label]"
+);
diff --git a/arch/powerpc/cpu/ppc4xx/cmd_ecctest.c b/arch/powerpc/cpu/ppc4xx/cmd_ecctest.c
new file mode 100644
index 0000000..231f69e
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cmd_ecctest.c
@@ -0,0 +1,279 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/ppc4xx.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/cache.h>
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \
+ defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC)
+
+#if defined(CONFIG_405EX)
+/*
+ * Currently only 405EX uses 16bit data bus width as an alternative
+ * option to 32bit data width (SDRAM0_MCOPT1_WDTH)
+ */
+#define SDRAM_DATA_ALT_WIDTH 2
+#else
+#define SDRAM_DATA_ALT_WIDTH 8
+#endif
+
+#if defined(CONFIG_SYS_OCM_BASE)
+#define CONFIG_FUNC_ISRAM_ADDR CONFIG_SYS_OCM_BASE
+#endif
+
+#if defined(CONFIG_SYS_ISRAM_BASE)
+#define CONFIG_FUNC_ISRAM_ADDR CONFIG_SYS_ISRAM_BASE
+#endif
+
+#if !defined(CONFIG_FUNC_ISRAM_ADDR)
+#error "No internal SRAM/OCM provided!"
+#endif
+
+#define force_inline inline __attribute__ ((always_inline))
+
+static inline void machine_check_disable(void)
+{
+ mtmsr(mfmsr() & ~MSR_ME);
+}
+
+static inline void machine_check_enable(void)
+{
+ mtmsr(mfmsr() | MSR_ME);
+}
+
+/*
+ * These helper functions need to be inlined, since they
+ * are called from the functions running from internal SRAM.
+ * SDRAM operation is forbidden at that time, so calling
+ * functions in SDRAM has to be avoided.
+ */
+static force_inline void wait_ddr_idle(void)
+{
+ u32 val;
+
+ do {
+ mfsdram(SDRAM_MCSTAT, val);
+ } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
+}
+
+static force_inline void recalibrate_ddr(void)
+{
+ u32 val;
+
+ /*
+ * Rewrite RQDC & RFDC to calibrate again. If this is not
+ * done, the SDRAM controller is working correctly after
+ * changing the MCOPT1_MCHK bits.
+ */
+ mfsdram(SDRAM_RQDC, val);
+ mtsdram(SDRAM_RQDC, val);
+ mfsdram(SDRAM_RFDC, val);
+ mtsdram(SDRAM_RFDC, val);
+}
+
+static force_inline void set_mcopt1_mchk(u32 bits)
+{
+ u32 val;
+
+ wait_ddr_idle();
+ mfsdram(SDRAM_MCOPT1, val);
+ mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | bits);
+ recalibrate_ddr();
+}
+
+/*
+ * The next 2 functions are copied to internal SRAM/OCM and run
+ * there. No function calls allowed here. No SDRAM acitivity should
+ * be done here.
+ */
+static void inject_ecc_error(void *ptr, int par)
+{
+ /*
+ * Taken from PPC460EX/EXr/GT users manual (Rev 1.21)
+ * 22.2.17.13 ECC Diagnostics
+ *
+ * Items 1 ... 5 are already done by now, running from RAM
+ * with ECC enabled
+ */
+
+ out_be32(ptr, 0x00000000);
+ in_be32(ptr);
+
+ /* 6. Set memory controller to no error checking */
+ set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_NON);
+
+ /* 7. Modify one or two bits for error simulation */
+ if (par == 1)
+ out_be32(ptr, in_be32(ptr) ^ 0x00000001);
+ else
+ out_be32(ptr, in_be32(ptr) ^ 0x00000003);
+
+ /* 8. Wait for SDRAM idle */
+ in_be32(ptr);
+ set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_CHK_REP);
+
+ /* Wait for SDRAM idle */
+ wait_ddr_idle();
+
+ /* Continue with 9. in calling function... */
+}
+
+static void rewrite_ecc_parity(void *ptr, int par)
+{
+ u32 current_address = (u32)ptr;
+ u32 end_address;
+ u32 address_increment;
+ u32 mcopt1;
+
+ /*
+ * Fill ECC parity byte again. Otherwise further accesses to
+ * the failure address will result in exceptions.
+ */
+
+ /* Wait for SDRAM idle */
+ in_be32(0x00000000);
+ set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_GEN);
+
+ /* ECC bit set method for non-cached memory */
+ mfsdram(SDRAM_MCOPT1, mcopt1);
+ if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
+ address_increment = 4;
+ else
+ address_increment = SDRAM_DATA_ALT_WIDTH;
+ end_address = current_address + CONFIG_SYS_CACHELINE_SIZE;
+
+ while (current_address < end_address) {
+ *((unsigned long *)current_address) = 0;
+ current_address += address_increment;
+ }
+
+ set_mcopt1_mchk(SDRAM_MCOPT1_MCHK_CHK_REP);
+
+ /* Wait for SDRAM idle */
+ wait_ddr_idle();
+}
+
+static int do_ecctest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ u32 old_val;
+ u32 val;
+ u32 *ptr;
+ void (*sram_func)(u32 *, int);
+ int error;
+
+ if (argc < 3) {
+ return cmd_usage(cmdtp);
+ }
+
+ ptr = (u32 *)simple_strtoul(argv[1], NULL, 16);
+ error = simple_strtoul(argv[2], NULL, 16);
+ if ((error < 1) || (error > 2)) {
+ return cmd_usage(cmdtp);
+ }
+
+ printf("Using address %p for %d bit ECC error injection\n",
+ ptr, error);
+
+ /*
+ * Save value to restore it later on
+ */
+ old_val = in_be32(ptr);
+
+ /*
+ * Copy ECC injection function into internal SRAM/OCM
+ */
+ sram_func = (void *)CONFIG_FUNC_ISRAM_ADDR;
+ memcpy((void *)CONFIG_FUNC_ISRAM_ADDR, inject_ecc_error, 0x10000);
+
+ /*
+ * Disable interrupts and exceptions before calling this
+ * function in internal SRAM/OCM
+ */
+ disable_interrupts();
+ machine_check_disable();
+ eieio();
+
+ /*
+ * Jump to ECC simulation function in internal SRAM/OCM
+ */
+ (*sram_func)(ptr, error);
+
+ /* 10. Read the corresponding address */
+ val = in_be32(ptr);
+
+ /*
+ * Read and print ECC status register/info:
+ * The faulting address is only known upon uncorrectable ECC
+ * errors.
+ */
+ mfsdram(SDRAM_ECCES, val);
+ if (val & SDRAM_ECCES_CE)
+ printf("ECC: Correctable error\n");
+ if (val & SDRAM_ECCES_UE) {
+ printf("ECC: Uncorrectable error at 0x%02x%08x\n",
+ mfdcr(SDRAM_ERRADDULL), mfdcr(SDRAM_ERRADDLLL));
+ }
+
+ /*
+ * Clear pending interrupts/exceptions
+ */
+ mtsdram(SDRAM_ECCES, 0xffffffff);
+ mtdcr(SDRAM_ERRSTATLL, 0xff000000);
+ set_mcsr(get_mcsr());
+
+ /* Now enable interrupts and exceptions again */
+ eieio();
+ machine_check_enable();
+ enable_interrupts();
+
+ /*
+ * The ECC parity byte need to be re-written for the
+ * corresponding address. Otherwise future accesses to it
+ * will result in exceptions.
+ *
+ * Jump to ECC parity generation function
+ */
+ memcpy((void *)CONFIG_FUNC_ISRAM_ADDR, rewrite_ecc_parity, 0x10000);
+ (*sram_func)(ptr, 0);
+
+ /*
+ * Restore value in corresponding address
+ */
+ out_be32(ptr, old_val);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ ecctest, 3, 0, do_ecctest,
+ "Test ECC by single and double error bit injection",
+ "address 1/2"
+);
+
+#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */
+#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */
diff --git a/arch/powerpc/cpu/ppc4xx/config.mk b/arch/powerpc/cpu/ppc4xx/config.mk
new file mode 100644
index 0000000..f5cbbbd
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/config.mk
@@ -0,0 +1,34 @@
+#
+# (C) Copyright 2000-2010
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -meabi
+PLATFORM_CPPFLAGS += -DCONFIG_4xx -ffixed-r2 -mstring -msoft-float
+
+cfg=$(shell grep configs $(OBJTREE)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
+is440:=$(shell grep CONFIG_440 $(TOPDIR)/include/$(cfg))
+
+ifneq (,$(findstring CONFIG_440,$(is440)))
+PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440
+else
+PLATFORM_CPPFLAGS += -Wa,-m405 -mcpu=405
+endif
diff --git a/arch/powerpc/cpu/ppc4xx/cpu.c b/arch/powerpc/cpu/ppc4xx/cpu.c
new file mode 100644
index 0000000..60aba8c
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cpu.c
@@ -0,0 +1,751 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * CPU specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ *
+ * minor modifications by
+ * Wolfgang Denk <wd@denx.de>
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <asm/ppc4xx.h>
+#include <netdev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void board_reset(void);
+
+/*
+ * To provide an interface to detect CPU number for boards that support
+ * more then one CPU, we implement the "weak" default functions here.
+ *
+ * Returns CPU number
+ */
+int __get_cpu_num(void)
+{
+ return NA_OR_UNKNOWN_CPU;
+}
+int get_cpu_num(void) __attribute__((weak, alias("__get_cpu_num")));
+
+#if defined(CONFIG_PCI)
+#if defined(CONFIG_405GP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+
+#define PCI_ASYNC
+
+static int pci_async_enabled(void)
+{
+#if defined(CONFIG_405GP)
+ return (mfdcr(CPC0_PSR) & PSR_PCI_ASYNC_EN);
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ unsigned long val;
+
+ mfsdr(SDR0_SDSTP1, val);
+ return (val & SDR0_SDSTP1_PAME_MASK);
+#endif
+}
+#endif
+#endif /* CONFIG_PCI */
+
+#if defined(CONFIG_PCI) && \
+ !defined(CONFIG_405) && !defined(CONFIG_405EX)
+int pci_arbiter_enabled(void)
+{
+#if defined(CONFIG_405GP)
+ return (mfdcr(CPC0_PSR) & PSR_PCI_ARBIT_EN);
+#endif
+
+#if defined(CONFIG_405EP)
+ return (mfdcr(CPC0_PCI) & CPC0_PCI_ARBIT_EN);
+#endif
+
+#if defined(CONFIG_440GP)
+ return (mfdcr(CPC0_STRP1) & CPC0_STRP1_PAE_MASK);
+#endif
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+ unsigned long val;
+
+ mfsdr(SDR0_XCR0, val);
+ return (val & SDR0_XCR0_PAE_MASK);
+#endif
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ unsigned long val;
+
+ mfsdr(SDR0_PCI0, val);
+ return (val & SDR0_PCI0_PAE_MASK);
+#endif
+}
+#endif
+
+#if defined(CONFIG_405EP)
+#define I2C_BOOTROM
+
+static int i2c_bootrom_enabled(void)
+{
+#if defined(CONFIG_405EP)
+ return (mfdcr(CPC0_BOOT) & CPC0_BOOT_SEP);
+#else
+ unsigned long val;
+
+ mfsdr(SDR0_SDCS0, val);
+ return (val & SDR0_SDCS_SDD);
+#endif
+}
+#endif
+
+#if defined(CONFIG_440GX)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (16 bits)",
+ "EBC (8 bits)",
+ "EBC (32 bits)",
+ "EBC (8 bits)",
+ "PCI",
+ "I2C (Addr 0x54)",
+ "Reserved",
+ "I2C (Addr 0x50)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'B', 'D', 'E', 'x', 'F' };
+#endif
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+#define SDR0_PINSTP_SHIFT 30
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "PCI",
+ "I2C (Addr 0x54)",
+ "I2C (Addr 0x50)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D'};
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "PCI",
+ "NAND (8 bits)",
+ "EBC (16 bits)",
+ "EBC (16 bits)",
+ "I2C (Addr 0x54)",
+ "PCI",
+ "I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
+#endif
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "EBC (16 bits)",
+ "EBC (16 bits)",
+ "NAND (8 bits)",
+ "PCI",
+ "I2C (Addr 0x54)",
+ "PCI",
+ "I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "EBC (16 bits)",
+ "PCI",
+ "PCI",
+ "EBC (16 bits)",
+ "NAND (8 bits)",
+ "I2C (Addr 0x54)", /* A8 */
+ "I2C (Addr 0x52)", /* A4 */
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
+#endif
+
+#if defined(CONFIG_460SX)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "EBC (16 bits)",
+ "EBC (32 bits)",
+ "NAND (8 bits)",
+ "I2C (Addr 0x54)", /* A8 */
+ "I2C (Addr 0x52)", /* A4 */
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G' };
+#endif
+
+#if defined(CONFIG_405EZ)
+#define SDR0_PINSTP_SHIFT 28
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "SPI (fast)",
+ "NAND (512 page, 4 addr cycle)",
+ "I2C (Addr 0x50)",
+ "EBC (32 bits)",
+ "I2C (Addr 0x50)",
+ "NAND (2K page, 5 addr cycle)",
+ "I2C (Addr 0x50)",
+ "EBC (16 bits)",
+ "Reserved",
+ "NAND (2K page, 4 addr cycle)",
+ "I2C (Addr 0x50)",
+ "NAND (512 page, 3 addr cycle)",
+ "I2C (Addr 0x50)",
+ "SPI (slow)",
+ "I2C (Addr 0x50)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', \
+ 'I', 'x', 'K', 'L', 'M', 'N', 'O', 'P' };
+#endif
+
+#if defined(CONFIG_405EX)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "EBC (8 bits)",
+ "EBC (16 bits)",
+ "EBC (16 bits)",
+ "NAND (8 bits)",
+ "NAND (8 bits)",
+ "I2C (Addr 0x54)",
+ "EBC (8 bits)",
+ "I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'G', 'F', 'H' };
+#endif
+#if defined(CONFIG_APM821XX)
+#define SDR0_PINSTP_SHIFT 29
+static char *bootstrap_str[] = {
+ "RESERVED",
+ "RESERVED",
+ "RESERVED",
+ "NAND (8 bits)",
+ "NOR (8 bits)",
+ "NOR (8 bits) w/PLL Bypassed",
+ "I2C (Addr 0x54)",
+ "I2C (Addr 0x52)",
+};
+static char bootstrap_char[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
+#endif
+
+#if defined(SDR0_PINSTP_SHIFT)
+static int bootstrap_option(void)
+{
+ unsigned long val;
+
+ mfsdr(SDR0_PINSTP, val);
+ return ((val & 0xf0000000) >> SDR0_PINSTP_SHIFT);
+}
+#endif /* SDR0_PINSTP_SHIFT */
+
+
+#if defined(CONFIG_440GP)
+static int do_chip_reset (unsigned long sys0, unsigned long sys1)
+{
+ /* Changes to CPC0_SYS0 and CPC0_SYS1 require chip
+ * reset.
+ */
+ mtdcr (CPC0_CR0, mfdcr (CPC0_CR0) | 0x80000000); /* Set SWE */
+ mtdcr (CPC0_SYS0, sys0);
+ mtdcr (CPC0_SYS1, sys1);
+ mtdcr (CPC0_CR0, mfdcr (CPC0_CR0) & ~0x80000000); /* Clr SWE */
+ mtspr (SPRN_DBCR0, 0x20000000); /* Reset the chip */
+
+ return 1;
+}
+#endif /* CONFIG_440GP */
+
+
+int checkcpu (void)
+{
+#if !defined(CONFIG_405) /* not used on Xilinx 405 FPGA implementations */
+ uint pvr = get_pvr();
+ ulong clock = gd->cpu_clk;
+ char buf[32];
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 reg;
+#endif
+
+ char addstr[64] = "";
+ sys_info_t sys_info;
+ int cpu_num;
+
+ cpu_num = get_cpu_num();
+ if (cpu_num >= 0)
+ printf("CPU%d: ", cpu_num);
+ else
+ puts("CPU: ");
+
+ get_sys_info(&sys_info);
+
+#if defined(CONFIG_XILINX_440)
+ puts("IBM PowerPC ");
+#else
+ puts("AMCC PowerPC ");
+#endif
+
+ switch (pvr) {
+
+#if !defined(CONFIG_440)
+ case PVR_405GP_RB:
+ puts("405GP Rev. B");
+ break;
+
+ case PVR_405GP_RC:
+ puts("405GP Rev. C");
+ break;
+
+ case PVR_405GP_RD:
+ puts("405GP Rev. D");
+ break;
+
+#ifdef CONFIG_405GP
+ case PVR_405GP_RE: /* 405GP rev E and 405CR rev C have same PVR */
+ puts("405GP Rev. E");
+ break;
+#endif
+
+ case PVR_405CR_RA:
+ puts("405CR Rev. A");
+ break;
+
+ case PVR_405CR_RB:
+ puts("405CR Rev. B");
+ break;
+
+#ifdef CONFIG_405CR
+ case PVR_405CR_RC: /* 405GP rev E and 405CR rev C have same PVR */
+ puts("405CR Rev. C");
+ break;
+#endif
+
+ case PVR_405GPR_RB:
+ puts("405GPr Rev. B");
+ break;
+
+ case PVR_405EP_RB:
+ puts("405EP Rev. B");
+ break;
+
+ case PVR_405EZ_RA:
+ puts("405EZ Rev. A");
+ break;
+
+ case PVR_405EX1_RA:
+ puts("405EX Rev. A");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_405EXR2_RA:
+ puts("405EXr Rev. A");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_405EX1_RC:
+ puts("405EX Rev. C");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_405EX2_RC:
+ puts("405EX Rev. C");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_405EXR1_RC:
+ puts("405EXr Rev. C");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_405EXR2_RC:
+ puts("405EXr Rev. C");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_405EX1_RD:
+ puts("405EX Rev. D");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_405EX2_RD:
+ puts("405EX Rev. D");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_405EXR1_RD:
+ puts("405EXr Rev. D");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_405EXR2_RD:
+ puts("405EXr Rev. D");
+ strcpy(addstr, "No Security support");
+ break;
+
+#else /* CONFIG_440 */
+
+#if defined(CONFIG_440GP)
+ case PVR_440GP_RB:
+ puts("440GP Rev. B");
+ /* See errata 1.12: CHIP_4 */
+ if ((mfdcr(CPC0_SYS0) != mfdcr(CPC0_STRP0)) ||
+ (mfdcr(CPC0_SYS1) != mfdcr(CPC0_STRP1)) ){
+ puts ( "\n\t CPC0_SYSx DCRs corrupted. "
+ "Resetting chip ...\n");
+ udelay( 1000 * 1000 ); /* Give time for serial buf to clear */
+ do_chip_reset ( mfdcr(CPC0_STRP0),
+ mfdcr(CPC0_STRP1) );
+ }
+ break;
+
+ case PVR_440GP_RC:
+ puts("440GP Rev. C");
+ break;
+#endif /* CONFIG_440GP */
+
+ case PVR_440GX_RA:
+ puts("440GX Rev. A");
+ break;
+
+ case PVR_440GX_RB:
+ puts("440GX Rev. B");
+ break;
+
+ case PVR_440GX_RC:
+ puts("440GX Rev. C");
+ break;
+
+ case PVR_440GX_RF:
+ puts("440GX Rev. F");
+ break;
+
+ case PVR_440EP_RA:
+ puts("440EP Rev. A");
+ break;
+
+#ifdef CONFIG_440EP
+ case PVR_440EP_RB: /* 440EP rev B and 440GR rev A have same PVR */
+ puts("440EP Rev. B");
+ break;
+
+ case PVR_440EP_RC: /* 440EP rev C and 440GR rev B have same PVR */
+ puts("440EP Rev. C");
+ break;
+#endif /* CONFIG_440EP */
+
+#ifdef CONFIG_440GR
+ case PVR_440GR_RA: /* 440EP rev B and 440GR rev A have same PVR */
+ puts("440GR Rev. A");
+ break;
+
+ case PVR_440GR_RB: /* 440EP rev C and 440GR rev B have same PVR */
+ puts("440GR Rev. B");
+ break;
+#endif /* CONFIG_440GR */
+
+#ifdef CONFIG_440EPX
+ case PVR_440EPX1_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+ puts("440EPx Rev. A");
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+
+ case PVR_440EPX2_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+ puts("440EPx Rev. A");
+ strcpy(addstr, "No Security/Kasumi support");
+ break;
+#endif /* CONFIG_440EPX */
+
+#ifdef CONFIG_440GRX
+ case PVR_440GRX1_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+ puts("440GRx Rev. A");
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+
+ case PVR_440GRX2_RA: /* 440EPx rev A and 440GRx rev A have same PVR */
+ puts("440GRx Rev. A");
+ strcpy(addstr, "No Security/Kasumi support");
+ break;
+#endif /* CONFIG_440GRX */
+
+ case PVR_440SP_6_RAB:
+ puts("440SP Rev. A/B");
+ strcpy(addstr, "RAID 6 support");
+ break;
+
+ case PVR_440SP_RAB:
+ puts("440SP Rev. A/B");
+ strcpy(addstr, "No RAID 6 support");
+ break;
+
+ case PVR_440SP_6_RC:
+ puts("440SP Rev. C");
+ strcpy(addstr, "RAID 6 support");
+ break;
+
+ case PVR_440SP_RC:
+ puts("440SP Rev. C");
+ strcpy(addstr, "No RAID 6 support");
+ break;
+
+ case PVR_440SPe_6_RA:
+ puts("440SPe Rev. A");
+ strcpy(addstr, "RAID 6 support");
+ break;
+
+ case PVR_440SPe_RA:
+ puts("440SPe Rev. A");
+ strcpy(addstr, "No RAID 6 support");
+ break;
+
+ case PVR_440SPe_6_RB:
+ puts("440SPe Rev. B");
+ strcpy(addstr, "RAID 6 support");
+ break;
+
+ case PVR_440SPe_RB:
+ puts("440SPe Rev. B");
+ strcpy(addstr, "No RAID 6 support");
+ break;
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ case PVR_460EX_RA:
+ puts("460EX Rev. A");
+ strcpy(addstr, "No Security/Kasumi support");
+ break;
+
+ case PVR_460EX_SE_RA:
+ puts("460EX Rev. A");
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+
+ case PVR_460EX_RB:
+ puts("460EX Rev. B");
+ mfsdr(SDR0_ECID3, reg);
+ if (reg & 0x00100000)
+ strcpy(addstr, "No Security/Kasumi support");
+ else
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+
+ case PVR_460GT_RA:
+ puts("460GT Rev. A");
+ strcpy(addstr, "No Security/Kasumi support");
+ break;
+
+ case PVR_460GT_SE_RA:
+ puts("460GT Rev. A");
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+
+ case PVR_460GT_RB:
+ puts("460GT Rev. B");
+ mfsdr(SDR0_ECID3, reg);
+ if (reg & 0x00100000)
+ strcpy(addstr, "No Security/Kasumi support");
+ else
+ strcpy(addstr, "Security/Kasumi support");
+ break;
+#endif
+
+ case PVR_460SX_RA:
+ puts("460SX Rev. A");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_460SX_RA_V1:
+ puts("460SX Rev. A");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_460GX_RA:
+ puts("460GX Rev. A");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_460GX_RA_V1:
+ puts("460GX Rev. A");
+ strcpy(addstr, "No Security support");
+ break;
+
+ case PVR_APM821XX_RA:
+ puts("APM821XX Rev. A");
+ strcpy(addstr, "Security support");
+ break;
+
+ case PVR_VIRTEX5:
+ puts("440x5 VIRTEX5");
+ break;
+#endif /* CONFIG_440 */
+
+ default:
+ printf (" UNKNOWN (PVR=%08x)", pvr);
+ break;
+ }
+
+ printf (" at %s MHz (PLB=%lu OPB=%lu EBC=%lu",
+ strmhz(buf, clock),
+ sys_info.freqPLB / 1000000,
+ get_OPB_freq() / 1000000,
+ sys_info.freqEBC / 1000000);
+#if defined(CONFIG_PCI) && \
+ (defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRX))
+ printf(" PCI=%lu MHz", sys_info.freqPCI / 1000000);
+#endif
+ printf(")\n");
+
+ if (addstr[0] != 0)
+ printf(" %s\n", addstr);
+
+#if defined(I2C_BOOTROM)
+ printf (" I2C boot EEPROM %sabled\n", i2c_bootrom_enabled() ? "en" : "dis");
+#endif /* I2C_BOOTROM */
+#if defined(SDR0_PINSTP_SHIFT)
+ printf (" Bootstrap Option %c - ", bootstrap_char[bootstrap_option()]);
+ printf ("Boot ROM Location %s", bootstrap_str[bootstrap_option()]);
+#ifdef CONFIG_NAND_U_BOOT
+ puts(", booting from NAND");
+#endif /* CONFIG_NAND_U_BOOT */
+ putc('\n');
+#endif /* SDR0_PINSTP_SHIFT */
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_405EX)
+ printf (" Internal PCI arbiter %sabled", pci_arbiter_enabled() ? "en" : "dis");
+#endif
+
+#if defined(CONFIG_PCI) && defined(PCI_ASYNC)
+ if (pci_async_enabled()) {
+ printf (", PCI async ext clock used");
+ } else {
+ printf (", PCI sync clock at %lu MHz",
+ sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
+ }
+#endif
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_405EX)
+ putc('\n');
+#endif
+
+#if defined(CONFIG_405EP) || defined(CONFIG_405EZ) || defined(CONFIG_405EX)
+ printf (" 16 kB I-Cache 16 kB D-Cache");
+#elif defined(CONFIG_440)
+ printf (" 32 kB I-Cache 32 kB D-Cache");
+#else
+ printf (" 16 kB I-Cache %d kB D-Cache",
+ ((pvr | 0x00000001) == PVR_405GPR_RB) ? 16 : 8);
+#endif
+
+#endif /* !defined(CONFIG_405) */
+
+ putc ('\n');
+
+ return 0;
+}
+
+int ppc440spe_revB() {
+ unsigned int pvr;
+
+ pvr = get_pvr();
+ if ((pvr == PVR_440SPe_6_RB) || (pvr == PVR_440SPe_RB))
+ return 1;
+ else
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+#if defined(CONFIG_BOARD_RESET)
+ board_reset();
+#else
+#if defined(CONFIG_SYS_4xx_RESET_TYPE)
+ mtspr(SPRN_DBCR0, CONFIG_SYS_4xx_RESET_TYPE << 28);
+#else
+ /*
+ * Initiate system reset in debug control register DBCR
+ */
+ mtspr(SPRN_DBCR0, 0x30000000);
+#endif /* defined(CONFIG_SYS_4xx_RESET_TYPE) */
+#endif /* defined(CONFIG_BOARD_RESET) */
+
+ return 1;
+}
+
+
+/*
+ * Get timebase clock frequency
+ */
+unsigned long get_tbclk (void)
+{
+ sys_info_t sys_info;
+
+ get_sys_info(&sys_info);
+ return (sys_info.freqProcessor);
+}
+
+
+#if defined(CONFIG_WATCHDOG)
+void watchdog_reset(void)
+{
+ int re_enable = disable_interrupts();
+ reset_4xx_watchdog();
+ if (re_enable) enable_interrupts();
+}
+
+void reset_4xx_watchdog(void)
+{
+ /*
+ * Clear TSR(WIS) bit
+ */
+ mtspr(SPRN_TSR, 0x40000000);
+}
+#endif /* CONFIG_WATCHDOG */
+
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_PPC4xx_EMAC)
+ ppc_4xx_eth_initialize(bis);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c
new file mode 100644
index 0000000..970a8c1
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/cpu_init.c
@@ -0,0 +1,559 @@
+/*
+ * (C) Copyright 2000-2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/ppc4xx-emac.h>
+#include <asm/processor.h>
+#include <asm/ppc4xx-gpio.h>
+#include <asm/ppc4xx.h>
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+#ifndef CONFIG_SYS_PLL_RECONFIG
+#define CONFIG_SYS_PLL_RECONFIG 0
+#endif
+
+#if defined(CONFIG_440EPX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+static void reset_with_rli(void)
+{
+ u32 reg;
+
+ /*
+ * Set reload inhibit so configuration will persist across
+ * processor resets
+ */
+ mfcpr(CPR0_ICFG, reg);
+ reg |= CPR0_ICFG_RLI_MASK;
+ mtcpr(CPR0_ICFG, reg);
+
+ /* Reset processor if configuration changed */
+ __asm__ __volatile__ ("sync; isync");
+ mtspr(SPRN_DBCR0, 0x20000000);
+}
+#endif
+
+void reconfigure_pll(u32 new_cpu_freq)
+{
+#if defined(CONFIG_440EPX)
+ int reset_needed = 0;
+ u32 reg, temp;
+ u32 prbdv0, target_prbdv0, /* CLK_PRIMBD */
+ fwdva, target_fwdva, fwdvb, target_fwdvb, /* CLK_PLLD */
+ fbdv, target_fbdv, lfbdv, target_lfbdv,
+ perdv0, target_perdv0, /* CLK_PERD */
+ spcid0, target_spcid0; /* CLK_SPCID */
+
+ /* Reconfigure clocks if necessary.
+ * See PPC440EPx User's Manual, sections 8.2 and 14 */
+ if (new_cpu_freq == 667) {
+ target_prbdv0 = 2;
+ target_fwdva = 2;
+ target_fwdvb = 4;
+ target_fbdv = 20;
+ target_lfbdv = 1;
+ target_perdv0 = 4;
+ target_spcid0 = 4;
+
+ mfcpr(CPR0_PRIMBD0, reg);
+ temp = (reg & PRBDV_MASK) >> 24;
+ prbdv0 = temp ? temp : 8;
+ if (prbdv0 != target_prbdv0) {
+ reg &= ~PRBDV_MASK;
+ reg |= ((target_prbdv0 == 8 ? 0 : target_prbdv0) << 24);
+ mtcpr(CPR0_PRIMBD0, reg);
+ reset_needed = 1;
+ }
+
+ mfcpr(CPR0_PLLD, reg);
+
+ temp = (reg & PLLD_FWDVA_MASK) >> 16;
+ fwdva = temp ? temp : 16;
+
+ temp = (reg & PLLD_FWDVB_MASK) >> 8;
+ fwdvb = temp ? temp : 8;
+
+ temp = (reg & PLLD_FBDV_MASK) >> 24;
+ fbdv = temp ? temp : 32;
+
+ temp = (reg & PLLD_LFBDV_MASK);
+ lfbdv = temp ? temp : 64;
+
+ if (fwdva != target_fwdva || fbdv != target_fbdv || lfbdv != target_lfbdv) {
+ reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
+ PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
+ reg |= ((target_fwdva == 16 ? 0 : target_fwdva) << 16) |
+ ((target_fwdvb == 8 ? 0 : target_fwdvb) << 8) |
+ ((target_fbdv == 32 ? 0 : target_fbdv) << 24) |
+ (target_lfbdv == 64 ? 0 : target_lfbdv);
+ mtcpr(CPR0_PLLD, reg);
+ reset_needed = 1;
+ }
+
+ mfcpr(CPR0_PERD, reg);
+ perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24;
+ if (perdv0 != target_perdv0) {
+ reg &= ~CPR0_PERD_PERDV0_MASK;
+ reg |= (target_perdv0 << 24);
+ mtcpr(CPR0_PERD, reg);
+ reset_needed = 1;
+ }
+
+ mfcpr(CPR0_SPCID, reg);
+ temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24;
+ spcid0 = temp ? temp : 4;
+ if (spcid0 != target_spcid0) {
+ reg &= ~CPR0_SPCID_SPCIDV0_MASK;
+ reg |= ((target_spcid0 == 4 ? 0 : target_spcid0) << 24);
+ mtcpr(CPR0_SPCID, reg);
+ reset_needed = 1;
+ }
+ }
+
+ /* Get current value of FWDVA.*/
+ mfcpr(CPR0_PLLD, reg);
+ temp = (reg & PLLD_FWDVA_MASK) >> 16;
+
+ /*
+ * Check to see if FWDVA has been set to value of 1. if it has we must
+ * modify it.
+ */
+ if (temp == 1) {
+ /*
+ * Load register that contains current boot strapping option.
+ */
+ mfcpr(CPR0_ICFG, reg);
+ /*
+ * Strapping option bits (ICS) are already in correct position,
+ * only masking needed.
+ */
+ reg &= CPR0_ICFG_ICS_MASK;
+
+ if ((reg == BOOT_STRAP_OPTION_A) || (reg == BOOT_STRAP_OPTION_B) ||
+ (reg == BOOT_STRAP_OPTION_D) || (reg == BOOT_STRAP_OPTION_E)) {
+ mfcpr(CPR0_PLLD, reg);
+
+ /* Get current value of fbdv. */
+ temp = (reg & PLLD_FBDV_MASK) >> 24;
+ fbdv = temp ? temp : 32;
+
+ /* Get current value of lfbdv. */
+ temp = (reg & PLLD_LFBDV_MASK);
+ lfbdv = temp ? temp : 64;
+
+ /*
+ * Get current value of FWDVA. Assign current FWDVA to
+ * new FWDVB.
+ */
+ mfcpr(CPR0_PLLD, reg);
+ target_fwdvb = (reg & PLLD_FWDVA_MASK) >> 16;
+ fwdvb = target_fwdvb ? target_fwdvb : 8;
+
+ /*
+ * Get current value of FWDVB. Assign current FWDVB to
+ * new FWDVA.
+ */
+ target_fwdva = (reg & PLLD_FWDVB_MASK) >> 8;
+ fwdva = target_fwdva ? target_fwdva : 16;
+
+ /*
+ * Update CPR0_PLLD with switched FWDVA and FWDVB.
+ */
+ reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK |
+ PLLD_FBDV_MASK | PLLD_LFBDV_MASK);
+ reg |= ((fwdva == 16 ? 0 : fwdva) << 16) |
+ ((fwdvb == 8 ? 0 : fwdvb) << 8) |
+ ((fbdv == 32 ? 0 : fbdv) << 24) |
+ (lfbdv == 64 ? 0 : lfbdv);
+ mtcpr(CPR0_PLLD, reg);
+
+ /* Acknowledge that a reset is required. */
+ reset_needed = 1;
+ }
+ }
+
+ /* Now reset the CPU if needed */
+ if (reset_needed)
+ reset_with_rli();
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 reg;
+
+ /*
+ * See "9.2.1.1 Booting with Option E" in the 460EX/GT
+ * users manual
+ */
+ mfcpr(CPR0_PLLC, reg);
+ if ((reg & (CPR0_PLLC_RST | CPR0_PLLC_ENG)) == CPR0_PLLC_RST) {
+ /*
+ * Set engage bit
+ */
+ reg = (reg & ~CPR0_PLLC_RST) | CPR0_PLLC_ENG;
+ mtcpr(CPR0_PLLC, reg);
+
+ /* Now reset the CPU */
+ reset_with_rli();
+ }
+#endif
+}
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
+void
+chip_21_errata(void)
+{
+ /*
+ * See rev 1.09 of the 405EX/405EXr errata. CHIP_21 says that
+ * sometimes reading the PVR and/or SDR0_ECID results in incorrect
+ * values. Since the rev-D chip uses the SDR0_ECID bits to control
+ * internal features, that means the second PCIe or ethernet of an EX
+ * variant could fail to work. Also, security features of both EX and
+ * EXr might be incorrectly disabled.
+ *
+ * The suggested workaround is as follows (covering rev-C and rev-D):
+ *
+ * 1.Read the PVR and SDR0_ECID3.
+ *
+ * 2.If the PVR matches an expected Revision C PVR value AND if
+ * SDR0_ECID3[12:15] is different from PVR[28:31], then processor is
+ * Revision C: continue executing the initialization code (no reset
+ * required). else go to step 3.
+ *
+ * 3.If the PVR matches an expected Revision D PVR value AND if
+ * SDR0_ECID3[10:11] matches its expected value, then continue
+ * executing initialization code, no reset required. else write
+ * DBCR0[RST] = 0b11 to generate a SysReset.
+ */
+
+ u32 pvr;
+ u32 pvr_28_31;
+ u32 ecid3;
+ u32 ecid3_10_11;
+ u32 ecid3_12_15;
+
+ /* Step 1: */
+ pvr = get_pvr();
+ mfsdr(SDR0_ECID3, ecid3);
+
+ /* Step 2: */
+ pvr_28_31 = pvr & 0xf;
+ ecid3_10_11 = (ecid3 >> 20) & 0x3;
+ ecid3_12_15 = (ecid3 >> 16) & 0xf;
+ if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_C) &&
+ (pvr_28_31 != ecid3_12_15)) {
+ /* No reset required. */
+ return;
+ }
+
+ /* Step 3: */
+ if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_D) &&
+ (ecid3_10_11 == CONFIG_405EX_CHIP21_ECID3_REV_D)) {
+ /* No reset required. */
+ return;
+ }
+
+ /* Reset required. */
+ __asm__ __volatile__ ("sync; isync");
+ mtspr(SPRN_DBCR0, 0x30000000);
+}
+#endif
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Reconfigure PLL if necessary,
+ * set up the memory map,
+ * initialize a bunch of registers
+ */
+void
+cpu_init_f (void)
+{
+#if defined(CONFIG_WATCHDOG) || defined(CONFIG_440GX) || defined(CONFIG_460EX)
+ u32 val;
+#endif
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
+ chip_21_errata();
+#endif
+
+ reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
+
+#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && \
+ !defined(CONFIG_APM821XX) &&!defined(CONFIG_SYS_4xx_GPIO_TABLE)
+ /*
+ * GPIO0 setup (select GPIO or alternate function)
+ */
+#if defined(CONFIG_SYS_GPIO0_OR)
+ out32(GPIO0_OR, CONFIG_SYS_GPIO0_OR); /* set initial state of output pins */
+#endif
+#if defined(CONFIG_SYS_GPIO0_ODR)
+ out32(GPIO0_ODR, CONFIG_SYS_GPIO0_ODR); /* open-drain select */
+#endif
+ out32(GPIO0_OSRH, CONFIG_SYS_GPIO0_OSRH); /* output select */
+ out32(GPIO0_OSRL, CONFIG_SYS_GPIO0_OSRL);
+ out32(GPIO0_ISR1H, CONFIG_SYS_GPIO0_ISR1H); /* input select */
+ out32(GPIO0_ISR1L, CONFIG_SYS_GPIO0_ISR1L);
+ out32(GPIO0_TSRH, CONFIG_SYS_GPIO0_TSRH); /* three-state select */
+ out32(GPIO0_TSRL, CONFIG_SYS_GPIO0_TSRL);
+#if defined(CONFIG_SYS_GPIO0_ISR2H)
+ out32(GPIO0_ISR2H, CONFIG_SYS_GPIO0_ISR2H);
+ out32(GPIO0_ISR2L, CONFIG_SYS_GPIO0_ISR2L);
+#endif
+#if defined (CONFIG_SYS_GPIO0_TCR)
+ out32(GPIO0_TCR, CONFIG_SYS_GPIO0_TCR); /* enable output driver for outputs */
+#endif
+#endif /* CONFIG_405EP ... && !CONFIG_SYS_4xx_GPIO_TABLE */
+
+#if defined (CONFIG_405EP)
+ /*
+ * Set EMAC noise filter bits
+ */
+ mtdcr(CPC0_EPCTL, CPC0_EPCTL_E0NFE | CPC0_EPCTL_E1NFE);
+#endif /* CONFIG_405EP */
+
+#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
+ gpio_set_chip_configuration();
+#endif /* CONFIG_SYS_4xx_GPIO_TABLE */
+
+ /*
+ * External Bus Controller (EBC) Setup
+ */
+#if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))
+#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+ defined(CONFIG_405EX) || defined(CONFIG_405))
+ /*
+ * Move the next instructions into icache, since these modify the flash
+ * we are running from!
+ */
+ asm volatile(" bl 0f" ::: "lr");
+ asm volatile("0: mflr 3" ::: "r3");
+ asm volatile(" addi 4, 0, 14" ::: "r4");
+ asm volatile(" mtctr 4" ::: "ctr");
+ asm volatile("1: icbt 0, 3");
+ asm volatile(" addi 3, 3, 32" ::: "r3");
+ asm volatile(" bdnz 1b" ::: "ctr", "cr0");
+ asm volatile(" addis 3, 0, 0x0" ::: "r3");
+ asm volatile(" ori 3, 3, 0xA000" ::: "r3");
+ asm volatile(" mtctr 3" ::: "ctr");
+ asm volatile("2: bdnz 2b" ::: "ctr", "cr0");
+#endif
+
+ mtebc(PB0AP, CONFIG_SYS_EBC_PB0AP);
+ mtebc(PB0CR, CONFIG_SYS_EBC_PB0CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 1))
+ mtebc(PB1AP, CONFIG_SYS_EBC_PB1AP);
+ mtebc(PB1CR, CONFIG_SYS_EBC_PB1CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 2))
+ mtebc(PB2AP, CONFIG_SYS_EBC_PB2AP);
+ mtebc(PB2CR, CONFIG_SYS_EBC_PB2CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 3))
+ mtebc(PB3AP, CONFIG_SYS_EBC_PB3AP);
+ mtebc(PB3CR, CONFIG_SYS_EBC_PB3CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 4))
+ mtebc(PB4AP, CONFIG_SYS_EBC_PB4AP);
+ mtebc(PB4CR, CONFIG_SYS_EBC_PB4CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 5))
+ mtebc(PB5AP, CONFIG_SYS_EBC_PB5AP);
+ mtebc(PB5CR, CONFIG_SYS_EBC_PB5CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 6))
+ mtebc(PB6AP, CONFIG_SYS_EBC_PB6AP);
+ mtebc(PB6CR, CONFIG_SYS_EBC_PB6CR);
+#endif
+
+#if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR) && !(CONFIG_SYS_INIT_DCACHE_CS == 7))
+ mtebc(PB7AP, CONFIG_SYS_EBC_PB7AP);
+ mtebc(PB7CR, CONFIG_SYS_EBC_PB7CR);
+#endif
+
+#if defined (CONFIG_SYS_EBC_CFG)
+ mtebc(EBC0_CFG, CONFIG_SYS_EBC_CFG);
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+ val = mfspr(SPRN_TCR);
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+ val |= 0xb8000000; /* generate system reset after 1.34 seconds */
+#elif defined(CONFIG_440EPX)
+ val |= 0xb0000000; /* generate system reset after 1.34 seconds */
+#else
+ val |= 0xf0000000; /* generate system reset after 2.684 seconds */
+#endif
+#if defined(CONFIG_SYS_4xx_RESET_TYPE)
+ val &= ~0x30000000; /* clear WRC bits */
+ val |= CONFIG_SYS_4xx_RESET_TYPE << 28; /* set board specific WRC type */
+#endif
+ mtspr(SPRN_TCR, val);
+
+ val = mfspr(SPRN_TSR);
+ val |= 0x80000000; /* enable watchdog timer */
+ mtspr(SPRN_TSR, val);
+
+ reset_4xx_watchdog();
+#endif /* CONFIG_WATCHDOG */
+
+#if defined(CONFIG_440GX)
+ /* Take the GX out of compatibility mode
+ * Travis Sawyer, 9 Mar 2004
+ * NOTE: 440gx user manual inconsistency here
+ * Compatibility mode and Ethernet Clock select are not
+ * correct in the manual
+ */
+ mfsdr(SDR0_MFR, val);
+ val &= ~0x10000000;
+ mtsdr(SDR0_MFR,val);
+#endif /* CONFIG_440GX */
+
+#if defined(CONFIG_460EX)
+ /*
+ * Set SDR0_AHB_CFG[A2P_INCR4] (bit 24) and
+ * clear SDR0_AHB_CFG[A2P_PROT2] (bit 25) for a new 460EX errata
+ * regarding concurrent use of AHB USB OTG, USB 2.0 host and SATA
+ */
+ mfsdr(SDR0_AHB_CFG, val);
+ val |= 0x80;
+ val &= ~0x40;
+ mtsdr(SDR0_AHB_CFG, val);
+ mfsdr(SDR0_USB2HOST_CFG, val);
+ val &= ~0xf00;
+ val |= 0x400;
+ mtsdr(SDR0_USB2HOST_CFG, val);
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_405EX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
+ /*
+ * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read
+ */
+ mtdcr(PLB4A0_ACR, (mfdcr(PLB4A0_ACR) & ~PLB4Ax_ACR_RDP_MASK) |
+ PLB4Ax_ACR_RDP_4DEEP);
+ mtdcr(PLB4A1_ACR, (mfdcr(PLB4A1_ACR) & ~PLB4Ax_ACR_RDP_MASK) |
+ PLB4Ax_ACR_RDP_4DEEP);
+#endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+int cpu_init_r (void)
+{
+#if defined(CONFIG_405GP)
+ uint pvr = get_pvr();
+
+ /*
+ * Set edge conditioning circuitry on PPC405GPr
+ * for compatibility to existing PPC405GP designs.
+ */
+ if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
+ mtdcr(CPC0_ECR, 0x60606000);
+ }
+#endif /* defined(CONFIG_405GP) */
+
+ return 0;
+}
+
+#if defined(CONFIG_PCI) && \
+ (defined(CONFIG_440EP) || defined(CONFIG_440EPX) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRX))
+/*
+ * 440EP(x)/GR(x) PCI async/sync clocking restriction:
+ *
+ * In asynchronous PCI mode, the synchronous PCI clock must meet
+ * certain requirements. The following equation describes the
+ * relationship that must be maintained between the asynchronous PCI
+ * clock and synchronous PCI clock. Select an appropriate PCI:PLB
+ * ratio to maintain the relationship:
+ *
+ * AsyncPCIClk - 1MHz <= SyncPCIclock <= (2 * AsyncPCIClk) - 1MHz
+ */
+static int ppc4xx_pci_sync_clock_ok(u32 sync, u32 async)
+{
+ if (((async - 1000000) > sync) || (sync > ((2 * async) - 1000000)))
+ return 0;
+ else
+ return 1;
+}
+
+int ppc4xx_pci_sync_clock_config(u32 async)
+{
+ sys_info_t sys_info;
+ u32 sync;
+ int div;
+ u32 reg;
+ u32 spcid_val[] = {
+ CPR0_SPCID_SPCIDV0_DIV1, CPR0_SPCID_SPCIDV0_DIV2,
+ CPR0_SPCID_SPCIDV0_DIV3, CPR0_SPCID_SPCIDV0_DIV4 };
+
+ get_sys_info(&sys_info);
+ sync = sys_info.freqPCI;
+
+ /*
+ * First check if the equation above is met
+ */
+ if (!ppc4xx_pci_sync_clock_ok(sync, async)) {
+ /*
+ * Reconfigure PCI sync clock to meet the equation.
+ * Start with highest possible PCI sync frequency
+ * (divider 1).
+ */
+ for (div = 1; div <= 4; div++) {
+ sync = sys_info.freqPLB / div;
+ if (ppc4xx_pci_sync_clock_ok(sync, async))
+ break;
+ }
+
+ if (div <= 4) {
+ mtcpr(CPR0_SPCID, spcid_val[div]);
+
+ mfcpr(CPR0_ICFG, reg);
+ reg |= CPR0_ICFG_RLI_MASK;
+ mtcpr(CPR0_ICFG, reg);
+
+ /* do chip reset */
+ mtspr(SPRN_DBCR0, 0x20000000);
+ } else {
+ /* Impossible to configure the PCI sync clock */
+ return -1;
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/dcr.S b/arch/powerpc/cpu/ppc4xx/dcr.S
new file mode 100644
index 0000000..e668e05
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/dcr.S
@@ -0,0 +1,198 @@
+/*
+ * (C) Copyright 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <config.h>
+
+#if defined(CONFIG_4xx) && defined(CONFIG_CMD_SETGETDCR)
+
+#include <asm/ppc4xx.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#define _ASMLANGUAGE
+
+/*****************************************************************************
+ *
+ * XXX - DANGER
+ * These routines make use of self modifying code. DO NOT CALL THEM
+ * UNTIL THEY ARE RELOCATED TO RAM. Additionally, I do not
+ * recommend them for use in anything other than an interactive
+ * debugging environment. This is mainly due to performance reasons.
+ *
+ ****************************************************************************/
+
+/*
+ * static void _create_MFDCR(unsigned short dcrn)
+ *
+ * Builds a 'mfdcr' instruction for get_dcr
+ * function.
+ */
+ .section ".text"
+ .align 2
+ .type _create_MFDCR,@function
+_create_MFDCR:
+ /*
+ * Build up a 'mfdcr' instruction formatted as follows:
+ *
+ * OPCD | RT | DCRF | XO | CR |
+ * ---------------|--------------|--------------|----|
+ * 0 5 | 6 10 | 11 20 | 21 30 | 31 |
+ * | | DCRN | | |
+ * 31 | %r3 | (5..9|0..4) | 323 | 0 |
+ *
+ * Where:
+ * OPCD = opcode - 31
+ * RT = destination register - %r3 return register
+ * DCRF = DCRN # with upper and lower halves swapped
+ * XO = extended opcode - 323
+ * CR = CR[CR0] NOT undefined - 0
+ */
+ rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */
+ rlwinm r3, r3, 5, 22, 26
+ or r3, r3, r0
+ slwi r3, r3, 10
+ oris r3, r3, 0x3e30 /* RT = %r3 */
+ ori r3, r3, 323 /* XO = 323 */
+ slwi r3, r3, 1 /* CR = 0 */
+
+ mflr r4
+ stw r3, 0(r4) /* Store instr in get_dcr() */
+ dcbst r0, r4 /* Make sure val is written out */
+ sync /* Wait for write to complete */
+ icbi r0, r4 /* Make sure old instr is dumped */
+ isync /* Wait for icbi to complete */
+
+ blr
+.Lfe1: .size _create_MFDCR,.Lfe1-_create_MFDCR
+/* end _create_MFDCR() */
+
+/*
+ * static void _create_MTDCR(unsigned short dcrn, unsigned long value)
+ *
+ * Builds a 'mtdcr' instruction for set_dcr
+ * function.
+ */
+ .section ".text"
+ .align 2
+ .type _create_MTDCR,@function
+_create_MTDCR:
+ /*
+ * Build up a 'mtdcr' instruction formatted as follows:
+ *
+ * OPCD | RS | DCRF | XO | CR |
+ * ---------------|--------------|--------------|----|
+ * 0 5 | 6 10 | 11 20 | 21 30 | 31 |
+ * | | DCRN | | |
+ * 31 | %r3 | (5..9|0..4) | 451 | 0 |
+ *
+ * Where:
+ * OPCD = opcode - 31
+ * RS = source register - %r4
+ * DCRF = dest. DCRN # with upper and lower halves swapped
+ * XO = extended opcode - 451
+ * CR = CR[CR0] NOT undefined - 0
+ */
+ rlwinm r0, r3, 27, 27, 31 /* OPCD = 31 */
+ rlwinm r3, r3, 5, 22, 26
+ or r3, r3, r0
+ slwi r3, r3, 10
+ oris r3, r3, 0x3e40 /* RS = %r4 */
+ ori r3, r3, 451 /* XO = 451 */
+ slwi r3, r3, 1 /* CR = 0 */
+
+ mflr r5
+ stw r3, 0(r5) /* Store instr in set_dcr() */
+ dcbst r0, r5 /* Make sure val is written out */
+ sync /* Wait for write to complete */
+ icbi r0, r5 /* Make sure old instr is dumped */
+ isync /* Wait for icbi to complete */
+
+ blr
+.Lfe2: .size _create_MTDCR,.Lfe2-_create_MTDCR
+/* end _create_MTDCR() */
+
+
+/*
+ * unsigned long get_dcr(unsigned short dcrn)
+ *
+ * Return a given DCR's value.
+ */
+ /* */
+ /* XXX - This is self modifying code, hence */
+ /* it is in the data section. */
+ /* */
+ .section ".data"
+ .align 2
+ .globl get_dcr
+ .type get_dcr,@function
+get_dcr:
+ mflr r0 /* Get link register */
+ stwu r1, -32(r1) /* Save back chain and move SP */
+ stw r0, +36(r1) /* Save link register */
+
+ bl _create_MFDCR /* Build following instruction */
+ /* XXX - we build this instuction up on the fly. */
+ .long 0 /* Get DCR's value */
+
+ lwz r0, +36(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ addi r1, r1, +32 /* Remove frame from stack */
+ blr /* Return to calling function */
+.Lfe3: .size get_dcr,.Lfe3-get_dcr
+/* end get_dcr() */
+
+
+/*
+ * unsigned void set_dcr(unsigned short dcrn, unsigned long value)
+ *
+ * Return a given DCR's value.
+ */
+ /*
+ * XXX - This is self modifying code, hence
+ * it is in the data section.
+ */
+ .section ".data"
+ .align 2
+ .globl set_dcr
+ .type set_dcr,@function
+set_dcr:
+ mflr r0 /* Get link register */
+ stwu r1, -32(r1) /* Save back chain and move SP */
+ stw r0, +36(r1) /* Save link register */
+
+ bl _create_MTDCR /* Build following instruction */
+ /* XXX - we build this instuction up on the fly. */
+ .long 0 /* Set DCR's value */
+
+ lwz r0, +36(r1) /* Get saved link register */
+ mtlr r0 /* Restore link register */
+ addi r1, r1, +32 /* Remove frame from stack */
+ blr /* Return to calling function */
+.Lfe4: .size set_dcr,.Lfe4-set_dcr
+/* end set_dcr() */
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/denali_data_eye.c b/arch/powerpc/cpu/ppc4xx/denali_data_eye.c
new file mode 100644
index 0000000..19b65be
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/denali_data_eye.c
@@ -0,0 +1,389 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/denali_data_eye.c
+ * Extracted from board/amcc/sequoia/sdram.c by Larry Johnson <lrj@acm.org>.
+ *
+ * (C) Copyright 2006
+ * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com
+ * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com
+ * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com
+ * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com
+ * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com
+ *
+ * (C) Copyright 2006-2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/ppc4xx.h>
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+/*-----------------------------------------------------------------------------+
+ * denali_wait_for_dlllock.
+ +----------------------------------------------------------------------------*/
+int denali_wait_for_dlllock(void)
+{
+ u32 val;
+ int wait;
+
+ /* -----------------------------------------------------------+
+ * Wait for the DCC master delay line to finish calibration
+ * ----------------------------------------------------------*/
+ for (wait = 0; wait != 0xffff; ++wait) {
+ mfsdram(DDR0_17, val);
+ if (DDR0_17_DLLLOCKREG_DECODE(val)) {
+ /* dlllockreg bit on */
+ return 0;
+ }
+ }
+ debug("0x%04x: DDR0_17 Value (dlllockreg bit): 0x%08x\n", wait, val);
+ debug("Waiting for dlllockreg bit to raise\n");
+ return -1;
+}
+
+#if defined(CONFIG_DDR_DATA_EYE)
+#define DDR_DCR_BASE 0x10
+#define ddrcfga (DDR_DCR_BASE+0x0) /* DDR configuration address reg */
+#define ddrcfgd (DDR_DCR_BASE+0x1) /* DDR configuration data reg */
+
+/*-----------------------------------------------------------------------------+
+ * wait_for_dram_init_complete.
+ +----------------------------------------------------------------------------*/
+static int wait_for_dram_init_complete(void)
+{
+ unsigned long val;
+ int wait = 0;
+
+ /* --------------------------------------------------------------+
+ * Wait for 'DRAM initialization complete' bit in status register
+ * -------------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_00);
+
+ while (wait != 0xffff) {
+ val = mfdcr(ddrcfgd);
+ if ((val & DDR0_00_INT_STATUS_BIT6) == DDR0_00_INT_STATUS_BIT6)
+ /* 'DRAM initialization complete' bit */
+ return 0;
+ else
+ wait++;
+ }
+ debug("DRAM initialization complete bit in status register did not "
+ "rise\n");
+ return -1;
+}
+
+#define NUM_TRIES 64
+#define NUM_READS 10
+
+/*-----------------------------------------------------------------------------+
+ * denali_core_search_data_eye.
+ +----------------------------------------------------------------------------*/
+void denali_core_search_data_eye(void)
+{
+ int k, j;
+ u32 val;
+ u32 wr_dqs_shift, dqs_out_shift, dll_dqs_delay_X;
+ u32 max_passing_cases = 0, wr_dqs_shift_with_max_passing_cases = 0;
+ u32 passing_cases = 0, dll_dqs_delay_X_sw_val = 0;
+ u32 dll_dqs_delay_X_start_window = 0, dll_dqs_delay_X_end_window = 0;
+ volatile u32 *ram_pointer;
+ u32 test[NUM_TRIES] = {
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55
+ };
+
+ ram_pointer = (volatile u32 *)(CONFIG_SYS_SDRAM_BASE);
+
+ for (wr_dqs_shift = 64; wr_dqs_shift < 96; wr_dqs_shift++) {
+ /* for (wr_dqs_shift=1; wr_dqs_shift<96; wr_dqs_shift++) { */
+
+ /* -----------------------------------------------------------+
+ * De-assert 'start' parameter.
+ * ----------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_02);
+ val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
+ DDR0_02_START_OFF;
+ mtdcr(ddrcfgd, val);
+
+ /* -----------------------------------------------------------+
+ * Set 'wr_dqs_shift'
+ * ----------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_09);
+ val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK) |
+ DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
+ mtdcr(ddrcfgd, val);
+
+ /* -----------------------------------------------------------+
+ * Set 'dqs_out_shift' = wr_dqs_shift + 32
+ * ----------------------------------------------------------*/
+ dqs_out_shift = wr_dqs_shift + 32;
+ mtdcr(ddrcfga, DDR0_22);
+ val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK) |
+ DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
+ mtdcr(ddrcfgd, val);
+
+ passing_cases = 0;
+
+ for (dll_dqs_delay_X = 1; dll_dqs_delay_X < 64;
+ dll_dqs_delay_X++) {
+ /* for (dll_dqs_delay_X=1; dll_dqs_delay_X<128;
+ dll_dqs_delay_X++) { */
+ /* -----------------------------------------------------------+
+ * Set 'dll_dqs_delay_X'.
+ * ----------------------------------------------------------*/
+ /* dll_dqs_delay_0 */
+ mtdcr(ddrcfga, DDR0_17);
+ val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
+ | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
+ mtdcr(ddrcfgd, val);
+ /* dll_dqs_delay_1 to dll_dqs_delay_4 */
+ mtdcr(ddrcfga, DDR0_18);
+ val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
+ | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
+ | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
+ | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
+ | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
+ mtdcr(ddrcfgd, val);
+ /* dll_dqs_delay_5 to dll_dqs_delay_8 */
+ mtdcr(ddrcfga, DDR0_19);
+ val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
+ | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
+ | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
+ | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
+ | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
+ mtdcr(ddrcfgd, val);
+ /* clear any ECC errors */
+ mtdcr(ddrcfga, DDR0_00);
+ mtdcr(ddrcfgd,
+ mfdcr(ddrcfgd) | DDR0_00_INT_ACK_ENCODE(0x3C));
+
+ sync();
+ eieio();
+
+ /* -----------------------------------------------------------+
+ * Assert 'start' parameter.
+ * ----------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_02);
+ val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
+ DDR0_02_START_ON;
+ mtdcr(ddrcfgd, val);
+
+ sync();
+ eieio();
+
+ /* -----------------------------------------------------------+
+ * Wait for the DCC master delay line to finish calibration
+ * ----------------------------------------------------------*/
+ if (denali_wait_for_dlllock() != 0) {
+ printf("dll lock did not occur !!!\n");
+ printf("denali_core_search_data_eye!!!\n");
+ printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
+ "%d\n", wr_dqs_shift, dll_dqs_delay_X);
+ hang();
+ }
+ sync();
+ eieio();
+
+ if (wait_for_dram_init_complete() != 0) {
+ printf("dram init complete did not occur!!!\n");
+ printf("denali_core_search_data_eye!!!\n");
+ printf("wr_dqs_shift = %d - dll_dqs_delay_X = "
+ "%d\n", wr_dqs_shift, dll_dqs_delay_X);
+ hang();
+ }
+ udelay(100); /* wait 100us to ensure init is really completed !!! */
+
+ /* write values */
+ for (j = 0; j < NUM_TRIES; j++) {
+ ram_pointer[j] = test[j];
+
+ /* clear any cache at ram location */
+ __asm__("dcbf 0,%0": :"r"(&ram_pointer[j]));
+ }
+
+ /* read values back */
+ for (j = 0; j < NUM_TRIES; j++) {
+ for (k = 0; k < NUM_READS; k++) {
+ /* clear any cache at ram location */
+ __asm__("dcbf 0,%0": :"r"(&ram_pointer
+ [j]));
+
+ if (ram_pointer[j] != test[j])
+ break;
+ }
+
+ /* read error */
+ if (k != NUM_READS)
+ break;
+ }
+
+ /* See if the dll_dqs_delay_X value passed. */
+ mtdcr(ddrcfga, DDR0_00);
+ if (j < NUM_TRIES
+ || (DDR0_00_INT_STATUS_DECODE(mfdcr(ddrcfgd)) &
+ 0x3F)) {
+ /* Failed */
+ passing_cases = 0;
+ /* break; */
+ } else {
+ /* Passed */
+ if (passing_cases == 0)
+ dll_dqs_delay_X_sw_val =
+ dll_dqs_delay_X;
+ passing_cases++;
+ if (passing_cases >= max_passing_cases) {
+ max_passing_cases = passing_cases;
+ wr_dqs_shift_with_max_passing_cases =
+ wr_dqs_shift;
+ dll_dqs_delay_X_start_window =
+ dll_dqs_delay_X_sw_val;
+ dll_dqs_delay_X_end_window =
+ dll_dqs_delay_X;
+ }
+ }
+
+ /* -----------------------------------------------------------+
+ * De-assert 'start' parameter.
+ * ----------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_02);
+ val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) |
+ DDR0_02_START_OFF;
+ mtdcr(ddrcfgd, val);
+ } /* for (dll_dqs_delay_X=0; dll_dqs_delay_X<128; dll_dqs_delay_X++) */
+ } /* for (wr_dqs_shift=0; wr_dqs_shift<96; wr_dqs_shift++) */
+
+ /* -----------------------------------------------------------+
+ * Largest passing window is now detected.
+ * ----------------------------------------------------------*/
+
+ /* Compute dll_dqs_delay_X value */
+ dll_dqs_delay_X = (dll_dqs_delay_X_end_window +
+ dll_dqs_delay_X_start_window) / 2;
+ wr_dqs_shift = wr_dqs_shift_with_max_passing_cases;
+
+ debug("DQS calibration - Window detected:\n");
+ debug("max_passing_cases = %d\n", max_passing_cases);
+ debug("wr_dqs_shift = %d\n", wr_dqs_shift);
+ debug("dll_dqs_delay_X = %d\n", dll_dqs_delay_X);
+ debug("dll_dqs_delay_X window = %d - %d\n",
+ dll_dqs_delay_X_start_window, dll_dqs_delay_X_end_window);
+
+ /* -----------------------------------------------------------+
+ * De-assert 'start' parameter.
+ * ----------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_02);
+ val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_OFF;
+ mtdcr(ddrcfgd, val);
+
+ /* -----------------------------------------------------------+
+ * Set 'wr_dqs_shift'
+ * ----------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_09);
+ val = (mfdcr(ddrcfgd) & ~DDR0_09_WR_DQS_SHIFT_MASK)
+ | DDR0_09_WR_DQS_SHIFT_ENCODE(wr_dqs_shift);
+ mtdcr(ddrcfgd, val);
+ debug("DDR0_09=0x%08x\n", val);
+
+ /* -----------------------------------------------------------+
+ * Set 'dqs_out_shift' = wr_dqs_shift + 32
+ * ----------------------------------------------------------*/
+ dqs_out_shift = wr_dqs_shift + 32;
+ mtdcr(ddrcfga, DDR0_22);
+ val = (mfdcr(ddrcfgd) & ~DDR0_22_DQS_OUT_SHIFT_MASK)
+ | DDR0_22_DQS_OUT_SHIFT_ENCODE(dqs_out_shift);
+ mtdcr(ddrcfgd, val);
+ debug("DDR0_22=0x%08x\n", val);
+
+ /* -----------------------------------------------------------+
+ * Set 'dll_dqs_delay_X'.
+ * ----------------------------------------------------------*/
+ /* dll_dqs_delay_0 */
+ mtdcr(ddrcfga, DDR0_17);
+ val = (mfdcr(ddrcfgd) & ~DDR0_17_DLL_DQS_DELAY_0_MASK)
+ | DDR0_17_DLL_DQS_DELAY_0_ENCODE(dll_dqs_delay_X);
+ mtdcr(ddrcfgd, val);
+ debug("DDR0_17=0x%08x\n", val);
+
+ /* dll_dqs_delay_1 to dll_dqs_delay_4 */
+ mtdcr(ddrcfga, DDR0_18);
+ val = (mfdcr(ddrcfgd) & ~DDR0_18_DLL_DQS_DELAY_X_MASK)
+ | DDR0_18_DLL_DQS_DELAY_4_ENCODE(dll_dqs_delay_X)
+ | DDR0_18_DLL_DQS_DELAY_3_ENCODE(dll_dqs_delay_X)
+ | DDR0_18_DLL_DQS_DELAY_2_ENCODE(dll_dqs_delay_X)
+ | DDR0_18_DLL_DQS_DELAY_1_ENCODE(dll_dqs_delay_X);
+ mtdcr(ddrcfgd, val);
+ debug("DDR0_18=0x%08x\n", val);
+
+ /* dll_dqs_delay_5 to dll_dqs_delay_8 */
+ mtdcr(ddrcfga, DDR0_19);
+ val = (mfdcr(ddrcfgd) & ~DDR0_19_DLL_DQS_DELAY_X_MASK)
+ | DDR0_19_DLL_DQS_DELAY_8_ENCODE(dll_dqs_delay_X)
+ | DDR0_19_DLL_DQS_DELAY_7_ENCODE(dll_dqs_delay_X)
+ | DDR0_19_DLL_DQS_DELAY_6_ENCODE(dll_dqs_delay_X)
+ | DDR0_19_DLL_DQS_DELAY_5_ENCODE(dll_dqs_delay_X);
+ mtdcr(ddrcfgd, val);
+ debug("DDR0_19=0x%08x\n", val);
+
+ /* -----------------------------------------------------------+
+ * Assert 'start' parameter.
+ * ----------------------------------------------------------*/
+ mtdcr(ddrcfga, DDR0_02);
+ val = (mfdcr(ddrcfgd) & ~DDR0_02_START_MASK) | DDR0_02_START_ON;
+ mtdcr(ddrcfgd, val);
+
+ sync();
+ eieio();
+
+ /* -----------------------------------------------------------+
+ * Wait for the DCC master delay line to finish calibration
+ * ----------------------------------------------------------*/
+ if (denali_wait_for_dlllock() != 0) {
+ printf("dll lock did not occur !!!\n");
+ hang();
+ }
+ sync();
+ eieio();
+
+ if (wait_for_dram_init_complete() != 0) {
+ printf("dram init complete did not occur !!!\n");
+ hang();
+ }
+ udelay(100); /* wait 100us to ensure init is really completed !!! */
+}
+#endif /* defined(CONFIG_DDR_DATA_EYE) */
+#endif /* defined(CONFIG_440EPX) || defined(CONFIG_440GRX) */
diff --git a/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c b/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c
new file mode 100644
index 0000000..3ceab32
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c
@@ -0,0 +1,1249 @@
+/*
+ * arch/powerpc/cpu/ppc4xx/denali_spd_ddr2.c
+ * This SPD SDRAM detection code supports AMCC PPC44x CPUs with a Denali-core
+ * DDR2 controller, specifically the 440EPx/GRx.
+ *
+ * (C) Copyright 2007-2008
+ * Larry Johnson, lrj@acm.org.
+ *
+ * Based primarily on arch/powerpc/cpu/ppc4xx/4xx_spd_ddr2.c, which is...
+ *
+ * (C) Copyright 2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * COPYRIGHT AMCC CORPORATION 2004
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <command.h>
+#include <asm/ppc4xx.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+
+#if defined(CONFIG_SPD_EEPROM) && \
+ (defined(CONFIG_440EPX) || defined(CONFIG_440GRX))
+
+/*-----------------------------------------------------------------------------+
+ * Defines
+ *-----------------------------------------------------------------------------*/
+#define MAXDIMMS 2
+#define MAXRANKS 2
+
+#define ONE_BILLION 1000000000
+
+#define MULDIV64(m1, m2, d) (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
+
+#define DLL_DQS_DELAY 0x19
+#define DLL_DQS_BYPASS 0x0B
+#define DQS_OUT_SHIFT 0x7F
+
+/*
+ * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory
+ * region. Right now the cache should still be disabled in U-Boot because of the
+ * EMAC driver, that need it's buffer descriptor to be located in non cached
+ * memory.
+ *
+ * If at some time this restriction doesn't apply anymore, just define
+ * CONFIG_4xx_DCACHE in the board config file and this code should setup
+ * everything correctly.
+ */
+#if defined(CONFIG_4xx_DCACHE)
+#define MY_TLB_WORD2_I_ENABLE 0 /* enable caching on SDRAM */
+#else
+#define MY_TLB_WORD2_I_ENABLE TLB_WORD2_I_ENABLE /* disable caching on SDRAM */
+#endif
+
+/*-----------------------------------------------------------------------------+
+ * Prototypes
+ *-----------------------------------------------------------------------------*/
+extern int denali_wait_for_dlllock(void);
+extern void denali_core_search_data_eye(void);
+extern void dcbz_area(u32 start_address, u32 num_bytes);
+
+/*
+ * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
+ */
+void __spd_ddr_init_hang(void)
+{
+ hang();
+}
+void spd_ddr_init_hang(void)
+ __attribute__ ((weak, alias("__spd_ddr_init_hang")));
+
+#if defined(DEBUG)
+static void print_mcsr(void)
+{
+ printf("MCSR = 0x%08X\n", mfspr(SPRN_MCSR));
+}
+
+static void denali_sdram_register_dump(void)
+{
+ unsigned int sdram_data;
+
+ printf("\n Register Dump:\n");
+ mfsdram(DDR0_00, sdram_data);
+ printf(" DDR0_00 = 0x%08X", sdram_data);
+ mfsdram(DDR0_01, sdram_data);
+ printf(" DDR0_01 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_02, sdram_data);
+ printf(" DDR0_02 = 0x%08X", sdram_data);
+ mfsdram(DDR0_03, sdram_data);
+ printf(" DDR0_03 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_04, sdram_data);
+ printf(" DDR0_04 = 0x%08X", sdram_data);
+ mfsdram(DDR0_05, sdram_data);
+ printf(" DDR0_05 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_06, sdram_data);
+ printf(" DDR0_06 = 0x%08X", sdram_data);
+ mfsdram(DDR0_07, sdram_data);
+ printf(" DDR0_07 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_08, sdram_data);
+ printf(" DDR0_08 = 0x%08X", sdram_data);
+ mfsdram(DDR0_09, sdram_data);
+ printf(" DDR0_09 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_10, sdram_data);
+ printf(" DDR0_10 = 0x%08X", sdram_data);
+ mfsdram(DDR0_11, sdram_data);
+ printf(" DDR0_11 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_12, sdram_data);
+ printf(" DDR0_12 = 0x%08X", sdram_data);
+ mfsdram(DDR0_14, sdram_data);
+ printf(" DDR0_14 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_17, sdram_data);
+ printf(" DDR0_17 = 0x%08X", sdram_data);
+ mfsdram(DDR0_18, sdram_data);
+ printf(" DDR0_18 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_19, sdram_data);
+ printf(" DDR0_19 = 0x%08X", sdram_data);
+ mfsdram(DDR0_20, sdram_data);
+ printf(" DDR0_20 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_21, sdram_data);
+ printf(" DDR0_21 = 0x%08X", sdram_data);
+ mfsdram(DDR0_22, sdram_data);
+ printf(" DDR0_22 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_23, sdram_data);
+ printf(" DDR0_23 = 0x%08X", sdram_data);
+ mfsdram(DDR0_24, sdram_data);
+ printf(" DDR0_24 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_25, sdram_data);
+ printf(" DDR0_25 = 0x%08X", sdram_data);
+ mfsdram(DDR0_26, sdram_data);
+ printf(" DDR0_26 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_27, sdram_data);
+ printf(" DDR0_27 = 0x%08X", sdram_data);
+ mfsdram(DDR0_28, sdram_data);
+ printf(" DDR0_28 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_31, sdram_data);
+ printf(" DDR0_31 = 0x%08X", sdram_data);
+ mfsdram(DDR0_32, sdram_data);
+ printf(" DDR0_32 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_33, sdram_data);
+ printf(" DDR0_33 = 0x%08X", sdram_data);
+ mfsdram(DDR0_34, sdram_data);
+ printf(" DDR0_34 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_35, sdram_data);
+ printf(" DDR0_35 = 0x%08X", sdram_data);
+ mfsdram(DDR0_36, sdram_data);
+ printf(" DDR0_36 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_37, sdram_data);
+ printf(" DDR0_37 = 0x%08X", sdram_data);
+ mfsdram(DDR0_38, sdram_data);
+ printf(" DDR0_38 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_39, sdram_data);
+ printf(" DDR0_39 = 0x%08X", sdram_data);
+ mfsdram(DDR0_40, sdram_data);
+ printf(" DDR0_40 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_41, sdram_data);
+ printf(" DDR0_41 = 0x%08X", sdram_data);
+ mfsdram(DDR0_42, sdram_data);
+ printf(" DDR0_42 = 0x%08X\n", sdram_data);
+ mfsdram(DDR0_43, sdram_data);
+ printf(" DDR0_43 = 0x%08X", sdram_data);
+ mfsdram(DDR0_44, sdram_data);
+ printf(" DDR0_44 = 0x%08X\n", sdram_data);
+}
+#else
+static inline void denali_sdram_register_dump(void)
+{
+}
+
+inline static void print_mcsr(void)
+{
+}
+#endif /* defined(DEBUG) */
+
+static int is_ecc_enabled(void)
+{
+ u32 val;
+
+ mfsdram(DDR0_22, val);
+ return 0x3 == DDR0_22_CTRL_RAW_DECODE(val);
+}
+
+static unsigned char spd_read(u8 chip, unsigned int addr)
+{
+ u8 data[2];
+
+ if (0 != i2c_probe(chip) || 0 != i2c_read(chip, addr, 1, data, 1)) {
+ debug("spd_read(0x%02X, 0x%02X) failed\n", chip, addr);
+ return 0;
+ }
+ debug("spd_read(0x%02X, 0x%02X) returned 0x%02X\n",
+ chip, addr, data[0]);
+ return data[0];
+}
+
+static unsigned long get_tcyc(unsigned char reg)
+{
+ /*
+ * Byte 9, et al: Cycle time for CAS Latency=X, is split into two
+ * nibbles: the higher order nibble (bits 4-7) designates the cycle time
+ * to a granularity of 1ns; the value presented by the lower order
+ * nibble (bits 0-3) has a granularity of .1ns and is added to the value
+ * designated by the higher nibble. In addition, four lines of the lower
+ * order nibble are assigned to support +.25, +.33, +.66, and +.75.
+ */
+
+ unsigned char subfield_b = reg & 0x0F;
+
+ switch (subfield_b & 0x0F) {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ return 1000 * (reg >> 4) + 100 * subfield_b;
+ case 0xA:
+ return 1000 * (reg >> 4) + 250;
+ case 0xB:
+ return 1000 * (reg >> 4) + 333;
+ case 0xC:
+ return 1000 * (reg >> 4) + 667;
+ case 0xD:
+ return 1000 * (reg >> 4) + 750;
+ }
+ return 0;
+}
+
+/*------------------------------------------------------------------
+ * Find the installed DIMMs, make sure that the are DDR2, and fill
+ * in the dimm_ranks array. Then dimm_ranks[dimm_num] > 0 iff the
+ * DIMM and dimm_num is present.
+ * Note: Because there are only two chip-select lines, it is assumed
+ * that a board with a single socket can support two ranks on that
+ * socket, while a board with two sockets can support only one rank
+ * on each socket.
+ *-----------------------------------------------------------------*/
+static void get_spd_info(unsigned long dimm_ranks[],
+ unsigned long *ranks,
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long dimm_found = false;
+ unsigned long const max_ranks_per_dimm = (1 == num_dimm_banks) ? 2 : 1;
+ unsigned char num_of_bytes;
+ unsigned char total_size;
+
+ *ranks = 0;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ num_of_bytes = 0;
+ total_size = 0;
+
+ num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0);
+ total_size = spd_read(iic0_dimm_addr[dimm_num], 1);
+ if ((num_of_bytes != 0) && (total_size != 0)) {
+ unsigned char const dimm_type =
+ spd_read(iic0_dimm_addr[dimm_num], 2);
+
+ unsigned long ranks_on_dimm =
+ (spd_read(iic0_dimm_addr[dimm_num], 5) & 0x07) + 1;
+
+ if (8 != dimm_type) {
+ switch (dimm_type) {
+ case 1:
+ printf("ERROR: Standard Fast Page Mode "
+ "DRAM DIMM");
+ break;
+ case 2:
+ printf("ERROR: EDO DIMM");
+ break;
+ case 3:
+ printf("ERROR: Pipelined Nibble DIMM");
+ break;
+ case 4:
+ printf("ERROR: SDRAM DIMM");
+ break;
+ case 5:
+ printf("ERROR: Multiplexed ROM DIMM");
+ break;
+ case 6:
+ printf("ERROR: SGRAM DIMM");
+ break;
+ case 7:
+ printf("ERROR: DDR1 DIMM");
+ break;
+ default:
+ printf("ERROR: Unknown DIMM (type %d)",
+ (unsigned int)dimm_type);
+ break;
+ }
+ printf(" detected in slot %lu.\n", dimm_num);
+ printf("Only DDR2 SDRAM DIMMs are supported."
+ "\n");
+ printf("Replace the module with a DDR2 DIMM."
+ "\n\n");
+ spd_ddr_init_hang();
+ }
+ dimm_found = true;
+ debug("DIMM slot %lu: populated with %lu-rank DDR2 DIMM"
+ "\n", dimm_num, ranks_on_dimm);
+ if (ranks_on_dimm > max_ranks_per_dimm) {
+ printf("WARNING: DRAM DIMM in slot %lu has %lu "
+ "ranks.\n", dimm_num, ranks_on_dimm);
+ if (1 == max_ranks_per_dimm) {
+ printf("Only one rank will be used.\n");
+ } else {
+ printf
+ ("Only two ranks will be used.\n");
+ }
+ ranks_on_dimm = max_ranks_per_dimm;
+ }
+ dimm_ranks[dimm_num] = ranks_on_dimm;
+ *ranks += ranks_on_dimm;
+ } else {
+ dimm_ranks[dimm_num] = 0;
+ debug("DIMM slot %lu: Not populated\n", dimm_num);
+ }
+ }
+ if (dimm_found == false) {
+ printf("ERROR: No memory installed.\n");
+ printf("Install at least one DDR2 DIMM.\n\n");
+ spd_ddr_init_hang();
+ }
+ debug("Total number of ranks = %ld\n", *ranks);
+}
+
+/*------------------------------------------------------------------
+ * For the memory DIMMs installed, this routine verifies that
+ * frequency previously calculated is supported.
+ *-----------------------------------------------------------------*/
+static void check_frequency(unsigned long *dimm_ranks,
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long sdram_freq)
+{
+ unsigned long dimm_num;
+ unsigned long cycle_time;
+ unsigned long calc_cycle_time;
+
+ /*
+ * calc_cycle_time is calculated from DDR frequency set by board/chip
+ * and is expressed in picoseconds to match the way DIMM cycle time is
+ * calculated below.
+ */
+ calc_cycle_time = MULDIV64(ONE_BILLION, 1000, sdram_freq);
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_ranks[dimm_num]) {
+ cycle_time =
+ get_tcyc(spd_read(iic0_dimm_addr[dimm_num], 9));
+ debug("cycle_time=%ld ps\n", cycle_time);
+
+ if (cycle_time > (calc_cycle_time + 10)) {
+ /*
+ * the provided sdram cycle_time is too small
+ * for the available DIMM cycle_time. The
+ * additionnal 10ps is here to accept a small
+ * incertainty.
+ */
+ printf
+ ("ERROR: DRAM DIMM detected with cycle_time %d ps in "
+ "slot %d \n while calculated cycle time is %d ps.\n",
+ (unsigned int)cycle_time,
+ (unsigned int)dimm_num,
+ (unsigned int)calc_cycle_time);
+ printf
+ ("Replace the DIMM, or change DDR frequency via "
+ "strapping bits.\n\n");
+ spd_ddr_init_hang();
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------
+ * This routine gets size information for the installed memory
+ * DIMMs.
+ *-----------------------------------------------------------------*/
+static void get_dimm_size(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long *const rows,
+ unsigned long *const banks,
+ unsigned long *const cols, unsigned long *const width)
+{
+ unsigned long dimm_num;
+
+ *rows = 0;
+ *banks = 0;
+ *cols = 0;
+ *width = 0;
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_ranks[dimm_num]) {
+ unsigned long t;
+
+ /* Rows */
+ t = spd_read(iic0_dimm_addr[dimm_num], 3);
+ if (0 == *rows) {
+ *rows = t;
+ } else if (t != *rows) {
+ printf("ERROR: DRAM DIMM modules do not all "
+ "have the same number of rows.\n\n");
+ spd_ddr_init_hang();
+ }
+ /* Banks */
+ t = spd_read(iic0_dimm_addr[dimm_num], 17);
+ if (0 == *banks) {
+ *banks = t;
+ } else if (t != *banks) {
+ printf("ERROR: DRAM DIMM modules do not all "
+ "have the same number of banks.\n\n");
+ spd_ddr_init_hang();
+ }
+ /* Columns */
+ t = spd_read(iic0_dimm_addr[dimm_num], 4);
+ if (0 == *cols) {
+ *cols = t;
+ } else if (t != *cols) {
+ printf("ERROR: DRAM DIMM modules do not all "
+ "have the same number of columns.\n\n");
+ spd_ddr_init_hang();
+ }
+ /* Data width */
+ t = spd_read(iic0_dimm_addr[dimm_num], 6);
+ if (0 == *width) {
+ *width = t;
+ } else if (t != *width) {
+ printf("ERROR: DRAM DIMM modules do not all "
+ "have the same data width.\n\n");
+ spd_ddr_init_hang();
+ }
+ }
+ }
+ debug("Number of rows = %ld\n", *rows);
+ debug("Number of columns = %ld\n", *cols);
+ debug("Number of banks = %ld\n", *banks);
+ debug("Data width = %ld\n", *width);
+ if (*rows > 14) {
+ printf("ERROR: DRAM DIMM modules have %lu address rows.\n",
+ *rows);
+ printf("Only modules with 14 or fewer rows are supported.\n\n");
+ spd_ddr_init_hang();
+ }
+ if (4 != *banks && 8 != *banks) {
+ printf("ERROR: DRAM DIMM modules have %lu banks.\n", *banks);
+ printf("Only modules with 4 or 8 banks are supported.\n\n");
+ spd_ddr_init_hang();
+ }
+ if (*cols > 12) {
+ printf("ERROR: DRAM DIMM modules have %lu address columns.\n",
+ *cols);
+ printf("Only modules with 12 or fewer columns are "
+ "supported.\n\n");
+ spd_ddr_init_hang();
+ }
+ if (32 != *width && 40 != *width && 64 != *width && 72 != *width) {
+ printf("ERROR: DRAM DIMM modules have a width of %lu bit.\n",
+ *width);
+ printf("Only modules with widths of 32, 40, 64, and 72 bits "
+ "are supported.\n\n");
+ spd_ddr_init_hang();
+ }
+}
+
+/*------------------------------------------------------------------
+ * Only 1.8V modules are supported. This routine verifies this.
+ *-----------------------------------------------------------------*/
+static void check_voltage_type(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks)
+{
+ unsigned long dimm_num;
+ unsigned long voltage_type;
+
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ if (dimm_ranks[dimm_num]) {
+ voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8);
+ if (0x05 != voltage_type) { /* 1.8V for DDR2 */
+ printf("ERROR: Slot %lu provides 1.8V for DDR2 "
+ "DIMMs.\n", dimm_num);
+ switch (voltage_type) {
+ case 0x00:
+ printf("This DIMM is 5.0 Volt/TTL.\n");
+ break;
+ case 0x01:
+ printf("This DIMM is LVTTL.\n");
+ break;
+ case 0x02:
+ printf("This DIMM is 1.5 Volt.\n");
+ break;
+ case 0x03:
+ printf("This DIMM is 3.3 Volt/TTL.\n");
+ break;
+ case 0x04:
+ printf("This DIMM is 2.5 Volt.\n");
+ break;
+ default:
+ printf("This DIMM is an unknown "
+ "voltage.\n");
+ break;
+ }
+ printf("Replace it with a 1.8V DDR2 DIMM.\n\n");
+ spd_ddr_init_hang();
+ }
+ }
+ }
+}
+
+static void program_ddr0_03(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long sdram_freq,
+ unsigned long rows, unsigned long *cas_latency)
+{
+ unsigned long dimm_num;
+ unsigned long cas_index;
+ unsigned long cycle_2_0_clk;
+ unsigned long cycle_3_0_clk;
+ unsigned long cycle_4_0_clk;
+ unsigned long cycle_5_0_clk;
+ unsigned long max_2_0_tcyc_ps = 100;
+ unsigned long max_3_0_tcyc_ps = 100;
+ unsigned long max_4_0_tcyc_ps = 100;
+ unsigned long max_5_0_tcyc_ps = 100;
+ unsigned char cas_available = 0x3C; /* value for DDR2 */
+ u32 ddr0_03 = DDR0_03_BSTLEN_ENCODE(0x2) | DDR0_03_INITAREF_ENCODE(0x2);
+ unsigned int const tcyc_addr[3] = { 9, 23, 25 };
+
+ /*------------------------------------------------------------------
+ * Get the board configuration info.
+ *-----------------------------------------------------------------*/
+ debug("sdram_freq = %ld\n", sdram_freq);
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_ranks[dimm_num]) {
+ unsigned char const cas_bit =
+ spd_read(iic0_dimm_addr[dimm_num], 18);
+ unsigned char cas_mask;
+
+ cas_available &= cas_bit;
+ for (cas_mask = 0x80; cas_mask; cas_mask >>= 1) {
+ if (cas_bit & cas_mask)
+ break;
+ }
+ debug("cas_bit (SPD byte 18) = %02X, cas_mask = %02X\n",
+ cas_bit, cas_mask);
+
+ for (cas_index = 0; cas_index < 3;
+ cas_mask >>= 1, cas_index++) {
+ unsigned long cycle_time_ps;
+
+ if (!(cas_available & cas_mask)) {
+ continue;
+ }
+ cycle_time_ps =
+ get_tcyc(spd_read(iic0_dimm_addr[dimm_num],
+ tcyc_addr[cas_index]));
+
+ debug("cas_index = %ld: cycle_time_ps = %ld\n",
+ cas_index, cycle_time_ps);
+ /*
+ * DDR2 devices use the following bitmask for CAS latency:
+ * Bit 7 6 5 4 3 2 1 0
+ * TBD 6.0 5.0 4.0 3.0 2.0 TBD TBD
+ */
+ switch (cas_mask) {
+ case 0x20:
+ max_5_0_tcyc_ps =
+ max(max_5_0_tcyc_ps, cycle_time_ps);
+ break;
+ case 0x10:
+ max_4_0_tcyc_ps =
+ max(max_4_0_tcyc_ps, cycle_time_ps);
+ break;
+ case 0x08:
+ max_3_0_tcyc_ps =
+ max(max_3_0_tcyc_ps, cycle_time_ps);
+ break;
+ case 0x04:
+ max_2_0_tcyc_ps =
+ max(max_2_0_tcyc_ps, cycle_time_ps);
+ break;
+ }
+ }
+ }
+ }
+ debug("cas_available (bit map) = 0x%02X\n", cas_available);
+
+ /*------------------------------------------------------------------
+ * Set the SDRAM mode, SDRAM_MMODE
+ *-----------------------------------------------------------------*/
+
+ /* add 10 here because of rounding problems */
+ cycle_2_0_clk = MULDIV64(ONE_BILLION, 1000, max_2_0_tcyc_ps) + 10;
+ cycle_3_0_clk = MULDIV64(ONE_BILLION, 1000, max_3_0_tcyc_ps) + 10;
+ cycle_4_0_clk = MULDIV64(ONE_BILLION, 1000, max_4_0_tcyc_ps) + 10;
+ cycle_5_0_clk = MULDIV64(ONE_BILLION, 1000, max_5_0_tcyc_ps) + 10;
+ debug("cycle_2_0_clk = %ld\n", cycle_2_0_clk);
+ debug("cycle_3_0_clk = %ld\n", cycle_3_0_clk);
+ debug("cycle_4_0_clk = %ld\n", cycle_4_0_clk);
+ debug("cycle_5_0_clk = %ld\n", cycle_5_0_clk);
+
+ if ((cas_available & 0x04) && (sdram_freq <= cycle_2_0_clk)) {
+ *cas_latency = 2;
+ ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x2) |
+ DDR0_03_CASLAT_LIN_ENCODE(0x4);
+ } else if ((cas_available & 0x08) && (sdram_freq <= cycle_3_0_clk)) {
+ *cas_latency = 3;
+ ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x3) |
+ DDR0_03_CASLAT_LIN_ENCODE(0x6);
+ } else if ((cas_available & 0x10) && (sdram_freq <= cycle_4_0_clk)) {
+ *cas_latency = 4;
+ ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x4) |
+ DDR0_03_CASLAT_LIN_ENCODE(0x8);
+ } else if ((cas_available & 0x20) && (sdram_freq <= cycle_5_0_clk)) {
+ *cas_latency = 5;
+ ddr0_03 |= DDR0_03_CASLAT_ENCODE(0x5) |
+ DDR0_03_CASLAT_LIN_ENCODE(0xA);
+ } else {
+ printf("ERROR: Cannot find a supported CAS latency with the "
+ "installed DIMMs.\n");
+ printf("Only DDR2 DIMMs with CAS latencies of 2.0, 3.0, 4.0, "
+ "and 5.0 are supported.\n");
+ printf("Make sure the PLB speed is within the supported range "
+ "of the DIMMs.\n");
+ printf("sdram_freq=%ld cycle2=%ld cycle3=%ld cycle4=%ld "
+ "cycle5=%ld\n\n", sdram_freq, cycle_2_0_clk,
+ cycle_3_0_clk, cycle_4_0_clk, cycle_5_0_clk);
+ spd_ddr_init_hang();
+ }
+ debug("CAS latency = %ld\n", *cas_latency);
+ mtsdram(DDR0_03, ddr0_03);
+}
+
+static void program_ddr0_04(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long sdram_freq)
+{
+ unsigned long dimm_num;
+ unsigned long t_rc_ps = 0;
+ unsigned long t_rrd_ps = 0;
+ unsigned long t_rtp_ps = 0;
+ unsigned long t_rc_clk;
+ unsigned long t_rrd_clk;
+ unsigned long t_rtp_clk;
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_ranks[dimm_num]) {
+ unsigned long ps;
+
+ /* tRC */
+ ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 41);
+ switch (spd_read(iic0_dimm_addr[dimm_num], 40) >> 4) {
+ case 0x1:
+ ps += 250;
+ break;
+ case 0x2:
+ ps += 333;
+ break;
+ case 0x3:
+ ps += 500;
+ break;
+ case 0x4:
+ ps += 667;
+ break;
+ case 0x5:
+ ps += 750;
+ break;
+ }
+ t_rc_ps = max(t_rc_ps, ps);
+ /* tRRD */
+ ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 28);
+ t_rrd_ps = max(t_rrd_ps, ps);
+ /* tRTP */
+ ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 38);
+ t_rtp_ps = max(t_rtp_ps, ps);
+ }
+ }
+ debug("t_rc_ps = %ld\n", t_rc_ps);
+ t_rc_clk = (MULDIV64(sdram_freq, t_rc_ps, ONE_BILLION) + 999) / 1000;
+ debug("t_rrd_ps = %ld\n", t_rrd_ps);
+ t_rrd_clk = (MULDIV64(sdram_freq, t_rrd_ps, ONE_BILLION) + 999) / 1000;
+ debug("t_rtp_ps = %ld\n", t_rtp_ps);
+ t_rtp_clk = (MULDIV64(sdram_freq, t_rtp_ps, ONE_BILLION) + 999) / 1000;
+ mtsdram(DDR0_04, DDR0_04_TRC_ENCODE(t_rc_clk) |
+ DDR0_04_TRRD_ENCODE(t_rrd_clk) |
+ DDR0_04_TRTP_ENCODE(t_rtp_clk));
+}
+
+static void program_ddr0_05(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long sdram_freq)
+{
+ unsigned long dimm_num;
+ unsigned long t_rp_ps = 0;
+ unsigned long t_ras_ps = 0;
+ unsigned long t_rp_clk;
+ unsigned long t_ras_clk;
+ u32 ddr0_05 = DDR0_05_TMRD_ENCODE(0x2) | DDR0_05_TEMRS_ENCODE(0x2);
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_ranks[dimm_num]) {
+ unsigned long ps;
+
+ /* tRP */
+ ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 27);
+ t_rp_ps = max(t_rp_ps, ps);
+ /* tRAS */
+ ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 30);
+ t_ras_ps = max(t_ras_ps, ps);
+ }
+ }
+ debug("t_rp_ps = %ld\n", t_rp_ps);
+ t_rp_clk = (MULDIV64(sdram_freq, t_rp_ps, ONE_BILLION) + 999) / 1000;
+ debug("t_ras_ps = %ld\n", t_ras_ps);
+ t_ras_clk = (MULDIV64(sdram_freq, t_ras_ps, ONE_BILLION) + 999) / 1000;
+ mtsdram(DDR0_05, ddr0_05 | DDR0_05_TRP_ENCODE(t_rp_clk) |
+ DDR0_05_TRAS_MIN_ENCODE(t_ras_clk));
+}
+
+static void program_ddr0_06(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long sdram_freq)
+{
+ unsigned long dimm_num;
+ unsigned char spd_40;
+ unsigned long t_wtr_ps = 0;
+ unsigned long t_rfc_ps = 0;
+ unsigned long t_wtr_clk;
+ unsigned long t_rfc_clk;
+ u32 ddr0_06 =
+ DDR0_06_WRITEINTERP_ENCODE(0x1) | DDR0_06_TDLL_ENCODE(200);
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_ranks[dimm_num]) {
+ unsigned long ps;
+
+ /* tWTR */
+ ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 37);
+ t_wtr_ps = max(t_wtr_ps, ps);
+ /* tRFC */
+ ps = 1000 * spd_read(iic0_dimm_addr[dimm_num], 42);
+ spd_40 = spd_read(iic0_dimm_addr[dimm_num], 40);
+ ps += 256000 * (spd_40 & 0x01);
+ switch ((spd_40 & 0x0E) >> 1) {
+ case 0x1:
+ ps += 250;
+ break;
+ case 0x2:
+ ps += 333;
+ break;
+ case 0x3:
+ ps += 500;
+ break;
+ case 0x4:
+ ps += 667;
+ break;
+ case 0x5:
+ ps += 750;
+ break;
+ }
+ t_rfc_ps = max(t_rfc_ps, ps);
+ }
+ }
+ debug("t_wtr_ps = %ld\n", t_wtr_ps);
+ t_wtr_clk = (MULDIV64(sdram_freq, t_wtr_ps, ONE_BILLION) + 999) / 1000;
+ debug("t_rfc_ps = %ld\n", t_rfc_ps);
+ t_rfc_clk = (MULDIV64(sdram_freq, t_rfc_ps, ONE_BILLION) + 999) / 1000;
+ mtsdram(DDR0_06, ddr0_06 | DDR0_06_TWTR_ENCODE(t_wtr_clk) |
+ DDR0_06_TRFC_ENCODE(t_rfc_clk));
+}
+
+static void program_ddr0_10(unsigned long dimm_ranks[], unsigned long ranks)
+{
+ unsigned long csmap;
+
+ if (2 == ranks) {
+ /* Both chip selects in use */
+ csmap = 0x03;
+ } else {
+ /* One chip select in use */
+ csmap = (1 == dimm_ranks[0]) ? 0x1 : 0x2;
+ }
+ mtsdram(DDR0_10, DDR0_10_WRITE_MODEREG_ENCODE(0x0) |
+ DDR0_10_CS_MAP_ENCODE(csmap) |
+ DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(0));
+}
+
+static void program_ddr0_11(unsigned long sdram_freq)
+{
+ unsigned long const t_xsnr_ps = 200000; /* 200 ns */
+ unsigned long t_xsnr_clk;
+
+ debug("t_xsnr_ps = %ld\n", t_xsnr_ps);
+ t_xsnr_clk =
+ (MULDIV64(sdram_freq, t_xsnr_ps, ONE_BILLION) + 999) / 1000;
+ mtsdram(DDR0_11, DDR0_11_SREFRESH_ENCODE(0) |
+ DDR0_11_TXSNR_ENCODE(t_xsnr_clk) | DDR0_11_TXSR_ENCODE(200));
+}
+
+static void program_ddr0_22(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks, unsigned long width)
+{
+#if defined(CONFIG_DDR_ECC)
+ unsigned long dimm_num;
+ unsigned long ecc_available = width >= 64;
+ u32 ddr0_22 = DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) |
+ DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) |
+ DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS);
+
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_ranks[dimm_num]) {
+ /* Check for ECC */
+ if (0 == (spd_read(iic0_dimm_addr[dimm_num], 11) &
+ 0x02)) {
+ ecc_available = false;
+ }
+ }
+ }
+ if (ecc_available) {
+ debug("ECC found on all DIMMs present\n");
+ mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x3));
+ } else {
+ debug("ECC not found on some or all DIMMs present\n");
+ mtsdram(DDR0_22, ddr0_22 | DDR0_22_CTRL_RAW_ENCODE(0x0));
+ }
+#else
+ mtsdram(DDR0_22, DDR0_22_CTRL_RAW_ENCODE(0x0) |
+ DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(0x26) |
+ DDR0_22_DQS_OUT_SHIFT_ENCODE(DQS_OUT_SHIFT) |
+ DDR0_22_DLL_DQS_BYPASS_8_ENCODE(DLL_DQS_BYPASS));
+#endif /* defined(CONFIG_DDR_ECC) */
+}
+
+static void program_ddr0_24(unsigned long ranks)
+{
+ u32 ddr0_24 = DDR0_24_RTT_PAD_TERMINATION_ENCODE(0x1) | /* 75 ohm */
+ DDR0_24_ODT_RD_MAP_CS1_ENCODE(0x0);
+
+ if (2 == ranks) {
+ /* Both chip selects in use */
+ ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x1) |
+ DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x2);
+ } else {
+ /* One chip select in use */
+ /* One of the two fields added to ddr0_24 is a "don't care" */
+ ddr0_24 |= DDR0_24_ODT_WR_MAP_CS1_ENCODE(0x2) |
+ DDR0_24_ODT_WR_MAP_CS0_ENCODE(0x1);
+ }
+ mtsdram(DDR0_24, ddr0_24);
+}
+
+static void program_ddr0_26(unsigned long sdram_freq)
+{
+ unsigned long const t_ref_ps = 7800000; /* 7.8 us. refresh */
+ /* TODO: check definition of tRAS_MAX */
+ unsigned long const t_ras_max_ps = 9 * t_ref_ps;
+ unsigned long t_ras_max_clk;
+ unsigned long t_ref_clk;
+
+ /* Round down t_ras_max_clk and t_ref_clk */
+ debug("t_ras_max_ps = %ld\n", t_ras_max_ps);
+ t_ras_max_clk = MULDIV64(sdram_freq, t_ras_max_ps, ONE_BILLION) / 1000;
+ debug("t_ref_ps = %ld\n", t_ref_ps);
+ t_ref_clk = MULDIV64(sdram_freq, t_ref_ps, ONE_BILLION) / 1000;
+ mtsdram(DDR0_26, DDR0_26_TRAS_MAX_ENCODE(t_ras_max_clk) |
+ DDR0_26_TREF_ENCODE(t_ref_clk));
+}
+
+static void program_ddr0_27(unsigned long sdram_freq)
+{
+ unsigned long const t_init_ps = 200000000; /* 200 us. init */
+ unsigned long t_init_clk;
+
+ debug("t_init_ps = %ld\n", t_init_ps);
+ t_init_clk =
+ (MULDIV64(sdram_freq, t_init_ps, ONE_BILLION) + 999) / 1000;
+ mtsdram(DDR0_27, DDR0_27_EMRS_DATA_ENCODE(0x0000) |
+ DDR0_27_TINIT_ENCODE(t_init_clk));
+}
+
+static void program_ddr0_43(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long sdram_freq,
+ unsigned long cols, unsigned long banks)
+{
+ unsigned long dimm_num;
+ unsigned long t_wr_ps = 0;
+ unsigned long t_wr_clk;
+ u32 ddr0_43 = DDR0_43_APREBIT_ENCODE(10) |
+ DDR0_43_COLUMN_SIZE_ENCODE(12 - cols) |
+ DDR0_43_EIGHT_BANK_MODE_ENCODE(8 == banks ? 1 : 0);
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_ranks[dimm_num]) {
+ unsigned long ps;
+
+ ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 36);
+ t_wr_ps = max(t_wr_ps, ps);
+ }
+ }
+ debug("t_wr_ps = %ld\n", t_wr_ps);
+ t_wr_clk = (MULDIV64(sdram_freq, t_wr_ps, ONE_BILLION) + 999) / 1000;
+ mtsdram(DDR0_43, ddr0_43 | DDR0_43_TWR_ENCODE(t_wr_clk));
+}
+
+static void program_ddr0_44(unsigned long dimm_ranks[],
+ unsigned char const iic0_dimm_addr[],
+ unsigned long num_dimm_banks,
+ unsigned long sdram_freq)
+{
+ unsigned long dimm_num;
+ unsigned long t_rcd_ps = 0;
+ unsigned long t_rcd_clk;
+
+ /*------------------------------------------------------------------
+ * Handle the timing. We need to find the worst case timing of all
+ * the dimm modules installed.
+ *-----------------------------------------------------------------*/
+ /* loop through all the DIMM slots on the board */
+ for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) {
+ /* If a dimm is installed in a particular slot ... */
+ if (dimm_ranks[dimm_num]) {
+ unsigned long ps;
+
+ ps = 250 * spd_read(iic0_dimm_addr[dimm_num], 29);
+ t_rcd_ps = max(t_rcd_ps, ps);
+ }
+ }
+ debug("t_rcd_ps = %ld\n", t_rcd_ps);
+ t_rcd_clk = (MULDIV64(sdram_freq, t_rcd_ps, ONE_BILLION) + 999) / 1000;
+ mtsdram(DDR0_44, DDR0_44_TRCD_ENCODE(t_rcd_clk));
+}
+
+/*-----------------------------------------------------------------------------+
+ * initdram. Initializes the 440EPx/GPx DDR SDRAM controller.
+ * Note: This routine runs from flash with a stack set up in the chip's
+ * sram space. It is important that the routine does not require .sbss, .bss or
+ * .data sections. It also cannot call routines that require these sections.
+ *-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ * Function: initdram
+ * Description: Configures SDRAM memory banks for DDR operation.
+ * Auto Memory Configuration option reads the DDR SDRAM EEPROMs
+ * via the IIC bus and then configures the DDR SDRAM memory
+ * banks appropriately. If Auto Memory Configuration is
+ * not used, it is assumed that no DIMM is plugged
+ *-----------------------------------------------------------------------------*/
+phys_size_t initdram(int board_type)
+{
+ unsigned char const iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
+ unsigned long dimm_ranks[MAXDIMMS];
+ unsigned long ranks;
+ unsigned long rows;
+ unsigned long banks;
+ unsigned long cols;
+ unsigned long width;
+ unsigned long const sdram_freq = get_bus_freq(0);
+ unsigned long const num_dimm_banks = sizeof(iic0_dimm_addr); /* on board dimm banks */
+ unsigned long cas_latency = 0; /* to quiet initialization warning */
+ unsigned long dram_size;
+
+ debug("\nEntering initdram()\n");
+
+ /*------------------------------------------------------------------
+ * Stop the DDR-SDRAM controller.
+ *-----------------------------------------------------------------*/
+ mtsdram(DDR0_02, DDR0_02_START_ENCODE(0));
+
+ /*
+ * Make sure I2C controller is initialized
+ * before continuing.
+ */
+ /* switch to correct I2C bus */
+ I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM);
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+ /*------------------------------------------------------------------
+ * Clear out the serial presence detect buffers.
+ * Perform IIC reads from the dimm. Fill in the spds.
+ * Check to see if the dimm slots are populated
+ *-----------------------------------------------------------------*/
+ get_spd_info(dimm_ranks, &ranks, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Check the frequency supported for the dimms plugged.
+ *-----------------------------------------------------------------*/
+ check_frequency(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+ /*------------------------------------------------------------------
+ * Check and get size information.
+ *-----------------------------------------------------------------*/
+ get_dimm_size(dimm_ranks, iic0_dimm_addr, num_dimm_banks, &rows, &banks,
+ &cols, &width);
+
+ /*------------------------------------------------------------------
+ * Check the voltage type for the dimms plugged.
+ *-----------------------------------------------------------------*/
+ check_voltage_type(dimm_ranks, iic0_dimm_addr, num_dimm_banks);
+
+ /*------------------------------------------------------------------
+ * Program registers for SDRAM controller.
+ *-----------------------------------------------------------------*/
+ mtsdram(DDR0_00, DDR0_00_DLL_INCREMENT_ENCODE(0x19) |
+ DDR0_00_DLL_START_POINT_DECODE(0x0A));
+
+ mtsdram(DDR0_01, DDR0_01_PLB0_DB_CS_LOWER_ENCODE(0x01) |
+ DDR0_01_PLB0_DB_CS_UPPER_ENCODE(0x00) |
+ DDR0_01_INT_MASK_ENCODE(0xFF));
+
+ program_ddr0_03(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq,
+ rows, &cas_latency);
+
+ program_ddr0_04(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+ program_ddr0_05(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+ program_ddr0_06(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+ /*
+ * TODO: tFAW not found in SPD. Value of 13 taken from Sequoia
+ * board SDRAM, but may be overly conservative.
+ */
+ mtsdram(DDR0_07, DDR0_07_NO_CMD_INIT_ENCODE(0) |
+ DDR0_07_TFAW_ENCODE(13) |
+ DDR0_07_AUTO_REFRESH_MODE_ENCODE(1) |
+ DDR0_07_AREFRESH_ENCODE(0));
+
+ mtsdram(DDR0_08, DDR0_08_WRLAT_ENCODE(cas_latency - 1) |
+ DDR0_08_TCPD_ENCODE(200) | DDR0_08_DQS_N_EN_ENCODE(0) |
+ DDR0_08_DDRII_ENCODE(1));
+
+ mtsdram(DDR0_09, DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(0x00) |
+ DDR0_09_RTT_0_ENCODE(0x1) |
+ DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(0x1D) |
+ DDR0_09_WR_DQS_SHIFT_ENCODE(DQS_OUT_SHIFT - 0x20));
+
+ program_ddr0_10(dimm_ranks, ranks);
+
+ program_ddr0_11(sdram_freq);
+
+ mtsdram(DDR0_12, DDR0_12_TCKE_ENCODE(3));
+
+ mtsdram(DDR0_14, DDR0_14_DLL_BYPASS_MODE_ENCODE(0) |
+ DDR0_14_REDUC_ENCODE(width <= 40 ? 1 : 0) |
+ DDR0_14_REG_DIMM_ENABLE_ENCODE(0));
+
+ mtsdram(DDR0_17, DDR0_17_DLL_DQS_DELAY_0_ENCODE(DLL_DQS_DELAY));
+
+ mtsdram(DDR0_18, DDR0_18_DLL_DQS_DELAY_4_ENCODE(DLL_DQS_DELAY) |
+ DDR0_18_DLL_DQS_DELAY_3_ENCODE(DLL_DQS_DELAY) |
+ DDR0_18_DLL_DQS_DELAY_2_ENCODE(DLL_DQS_DELAY) |
+ DDR0_18_DLL_DQS_DELAY_1_ENCODE(DLL_DQS_DELAY));
+
+ mtsdram(DDR0_19, DDR0_19_DLL_DQS_DELAY_8_ENCODE(DLL_DQS_DELAY) |
+ DDR0_19_DLL_DQS_DELAY_7_ENCODE(DLL_DQS_DELAY) |
+ DDR0_19_DLL_DQS_DELAY_6_ENCODE(DLL_DQS_DELAY) |
+ DDR0_19_DLL_DQS_DELAY_5_ENCODE(DLL_DQS_DELAY));
+
+ mtsdram(DDR0_20, DDR0_20_DLL_DQS_BYPASS_3_ENCODE(DLL_DQS_BYPASS) |
+ DDR0_20_DLL_DQS_BYPASS_2_ENCODE(DLL_DQS_BYPASS) |
+ DDR0_20_DLL_DQS_BYPASS_1_ENCODE(DLL_DQS_BYPASS) |
+ DDR0_20_DLL_DQS_BYPASS_0_ENCODE(DLL_DQS_BYPASS));
+
+ mtsdram(DDR0_21, DDR0_21_DLL_DQS_BYPASS_7_ENCODE(DLL_DQS_BYPASS) |
+ DDR0_21_DLL_DQS_BYPASS_6_ENCODE(DLL_DQS_BYPASS) |
+ DDR0_21_DLL_DQS_BYPASS_5_ENCODE(DLL_DQS_BYPASS) |
+ DDR0_21_DLL_DQS_BYPASS_4_ENCODE(DLL_DQS_BYPASS));
+
+ program_ddr0_22(dimm_ranks, iic0_dimm_addr, num_dimm_banks, width);
+
+ mtsdram(DDR0_23, DDR0_23_ODT_RD_MAP_CS0_ENCODE(0x0) |
+ DDR0_23_FWC_ENCODE(0));
+
+ program_ddr0_24(ranks);
+
+ program_ddr0_26(sdram_freq);
+
+ program_ddr0_27(sdram_freq);
+
+ mtsdram(DDR0_28, DDR0_28_EMRS3_DATA_ENCODE(0x0000) |
+ DDR0_28_EMRS2_DATA_ENCODE(0x0000));
+
+ mtsdram(DDR0_31, DDR0_31_XOR_CHECK_BITS_ENCODE(0x0000));
+
+ mtsdram(DDR0_42, DDR0_42_ADDR_PINS_ENCODE(14 - rows) |
+ DDR0_42_CASLAT_LIN_GATE_ENCODE(2 * cas_latency));
+
+ program_ddr0_43(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq,
+ cols, banks);
+
+ program_ddr0_44(dimm_ranks, iic0_dimm_addr, num_dimm_banks, sdram_freq);
+
+ denali_sdram_register_dump();
+
+ dram_size = (width >= 64) ? 8 : 4;
+ dram_size *= 1 << cols;
+ dram_size *= banks;
+ dram_size *= 1 << rows;
+ dram_size *= ranks;
+ debug("dram_size = %lu\n", dram_size);
+
+ /* Start the SDRAM controler */
+ mtsdram(DDR0_02, DDR0_02_START_ENCODE(1));
+ denali_wait_for_dlllock();
+
+#if defined(CONFIG_DDR_DATA_EYE)
+ /*
+ * Map the first 1 MiB of memory in the TLB, and perform the data eye
+ * search.
+ */
+ program_tlb(0, CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE, TLB_WORD2_I_ENABLE);
+ denali_core_search_data_eye();
+ denali_sdram_register_dump();
+ remove_tlb(CONFIG_SYS_SDRAM_BASE, TLB_1MB_SIZE);
+#endif
+
+#if defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC)
+ program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, 0);
+ sync();
+ /* Zero the memory */
+ debug("Zeroing SDRAM...");
+#if defined(CONFIG_SYS_MEM_TOP_HIDE)
+ dcbz_area(CONFIG_SYS_SDRAM_BASE, dram_size - CONFIG_SYS_MEM_TOP_HIDE);
+#else
+#error Please define CONFIG_SYS_MEM_TOP_HIDE (see README) in your board config file
+#endif
+ /* Write modified dcache lines back to memory */
+ clean_dcache_range(CONFIG_SYS_SDRAM_BASE, CONFIG_SYS_SDRAM_BASE + dram_size - CONFIG_SYS_MEM_TOP_HIDE);
+ debug("Completed\n");
+ sync();
+ remove_tlb(CONFIG_SYS_SDRAM_BASE, dram_size);
+
+#if defined(CONFIG_DDR_ECC)
+ /*
+ * If ECC is enabled, clear and enable interrupts
+ */
+ if (is_ecc_enabled()) {
+ u32 val;
+
+ sync();
+ /* Clear error status */
+ mfsdram(DDR0_00, val);
+ mtsdram(DDR0_00, val | DDR0_00_INT_ACK_ALL);
+ /* Set 'int_mask' parameter to functionnal value */
+ mfsdram(DDR0_01, val);
+ mtsdram(DDR0_01, (val & ~DDR0_01_INT_MASK_MASK) |
+ DDR0_01_INT_MASK_ALL_OFF);
+#if defined(CONFIG_DDR_DATA_EYE)
+ /*
+ * Running denali_core_search_data_eye() when ECC is enabled
+ * causes non-ECC machine checks. This clears them.
+ */
+ print_mcsr();
+ mtspr(SPRN_MCSR, mfspr(SPRN_MCSR));
+ print_mcsr();
+#endif
+ sync();
+ }
+#endif /* defined(CONFIG_DDR_ECC) */
+#endif /* defined(CONFIG_ZERO_SDRAM) || defined(CONFIG_DDR_ECC) */
+
+ program_tlb(0, CONFIG_SYS_SDRAM_BASE, dram_size, MY_TLB_WORD2_I_ENABLE);
+ return dram_size;
+}
+
+void board_add_ram_info(int use_default)
+{
+ u32 val;
+
+ printf(" (ECC");
+ if (!is_ecc_enabled()) {
+ printf(" not");
+ }
+ printf(" enabled, %ld MHz", (2 * get_bus_freq(0)) / 1000000);
+
+ mfsdram(DDR0_03, val);
+ printf(", CL%d)", DDR0_03_CASLAT_LIN_DECODE(val) >> 1);
+}
+#endif /* CONFIG_SPD_EEPROM */
diff --git a/arch/powerpc/cpu/ppc4xx/ecc.c b/arch/powerpc/cpu/ppc4xx/ecc.c
new file mode 100644
index 0000000..7fe5dbb
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/ecc.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2008 Nuovation System Designs, LLC
+ * Grant Erickson <gerickson@nuovations.com>
+ *
+ * (C) Copyright 2005-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2002
+ * Jun Gu, Artesyn Technology, jung@artesyncp.com
+ *
+ * (C) Copyright 2001
+ * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will abe useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Description:
+ * This file implements generic DRAM ECC initialization for
+ * PowerPC processors using a SDRAM DDR/DDR2 controller,
+ * including the 405EX(r), 440GP/GX/EP/GR, 440SP(E), and
+ * 460EX/GT.
+ */
+
+#include <common.h>
+#include <asm/ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <asm/cache.h>
+
+#include "ecc.h"
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \
+ defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC)
+
+#if defined(CONFIG_405EX)
+/*
+ * Currently only 405EX uses 16bit data bus width as an alternative
+ * option to 32bit data width (SDRAM0_MCOPT1_WDTH)
+ */
+#define SDRAM_DATA_ALT_WIDTH 2
+#else
+#define SDRAM_DATA_ALT_WIDTH 8
+#endif
+
+static void wait_ddr_idle(void)
+{
+ u32 val;
+
+ do {
+ mfsdram(SDRAM_MCSTAT, val);
+ } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
+}
+
+static void program_ecc_addr(unsigned long start_address,
+ unsigned long num_bytes,
+ unsigned long tlb_word2_i_value)
+{
+ unsigned long current_address;
+ unsigned long end_address;
+ unsigned long address_increment;
+ unsigned long mcopt1;
+ char str[] = "ECC generation -";
+ char slash[] = "\\|/-\\|/-";
+ int loop = 0;
+ int loopi = 0;
+
+ current_address = start_address;
+ mfsdram(SDRAM_MCOPT1, mcopt1);
+ if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+ mtsdram(SDRAM_MCOPT1,
+ (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN);
+ sync();
+ eieio();
+ wait_ddr_idle();
+
+ puts(str);
+
+#ifdef CONFIG_440
+ if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
+#endif
+ /* ECC bit set method for non-cached memory */
+ if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
+ address_increment = 4;
+ else
+ address_increment = SDRAM_DATA_ALT_WIDTH;
+ end_address = current_address + num_bytes;
+
+ while (current_address < end_address) {
+ *((unsigned long *)current_address) = 0;
+ current_address += address_increment;
+
+ if ((loop++ % (2 << 20)) == 0) {
+ putc('\b');
+ putc(slash[loopi++ % 8]);
+ }
+ }
+#ifdef CONFIG_440
+ } else {
+ /* ECC bit set method for cached memory */
+ dcbz_area(start_address, num_bytes);
+ /* Write modified dcache lines back to memory */
+ clean_dcache_range(start_address, start_address + num_bytes);
+ }
+#endif /* CONFIG_440 */
+
+ blank_string(strlen(str));
+
+ sync();
+ eieio();
+ wait_ddr_idle();
+
+ /* clear ECC error repoting registers */
+ mtsdram(SDRAM_ECCES, 0xffffffff);
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+ /*
+ * IBM DDR(1) core (440GX):
+ * Clear Mx bits in SDRAM0_BESR0/1
+ */
+ mtsdram(SDRAM0_BESR0, 0xffffffff);
+ mtsdram(SDRAM0_BESR1, 0xffffffff);
+#elif defined(CONFIG_440)
+ /*
+ * 440/460 DDR2 core:
+ * Clear EMID (Error PLB Master ID) in MQ0_ESL
+ */
+ mtdcr(SDRAM_ERRSTATLL, 0xfff00000);
+#else
+ /*
+ * 405EX(r) DDR2 core:
+ * Clear M0ID (Error PLB Master ID) in SDRAM_BESR
+ */
+ mtsdram(SDRAM_BESR, 0xf0000000);
+#endif
+
+ mtsdram(SDRAM_MCOPT1,
+ (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
+ sync();
+ eieio();
+ wait_ddr_idle();
+ }
+}
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+void ecc_init(unsigned long * const start, unsigned long size)
+{
+ /*
+ * Init ECC with cache disabled (on PPC's with IBM DDR
+ * controller (non DDR2), not tested with cache enabled yet
+ */
+ program_ecc_addr((u32)start, size, TLB_WORD2_I_ENABLE);
+}
+#endif
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+void do_program_ecc(unsigned long tlb_word2_i_value)
+{
+ unsigned long mcopt1;
+ unsigned long mcopt2;
+ unsigned long mcstat;
+ phys_size_t memsize = sdram_memsize();
+
+ if (memsize > CONFIG_MAX_MEM_MAPPED) {
+ printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
+ return;
+ }
+
+ mfsdram(SDRAM_MCOPT1, mcopt1);
+ mfsdram(SDRAM_MCOPT2, mcopt2);
+
+ if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
+ /* DDR controller must be enabled and not in self-refresh. */
+ mfsdram(SDRAM_MCSTAT, mcstat);
+ if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
+ && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
+ && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
+ == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
+
+ program_ecc_addr(0, memsize, tlb_word2_i_value);
+ }
+ }
+}
+#endif
+
+#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */
+#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */
diff --git a/arch/powerpc/cpu/ppc4xx/ecc.h b/arch/powerpc/cpu/ppc4xx/ecc.h
new file mode 100644
index 0000000..b258891
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/ecc.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2008 Nuovation System Designs, LLC
+ * Grant Erickson <gerickson@nuovations.com>
+ *
+ * Copyright (c) 2007-2009 DENX Software Engineering, GmbH
+ * Stefan Roese <sr@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will abe useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Description:
+ * This file implements ECC initialization for PowerPC processors
+ * using the IBM SDRAM DDR1 & DDR2 controller.
+ *
+ */
+
+#ifndef _ECC_H_
+#define _ECC_H_
+
+/*
+ * Since the IBM DDR controller used on 440GP/GX/EP/GR is not register
+ * compatible to the IBM DDR/2 controller used on 405EX/440SP/SPe/460EX/GT
+ * we need to make some processor dependant defines used later on by the
+ * driver.
+ */
+
+/* For 440GP/GX/EP/GR */
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+#define SDRAM_MCOPT1 SDRAM_CFG0
+#define SDRAM_MCOPT1_MCHK_MASK SDRAM_CFG0_MCHK_MASK
+#define SDRAM_MCOPT1_MCHK_NON SDRAM_CFG0_MCHK_NON
+#define SDRAM_MCOPT1_MCHK_GEN SDRAM_CFG0_MCHK_GEN
+#define SDRAM_MCOPT1_MCHK_CHK SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_MCHK_CHK_REP SDRAM_CFG0_MCHK_CHK
+#define SDRAM_MCOPT1_DMWD_MASK SDRAM_CFG0_DMWD_MASK
+#define SDRAM_MCOPT1_DMWD_32 SDRAM_CFG0_DMWD_32
+
+#define SDRAM_MCSTAT SDRAM0_MCSTS
+#define SDRAM_MCSTAT_IDLE_MASK SDRAM_MCSTS_CIS
+#define SDRAM_MCSTAT_IDLE_NOT SDRAM_MCSTS_IDLE_NOT
+
+#define SDRAM_ECCES SDRAM0_ECCESR
+#endif
+
+void ecc_init(unsigned long * const start, unsigned long size);
+void do_program_ecc(unsigned long tlb_word2_i_value);
+
+static void inline blank_string(int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ putc('\b');
+ for (i = 0; i < size; i++)
+ putc(' ');
+ for (i = 0; i < size; i++)
+ putc('\b');
+}
+
+#endif /* _ECC_H_ */
diff --git a/arch/powerpc/cpu/ppc4xx/fdt.c b/arch/powerpc/cpu/ppc4xx/fdt.c
new file mode 100644
index 0000000..3cdd531
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/fdt.c
@@ -0,0 +1,176 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/cache.h>
+#include <asm/ppc4xx.h>
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/4xx_pcie.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void __ft_board_setup(void *blob, bd_t *bd)
+{
+ int rc;
+ int i;
+ u32 bxcr;
+ u32 ranges[EBC_NUM_BANKS * 4];
+ u32 *p = ranges;
+ char ebc_path[] = "/plb/opb/ebc";
+
+ ft_cpu_setup(blob, bd);
+
+ /*
+ * Read 4xx EBC bus bridge registers to get mappings of the
+ * peripheral banks into the OPB/PLB address space
+ */
+ for (i = 0; i < EBC_NUM_BANKS; i++) {
+ mtdcr(EBC0_CFGADDR, EBC_BXCR(i));
+ bxcr = mfdcr(EBC0_CFGDATA);
+
+ if ((bxcr & EBC_BXCR_BU_MASK) != EBC_BXCR_BU_NONE) {
+ *p++ = i;
+ *p++ = 0;
+ *p++ = bxcr & EBC_BXCR_BAS_MASK;
+ *p++ = EBC_BXCR_BANK_SIZE(bxcr);
+ }
+ }
+
+
+#ifdef CONFIG_FDT_FIXUP_NOR_FLASH_SIZE
+ /* Update reg property in all nor flash nodes too */
+ fdt_fixup_nor_flash_size(blob);
+#endif
+
+ /* Some 405 PPC's have EBC as direct PLB child in the dts */
+ if (fdt_path_offset(blob, ebc_path) < 0)
+ strcpy(ebc_path, "/plb/ebc");
+ rc = fdt_find_and_setprop(blob, ebc_path, "ranges", ranges,
+ (p - ranges) * sizeof(u32), 1);
+ if (rc) {
+ printf("Unable to update property EBC mappings, err=%s\n",
+ fdt_strerror(rc));
+ }
+}
+void ft_board_setup(void *blob, bd_t *bd) __attribute__((weak, alias("__ft_board_setup")));
+
+/*
+ * Fixup all PCIe nodes by setting the device_type property
+ * to "pci-endpoint" instead is "pci" for endpoint ports.
+ * This property will get checked later by the Linux driver
+ * to properly configure the PCIe port in Linux (again).
+ */
+void fdt_pcie_setup(void *blob)
+{
+ const char *compat = "ibm,plb-pciex";
+ const char *prop = "device_type";
+ const char *prop_val = "pci-endpoint";
+ const u32 *port;
+ int no;
+ int rc;
+
+ /* Search first PCIe node */
+ no = fdt_node_offset_by_compatible(blob, -1, compat);
+ while (no != -FDT_ERR_NOTFOUND) {
+ port = fdt_getprop(blob, no, "port", NULL);
+ if (port == NULL) {
+ printf("WARNING: could not find port property\n");
+ } else {
+ if (is_end_point(*port)) {
+ rc = fdt_setprop(blob, no, prop, prop_val,
+ strlen(prop_val) + 1);
+ if (rc < 0)
+ printf("WARNING: could not set %s for %s: %s.\n",
+ prop, compat, fdt_strerror(rc));
+ }
+ }
+
+ /* Jump to next PCIe node */
+ no = fdt_node_offset_by_compatible(blob, no, compat);
+ }
+}
+
+void ft_cpu_setup(void *blob, bd_t *bd)
+{
+ sys_info_t sys_info;
+ int off, ndepth = 0;
+
+ get_sys_info(&sys_info);
+
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "timebase-frequency",
+ bd->bi_intfreq, 1);
+ do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, "clock-frequency",
+ bd->bi_intfreq, 1);
+ do_fixup_by_path_u32(blob, "/plb", "clock-frequency", sys_info.freqPLB, 1);
+ do_fixup_by_path_u32(blob, "/plb/opb", "clock-frequency", sys_info.freqOPB, 1);
+
+ if (fdt_path_offset(blob, "/plb/opb/ebc") >= 0)
+ do_fixup_by_path_u32(blob, "/plb/opb/ebc", "clock-frequency",
+ sys_info.freqEBC, 1);
+ else
+ do_fixup_by_path_u32(blob, "/plb/ebc", "clock-frequency",
+ sys_info.freqEBC, 1);
+
+ fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize);
+
+ /*
+ * Fixup all UART clocks for CPU internal UARTs
+ * (only these UARTs are definitely clocked by gd->arch.uart_clk)
+ *
+ * These UARTs are direct childs of /plb/opb. This code
+ * does not touch any UARTs that are connected to the ebc.
+ */
+ off = fdt_path_offset(blob, "/plb/opb");
+ while ((off = fdt_next_node(blob, off, &ndepth)) >= 0) {
+ /*
+ * process all sub nodes and stop when we are back
+ * at the starting depth
+ */
+ if (ndepth <= 0)
+ break;
+
+ /* only update direct childs */
+ if ((ndepth == 1) &&
+ (fdt_node_check_compatible(blob, off, "ns16550") == 0))
+ fdt_setprop(blob, off,
+ "clock-frequency",
+ (void *)&gd->arch.uart_clk, 4);
+ }
+
+ /*
+ * Fixup all ethernet nodes
+ * Note: aliases in the dts are required for this
+ */
+ fdt_fixup_ethernet(blob);
+
+ /*
+ * Fixup all available PCIe nodes by setting the device_type property
+ */
+ fdt_pcie_setup(blob);
+}
+#endif /* CONFIG_OF_LIBFDT && CONFIG_OF_BOARD_SETUP */
diff --git a/arch/powerpc/cpu/ppc4xx/gpio.c b/arch/powerpc/cpu/ppc4xx/gpio.c
new file mode 100644
index 0000000..20f0572
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/gpio.c
@@ -0,0 +1,260 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/ppc4xx-gpio.h>
+
+/* Only compile this file for boards with GPIO support */
+#if defined(GPIO0_BASE)
+
+#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
+gpio_param_s const gpio_tab[GPIO_GROUP_MAX][GPIO_MAX] = CONFIG_SYS_4xx_GPIO_TABLE;
+#endif
+
+#if defined(GPIO0_OSRL)
+/* Only some 4xx variants support alternate funtions on the GPIO's */
+void gpio_config(int pin, int in_out, int gpio_alt, int out_val)
+{
+ u32 mask;
+ u32 mask2;
+ u32 val;
+ u32 offs = 0;
+ u32 offs2 = 0;
+ int pin2 = pin << 1;
+
+ if (pin >= GPIO_MAX) {
+ offs = 0x100;
+ pin -= GPIO_MAX;
+ }
+
+ if (pin >= GPIO_MAX/2) {
+ offs2 = 0x4;
+ pin2 = (pin - GPIO_MAX/2) << 1;
+ }
+
+ mask = 0x80000000 >> pin;
+ mask2 = 0xc0000000 >> pin2;
+
+ /* first set TCR to 0 */
+ out_be32((void *)GPIO0_TCR + offs, in_be32((void *)GPIO0_TCR + offs) & ~mask);
+
+ if (in_out == GPIO_OUT) {
+ val = in_be32((void *)GPIO0_OSRL + offs + offs2) & ~mask2;
+ switch (gpio_alt) {
+ case GPIO_ALT1:
+ val |= GPIO_ALT1_SEL >> pin2;
+ break;
+ case GPIO_ALT2:
+ val |= GPIO_ALT2_SEL >> pin2;
+ break;
+ case GPIO_ALT3:
+ val |= GPIO_ALT3_SEL >> pin2;
+ break;
+ }
+ out_be32((void *)GPIO0_OSRL + offs + offs2, val);
+
+ /* setup requested output value */
+ if (out_val == GPIO_OUT_0)
+ out_be32((void *)GPIO0_OR + offs,
+ in_be32((void *)GPIO0_OR + offs) & ~mask);
+ else if (out_val == GPIO_OUT_1)
+ out_be32((void *)GPIO0_OR + offs,
+ in_be32((void *)GPIO0_OR + offs) | mask);
+
+ /* now configure TCR to drive output if selected */
+ out_be32((void *)GPIO0_TCR + offs,
+ in_be32((void *)GPIO0_TCR + offs) | mask);
+ } else {
+ val = in_be32((void *)GPIO0_ISR1L + offs + offs2) & ~mask2;
+ val |= GPIO_IN_SEL >> pin2;
+ out_be32((void *)GPIO0_ISR1L + offs + offs2, val);
+ }
+}
+#endif /* GPIO_OSRL */
+
+void gpio_write_bit(int pin, int val)
+{
+ u32 offs = 0;
+
+ if (pin >= GPIO_MAX) {
+ offs = 0x100;
+ pin -= GPIO_MAX;
+ }
+
+ if (val)
+ out_be32((void *)GPIO0_OR + offs,
+ in_be32((void *)GPIO0_OR + offs) | GPIO_VAL(pin));
+ else
+ out_be32((void *)GPIO0_OR + offs,
+ in_be32((void *)GPIO0_OR + offs) & ~GPIO_VAL(pin));
+}
+
+int gpio_read_out_bit(int pin)
+{
+ u32 offs = 0;
+
+ if (pin >= GPIO_MAX) {
+ offs = 0x100;
+ pin -= GPIO_MAX;
+ }
+
+ return (in_be32((void *)GPIO0_OR + offs) & GPIO_VAL(pin) ? 1 : 0);
+}
+
+int gpio_read_in_bit(int pin)
+{
+ u32 offs = 0;
+
+ if (pin >= GPIO_MAX) {
+ offs = 0x100;
+ pin -= GPIO_MAX;
+ }
+
+ return (in_be32((void *)GPIO0_IR + offs) & GPIO_VAL(pin) ? 1 : 0);
+}
+
+#if defined(CONFIG_SYS_4xx_GPIO_TABLE)
+void gpio_set_chip_configuration(void)
+{
+ unsigned char i=0, j=0, offs=0, gpio_core;
+ unsigned long reg, core_add;
+
+ for (gpio_core=0; gpio_core<GPIO_GROUP_MAX; gpio_core++) {
+ j = 0;
+ offs = 0;
+ /* GPIO config of the GPIOs 0 to 31 */
+ for (i=0; i<GPIO_MAX; i++, j++) {
+ if (i == GPIO_MAX/2) {
+ offs = 4;
+ j = i-16;
+ }
+
+ core_add = gpio_tab[gpio_core][i].add;
+
+ if ((gpio_tab[gpio_core][i].in_out == GPIO_IN) ||
+ (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
+
+ switch (gpio_tab[gpio_core][i].alt_nb) {
+ case GPIO_SEL:
+ break;
+
+ case GPIO_ALT1:
+ reg = in_be32((void *)GPIO_IS1(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_IN_SEL >> (j*2));
+ out_be32((void *)GPIO_IS1(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT2:
+ reg = in_be32((void *)GPIO_IS2(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_IN_SEL >> (j*2));
+ out_be32((void *)GPIO_IS2(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT3:
+ reg = in_be32((void *)GPIO_IS3(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (GPIO_IN_SEL >> (j*2));
+ out_be32((void *)GPIO_IS3(core_add+offs), reg);
+ break;
+ }
+ }
+
+ if ((gpio_tab[gpio_core][i].in_out == GPIO_OUT) ||
+ (gpio_tab[gpio_core][i].in_out == GPIO_BI)) {
+
+ u32 gpio_alt_sel = 0;
+
+ switch (gpio_tab[gpio_core][i].alt_nb) {
+ case GPIO_SEL:
+ /*
+ * Setup output value
+ * 1 -> high level
+ * 0 -> low level
+ * else -> don't touch
+ */
+ reg = in_be32((void *)GPIO_OR(core_add));
+ if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1)
+ reg |= (0x80000000 >> (i));
+ else if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_0)
+ reg &= ~(0x80000000 >> (i));
+ out_be32((void *)GPIO_OR(core_add), reg);
+
+ reg = in_be32((void *)GPIO_TCR(core_add)) |
+ (0x80000000 >> (i));
+ out_be32((void *)GPIO_TCR(core_add), reg);
+
+ reg = in_be32((void *)GPIO_OS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ out_be32((void *)GPIO_OS(core_add+offs), reg);
+ reg = in_be32((void *)GPIO_TS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ out_be32((void *)GPIO_TS(core_add+offs), reg);
+ break;
+
+ case GPIO_ALT1:
+ gpio_alt_sel = GPIO_ALT1_SEL;
+ break;
+
+ case GPIO_ALT2:
+ gpio_alt_sel = GPIO_ALT2_SEL;
+ break;
+
+ case GPIO_ALT3:
+ gpio_alt_sel = GPIO_ALT3_SEL;
+ break;
+ }
+
+ if (0 != gpio_alt_sel) {
+ reg = in_be32((void *)GPIO_OS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (gpio_alt_sel >> (j*2));
+ out_be32((void *)GPIO_OS(core_add+offs), reg);
+
+ if (gpio_tab[gpio_core][i].out_val == GPIO_OUT_1) {
+ reg = in_be32((void *)GPIO_TCR(core_add))
+ | (0x80000000 >> (i));
+ out_be32((void *)GPIO_TCR(core_add), reg);
+ reg = in_be32((void *)GPIO_TS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ out_be32((void *)GPIO_TS(core_add+offs), reg);
+ } else {
+ reg = in_be32((void *)GPIO_TCR(core_add))
+ & ~(0x80000000 >> (i));
+ out_be32((void *)GPIO_TCR(core_add), reg);
+ reg = in_be32((void *)GPIO_TS(core_add+offs))
+ & ~(GPIO_MASK >> (j*2));
+ reg = reg | (gpio_alt_sel >> (j*2));
+ out_be32((void *)GPIO_TS(core_add+offs), reg);
+ }
+ }
+ }
+ }
+ }
+}
+
+#endif /* GPIO0_BASE */
+#endif /* CONFIG_SYS_4xx_GPIO_TABLE */
diff --git a/arch/powerpc/cpu/ppc4xx/interrupts.c b/arch/powerpc/cpu/ppc4xx/interrupts.c
new file mode 100644
index 0000000..d0bca92
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/interrupts.c
@@ -0,0 +1,209 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 (440GX port)
+ * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+ *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <asm/ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * CPM interrupt vector functions.
+ */
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ int count;
+};
+static struct irq_action irq_vecs[IRQ_MAX];
+
+#if defined(CONFIG_440)
+
+/* SPRN changed in 440 */
+static __inline__ void set_evpr(unsigned long val)
+{
+ asm volatile("mtspr 0x03f,%0" : : "r" (val));
+}
+
+#else /* !defined(CONFIG_440) */
+
+static __inline__ void set_pit(unsigned long val)
+{
+ asm volatile("mtpit %0" : : "r" (val));
+}
+
+static __inline__ void set_evpr(unsigned long val)
+{
+ asm volatile("mtevpr %0" : : "r" (val));
+}
+#endif /* defined(CONFIG_440 */
+
+int interrupt_init_cpu (unsigned *decrementer_count)
+{
+ int vec;
+ unsigned long val;
+
+ /* decrementer is automatically reloaded */
+ *decrementer_count = 0;
+
+ /*
+ * Mark all irqs as free
+ */
+ for (vec = 0; vec < IRQ_MAX; vec++) {
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
+ irq_vecs[vec].count = 0;
+ }
+
+#ifdef CONFIG_4xx
+ /*
+ * Init PIT
+ */
+#if defined(CONFIG_440)
+ val = mfspr( SPRN_TCR );
+ val &= (~0x04400000); /* clear DIS & ARE */
+ mtspr( SPRN_TCR, val );
+ mtspr( SPRN_DEC, 0 ); /* Prevent exception after TSR clear*/
+ mtspr( SPRN_DECAR, 0 ); /* clear reload */
+ mtspr( SPRN_TSR, 0x08000000 ); /* clear DEC status */
+ val = gd->bd->bi_intfreq/1000; /* 1 msec */
+ mtspr( SPRN_DECAR, val ); /* Set auto-reload value */
+ mtspr( SPRN_DEC, val ); /* Set inital val */
+#else
+ set_pit(gd->bd->bi_intfreq / 1000);
+#endif
+#endif /* CONFIG_4xx */
+
+#ifdef CONFIG_ADCIOP
+ /*
+ * Init PIT
+ */
+ set_pit(66000);
+#endif
+
+ /*
+ * Enable PIT
+ */
+ val = mfspr(SPRN_TCR);
+ val |= 0x04400000;
+ mtspr(SPRN_TCR, val);
+
+ /*
+ * Set EVPR to 0
+ */
+ set_evpr(0x00000000);
+
+ /*
+ * Call uic or xilinx_irq pic_enable
+ */
+ pic_enable();
+
+ return (0);
+}
+
+void timer_interrupt_cpu(struct pt_regs *regs)
+{
+ /* nothing to do here */
+ return;
+}
+
+void interrupt_run_handler(int vec)
+{
+ irq_vecs[vec].count++;
+
+ if (irq_vecs[vec].handler != NULL) {
+ /* call isr */
+ (*irq_vecs[vec].handler) (irq_vecs[vec].arg);
+ } else {
+ pic_irq_disable(vec);
+ printf("Masking bogus interrupt vector %d\n", vec);
+ }
+
+ pic_irq_ack(vec);
+ return;
+}
+
+void irq_install_handler(int vec, interrupt_handler_t * handler, void *arg)
+{
+ /*
+ * Print warning when replacing with a different irq vector
+ */
+ if ((irq_vecs[vec].handler != NULL) && (irq_vecs[vec].handler != handler)) {
+ printf("Interrupt vector %d: handler 0x%x replacing 0x%x\n",
+ vec, (uint) handler, (uint) irq_vecs[vec].handler);
+ }
+ irq_vecs[vec].handler = handler;
+ irq_vecs[vec].arg = arg;
+
+ pic_irq_enable(vec);
+ return;
+}
+
+void irq_free_handler(int vec)
+{
+ debug("Free interrupt for vector %d ==> %p\n",
+ vec, irq_vecs[vec].handler);
+
+ pic_irq_disable(vec);
+
+ irq_vecs[vec].handler = NULL;
+ irq_vecs[vec].arg = NULL;
+ return;
+}
+
+#if defined(CONFIG_CMD_IRQ)
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int vec;
+
+ printf ("Interrupt-Information:\n");
+ printf ("Nr Routine Arg Count\n");
+
+ for (vec = 0; vec < IRQ_MAX; vec++) {
+ if (irq_vecs[vec].handler != NULL) {
+ printf ("%02d %08lx %08lx %d\n",
+ vec,
+ (ulong)irq_vecs[vec].handler,
+ (ulong)irq_vecs[vec].arg,
+ irq_vecs[vec].count);
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/kgdb.S b/arch/powerpc/cpu/ppc4xx/kgdb.S
new file mode 100644
index 0000000..417ba62
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/kgdb.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2000 Murray Jensen <Murray.Jensen@cmst.csiro.au>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <command.h>
+#include <asm/ppc4xx.h>
+#include <version.h>
+
+#define CONFIG_405GP 1 /* needed for Linux kernel header files */
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+#if defined(CONFIG_CMD_KGDB)
+ /*
+ * cache flushing routines for kgdb
+ */
+
+ .globl kgdb_flush_cache_all
+kgdb_flush_cache_all:
+ /* icache */
+ iccci r0,r0 /* iccci invalidates the entire I cache */
+ /* dcache */
+ addi r6,0,0x0000 /* clear GPR 6 */
+ addi r7,r0, 128 /* do loop for # of dcache lines */
+ /* NOTE: dccci invalidates both */
+ mtctr r7 /* ways in the D cache */
+..dcloop:
+ dccci 0,r6 /* invalidate line */
+ addi r6,r6, 32 /* bump to next line */
+ bdnz ..dcloop
+ blr
+
+ .globl kgdb_flush_cache_range
+kgdb_flush_cache_range:
+ li r5,L1_CACHE_BYTES-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,L1_CACHE_SHIFT
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,L1_CACHE_BYTES
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,L1_CACHE_BYTES
+ bdnz 2b
+ SYNC
+ blr
+
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/miiphy.c b/arch/powerpc/cpu/ppc4xx/miiphy.c
new file mode 100644
index 0000000..297155f
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/miiphy.c
@@ -0,0 +1,365 @@
+/*-----------------------------------------------------------------------------+
+ | This source code is dual-licensed. You may use it under the terms of the
+ | GNU General Public License version 2, or under the license below.
+ |
+ | This source code has been made available to you by IBM on an AS-IS
+ | basis. Anyone receiving this source is licensed under IBM
+ | copyrights to use it in any way he or she deems fit, including
+ | copying it, modifying it, compiling it, and redistributing it either
+ | with or without modifications. No license under IBM patents or
+ | patent applications is to be implied by the copyright license.
+ |
+ | Any user of this software should understand that IBM cannot provide
+ | technical support for this software and will not be responsible for
+ | any consequences resulting from the use of this software.
+ |
+ | Any person who transfers this source code or any derivative work
+ | must include the IBM copyright notice, this paragraph, and the
+ | preceding two paragraphs in the transferred software.
+ |
+ | COPYRIGHT I B M CORPORATION 1995
+ | LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
+ +-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------+
+ |
+ | File Name: miiphy.c
+ |
+ | Function: This module has utilities for accessing the MII PHY through
+ | the EMAC3 macro.
+ |
+ | Author: Mark Wisner
+ |
+ +-----------------------------------------------------------------------------*/
+
+/* define DEBUG for debugging output (obviously ;-)) */
+#if 0
+#define DEBUG
+#endif
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+#include <asm/ppc4xx-emac.h>
+#include <asm/ppc4xx-mal.h>
+#include <miiphy.h>
+
+#if !defined(CONFIG_PHY_CLK_FREQ)
+#define CONFIG_PHY_CLK_FREQ 0
+#endif
+
+/***********************************************************/
+/* Dump out to the screen PHY regs */
+/***********************************************************/
+
+void miiphy_dump (char *devname, unsigned char addr)
+{
+ unsigned long i;
+ unsigned short data;
+
+ for (i = 0; i < 0x1A; i++) {
+ if (miiphy_read (devname, addr, i, &data)) {
+ printf ("read error for reg %lx\n", i);
+ return;
+ }
+ printf ("Phy reg %lx ==> %4x\n", i, data);
+
+ /* jump to the next set of regs */
+ if (i == 0x07)
+ i = 0x0f;
+
+ } /* end for loop */
+} /* end dump */
+
+/***********************************************************/
+/* (Re)start autonegotiation */
+/***********************************************************/
+int phy_setup_aneg (char *devname, unsigned char addr)
+{
+ u16 bmcr;
+
+#if defined(CONFIG_PHY_DYNAMIC_ANEG)
+ /*
+ * Set up advertisement based on capablilities reported by the PHY.
+ * This should work for both copper and fiber.
+ */
+ u16 bmsr;
+#if defined(CONFIG_PHY_GIGE)
+ u16 exsr = 0x0000;
+#endif
+
+ miiphy_read (devname, addr, MII_BMSR, &bmsr);
+
+#if defined(CONFIG_PHY_GIGE)
+ if (bmsr & BMSR_ESTATEN)
+ miiphy_read (devname, addr, MII_ESTATUS, &exsr);
+
+ if (exsr & (ESTATUS_1000XF | ESTATUS_1000XH)) {
+ /* 1000BASE-X */
+ u16 anar = 0x0000;
+
+ if (exsr & ESTATUS_1000XF)
+ anar |= ADVERTISE_1000XFULL;
+
+ if (exsr & ESTATUS_1000XH)
+ anar |= ADVERTISE_1000XHALF;
+
+ miiphy_write (devname, addr, MII_ADVERTISE, anar);
+ } else
+#endif
+ {
+ u16 anar, btcr;
+
+ miiphy_read (devname, addr, MII_ADVERTISE, &anar);
+ anar &= ~(0x5000 | LPA_100BASE4 | LPA_100FULL |
+ LPA_100HALF | LPA_10FULL | LPA_10HALF);
+
+ miiphy_read (devname, addr, MII_CTRL1000, &btcr);
+ btcr &= ~(0x00FF | PHY_1000BTCR_1000FD | PHY_1000BTCR_1000HD);
+
+ if (bmsr & BMSR_100BASE4)
+ anar |= LPA_100BASE4;
+
+ if (bmsr & BMSR_100FULL)
+ anar |= LPA_100FULL;
+
+ if (bmsr & BMSR_100HALF)
+ anar |= LPA_100HALF;
+
+ if (bmsr & BMSR_10FULL)
+ anar |= LPA_10FULL;
+
+ if (bmsr & BMSR_10HALF)
+ anar |= LPA_10HALF;
+
+ miiphy_write (devname, addr, MII_ADVERTISE, anar);
+
+#if defined(CONFIG_PHY_GIGE)
+ if (exsr & ESTATUS_1000_TFULL)
+ btcr |= PHY_1000BTCR_1000FD;
+
+ if (exsr & ESTATUS_1000_THALF)
+ btcr |= PHY_1000BTCR_1000HD;
+
+ miiphy_write (devname, addr, MII_CTRL1000, btcr);
+#endif
+ }
+
+#else /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
+ /*
+ * Set up standard advertisement
+ */
+ u16 adv;
+
+ miiphy_read (devname, addr, MII_ADVERTISE, &adv);
+ adv |= (LPA_LPACK | LPA_100FULL | LPA_100HALF |
+ LPA_10FULL | LPA_10HALF);
+ miiphy_write (devname, addr, MII_ADVERTISE, adv);
+
+ miiphy_read (devname, addr, MII_CTRL1000, &adv);
+ adv |= (0x0300);
+ miiphy_write (devname, addr, MII_CTRL1000, adv);
+
+#endif /* defined(CONFIG_PHY_DYNAMIC_ANEG) */
+
+ /* Start/Restart aneg */
+ miiphy_read (devname, addr, MII_BMCR, &bmcr);
+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+ miiphy_write (devname, addr, MII_BMCR, bmcr);
+
+ return 0;
+}
+
+/***********************************************************/
+/* read a phy reg and return the value with a rc */
+/***********************************************************/
+/* AMCC_TODO:
+ * Find out of the choice for the emac for MDIO is from the bridges,
+ * i.e. ZMII or RGMII as approporiate. If the bridges are not used
+ * to determine the emac for MDIO, then is the SDR0_ETH_CFG[MDIO_SEL]
+ * used? If so, then this routine below does not apply to the 460EX/GT.
+ *
+ * sr: Currently on 460EX only EMAC0 works with MDIO, so we always
+ * return EMAC0 offset here
+ * vg: For 460EX/460GT if internal GPCS PHY address is specified
+ * return appropriate EMAC offset
+ */
+unsigned int miiphy_getemac_offset(u8 addr)
+{
+#if defined(CONFIG_440) && \
+ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) && \
+ !defined(CONFIG_460EX) && !defined(CONFIG_460GT)
+ unsigned long zmii;
+ unsigned long eoffset;
+
+ /* Need to find out which mdi port we're using */
+ zmii = in_be32((void *)ZMII0_FER);
+
+ if (zmii & (ZMII_FER_MDI << ZMII_FER_V (0)))
+ /* using port 0 */
+ eoffset = 0;
+
+ else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (1)))
+ /* using port 1 */
+ eoffset = 0x100;
+
+ else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (2)))
+ /* using port 2 */
+ eoffset = 0x400;
+
+ else if (zmii & (ZMII_FER_MDI << ZMII_FER_V (3)))
+ /* using port 3 */
+ eoffset = 0x600;
+
+ else {
+ /* None of the mdi ports are enabled! */
+ /* enable port 0 */
+ zmii |= ZMII_FER_MDI << ZMII_FER_V (0);
+ out_be32((void *)ZMII0_FER, zmii);
+ eoffset = 0;
+ /* need to soft reset port 0 */
+ zmii = in_be32((void *)EMAC0_MR0);
+ zmii |= EMAC_MR0_SRST;
+ out_be32((void *)EMAC0_MR0, zmii);
+ }
+
+ return (eoffset);
+#else
+
+#if defined(CONFIG_405EX)
+ unsigned long rgmii;
+ int devnum = 1;
+
+ rgmii = in_be32((void *)RGMII_FER);
+ if (rgmii & (1 << (19 - devnum)))
+ return 0x100;
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ u32 eoffset = 0;
+
+ switch (addr) {
+#if defined(CONFIG_HAS_ETH1) && defined(CONFIG_GPCS_PHY1_ADDR)
+ case CONFIG_GPCS_PHY1_ADDR:
+ if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x100)))
+ eoffset = 0x100;
+ break;
+#endif
+#if defined(CONFIG_HAS_ETH2) && defined(CONFIG_GPCS_PHY2_ADDR)
+ case CONFIG_GPCS_PHY2_ADDR:
+ if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x300)))
+ eoffset = 0x300;
+ break;
+#endif
+#if defined(CONFIG_HAS_ETH3) && defined(CONFIG_GPCS_PHY3_ADDR)
+ case CONFIG_GPCS_PHY3_ADDR:
+ if (addr == EMAC_MR1_IPPA_GET(in_be32((void *)EMAC0_MR1 + 0x400)))
+ eoffset = 0x400;
+ break;
+#endif
+ default:
+ eoffset = 0;
+ break;
+ }
+ return eoffset;
+#endif
+
+ return 0;
+#endif
+}
+
+static int emac_miiphy_wait(u32 emac_reg)
+{
+ u32 sta_reg;
+ int i;
+
+ /* wait for completion */
+ i = 0;
+ do {
+ sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
+ if (i++ > 5) {
+ debug("%s [%d]: Timeout! EMAC0_STACR=0x%0x\n", __func__,
+ __LINE__, sta_reg);
+ return -1;
+ }
+ udelay(10);
+ } while ((sta_reg & EMAC_STACR_OC) == EMAC_STACR_OC_MASK);
+
+ return 0;
+}
+
+static int emac_miiphy_command(u8 addr, u8 reg, int cmd, u16 value)
+{
+ u32 emac_reg;
+ u32 sta_reg;
+
+ emac_reg = miiphy_getemac_offset(addr);
+
+ /* wait for completion */
+ if (emac_miiphy_wait(emac_reg) != 0)
+ return -1;
+
+ sta_reg = reg; /* reg address */
+
+ /* set clock (50MHz) and read flags */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
+#if defined(CONFIG_IBM_EMAC4_V4) /* EMAC4 V4 changed bit setting */
+ sta_reg = (sta_reg & ~EMAC_STACR_OP_MASK) | cmd;
+#else
+ sta_reg |= cmd;
+#endif
+#else
+ sta_reg = (sta_reg | cmd) & ~EMAC_STACR_CLK_100MHZ;
+#endif
+
+ /* Some boards (mainly 405EP based) define the PHY clock freqency fixed */
+ sta_reg = sta_reg | CONFIG_PHY_CLK_FREQ;
+ sta_reg = sta_reg | ((u32)addr << 5); /* Phy address */
+ sta_reg = sta_reg | EMAC_STACR_OC_MASK; /* new IBM emac v4 */
+ if (cmd == EMAC_STACR_WRITE)
+ memcpy(&sta_reg, &value, 2); /* put in data */
+
+ out_be32((void *)EMAC0_STACR + emac_reg, sta_reg);
+ debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
+
+ /* wait for completion */
+ if (emac_miiphy_wait(emac_reg) != 0)
+ return -1;
+
+ debug("%s [%d]: sta_reg=%08x\n", __func__, __LINE__, sta_reg);
+ if ((sta_reg & EMAC_STACR_PHYE) != 0)
+ return -1;
+
+ return 0;
+}
+
+int emac4xx_miiphy_read (const char *devname, unsigned char addr, unsigned char reg,
+ unsigned short *value)
+{
+ unsigned long sta_reg;
+ unsigned long emac_reg;
+
+ emac_reg = miiphy_getemac_offset(addr);
+
+ if (emac_miiphy_command(addr, reg, EMAC_STACR_READ, 0) != 0)
+ return -1;
+
+ sta_reg = in_be32((void *)EMAC0_STACR + emac_reg);
+ *value = sta_reg >> 16;
+
+ return 0;
+}
+
+/***********************************************************/
+/* write a phy reg and return the value with a rc */
+/***********************************************************/
+
+int emac4xx_miiphy_write (const char *devname, unsigned char addr, unsigned char reg,
+ unsigned short value)
+{
+ return emac_miiphy_command(addr, reg, EMAC_STACR_WRITE, value);
+}
diff --git a/arch/powerpc/cpu/ppc4xx/reginfo.c b/arch/powerpc/cpu/ppc4xx/reginfo.c
new file mode 100644
index 0000000..2f1ab9e
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/reginfo.c
@@ -0,0 +1,370 @@
+/*
+ *(C) Copyright 2005-2009 Netstal Maschinen AG
+ * Bruno Hars (Bruno.Hars@netstal.com)
+ * Niklaus Giger (Niklaus.Giger@netstal.com)
+ *
+ * This source code is free software; you can redistribute it
+ * and/or modify it in source code form under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/*
+ * reginfo.c - register dump of HW-configuratin register for PPC4xx based board
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/ppc4xx-uic.h>
+#include <asm/ppc4xx-emac.h>
+
+enum REGISTER_TYPE {
+ IDCR1, /* Indirectly Accessed DCR via SDRAM0_CFGADDR/SDRAM0_CFGDATA */
+ IDCR2, /* Indirectly Accessed DCR via EBC0_CFGADDR/EBC0_CFGDATA */
+ IDCR3, /* Indirectly Accessed DCR via EBM0_CFGADDR/EBM0_CFGDATA */
+ IDCR4, /* Indirectly Accessed DCR via PPM0_CFGADDR/PPM0_CFGDATA */
+ IDCR5, /* Indirectly Accessed DCR via CPR0_CFGADDR/CPR0_CFGDATA */
+ IDCR6, /* Indirectly Accessed DCR via SDR0_CFGADDR/SDR0_CFGDATA */
+ MM /* Directly Accessed MMIO Register */
+};
+
+struct cpu_register {
+ char *name;
+ enum REGISTER_TYPE type;
+ u32 address;
+};
+
+/*
+ * PPC440EPx registers ordered for output
+ * name type addr size
+ * -------------------------------------------
+ */
+
+const struct cpu_register ppc4xx_reg[] = {
+ {"PB0CR", IDCR2, PB0CR},
+ {"PB0AP", IDCR2, PB0AP},
+ {"PB1CR", IDCR2, PB1CR},
+ {"PB1AP", IDCR2, PB1AP},
+ {"PB2CR", IDCR2, PB2CR},
+ {"PB2AP", IDCR2, PB2AP},
+ {"PB3CR", IDCR2, PB3CR},
+ {"PB3AP", IDCR2, PB3AP},
+
+ {"PB4CR", IDCR2, PB4CR},
+ {"PB4AP", IDCR2, PB4AP},
+#if !defined(CONFIG_405EP)
+ {"PB5CR", IDCR2, PB5CR},
+ {"PB5AP", IDCR2, PB5AP},
+ {"PB6CR", IDCR2, PB6CR},
+ {"PB6AP", IDCR2, PB6AP},
+ {"PB7CR", IDCR2, PB7CR},
+ {"PB7AP", IDCR2, PB7AP},
+#endif
+
+ {"PBEAR", IDCR2, PBEAR},
+#if defined(CONFIG_405EP) || defined (CONFIG_405GP)
+ {"PBESR0", IDCR2, PBESR0},
+ {"PBESR1", IDCR2, PBESR1},
+#endif
+ {"EBC0_CFG", IDCR2, EBC0_CFG},
+
+#ifdef CONFIG_405GP
+ {"SDRAM0_BESR0", IDCR1, SDRAM0_BESR0},
+ {"SDRAM0_BESRS0", IDCR1, SDRAM0_BESRS0},
+ {"SDRAM0_BESR1", IDCR1, SDRAM0_BESR1},
+ {"SDRAM0_BESRS1", IDCR1, SDRAM0_BESRS1},
+ {"SDRAM0_BEAR", IDCR1, SDRAM0_BEAR},
+ {"SDRAM0_CFG", IDCR1, SDRAM0_CFG},
+ {"SDRAM0_RTR", IDCR1, SDRAM0_RTR},
+ {"SDRAM0_PMIT", IDCR1, SDRAM0_PMIT},
+
+ {"SDRAM0_B0CR", IDCR1, SDRAM0_B0CR},
+ {"SDRAM0_B1CR", IDCR1, SDRAM0_B1CR},
+ {"SDRAM0_B2CR", IDCR1, SDRAM0_B2CR},
+ {"SDRAM0_B3CR", IDCR1, SDRAM0_B1CR},
+ {"SDRAM0_TR", IDCR1, SDRAM0_TR},
+ {"SDRAM0_ECCCFG", IDCR1, SDRAM0_B1CR},
+ {"SDRAM0_ECCESR", IDCR1, SDRAM0_ECCESR},
+
+
+#endif
+
+#ifdef CONFIG_440EPX
+ {"SDR0_SDSTP0", IDCR6, SDR0_SDSTP0},
+ {"SDR0_SDSTP1", IDCR6, SDR0_SDSTP1},
+ {"SDR0_SDSTP2", IDCR6, SDR0_SDSTP2},
+ {"SDR0_SDSTP3", IDCR6, SDR0_SDSTP3},
+ {"SDR0_CUST0", IDCR6, SDR0_CUST0},
+ {"SDR0_CUST1", IDCR6, SDR0_CUST1},
+ {"SDR0_EBC", IDCR6, SDR0_EBC},
+ {"SDR0_AMP0", IDCR6, SDR0_AMP0},
+ {"SDR0_AMP1", IDCR6, SDR0_AMP1},
+ {"SDR0_CP440", IDCR6, SDR0_CP440},
+ {"SDR0_CRYP0", IDCR6, SDR0_CRYP0},
+ {"SDR0_DDRCFG", IDCR6, SDR0_DDRCFG},
+ {"SDR0_EMAC0RXST", IDCR6, SDR0_EMAC0RXST},
+ {"SDR0_EMAC0TXST", IDCR6, SDR0_EMAC0TXST},
+ {"SDR0_MFR", IDCR6, SDR0_MFR},
+ {"SDR0_PCI0", IDCR6, SDR0_PCI0},
+ {"SDR0_PFC0", IDCR6, SDR0_PFC0},
+ {"SDR0_PFC1", IDCR6, SDR0_PFC1},
+ {"SDR0_PFC2", IDCR6, SDR0_PFC2},
+ {"SDR0_PFC4", IDCR6, SDR0_PFC4},
+ {"SDR0_UART0", IDCR6, SDR0_UART0},
+ {"SDR0_UART1", IDCR6, SDR0_UART1},
+ {"SDR0_UART2", IDCR6, SDR0_UART2},
+ {"SDR0_UART3", IDCR6, SDR0_UART3},
+ {"DDR0_02", IDCR1, DDR0_02},
+ {"DDR0_00", IDCR1, DDR0_00},
+ {"DDR0_01", IDCR1, DDR0_01},
+ {"DDR0_03", IDCR1, DDR0_03},
+ {"DDR0_04", IDCR1, DDR0_04},
+ {"DDR0_05", IDCR1, DDR0_05},
+ {"DDR0_06", IDCR1, DDR0_06},
+ {"DDR0_07", IDCR1, DDR0_07},
+ {"DDR0_08", IDCR1, DDR0_08},
+ {"DDR0_09", IDCR1, DDR0_09},
+ {"DDR0_10", IDCR1, DDR0_10},
+ {"DDR0_11", IDCR1, DDR0_11},
+ {"DDR0_12", IDCR1, DDR0_12},
+ {"DDR0_14", IDCR1, DDR0_14},
+ {"DDR0_17", IDCR1, DDR0_17},
+ {"DDR0_18", IDCR1, DDR0_18},
+ {"DDR0_19", IDCR1, DDR0_19},
+ {"DDR0_20", IDCR1, DDR0_20},
+ {"DDR0_21", IDCR1, DDR0_21},
+ {"DDR0_22", IDCR1, DDR0_22},
+ {"DDR0_23", IDCR1, DDR0_23},
+ {"DDR0_24", IDCR1, DDR0_24},
+ {"DDR0_25", IDCR1, DDR0_25},
+ {"DDR0_26", IDCR1, DDR0_26},
+ {"DDR0_27", IDCR1, DDR0_27},
+ {"DDR0_28", IDCR1, DDR0_28},
+ {"DDR0_31", IDCR1, DDR0_31},
+ {"DDR0_32", IDCR1, DDR0_32},
+ {"DDR0_33", IDCR1, DDR0_33},
+ {"DDR0_34", IDCR1, DDR0_34},
+ {"DDR0_35", IDCR1, DDR0_35},
+ {"DDR0_36", IDCR1, DDR0_36},
+ {"DDR0_37", IDCR1, DDR0_37},
+ {"DDR0_38", IDCR1, DDR0_38},
+ {"DDR0_39", IDCR1, DDR0_39},
+ {"DDR0_40", IDCR1, DDR0_40},
+ {"DDR0_41", IDCR1, DDR0_41},
+ {"DDR0_42", IDCR1, DDR0_42},
+ {"DDR0_43", IDCR1, DDR0_43},
+ {"DDR0_44", IDCR1, DDR0_44},
+ {"CPR0_ICFG", IDCR5, CPR0_ICFG},
+ {"CPR0_MALD", IDCR5, CPR0_MALD},
+ {"CPR0_OPBD00", IDCR5, CPR0_OPBD0},
+ {"CPR0_PERD0", IDCR5, CPR0_PERD},
+ {"CPR0_PLLC0", IDCR5, CPR0_PLLC},
+ {"CPR0_PLLD0", IDCR5, CPR0_PLLD},
+ {"CPR0_PRIMAD0", IDCR5, CPR0_PRIMAD0},
+ {"CPR0_PRIMBD0", IDCR5, CPR0_PRIMBD0},
+ {"CPR0_SPCID", IDCR5, CPR0_SPCID},
+ {"SPI0_MODE", MM, SPI0_MODE},
+ {"IIC0_CLKDIV", MM, PCIL0_PMM1MA},
+ {"PCIL0_PMM0MA", MM, PCIL0_PMM0MA},
+ {"PCIL0_PMM1MA", MM, PCIL0_PMM1MA},
+ {"PCIL0_PTM1LA", MM, PCIL0_PMM1MA},
+ {"PCIL0_PTM1MS", MM, PCIL0_PTM1MS},
+ {"PCIL0_PTM2LA", MM, PCIL0_PMM1MA},
+ {"PCIL0_PTM2MS", MM, PCIL0_PTM2MS},
+ {"ZMII0_FER", MM, ZMII0_FER},
+ {"ZMII0_SSR", MM, ZMII0_SSR},
+ {"EMAC0_IPGVR", MM, EMAC0_IPGVR},
+ {"EMAC0_MR1", MM, EMAC0_MR1},
+ {"EMAC0_PTR", MM, EMAC0_PTR},
+ {"EMAC0_RWMR", MM, EMAC0_RWMR},
+ {"EMAC0_STACR", MM, EMAC0_STACR},
+ {"EMAC0_TMR0", MM, EMAC0_TMR0},
+ {"EMAC0_TMR1", MM, EMAC0_TMR1},
+ {"EMAC0_TRTR", MM, EMAC0_TRTR},
+ {"EMAC1_MR1", MM, EMAC1_MR1},
+ {"GPIO0_OR", MM, GPIO0_OR},
+ {"GPIO1_OR", MM, GPIO1_OR},
+ {"GPIO0_TCR", MM, GPIO0_TCR},
+ {"GPIO1_TCR", MM, GPIO1_TCR},
+ {"GPIO0_ODR", MM, GPIO0_ODR},
+ {"GPIO1_ODR", MM, GPIO1_ODR},
+ {"GPIO0_OSRL", MM, GPIO0_OSRL},
+ {"GPIO0_OSRH", MM, GPIO0_OSRH},
+ {"GPIO1_OSRL", MM, GPIO1_OSRL},
+ {"GPIO1_OSRH", MM, GPIO1_OSRH},
+ {"GPIO0_TSRL", MM, GPIO0_TSRL},
+ {"GPIO0_TSRH", MM, GPIO0_TSRH},
+ {"GPIO1_TSRL", MM, GPIO1_TSRL},
+ {"GPIO1_TSRH", MM, GPIO1_TSRH},
+ {"GPIO0_IR", MM, GPIO0_IR},
+ {"GPIO1_IR", MM, GPIO1_IR},
+ {"GPIO0_ISR1L", MM, GPIO0_ISR1L},
+ {"GPIO0_ISR1H", MM, GPIO0_ISR1H},
+ {"GPIO1_ISR1L", MM, GPIO1_ISR1L},
+ {"GPIO1_ISR1H", MM, GPIO1_ISR1H},
+ {"GPIO0_ISR2L", MM, GPIO0_ISR2L},
+ {"GPIO0_ISR2H", MM, GPIO0_ISR2H},
+ {"GPIO1_ISR2L", MM, GPIO1_ISR2L},
+ {"GPIO1_ISR2H", MM, GPIO1_ISR2H},
+ {"GPIO0_ISR3L", MM, GPIO0_ISR3L},
+ {"GPIO0_ISR3H", MM, GPIO0_ISR3H},
+ {"GPIO1_ISR3L", MM, GPIO1_ISR3L},
+ {"GPIO1_ISR3H", MM, GPIO1_ISR3H},
+ {"SDR0_USB2PHY0CR", IDCR6, SDR0_USB2PHY0CR},
+ {"SDR0_USB2H0CR", IDCR6, SDR0_USB2H0CR},
+ {"SDR0_USB2D0CR", IDCR6, SDR0_USB2D0CR},
+#endif
+};
+
+/*
+ * CPU Register dump of PPC4xx HW configuration registers
+ * Output: first all DCR-registers, then in order of struct ppc4xx_reg
+ */
+#define PRINT_DCR(dcr) printf("0x%08x %-16s: 0x%08x\n", dcr,#dcr, mfdcr(dcr));
+
+void ppc4xx_reginfo(void)
+{
+ unsigned int i;
+ unsigned int n;
+ u32 value;
+ enum REGISTER_TYPE type;
+#if defined (CONFIG_405EP)
+ printf("Dump PPC405EP HW configuration registers\n\n");
+#elif CONFIG_405GP
+ printf ("Dump 405GP HW configuration registers\n\n");
+#elif CONFIG_440EPX
+ printf("Dump PPC440EPx HW configuration registers\n\n");
+#endif
+ printf("MSR: 0x%08x\n", mfmsr());
+
+ printf ("\nUniversal Interrupt Controller Regs\n");
+ PRINT_DCR(UIC0SR);
+ PRINT_DCR(UIC0ER);
+ PRINT_DCR(UIC0CR);
+ PRINT_DCR(UIC0PR);
+ PRINT_DCR(UIC0TR);
+ PRINT_DCR(UIC0MSR);
+ PRINT_DCR(UIC0VR);
+ PRINT_DCR(UIC0VCR);
+
+#if (UIC_MAX > 1)
+ PRINT_DCR(UIC2SR);
+ PRINT_DCR(UIC2ER);
+ PRINT_DCR(UIC2CR);
+ PRINT_DCR(UIC2PR);
+ PRINT_DCR(UIC2TR);
+ PRINT_DCR(UIC2MSR);
+ PRINT_DCR(UIC2VR);
+ PRINT_DCR(UIC2VCR);
+#endif
+
+#if (UIC_MAX > 2)
+ PRINT_DCR(UIC2SR);
+ PRINT_DCR(UIC2ER);
+ PRINT_DCR(UIC2CR);
+ PRINT_DCR(UIC2PR);
+ PRINT_DCR(UIC2TR);
+ PRINT_DCR(UIC2MSR);
+ PRINT_DCR(UIC2VR);
+ PRINT_DCR(UIC2VCR);
+#endif
+
+#if (UIC_MAX > 3)
+ PRINT_DCR(UIC3SR);
+ PRINT_DCR(UIC3ER);
+ PRINT_DCR(UIC3CR);
+ PRINT_DCR(UIC3PR);
+ PRINT_DCR(UIC3TR);
+ PRINT_DCR(UIC3MSR);
+ PRINT_DCR(UIC3VR);
+ PRINT_DCR(UIC3VCR);
+#endif
+
+#if defined (CONFIG_405EP) || defined (CONFIG_405GP)
+ printf ("\n\nDMA Channels\n");
+ PRINT_DCR(DMASR);
+ PRINT_DCR(DMASGC);
+ PRINT_DCR(DMAADR);
+
+ PRINT_DCR(DMACR0);
+ PRINT_DCR(DMACT0);
+ PRINT_DCR(DMADA0);
+ PRINT_DCR(DMASA0);
+ PRINT_DCR(DMASB0);
+
+ PRINT_DCR(DMACR1);
+ PRINT_DCR(DMACT1);
+ PRINT_DCR(DMADA1);
+ PRINT_DCR(DMASA1);
+ PRINT_DCR(DMASB1);
+
+ PRINT_DCR(DMACR2);
+ PRINT_DCR(DMACT2);
+ PRINT_DCR(DMADA2);
+ PRINT_DCR(DMASA2);
+ PRINT_DCR(DMASB2);
+
+ PRINT_DCR(DMACR3);
+ PRINT_DCR(DMACT3);
+ PRINT_DCR(DMADA3);
+ PRINT_DCR(DMASA3);
+ PRINT_DCR(DMASB3);
+#endif
+
+ printf ("\n\nVarious HW-Configuration registers\n");
+#if defined (CONFIG_440EPX)
+ PRINT_DCR(MAL0_CFG);
+ PRINT_DCR(CPM0_ER);
+ PRINT_DCR(CPM1_ER);
+ PRINT_DCR(PLB4A0_ACR);
+ PRINT_DCR(PLB4A1_ACR);
+ PRINT_DCR(PLB3A0_ACR);
+ PRINT_DCR(OPB2PLB40_BCTRL);
+ PRINT_DCR(P4P3BO0_CFG);
+#endif
+ n = sizeof(ppc4xx_reg) / sizeof(ppc4xx_reg[0]);
+ for (i = 0; i < n; i++) {
+ value = 0;
+ type = ppc4xx_reg[i].type;
+ switch (type) {
+ case IDCR1: /* Indirect via SDRAM0_CFGADDR/DDR0_CFGDATA */
+ mtdcr(SDRAM0_CFGADDR, ppc4xx_reg[i].address);
+ value = mfdcr(SDRAM0_CFGDATA);
+ break;
+ case IDCR2: /* Indirect via EBC0_CFGADDR/EBC0_CFGDATA */
+ mtdcr(EBC0_CFGADDR, ppc4xx_reg[i].address);
+ value = mfdcr(EBC0_CFGDATA);
+ break;
+ case IDCR5: /* Indirect via CPR0_CFGADDR/CPR0_CFGDATA */
+ mtdcr(CPR0_CFGADDR, ppc4xx_reg[i].address);
+ value = mfdcr(CPR0_CFGDATA);
+ break;
+ case IDCR6: /* Indirect via SDR0_CFGADDR/SDR0_CFGDATA */
+ mtdcr(SDR0_CFGADDR, ppc4xx_reg[i].address);
+ value = mfdcr(SDR0_CFGDATA);
+ break;
+ case MM: /* Directly Accessed MMIO Register */
+ value = in_be32((const volatile unsigned __iomem *)
+ ppc4xx_reg[i].address);
+ break;
+ default:
+ printf("\nERROR: struct entry %d: unknown register"
+ "type\n", i);
+ break;
+ }
+ printf("0x%08x %-16s: 0x%08x\n",ppc4xx_reg[i].address,
+ ppc4xx_reg[i].name, value);
+ }
+}
diff --git a/arch/powerpc/cpu/ppc4xx/resetvec.S b/arch/powerpc/cpu/ppc4xx/resetvec.S
new file mode 100644
index 0000000..b3308bd
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/resetvec.S
@@ -0,0 +1,12 @@
+/* Copyright MontaVista Software Incorporated, 2000 */
+#include <config.h>
+ .section .resetvec,"ax"
+#if defined(CONFIG_440)
+ b _start_440
+#else
+#if defined(CONFIG_BOOT_PCI) && defined(CONFIG_MIP405)
+ b _start_pci
+#else
+ b _start
+#endif
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/sdram.c b/arch/powerpc/cpu/ppc4xx/sdram.c
new file mode 100644
index 0000000..b827daf
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/sdram.c
@@ -0,0 +1,468 @@
+/*
+ * (C) Copyright 2005-2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2006
+ * DAVE Srl <www.dave-tech.it>
+ *
+ * (C) Copyright 2002-2004
+ * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/ppc4xx.h>
+#include <asm/processor.h>
+#include "sdram.h"
+#include "ecc.h"
+
+#ifdef CONFIG_SDRAM_BANK0
+
+#ifndef CONFIG_440
+
+#ifndef CONFIG_SYS_SDRAM_TABLE
+sdram_conf_t mb0cf[] = {
+ {(128 << 20), 13, 0x000A4001}, /* (0-128MB) Address Mode 3, 13x10(4) */
+ {(64 << 20), 13, 0x00084001}, /* (0-64MB) Address Mode 3, 13x9(4) */
+ {(32 << 20), 12, 0x00062001}, /* (0-32MB) Address Mode 2, 12x9(4) */
+ {(16 << 20), 12, 0x00046001}, /* (0-16MB) Address Mode 4, 12x8(4) */
+ {(4 << 20), 11, 0x00008001}, /* (0-4MB) Address Mode 5, 11x8(2) */
+};
+#else
+sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE;
+#endif
+
+#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+
+#ifdef CONFIG_SYS_SDRAM_CASL
+static ulong ns2clks(ulong ns)
+{
+ ulong bus_period_x_10 = ONE_BILLION / (get_bus_freq(0) / 10);
+
+ return ((ns * 10) + bus_period_x_10) / bus_period_x_10;
+}
+#endif /* CONFIG_SYS_SDRAM_CASL */
+
+static ulong compute_sdtr1(ulong speed)
+{
+#ifdef CONFIG_SYS_SDRAM_CASL
+ ulong tmp;
+ ulong sdtr1 = 0;
+
+ /* CASL */
+ if (CONFIG_SYS_SDRAM_CASL < 2)
+ sdtr1 |= (1 << SDRAM0_TR_CASL);
+ else
+ if (CONFIG_SYS_SDRAM_CASL > 4)
+ sdtr1 |= (3 << SDRAM0_TR_CASL);
+ else
+ sdtr1 |= ((CONFIG_SYS_SDRAM_CASL-1) << SDRAM0_TR_CASL);
+
+ /* PTA */
+ tmp = ns2clks(CONFIG_SYS_SDRAM_PTA);
+ if ((tmp >= 2) && (tmp <= 4))
+ sdtr1 |= ((tmp-1) << SDRAM0_TR_PTA);
+ else
+ sdtr1 |= ((4-1) << SDRAM0_TR_PTA);
+
+ /* CTP */
+ tmp = ns2clks(CONFIG_SYS_SDRAM_CTP);
+ if ((tmp >= 2) && (tmp <= 4))
+ sdtr1 |= ((tmp-1) << SDRAM0_TR_CTP);
+ else
+ sdtr1 |= ((4-1) << SDRAM0_TR_CTP);
+
+ /* LDF */
+ tmp = ns2clks(CONFIG_SYS_SDRAM_LDF);
+ if ((tmp >= 2) && (tmp <= 4))
+ sdtr1 |= ((tmp-1) << SDRAM0_TR_LDF);
+ else
+ sdtr1 |= ((2-1) << SDRAM0_TR_LDF);
+
+ /* RFTA */
+ tmp = ns2clks(CONFIG_SYS_SDRAM_RFTA);
+ if ((tmp >= 4) && (tmp <= 10))
+ sdtr1 |= ((tmp-4) << SDRAM0_TR_RFTA);
+ else
+ sdtr1 |= ((10-4) << SDRAM0_TR_RFTA);
+
+ /* RCD */
+ tmp = ns2clks(CONFIG_SYS_SDRAM_RCD);
+ if ((tmp >= 2) && (tmp <= 4))
+ sdtr1 |= ((tmp-1) << SDRAM0_TR_RCD);
+ else
+ sdtr1 |= ((4-1) << SDRAM0_TR_RCD);
+
+ return sdtr1;
+#else /* CONFIG_SYS_SDRAM_CASL */
+ /*
+ * If no values are configured in the board config file
+ * use the default values, which seem to be ok for most
+ * boards.
+ *
+ * REMARK:
+ * For new board ports we strongly recommend to define the
+ * correct values for the used SDRAM chips in your board
+ * config file (see PPChameleonEVB.h)
+ */
+ if (speed > 100000000) {
+ /*
+ * 133 MHz SDRAM
+ */
+ return 0x01074015;
+ } else {
+ /*
+ * default: 100 MHz SDRAM
+ */
+ return 0x0086400d;
+ }
+#endif /* CONFIG_SYS_SDRAM_CASL */
+}
+
+/* refresh is expressed in ms */
+static ulong compute_rtr(ulong speed, ulong rows, ulong refresh)
+{
+#ifdef CONFIG_SYS_SDRAM_CASL
+ ulong tmp;
+
+ tmp = ((refresh*1000*1000) / (1 << rows)) * (speed / 1000);
+ tmp /= 1000000;
+
+ return ((tmp & 0x00003FF8) << 16);
+#else /* CONFIG_SYS_SDRAM_CASL */
+ if (speed > 100000000) {
+ /*
+ * 133 MHz SDRAM
+ */
+ return 0x07f00000;
+ } else {
+ /*
+ * default: 100 MHz SDRAM
+ */
+ return 0x05f00000;
+ }
+#endif /* CONFIG_SYS_SDRAM_CASL */
+}
+
+/*
+ * Autodetect onboard SDRAM on 405 platforms
+ */
+phys_size_t initdram(int board_type)
+{
+ ulong speed;
+ ulong sdtr1;
+ int i;
+
+ /*
+ * Determine SDRAM speed
+ */
+ speed = get_bus_freq(0); /* parameter not used on ppc4xx */
+
+ /*
+ * sdtr1 (register SDRAM0_TR) must take into account timings listed
+ * in SDRAM chip datasheet. rtr (register SDRAM0_RTR) must take into
+ * account actual SDRAM size. So we can set up sdtr1 according to what
+ * is specified in board configuration file while rtr dependds on SDRAM
+ * size we are assuming before detection.
+ */
+ sdtr1 = compute_sdtr1(speed);
+
+ for (i=0; i<N_MB0CF; i++) {
+ /*
+ * Disable memory controller.
+ */
+ mtsdram(SDRAM0_CFG, 0x00000000);
+
+ /*
+ * Set MB0CF for bank 0.
+ */
+ mtsdram(SDRAM0_B0CR, mb0cf[i].reg);
+ mtsdram(SDRAM0_TR, sdtr1);
+ mtsdram(SDRAM0_RTR, compute_rtr(speed, mb0cf[i].rows, 64));
+
+ udelay(200);
+
+ /*
+ * Set memory controller options reg, MCOPT1.
+ * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst
+ * read/prefetch.
+ */
+ mtsdram(SDRAM0_CFG, 0x80800000);
+
+ udelay(10000);
+
+ if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
+ phys_size_t size = mb0cf[i].size;
+
+ /*
+ * OK, size detected. Enable second bank if
+ * defined (assumes same type as bank 0)
+ */
+#ifdef CONFIG_SDRAM_BANK1
+ mtsdram(SDRAM0_CFG, 0x00000000);
+ mtsdram(SDRAM0_B1CR, mb0cf[i].size | mb0cf[i].reg);
+ mtsdram(SDRAM0_CFG, 0x80800000);
+ udelay(10000);
+
+ /*
+ * Check if 2nd bank is really available.
+ * If the size not equal to the size of the first
+ * bank, then disable the 2nd bank completely.
+ */
+ if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size) !=
+ mb0cf[i].size) {
+ mtsdram(SDRAM0_B1CR, 0);
+ mtsdram(SDRAM0_CFG, 0);
+ } else {
+ /*
+ * We have two identical banks, so the size
+ * is twice the bank size
+ */
+ size = 2 * size;
+ }
+#endif
+
+ /*
+ * OK, size detected -> all done
+ */
+ return size;
+ }
+ }
+
+ return 0;
+}
+
+#else /* CONFIG_440 */
+
+/*
+ * Define some default values. Those can be overwritten in the
+ * board config file.
+ */
+
+#ifndef CONFIG_SYS_SDRAM_TABLE
+sdram_conf_t mb0cf[] = {
+ {(256 << 20), 13, 0x000C4001}, /* 256MB mode 3, 13x10(4) */
+ {(128 << 20), 13, 0x000A4001}, /* 128MB mode 3, 13x10(4) */
+ {(64 << 20), 12, 0x00082001} /* 64MB mode 2, 12x9(4) */
+};
+#else
+sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE;
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_TR0
+#define CONFIG_SYS_SDRAM0_TR0 0x41094012
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_WDDCTR
+#define CONFIG_SYS_SDRAM0_WDDCTR 0x00000000 /* wrcp=0 dcd=0 */
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_RTR
+#define CONFIG_SYS_SDRAM0_RTR 0x04100000 /* 7.8us @ 133MHz PLB */
+#endif
+
+#ifndef CONFIG_SYS_SDRAM0_CFG0
+#define CONFIG_SYS_SDRAM0_CFG0 0x82000000 /* DCEN=1, PMUD=0, 64-bit */
+#endif
+
+#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+
+#define NUM_TRIES 64
+#define NUM_READS 10
+
+static void sdram_tr1_set(int ram_address, int* tr1_value)
+{
+ int i;
+ int j, k;
+ volatile unsigned int* ram_pointer = (unsigned int *)ram_address;
+ int first_good = -1, last_bad = 0x1ff;
+
+ unsigned long test[NUM_TRIES] = {
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
+ 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55 };
+
+ /* go through all possible SDRAM0_TR1[RDCT] values */
+ for (i=0; i<=0x1ff; i++) {
+ /* set the current value for TR1 */
+ mtsdram(SDRAM0_TR1, (0x80800800 | i));
+
+ /* write values */
+ for (j=0; j<NUM_TRIES; j++) {
+ ram_pointer[j] = test[j];
+
+ /* clear any cache at ram location */
+ __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
+ }
+
+ /* read values back */
+ for (j=0; j<NUM_TRIES; j++) {
+ for (k=0; k<NUM_READS; k++) {
+ /* clear any cache at ram location */
+ __asm__("dcbf 0,%0": :"r" (&ram_pointer[j]));
+
+ if (ram_pointer[j] != test[j])
+ break;
+ }
+
+ /* read error */
+ if (k != NUM_READS)
+ break;
+ }
+
+ /* we have a SDRAM0_TR1[RDCT] that is part of the window */
+ if (j == NUM_TRIES) {
+ if (first_good == -1)
+ first_good = i; /* found beginning of window */
+ } else { /* bad read */
+ /* if we have not had a good read then don't care */
+ if (first_good != -1) {
+ /* first failure after a good read */
+ last_bad = i-1;
+ break;
+ }
+ }
+ }
+
+ /* return the current value for TR1 */
+ *tr1_value = (first_good + last_bad) / 2;
+}
+
+/*
+ * Autodetect onboard DDR SDRAM on 440 platforms
+ *
+ * NOTE: Some of the hardcoded values are hardware dependant,
+ * so this should be extended for other future boards
+ * using this routine!
+ */
+phys_size_t initdram(int board_type)
+{
+ int i;
+ int tr1_bank1;
+
+#if defined(CONFIG_440GX) || defined(CONFIG_440EP) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440SP)
+ /*
+ * Soft-reset SDRAM controller.
+ */
+ mtsdr(SDR0_SRST, SDR0_SRST_DMC);
+ mtsdr(SDR0_SRST, 0x00000000);
+#endif
+
+ for (i=0; i<N_MB0CF; i++) {
+ /*
+ * Disable memory controller.
+ */
+ mtsdram(SDRAM0_CFG0, 0x00000000);
+
+ /*
+ * Setup some default
+ */
+ mtsdram(SDRAM0_UABBA, 0x00000000); /* ubba=0 (default) */
+ mtsdram(SDRAM0_SLIO, 0x00000000); /* rdre=0 wrre=0 rarw=0 */
+ mtsdram(SDRAM0_DEVOPT, 0x00000000); /* dll=0 ds=0 (normal) */
+ mtsdram(SDRAM0_WDDCTR, CONFIG_SYS_SDRAM0_WDDCTR);
+ mtsdram(SDRAM0_CLKTR, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */
+
+ /*
+ * Following for CAS Latency = 2.5 @ 133 MHz PLB
+ */
+ mtsdram(SDRAM0_B0CR, mb0cf[i].reg);
+ mtsdram(SDRAM0_TR0, CONFIG_SYS_SDRAM0_TR0);
+ mtsdram(SDRAM0_TR1, 0x80800800); /* SS=T2 SL=STAGE 3 CD=1 CT=0x00*/
+ mtsdram(SDRAM0_RTR, CONFIG_SYS_SDRAM0_RTR);
+ mtsdram(SDRAM0_CFG1, 0x00000000); /* Self-refresh exit, disable PM*/
+ udelay(400); /* Delay 200 usecs (min) */
+
+ /*
+ * Enable the controller, then wait for DCEN to complete
+ */
+ mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0);
+ udelay(10000);
+
+ if (get_ram_size(0, mb0cf[i].size) == mb0cf[i].size) {
+ phys_size_t size = mb0cf[i].size;
+ /*
+ * Optimize TR1 to current hardware environment
+ */
+ sdram_tr1_set(0x00000000, &tr1_bank1);
+ mtsdram(SDRAM0_TR1, (tr1_bank1 | 0x80800800));
+
+
+ /*
+ * OK, size detected. Enable second bank if
+ * defined (assumes same type as bank 0)
+ */
+#ifdef CONFIG_SDRAM_BANK1
+ mtsdram(SDRAM0_CFG0, 0);
+ mtsdram(SDRAM0_B1CR, mb0cf[i].size | mb0cf[i].reg);
+ mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0);
+ udelay(10000);
+
+ /*
+ * Check if 2nd bank is really available.
+ * If the size not equal to the size of the first
+ * bank, then disable the 2nd bank completely.
+ */
+ if (get_ram_size((long *)mb0cf[i].size, mb0cf[i].size)
+ != mb0cf[i].size) {
+ mtsdram(SDRAM0_CFG0, 0);
+ mtsdram(SDRAM0_B1CR, 0);
+ mtsdram(SDRAM0_CFG0, CONFIG_SYS_SDRAM0_CFG0);
+ udelay(10000);
+ } else {
+ /*
+ * We have two identical banks, so the size
+ * is twice the bank size
+ */
+ size = 2 * size;
+ }
+#endif
+
+#ifdef CONFIG_SDRAM_ECC
+ ecc_init(0, size);
+#endif
+
+ /*
+ * OK, size detected -> all done
+ */
+ return size;
+ }
+ }
+
+ return 0; /* nothing found ! */
+}
+
+#endif /* CONFIG_440 */
+
+#endif /* CONFIG_SDRAM_BANK0 */
diff --git a/arch/powerpc/cpu/ppc4xx/sdram.h b/arch/powerpc/cpu/ppc4xx/sdram.h
new file mode 100644
index 0000000..bea3376
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/sdram.h
@@ -0,0 +1,76 @@
+/*
+ * (C) Copyright 2006
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2006
+ * DAVE Srl <www.dave-tech.it>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _SDRAM_H_
+#define _SDRAM_H_
+
+#include <config.h>
+
+#define ONE_BILLION 1000000000
+
+struct sdram_conf_s {
+ unsigned long size;
+ int rows;
+ unsigned long reg;
+};
+
+typedef struct sdram_conf_s sdram_conf_t;
+
+/* Bitfields offsets */
+#define SDRAM0_TR_CASL (31 - 8)
+#define SDRAM0_TR_PTA (31 - 13)
+#define SDRAM0_TR_CTP (31 - 15)
+#define SDRAM0_TR_LDF (31 - 17)
+#define SDRAM0_TR_RFTA (31 - 29)
+#define SDRAM0_TR_RCD (31 - 31)
+
+#ifdef CONFIG_SYS_SDRAM_CL
+/* SDRAM timings [ns] according to AMCC/IBM names (see SDRAM_faq.doc) */
+#define CONFIG_SYS_SDRAM_CASL CONFIG_SYS_SDRAM_CL
+#define CONFIG_SYS_SDRAM_PTA CONFIG_SYS_SDRAM_tRP
+#define CONFIG_SYS_SDRAM_CTP (CONFIG_SYS_SDRAM_tRC - CONFIG_SYS_SDRAM_tRCD - CONFIG_SYS_SDRAM_tRP)
+#define CONFIG_SYS_SDRAM_LDF 0
+#ifdef CONFIG_SYS_SDRAM_tRFC
+#define CONFIG_SYS_SDRAM_RFTA CONFIG_SYS_SDRAM_tRFC
+#else
+#define CONFIG_SYS_SDRAM_RFTA CONFIG_SYS_SDRAM_tRC
+#endif
+#define CONFIG_SYS_SDRAM_RCD CONFIG_SYS_SDRAM_tRCD
+#endif /* #ifdef CONFIG_SYS_SDRAM_CL */
+
+/*
+ * Some defines for the 440 DDR controller
+ */
+#define SDRAM_CFG0_DC_EN 0x80000000 /* SDRAM Controller Enable */
+#define SDRAM_CFG0_MEMCHK 0x30000000 /* Memory data error checking mask*/
+#define SDRAM_CFG0_MEMCHK_NON 0x00000000 /* No ECC generation */
+#define SDRAM_CFG0_MEMCHK_GEN 0x20000000 /* ECC generation */
+#define SDRAM_CFG0_MEMCHK_CHK 0x30000000 /* ECC generation and checking */
+#define SDRAM_CFG0_DRAMWDTH 0x02000000 /* DRAM width mask */
+#define SDRAM_CFG0_DRAMWDTH_32 0x00000000 /* 32 bits */
+#define SDRAM_CFG0_DRAMWDTH_64 0x02000000 /* 64 bits */
+
+#endif
diff --git a/arch/powerpc/cpu/ppc4xx/speed.c b/arch/powerpc/cpu/ppc4xx/speed.c
new file mode 100644
index 0000000..45ef035
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/speed.c
@@ -0,0 +1,1225 @@
+/*
+ * (C) Copyright 2000-2008
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <ppc_asm.tmpl>
+#include <asm/ppc4xx.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ONE_BILLION 1000000000
+#ifdef DEBUG
+#define DEBUGF(fmt,args...) printf(fmt ,##args)
+#else
+#define DEBUGF(fmt,args...)
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR)
+
+void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
+{
+ unsigned long pllmr;
+ unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+ uint pvr = get_pvr();
+ unsigned long psr;
+ unsigned long m;
+
+ /*
+ * Read PLL Mode register
+ */
+ pllmr = mfdcr (CPC0_PLLMR);
+
+ /*
+ * Read Pin Strapping register
+ */
+ psr = mfdcr (CPC0_PSR);
+
+ /*
+ * Determine FWD_DIV.
+ */
+ sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29);
+
+ /*
+ * Determine FBK_DIV.
+ */
+ sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25);
+ if (sysInfo->pllFbkDiv == 0) {
+ sysInfo->pllFbkDiv = 16;
+ }
+
+ /*
+ * Determine PLB_DIV.
+ */
+ sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1;
+
+ /*
+ * Determine PCI_DIV.
+ */
+ sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1;
+
+ /*
+ * Determine EXTBUS_DIV.
+ */
+ sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2;
+
+ /*
+ * Determine OPB_DIV.
+ */
+ sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1;
+
+ /*
+ * Check if PPC405GPr used (mask minor revision field)
+ */
+ if ((pvr & 0xfffffff0) == (PVR_405GPR_RB & 0xfffffff0)) {
+ /*
+ * Determine FWD_DIV B (only PPC405GPr with new mode strapping).
+ */
+ sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK);
+
+ /*
+ * Determine factor m depending on PLL feedback clock source
+ */
+ if (!(psr & PSR_PCI_ASYNC_EN)) {
+ if (psr & PSR_NEW_MODE_EN) {
+ /*
+ * sync pci clock used as feedback (new mode)
+ */
+ m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv;
+ } else {
+ /*
+ * sync pci clock used as feedback (legacy mode)
+ */
+ m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv;
+ }
+ } else if (psr & PSR_NEW_MODE_EN) {
+ if (psr & PSR_PERCLK_SYNC_MODE_EN) {
+ /*
+ * PerClk used as feedback (new mode)
+ */
+ m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv;
+ } else {
+ /*
+ * CPU clock used as feedback (new mode)
+ */
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
+ }
+ } else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) {
+ /*
+ * PerClk used as feedback (legacy mode)
+ */
+ m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv;
+ } else {
+ /*
+ * PLB clock used as feedback (legacy mode)
+ */
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv;
+ }
+
+ sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+ (unsigned long long)sysClkPeriodPs;
+ sysInfo->freqProcessor = sysInfo->freqVCOHz / sysInfo->pllFwdDiv;
+ sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv);
+ } else {
+ /*
+ * Check pllFwdDiv to see if running in bypass mode where the CPU speed
+ * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO
+ * to make sure it is within the proper range.
+ * spec: VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV
+ * Note freqVCO is calculated in MHz to avoid errors introduced by rounding.
+ */
+ if (sysInfo->pllFwdDiv == 1) {
+ sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ;
+ sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv;
+ } else {
+ sysInfo->freqVCOHz = ( 1000000000000LL *
+ (unsigned long long)sysInfo->pllFwdDiv *
+ (unsigned long long)sysInfo->pllFbkDiv *
+ (unsigned long long)sysInfo->pllPlbDiv
+ ) / (unsigned long long)sysClkPeriodPs;
+ sysInfo->freqPLB = (ONE_BILLION / ((sysClkPeriodPs * 10) /
+ sysInfo->pllFbkDiv)) * 10000;
+ sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv;
+ }
+ }
+
+ sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+ sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
+ sysInfo->freqUART = sysInfo->freqProcessor;
+}
+
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+ ulong val;
+ PPC4xx_SYS_INFO sys_info;
+
+ get_sys_info (&sys_info);
+ val = sys_info.freqPLB / sys_info.pllPciDiv;
+ return val;
+}
+
+
+#elif defined(CONFIG_440)
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
+static u8 pll_fwdv_multi_bits[] = {
+ /* values for: 1 - 16 */
+ 0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c,
+ 0x05, 0x08, 0x07, 0x02, 0x0b, 0x06
+};
+
+u32 get_cpr0_fwdv(unsigned long cpr_reg_fwdv)
+{
+ u32 index;
+
+ for (index = 0; index < ARRAY_SIZE(pll_fwdv_multi_bits); index++)
+ if (cpr_reg_fwdv == (u32)pll_fwdv_multi_bits[index])
+ return index + 1;
+
+ return 0;
+}
+
+static u8 pll_fbdv_multi_bits[] = {
+ /* values for: 1 - 100 */
+ 0x00, 0xff, 0x7e, 0xfd, 0x7a, 0xf5, 0x6a, 0xd5, 0x2a, 0xd4,
+ 0x29, 0xd3, 0x26, 0xcc, 0x19, 0xb3, 0x67, 0xce, 0x1d, 0xbb,
+ 0x77, 0xee, 0x5d, 0xba, 0x74, 0xe9, 0x52, 0xa5, 0x4b, 0x96,
+ 0x2c, 0xd8, 0x31, 0xe3, 0x46, 0x8d, 0x1b, 0xb7, 0x6f, 0xde,
+ 0x3d, 0xfb, 0x76, 0xed, 0x5a, 0xb5, 0x6b, 0xd6, 0x2d, 0xdb,
+ 0x36, 0xec, 0x59, 0xb2, 0x64, 0xc9, 0x12, 0xa4, 0x48, 0x91,
+ 0x23, 0xc7, 0x0e, 0x9c, 0x38, 0xf0, 0x61, 0xc2, 0x05, 0x8b,
+ 0x17, 0xaf, 0x5f, 0xbe, 0x7c, 0xf9, 0x72, 0xe5, 0x4a, 0x95,
+ 0x2b, 0xd7, 0x2e, 0xdc, 0x39, 0xf3, 0x66, 0xcd, 0x1a, 0xb4,
+ 0x68, 0xd1, 0x22, 0xc4, 0x09, 0x93, 0x27, 0xcf, 0x1e, 0xbc,
+ /* values for: 101 - 200 */
+ 0x78, 0xf1, 0x62, 0xc5, 0x0a, 0x94, 0x28, 0xd0, 0x21, 0xc3,
+ 0x06, 0x8c, 0x18, 0xb0, 0x60, 0xc1, 0x02, 0x84, 0x08, 0x90,
+ 0x20, 0xc0, 0x01, 0x83, 0x07, 0x8f, 0x1f, 0xbf, 0x7f, 0xfe,
+ 0x7d, 0xfa, 0x75, 0xea, 0x55, 0xaa, 0x54, 0xa9, 0x53, 0xa6,
+ 0x4c, 0x99, 0x33, 0xe7, 0x4e, 0x9d, 0x3b, 0xf7, 0x6e, 0xdd,
+ 0x3a, 0xf4, 0x69, 0xd2, 0x25, 0xcb, 0x16, 0xac, 0x58, 0xb1,
+ 0x63, 0xc6, 0x0d, 0x9b, 0x37, 0xef, 0x5e, 0xbd, 0x7b, 0xf6,
+ 0x6d, 0xda, 0x35, 0xeb, 0x56, 0xad, 0x5b, 0xb6, 0x6c, 0xd9,
+ 0x32, 0xe4, 0x49, 0x92, 0x24, 0xc8, 0x11, 0xa3, 0x47, 0x8e,
+ 0x1c, 0xb8, 0x70, 0xe1, 0x42, 0x85, 0x0b, 0x97, 0x2f, 0xdf,
+ /* values for: 201 - 255 */
+ 0x3e, 0xfc, 0x79, 0xf2, 0x65, 0xca, 0x15, 0xab, 0x57, 0xae,
+ 0x5c, 0xb9, 0x73, 0xe6, 0x4d, 0x9a, 0x34, 0xe8, 0x51, 0xa2,
+ 0x44, 0x89, 0x13, 0xa7, 0x4f, 0x9e, 0x3c, 0xf8, 0x71, 0xe2,
+ 0x45, 0x8a, 0x14, 0xa8, 0x50, 0xa1, 0x43, 0x86, 0x0c, 0x98,
+ 0x30, 0xe0, 0x41, 0x82, 0x04, 0x88, 0x10, 0xa0, 0x40, 0x81,
+ 0x03, 0x87, 0x0f, 0x9f, 0x3f /* END */
+};
+
+u32 get_cpr0_fbdv(unsigned long cpr_reg_fbdv)
+{
+ u32 index;
+
+ for (index = 0; index < ARRAY_SIZE(pll_fbdv_multi_bits); index++)
+ if (cpr_reg_fbdv == (u32)pll_fbdv_multi_bits[index])
+ return index + 1;
+
+ return 0;
+}
+
+#if defined(CONFIG_APM821XX)
+
+void get_sys_info(sys_info_t *sysInfo)
+{
+ unsigned long plld;
+ unsigned long temp;
+ unsigned long mul;
+ unsigned long cpudv;
+ unsigned long plb2dv;
+ unsigned long ddr2dv;
+
+ /* Calculate Forward divisor A and Feeback divisor */
+ mfcpr(CPR0_PLLD, plld);
+
+ temp = CPR0_PLLD_FWDVA(plld);
+ sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
+
+ temp = CPR0_PLLD_FDV(plld);
+ sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
+
+ /* Calculate OPB clock divisor */
+ mfcpr(CPR0_OPBD, temp);
+ temp = CPR0_OPBD_OPBDV(temp);
+ sysInfo->pllOpbDiv = temp ? temp : 4;
+
+ /* Calculate Peripheral clock divisor */
+ mfcpr(CPR0_PERD, temp);
+ temp = CPR0_PERD_PERDV(temp);
+ sysInfo->pllExtBusDiv = temp ? temp : 4;
+
+ /* Calculate CPU clock divisor */
+ mfcpr(CPR0_CPUD, temp);
+ temp = CPR0_CPUD_CPUDV(temp);
+ cpudv = temp ? temp : 8;
+
+ /* Calculate PLB2 clock divisor */
+ mfcpr(CPR0_PLB2D, temp);
+ temp = CPR0_PLB2D_PLB2DV(temp);
+ plb2dv = temp ? temp : 4;
+
+ /* Calculate DDR2 clock divisor */
+ mfcpr(CPR0_DDR2D, temp);
+ temp = CPR0_DDR2D_DDR2DV(temp);
+ ddr2dv = temp ? temp : 4;
+
+ /* Calculate 'M' based on feedback source */
+ mfcpr(CPR0_PLLC, temp);
+ temp = CPR0_PLLC_SEL(temp);
+ if (temp == 0) {
+ /* PLL internal feedback */
+ mul = sysInfo->pllFbkDiv;
+ } else {
+ /* PLL PerClk feedback */
+ mul = sysInfo->pllFwdDivA * sysInfo->pllFbkDiv * cpudv
+ * plb2dv * 2 * sysInfo->pllOpbDiv *
+ sysInfo->pllExtBusDiv;
+ }
+
+ /* Now calculate the individual clocks */
+ sysInfo->freqVCOMhz = (mul * CONFIG_SYS_CLK_FREQ) + (mul >> 1);
+ sysInfo->freqProcessor = sysInfo->freqVCOMhz /
+ sysInfo->pllFwdDivA / cpudv;
+ sysInfo->freqPLB = sysInfo->freqVCOMhz /
+ sysInfo->pllFwdDivA / cpudv / plb2dv / 2;
+ sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+ sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
+ sysInfo->freqDDR = sysInfo->freqVCOMhz /
+ sysInfo->pllFwdDivA / cpudv / ddr2dv / 2;
+ sysInfo->freqUART = sysInfo->freqPLB;
+}
+
+#else
+/*
+ * AMCC_TODO: verify this routine against latest EAS, cause stuff changed
+ * with latest EAS
+ */
+void get_sys_info (sys_info_t * sysInfo)
+{
+ unsigned long strp0;
+ unsigned long strp1;
+ unsigned long temp;
+ unsigned long m;
+ unsigned long plbedv0;
+
+ /* Extract configured divisors */
+ mfsdr(SDR0_SDSTP0, strp0);
+ mfsdr(SDR0_SDSTP1, strp1);
+
+ temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 4);
+ sysInfo->pllFwdDivA = get_cpr0_fwdv(temp);
+
+ temp = (strp0 & PLLSYS0_FWD_DIV_B_MASK);
+ sysInfo->pllFwdDivB = get_cpr0_fwdv(temp);
+
+ temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 8;
+ sysInfo->pllFbkDiv = get_cpr0_fbdv(temp);
+
+ temp = (strp1 & PLLSYS0_OPB_DIV_MASK) >> 26;
+ sysInfo->pllOpbDiv = temp ? temp : 4;
+
+ /* AMCC_TODO: verify the SDR0_SDSTP1.PERDV0 value sysInfo->pllExtBusDiv */
+ temp = (strp1 & PLLSYS0_PERCLK_DIV_MASK) >> 24;
+ sysInfo->pllExtBusDiv = temp ? temp : 4;
+
+ temp = (strp1 & PLLSYS0_PLBEDV0_DIV_MASK) >> 29;
+ plbedv0 = temp ? temp: 8;
+
+ /* Calculate 'M' based on feedback source */
+ temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
+ if (temp == 0) {
+ /* PLL internal feedback */
+ m = sysInfo->pllFbkDiv;
+ } else {
+ /* PLL PerClk feedback */
+ m = sysInfo->pllFwdDivA * plbedv0 * sysInfo->pllOpbDiv *
+ sysInfo->pllExtBusDiv;
+ }
+
+ /* Now calculate the individual clocks */
+ sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
+ sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+ sysInfo->freqPLB = sysInfo->freqVCOMhz / sysInfo->pllFwdDivA / plbedv0;
+ sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+ sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
+ sysInfo->freqDDR = sysInfo->freqPLB;
+ sysInfo->freqUART = sysInfo->freqPLB;
+
+ return;
+}
+#endif
+
+#elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+void get_sys_info (sys_info_t *sysInfo)
+{
+ unsigned long temp;
+ unsigned long reg;
+ unsigned long lfdiv;
+ unsigned long m;
+ unsigned long prbdv0;
+ /*
+ WARNING: ASSUMES the following:
+ ENG=1
+ PRADV0=1
+ PRBDV0=1
+ */
+
+ /* Decode CPR0_PLLD0 for divisors */
+ mfcpr(CPR0_PLLD, reg);
+ temp = (reg & PLLD_FWDVA_MASK) >> 16;
+ sysInfo->pllFwdDivA = temp ? temp : 16;
+ temp = (reg & PLLD_FWDVB_MASK) >> 8;
+ sysInfo->pllFwdDivB = temp ? temp: 8 ;
+ temp = (reg & PLLD_FBDV_MASK) >> 24;
+ sysInfo->pllFbkDiv = temp ? temp : 32;
+ lfdiv = reg & PLLD_LFBDV_MASK;
+
+ mfcpr(CPR0_OPBD0, reg);
+ temp = (reg & OPBDDV_MASK) >> 24;
+ sysInfo->pllOpbDiv = temp ? temp : 4;
+
+ mfcpr(CPR0_PERD, reg);
+ temp = (reg & PERDV_MASK) >> 24;
+ sysInfo->pllExtBusDiv = temp ? temp : 8;
+
+ mfcpr(CPR0_PRIMBD0, reg);
+ temp = (reg & PRBDV_MASK) >> 24;
+ prbdv0 = temp ? temp : 8;
+
+ mfcpr(CPR0_SPCID, reg);
+ temp = (reg & SPCID_MASK) >> 24;
+ sysInfo->pllPciDiv = temp ? temp : 4;
+
+ /* Calculate 'M' based on feedback source */
+ mfsdr(SDR0_SDSTP0, reg);
+ temp = (reg & PLLSYS0_SEL_MASK) >> 27;
+ if (temp == 0) { /* PLL output */
+ /* Figure which pll to use */
+ mfcpr(CPR0_PLLC, reg);
+ temp = (reg & PLLC_SRC_MASK) >> 29;
+ if (!temp) /* PLLOUTA */
+ m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
+ else /* PLLOUTB */
+ m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
+ }
+ else if (temp == 1) /* CPU output */
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+ else /* PerClk */
+ m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+
+ /* Now calculate the individual clocks */
+ sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+ sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+ sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
+ sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+ sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv;
+ sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv;
+ sysInfo->freqUART = sysInfo->freqPLB;
+
+ /* Figure which timer source to use */
+ if (mfspr(SPRN_CCR1) & 0x0080) {
+ /* External Clock, assume same as SYS_CLK */
+ temp = sysInfo->freqProcessor / 2; /* Max extern clock speed */
+ if (CONFIG_SYS_CLK_FREQ > temp)
+ sysInfo->freqTmrClk = temp;
+ else
+ sysInfo->freqTmrClk = CONFIG_SYS_CLK_FREQ;
+ }
+ else /* Internal clock */
+ sysInfo->freqTmrClk = sysInfo->freqProcessor;
+}
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+ sys_info_t sys_info;
+ get_sys_info (&sys_info);
+ return sys_info.freqPCI;
+}
+
+#elif !defined(CONFIG_440GX) && !defined(CONFIG_440SP) && !defined(CONFIG_440SPE) \
+ && !defined(CONFIG_XILINX_440)
+void get_sys_info (sys_info_t * sysInfo)
+{
+ unsigned long strp0;
+ unsigned long temp;
+ unsigned long m;
+
+ /* Extract configured divisors */
+ strp0 = mfdcr( CPC0_STRP0 );
+ sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15);
+ sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12);
+ temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18;
+ sysInfo->pllFbkDiv = temp ? temp : 16;
+ sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10);
+ sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8);
+
+ /* Calculate 'M' based on feedback source */
+ if( strp0 & PLLSYS0_EXTSL_MASK )
+ m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+ else
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+
+ /* Now calculate the individual clocks */
+ sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+ sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+ sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
+ if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
+ sysInfo->freqPLB >>= 1;
+ sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+ sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
+ sysInfo->freqUART = sysInfo->freqPLB;
+}
+#else
+
+#if !defined(CONFIG_XILINX_440)
+void get_sys_info (sys_info_t * sysInfo)
+{
+ unsigned long strp0;
+ unsigned long strp1;
+ unsigned long temp;
+ unsigned long temp1;
+ unsigned long lfdiv;
+ unsigned long m;
+ unsigned long prbdv0;
+
+#if defined(CONFIG_YUCCA)
+ unsigned long sys_freq;
+ unsigned long sys_per=0;
+ unsigned long msr;
+ unsigned long pci_clock_per;
+ unsigned long sdr_ddrpll;
+
+ /*-------------------------------------------------------------------------+
+ | Get the system clock period.
+ +-------------------------------------------------------------------------*/
+ sys_per = determine_sysper();
+
+ msr = (mfmsr () & ~(MSR_EE)); /* disable interrupts */
+
+ /*-------------------------------------------------------------------------+
+ | Calculate the system clock speed from the period.
+ +-------------------------------------------------------------------------*/
+ sys_freq = (ONE_BILLION / sys_per) * 1000;
+#endif
+
+ /* Extract configured divisors */
+ mfsdr( SDR0_SDSTP0,strp0 );
+ mfsdr( SDR0_SDSTP1,strp1 );
+
+ temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
+ sysInfo->pllFwdDivA = temp ? temp : 16 ;
+ temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
+ sysInfo->pllFwdDivB = temp ? temp: 8 ;
+ temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
+ sysInfo->pllFbkDiv = temp ? temp : 32;
+ temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
+ sysInfo->pllOpbDiv = temp ? temp : 4;
+ temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
+ sysInfo->pllExtBusDiv = temp ? temp : 4;
+ prbdv0 = (strp0 >> 2) & 0x7;
+
+ /* Calculate 'M' based on feedback source */
+ temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
+ temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
+ lfdiv = temp1 ? temp1 : 64;
+ if (temp == 0) { /* PLL output */
+ /* Figure which pll to use */
+ temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
+ if (!temp)
+ m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
+ else
+ m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
+ }
+ else if (temp == 1) /* CPU output */
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+ else /* PerClk */
+ m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+
+ /* Now calculate the individual clocks */
+#if defined(CONFIG_YUCCA)
+ sysInfo->freqVCOMhz = (m * sys_freq) ;
+#else
+ sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);
+#endif
+ sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
+ sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;
+ sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+ sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
+
+#if defined(CONFIG_YUCCA)
+ /* Determine PCI Clock Period */
+ pci_clock_per = determine_pci_clock_per();
+ sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000;
+ mfsdr(SDR0_DDR0, sdr_ddrpll);
+ sysInfo->freqDDR = ((sysInfo->freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll));
+#endif
+
+ sysInfo->freqUART = sysInfo->freqPLB;
+}
+
+#endif
+#endif /* CONFIG_XILINX_440 */
+
+#if defined(CONFIG_YUCCA)
+unsigned long determine_sysper(void)
+{
+ unsigned int fpga_clocking_reg;
+ unsigned int master_clock_selection;
+ unsigned long master_clock_per = 0;
+ unsigned long fb_div_selection;
+ unsigned int vco_div_reg_value;
+ unsigned long vco_div_selection;
+ unsigned long sys_per = 0;
+ int extClkVal;
+
+ /*-------------------------------------------------------------------------+
+ | Read FPGA reg 0 and reg 1 to get FPGA reg information
+ +-------------------------------------------------------------------------*/
+ fpga_clocking_reg = in16(FPGA_REG16);
+
+
+ /* Determine Master Clock Source Selection */
+ master_clock_selection = fpga_clocking_reg & FPGA_REG16_MASTER_CLK_MASK;
+
+ switch(master_clock_selection) {
+ case FPGA_REG16_MASTER_CLK_66_66:
+ master_clock_per = PERIOD_66_66MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_50:
+ master_clock_per = PERIOD_50_00MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_33_33:
+ master_clock_per = PERIOD_33_33MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_25:
+ master_clock_per = PERIOD_25_00MHZ;
+ break;
+ case FPGA_REG16_MASTER_CLK_EXT:
+ if ((extClkVal==EXTCLK_33_33)
+ && (extClkVal==EXTCLK_50)
+ && (extClkVal==EXTCLK_66_66)
+ && (extClkVal==EXTCLK_83)) {
+ /* calculate master clock period from external clock value */
+ master_clock_per=(ONE_BILLION/extClkVal) * 1000;
+ } else {
+ /* Unsupported */
+ DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
+ hang();
+ }
+ break;
+ default:
+ /* Unsupported */
+ DEBUGF ("%s[%d] *** master clock selection failed ***\n", __FUNCTION__,__LINE__);
+ hang();
+ break;
+ }
+
+ /* Determine FB divisors values */
+ if ((fpga_clocking_reg & FPGA_REG16_FB1_DIV_MASK) == FPGA_REG16_FB1_DIV_LOW) {
+ if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
+ fb_div_selection = FPGA_FB_DIV_6;
+ else
+ fb_div_selection = FPGA_FB_DIV_12;
+ } else {
+ if ((fpga_clocking_reg & FPGA_REG16_FB2_DIV_MASK) == FPGA_REG16_FB2_DIV_LOW)
+ fb_div_selection = FPGA_FB_DIV_10;
+ else
+ fb_div_selection = FPGA_FB_DIV_20;
+ }
+
+ /* Determine VCO divisors values */
+ vco_div_reg_value = fpga_clocking_reg & FPGA_REG16_VCO_DIV_MASK;
+
+ switch(vco_div_reg_value) {
+ case FPGA_REG16_VCO_DIV_4:
+ vco_div_selection = FPGA_VCO_DIV_4;
+ break;
+ case FPGA_REG16_VCO_DIV_6:
+ vco_div_selection = FPGA_VCO_DIV_6;
+ break;
+ case FPGA_REG16_VCO_DIV_8:
+ vco_div_selection = FPGA_VCO_DIV_8;
+ break;
+ case FPGA_REG16_VCO_DIV_10:
+ default:
+ vco_div_selection = FPGA_VCO_DIV_10;
+ break;
+ }
+
+ if (master_clock_selection == FPGA_REG16_MASTER_CLK_EXT) {
+ switch(master_clock_per) {
+ case PERIOD_25_00MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_75_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ break;
+ case PERIOD_33_33MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_6) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_50_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_33_33MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_10) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_83_33MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_10)
+ sys_per = PERIOD_33_33MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_100_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_66_66MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ break;
+ case PERIOD_50_00MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_6) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_75_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_10) {
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_83_33MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_10)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_100_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_75_00MHZ;
+ }
+ break;
+ case PERIOD_66_66MHZ:
+ if (fb_div_selection == FPGA_FB_DIV_6) {
+ if (vco_div_selection == FPGA_VCO_DIV_4)
+ sys_per = PERIOD_100_00MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_6)
+ sys_per = PERIOD_66_66MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_50_00MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_10) {
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_83_33MHZ;
+ if (vco_div_selection == FPGA_VCO_DIV_10)
+ sys_per = PERIOD_66_66MHZ;
+ }
+ if (fb_div_selection == FPGA_FB_DIV_12) {
+ if (vco_div_selection == FPGA_VCO_DIV_8)
+ sys_per = PERIOD_100_00MHZ;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (sys_per == 0) {
+ /* Other combinations are not supported */
+ DEBUGF ("%s[%d] *** sys period compute failed ***\n", __FUNCTION__,__LINE__);
+ hang();
+ }
+ } else {
+ /* calcul system clock without cheking */
+ /* if engineering option clock no check is selected */
+ /* sys_per = master_clock_per * vco_div_selection / fb_div_selection */
+ sys_per = (master_clock_per/fb_div_selection) * vco_div_selection;
+ }
+
+ return(sys_per);
+}
+
+/*-------------------------------------------------------------------------+
+| determine_pci_clock_per.
++-------------------------------------------------------------------------*/
+unsigned long determine_pci_clock_per(void)
+{
+ unsigned long pci_clock_selection, pci_period;
+
+ /*-------------------------------------------------------------------------+
+ | Read FPGA reg 6 to get PCI 0 FPGA reg information
+ +-------------------------------------------------------------------------*/
+ pci_clock_selection = in16(FPGA_REG16); /* was reg6 averifier */
+
+
+ pci_clock_selection = pci_clock_selection & FPGA_REG16_PCI0_CLK_MASK;
+
+ switch (pci_clock_selection) {
+ case FPGA_REG16_PCI0_CLK_133_33:
+ pci_period = PERIOD_133_33MHZ;
+ break;
+ case FPGA_REG16_PCI0_CLK_100:
+ pci_period = PERIOD_100_00MHZ;
+ break;
+ case FPGA_REG16_PCI0_CLK_66_66:
+ pci_period = PERIOD_66_66MHZ;
+ break;
+ default:
+ pci_period = PERIOD_33_33MHZ;;
+ break;
+ }
+
+ return(pci_period);
+}
+#endif
+
+#elif defined(CONFIG_XILINX_405)
+extern void get_sys_info (sys_info_t * sysInfo);
+extern ulong get_PCI_freq (void);
+
+#elif defined(CONFIG_405)
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+ sysInfo->freqVCOMhz=3125000;
+ sysInfo->freqProcessor=12*1000*1000;
+ sysInfo->freqPLB=50*1000*1000;
+ sysInfo->freqPCI=66*1000*1000;
+}
+
+#elif defined(CONFIG_405EP)
+void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
+{
+ unsigned long pllmr0;
+ unsigned long pllmr1;
+ unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+ unsigned long m;
+ unsigned long pllmr0_ccdv;
+
+ /*
+ * Read PLL Mode registers
+ */
+ pllmr0 = mfdcr (CPC0_PLLMR0);
+ pllmr1 = mfdcr (CPC0_PLLMR1);
+
+ /*
+ * Determine forward divider A
+ */
+ sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
+
+ /*
+ * Determine forward divider B (should be equal to A)
+ */
+ sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
+
+ /*
+ * Determine FBK_DIV.
+ */
+ sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
+ if (sysInfo->pllFbkDiv == 0)
+ sysInfo->pllFbkDiv = 16;
+
+ /*
+ * Determine PLB_DIV.
+ */
+ sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
+
+ /*
+ * Determine PCI_DIV.
+ */
+ sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
+
+ /*
+ * Determine EXTBUS_DIV.
+ */
+ sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
+
+ /*
+ * Determine OPB_DIV.
+ */
+ sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
+
+ /*
+ * Determine the M factor
+ */
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+
+ /*
+ * Determine VCO clock frequency
+ */
+ sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+ (unsigned long long)sysClkPeriodPs;
+
+ /*
+ * Determine CPU clock frequency
+ */
+ pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
+ if (pllmr1 & PLLMR1_SSCS_MASK) {
+ /*
+ * This is true if FWDVA == FWDVB:
+ * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
+ * / pllmr0_ccdv;
+ */
+ sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
+ / sysInfo->pllFwdDiv / pllmr0_ccdv;
+ } else {
+ sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
+ }
+
+ /*
+ * Determine PLB clock frequency
+ */
+ sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
+
+ sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv;
+
+ sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv;
+
+ sysInfo->freqUART = sysInfo->freqProcessor * pllmr0_ccdv;
+}
+
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+ ulong val;
+ PPC4xx_SYS_INFO sys_info;
+
+ get_sys_info (&sys_info);
+ val = sys_info.freqPLB / sys_info.pllPciDiv;
+ return val;
+}
+
+#elif defined(CONFIG_405EZ)
+void get_sys_info (PPC4xx_SYS_INFO * sysInfo)
+{
+ unsigned long cpr_plld;
+ unsigned long cpr_pllc;
+ unsigned long cpr_primad;
+ unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ/1000);
+ unsigned long primad_cpudv;
+ unsigned long m;
+ unsigned long plloutb;
+
+ /*
+ * Read PLL Mode registers
+ */
+ mfcpr(CPR0_PLLD, cpr_plld);
+ mfcpr(CPR0_PLLC, cpr_pllc);
+
+ /*
+ * Determine forward divider A
+ */
+ sysInfo->pllFwdDiv = ((cpr_plld & PLLD_FWDVA_MASK) >> 16);
+
+ /*
+ * Determine forward divider B
+ */
+ sysInfo->pllFwdDivB = ((cpr_plld & PLLD_FWDVB_MASK) >> 8);
+ if (sysInfo->pllFwdDivB == 0)
+ sysInfo->pllFwdDivB = 8;
+
+ /*
+ * Determine FBK_DIV.
+ */
+ sysInfo->pllFbkDiv = ((cpr_plld & PLLD_FBDV_MASK) >> 24);
+ if (sysInfo->pllFbkDiv == 0)
+ sysInfo->pllFbkDiv = 256;
+
+ /*
+ * Read CPR_PRIMAD register
+ */
+ mfcpr(CPR0_PRIMAD, cpr_primad);
+
+ /*
+ * Determine PLB_DIV.
+ */
+ sysInfo->pllPlbDiv = ((cpr_primad & PRIMAD_PLBDV_MASK) >> 16);
+ if (sysInfo->pllPlbDiv == 0)
+ sysInfo->pllPlbDiv = 16;
+
+ /*
+ * Determine EXTBUS_DIV.
+ */
+ sysInfo->pllExtBusDiv = (cpr_primad & PRIMAD_EBCDV_MASK);
+ if (sysInfo->pllExtBusDiv == 0)
+ sysInfo->pllExtBusDiv = 16;
+
+ /*
+ * Determine OPB_DIV.
+ */
+ sysInfo->pllOpbDiv = ((cpr_primad & PRIMAD_OPBDV_MASK) >> 8);
+ if (sysInfo->pllOpbDiv == 0)
+ sysInfo->pllOpbDiv = 16;
+
+ /*
+ * Determine the M factor
+ */
+ if (cpr_pllc & PLLC_SRC_MASK)
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+ else
+ m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv;
+
+ /*
+ * Determine VCO clock frequency
+ */
+ sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+ (unsigned long long)sysClkPeriodPs;
+
+ /*
+ * Determine CPU clock frequency
+ */
+ primad_cpudv = ((cpr_primad & PRIMAD_CPUDV_MASK) >> 24);
+ if (primad_cpudv == 0)
+ primad_cpudv = 16;
+
+ sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * m) /
+ sysInfo->pllFwdDiv / primad_cpudv;
+
+ /*
+ * Determine PLB clock frequency
+ */
+ sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) /
+ sysInfo->pllFwdDiv / sysInfo->pllPlbDiv;
+
+ sysInfo->freqOPB = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
+ sysInfo->pllOpbDiv;
+
+ sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) /
+ sysInfo->pllExtBusDiv;
+
+ plloutb = ((CONFIG_SYS_CLK_FREQ * ((cpr_pllc & PLLC_SRC_MASK) ?
+ sysInfo->pllFwdDivB : sysInfo->pllFwdDiv) * sysInfo->pllFbkDiv) /
+ sysInfo->pllFwdDivB);
+ sysInfo->freqUART = plloutb;
+}
+
+#elif defined(CONFIG_405EX)
+
+/*
+ * TODO: We need to get the CPR registers and calculate these values correctly!!!!
+ * We need the specs!!!!
+ */
+static unsigned char get_fbdv(unsigned char index)
+{
+ unsigned char ret = 0;
+ /* This is table should be 256 bytes.
+ * Only take first 52 values.
+ */
+ unsigned char fbdv_tb[] = {
+ 0x00, 0xff, 0x7f, 0xfd,
+ 0x7a, 0xf5, 0x6a, 0xd5,
+ 0x2a, 0xd4, 0x29, 0xd3,
+ 0x26, 0xcc, 0x19, 0xb3,
+ 0x67, 0xce, 0x1d, 0xbb,
+ 0x77, 0xee, 0x5d, 0xba,
+ 0x74, 0xe9, 0x52, 0xa5,
+ 0x4b, 0x96, 0x2c, 0xd8,
+ 0x31, 0xe3, 0x46, 0x8d,
+ 0x1b, 0xb7, 0x6f, 0xde,
+ 0x3d, 0xfb, 0x76, 0xed,
+ 0x5a, 0xb5, 0x6b, 0xd6,
+ 0x2d, 0xdb, 0x36, 0xec,
+
+ };
+
+ if ((index & 0x7f) == 0)
+ return 1;
+ while (ret < sizeof (fbdv_tb)) {
+ if (fbdv_tb[ret] == index)
+ break;
+ ret++;
+ }
+ ret++;
+
+ return ret;
+}
+
+#define PLL_FBK_PLL_LOCAL 0
+#define PLL_FBK_CPU 1
+#define PLL_FBK_PERCLK 5
+
+void get_sys_info (sys_info_t * sysInfo)
+{
+ unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+ unsigned long m = 1;
+ unsigned int tmp;
+ unsigned char fwdva[16] = {
+ 1, 2, 14, 9, 4, 11, 16, 13,
+ 12, 5, 6, 15, 10, 7, 8, 3,
+ };
+ unsigned char sel, cpudv0, plb2xDiv;
+
+ mfcpr(CPR0_PLLD, tmp);
+
+ /*
+ * Determine forward divider A
+ */
+ sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */
+
+ /*
+ * Determine FBK_DIV.
+ */
+ sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */
+
+ /*
+ * Determine PLBDV0
+ */
+ sysInfo->pllPlbDiv = 2;
+
+ /*
+ * Determine PERDV0
+ */
+ mfcpr(CPR0_PERD, tmp);
+ tmp = (tmp >> 24) & 0x03;
+ sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp;
+
+ /*
+ * Determine OPBDV0
+ */
+ mfcpr(CPR0_OPBD0, tmp);
+ tmp = (tmp >> 24) & 0x03;
+ sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp;
+
+ /* Determine PLB2XDV0 */
+ mfcpr(CPR0_PLBD, tmp);
+ tmp = (tmp >> 16) & 0x07;
+ plb2xDiv = (tmp == 0) ? 8 : tmp;
+
+ /* Determine CPUDV0 */
+ mfcpr(CPR0_CPUD, tmp);
+ tmp = (tmp >> 24) & 0x07;
+ cpudv0 = (tmp == 0) ? 8 : tmp;
+
+ /* Determine SEL(5:7) in CPR0_PLLC */
+ mfcpr(CPR0_PLLC, tmp);
+ sel = (tmp >> 24) & 0x07;
+
+ /*
+ * Determine the M factor
+ * PLL local: M = FBDV
+ * CPU clock: M = FBDV * FWDVA * CPUDV0
+ * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0
+ *
+ */
+ switch (sel) {
+ case PLL_FBK_CPU:
+ m = sysInfo->pllFwdDiv * cpudv0;
+ break;
+ case PLL_FBK_PERCLK:
+ m = sysInfo->pllFwdDiv * plb2xDiv * 2
+ * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv;
+ break;
+ case PLL_FBK_PLL_LOCAL:
+ break;
+ default:
+ printf("%s unknown m\n", __FUNCTION__);
+ return;
+
+ }
+ m *= sysInfo->pllFbkDiv;
+
+ /*
+ * Determine VCO clock frequency
+ */
+ sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) /
+ (unsigned long long)sysClkPeriodPs;
+
+ /*
+ * Determine CPU clock frequency
+ */
+ sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0);
+
+ /*
+ * Determine PLB clock frequency, ddr1x should be the same
+ */
+ sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2);
+ sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
+ sysInfo->freqDDR = sysInfo->freqPLB;
+ sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv;
+ sysInfo->freqUART = sysInfo->freqPLB;
+}
+
+#endif
+
+int get_clocks (void)
+{
+ sys_info_t sys_info;
+
+ get_sys_info (&sys_info);
+ gd->cpu_clk = sys_info.freqProcessor;
+ gd->bus_clk = sys_info.freqPLB;
+
+ return (0);
+}
+
+
+/********************************************
+ * get_bus_freq
+ * return PLB bus freq in Hz
+ *********************************************/
+ulong get_bus_freq (ulong dummy)
+{
+ ulong val;
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+ defined(CONFIG_405EX) || defined(CONFIG_405) || \
+ defined(CONFIG_440)
+ sys_info_t sys_info;
+
+ get_sys_info (&sys_info);
+ val = sys_info.freqPLB;
+#else
+# error get_bus_freq() not implemented
+#endif
+
+ return val;
+}
+
+ulong get_OPB_freq (void)
+{
+ PPC4xx_SYS_INFO sys_info;
+
+ get_sys_info (&sys_info);
+
+ return sys_info.freqOPB;
+}
diff --git a/arch/powerpc/cpu/ppc4xx/spl_boot.c b/arch/powerpc/cpu/ppc4xx/spl_boot.c
new file mode 100644
index 0000000..80869f6
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/spl_boot.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 Stefan Roese <sr@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <spl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Return selected boot device. On PPC4xx its only NOR flash right now.
+ */
+u32 spl_boot_device(void)
+{
+ return BOOT_DEVICE_NOR;
+}
+
+/*
+ * SPL version of board_init_f()
+ */
+void board_init_f(ulong bootflag)
+{
+ /*
+ * First we need to initialize the SDRAM, so that the real
+ * U-Boot or the OS (Linux) can be loaded
+ */
+ initdram(0);
+
+ /* Clear bss */
+ memset(__bss_start, '\0', __bss_end - __bss_start);
+
+ /*
+ * Init global_data pointer. Has to be done before calling
+ * get_clocks(), as it stores some clock values into gd needed
+ * later on in the serial driver.
+ */
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *)(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+ /* Clear initial global data */
+ memset((void *)gd, 0, sizeof(gd_t));
+
+ /*
+ * get_clocks() needs to be called so that the serial driver
+ * works correctly
+ */
+ get_clocks();
+
+ /*
+ * Do rudimental console / serial setup
+ */
+ preloader_console_init();
+
+ /*
+ * Call board_init_r() (SPL framework version) to load and boot
+ * real U-Boot or OS
+ */
+ board_init_r(NULL, 0);
+ /* Does not return!!! */
+}
diff --git a/arch/powerpc/cpu/ppc4xx/start.S b/arch/powerpc/cpu/ppc4xx/start.S
new file mode 100644
index 0000000..57ae1d3
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/start.S
@@ -0,0 +1,2096 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2007 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ * Copyright (c) 2008 Nuovation System Designs, LLC
+ * Grant Erickson <gerickson@nuovations.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+/*------------------------------------------------------------------------------+
+ * This source code is dual-licensed. You may use it under the terms of the
+ * GNU General Public License version 2, or under the license below.
+ *
+ * This source code has been made available to you by IBM on an AS-IS
+ * basis. Anyone receiving this source is licensed under IBM
+ * copyrights to use it in any way he or she deems fit, including
+ * copying it, modifying it, compiling it, and redistributing it either
+ * with or without modifications. No license under IBM patents or
+ * patent applications is to be implied by the copyright license.
+ *
+ * Any user of this software should understand that IBM cannot provide
+ * technical support for this software and will not be responsible for
+ * any consequences resulting from the use of this software.
+ *
+ * Any person who transfers this source code or any derivative work
+ * must include the IBM copyright notice, this paragraph, and the
+ * preceding two paragraphs in the transferred software.
+ *
+ * COPYRIGHT I B M CORPORATION 1995
+ * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
+ *-------------------------------------------------------------------------------
+ */
+
+/*
+ * Startup code for IBM/AMCC PowerPC 4xx (PPC4xx) based boards
+ *
+ * The following description only applies to the NOR flash style booting.
+ * NAND booting is different. For more details about NAND booting on 4xx
+ * take a look at doc/README.nand-boot-ppc440.
+ *
+ * The CPU starts at address 0xfffffffc (last word in the address space).
+ * The U-Boot image therefore has to be located in the "upper" area of the
+ * flash (e.g. 512MiB - 0xfff80000 ... 0xffffffff). The default value for
+ * the boot chip-select (CS0) is quite big and covers this area. On the
+ * 405EX this is for example 0xffe00000 ... 0xffffffff. U-Boot will
+ * reconfigure this CS0 (and other chip-selects as well when configured
+ * this way) in the boot process to the "correct" values matching the
+ * board layout.
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/ppc4xx.h>
+#include <version.h>
+
+#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <asm/ppc4xx-isram.h>
+
+#ifdef CONFIG_SYS_INIT_DCACHE_CS
+# if (CONFIG_SYS_INIT_DCACHE_CS == 0)
+# define PBxAP PB1AP
+# define PBxCR PB0CR
+# if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB0AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB0CR
+# endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 1)
+# define PBxAP PB1AP
+# define PBxCR PB1CR
+# if (defined(CONFIG_SYS_EBC_PB1AP) && defined(CONFIG_SYS_EBC_PB1CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB1AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB1CR
+# endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 2)
+# define PBxAP PB2AP
+# define PBxCR PB2CR
+# if (defined(CONFIG_SYS_EBC_PB2AP) && defined(CONFIG_SYS_EBC_PB2CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB2AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB2CR
+# endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 3)
+# define PBxAP PB3AP
+# define PBxCR PB3CR
+# if (defined(CONFIG_SYS_EBC_PB3AP) && defined(CONFIG_SYS_EBC_PB3CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB3AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB3CR
+# endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 4)
+# define PBxAP PB4AP
+# define PBxCR PB4CR
+# if (defined(CONFIG_SYS_EBC_PB4AP) && defined(CONFIG_SYS_EBC_PB4CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB4AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB4CR
+# endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 5)
+# define PBxAP PB5AP
+# define PBxCR PB5CR
+# if (defined(CONFIG_SYS_EBC_PB5AP) && defined(CONFIG_SYS_EBC_PB5CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB5AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB5CR
+# endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 6)
+# define PBxAP PB6AP
+# define PBxCR PB6CR
+# if (defined(CONFIG_SYS_EBC_PB6AP) && defined(CONFIG_SYS_EBC_PB6CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB6AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB6CR
+# endif
+# endif
+# if (CONFIG_SYS_INIT_DCACHE_CS == 7)
+# define PBxAP PB7AP
+# define PBxCR PB7CR
+# if (defined(CONFIG_SYS_EBC_PB7AP) && defined(CONFIG_SYS_EBC_PB7CR))
+# define PBxAP_VAL CONFIG_SYS_EBC_PB7AP
+# define PBxCR_VAL CONFIG_SYS_EBC_PB7CR
+# endif
+# endif
+# ifndef PBxAP_VAL
+# define PBxAP_VAL 0
+# endif
+# ifndef PBxCR_VAL
+# define PBxCR_VAL 0
+# endif
+/*
+ * Memory Bank x (nothingness) initialization CONFIG_SYS_INIT_RAM_ADDR + 64 MiB
+ * used as temporary stack pointer for the primordial stack
+ */
+# ifndef CONFIG_SYS_INIT_DCACHE_PBxAR
+# define CONFIG_SYS_INIT_DCACHE_PBxAR (EBC_BXAP_BME_DISABLED | \
+ EBC_BXAP_TWT_ENCODE(7) | \
+ EBC_BXAP_BCE_DISABLE | \
+ EBC_BXAP_BCT_2TRANS | \
+ EBC_BXAP_CSN_ENCODE(0) | \
+ EBC_BXAP_OEN_ENCODE(0) | \
+ EBC_BXAP_WBN_ENCODE(0) | \
+ EBC_BXAP_WBF_ENCODE(0) | \
+ EBC_BXAP_TH_ENCODE(2) | \
+ EBC_BXAP_RE_DISABLED | \
+ EBC_BXAP_SOR_NONDELAYED | \
+ EBC_BXAP_BEM_WRITEONLY | \
+ EBC_BXAP_PEN_DISABLED)
+# endif /* CONFIG_SYS_INIT_DCACHE_PBxAR */
+# ifndef CONFIG_SYS_INIT_DCACHE_PBxCR
+# define CONFIG_SYS_INIT_DCACHE_PBxCR (EBC_BXCR_BAS_ENCODE(CONFIG_SYS_INIT_RAM_ADDR) | \
+ EBC_BXCR_BS_64MB | \
+ EBC_BXCR_BU_RW | \
+ EBC_BXCR_BW_16BIT)
+# endif /* CONFIG_SYS_INIT_DCACHE_PBxCR */
+# ifndef CONFIG_SYS_INIT_RAM_PATTERN
+# define CONFIG_SYS_INIT_RAM_PATTERN 0xDEADDEAD
+# endif
+#endif /* CONFIG_SYS_INIT_DCACHE_CS */
+
+#if (defined(CONFIG_SYS_INIT_RAM_DCACHE) && (CONFIG_SYS_INIT_RAM_SIZE > (4 << 10)))
+#error Only 4k of init-ram is supported - please adjust CONFIG_SYS_INIT_RAM_SIZE!
+#endif
+
+/*
+ * Unless otherwise overriden, enable two 128MB cachable instruction regions
+ * at CONFIG_SYS_SDRAM_BASE and another 128MB cacheable instruction region covering
+ * NOR flash at CONFIG_SYS_FLASH_BASE. Disable all cacheable data regions.
+ */
+#if !defined(CONFIG_SYS_FLASH_BASE)
+/* If not already defined, set it to the "last" 128MByte region */
+# define CONFIG_SYS_FLASH_BASE 0xf8000000
+#endif
+#if !defined(CONFIG_SYS_ICACHE_SACR_VALUE)
+# define CONFIG_SYS_ICACHE_SACR_VALUE \
+ (PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + ( 0 << 20)) | \
+ PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (128 << 20)) | \
+ PPC_128MB_SACR_VALUE(CONFIG_SYS_FLASH_BASE))
+#endif /* !defined(CONFIG_SYS_ICACHE_SACR_VALUE) */
+
+#if !defined(CONFIG_SYS_DCACHE_SACR_VALUE)
+# define CONFIG_SYS_DCACHE_SACR_VALUE \
+ (0x00000000)
+#endif /* !defined(CONFIG_SYS_DCACHE_SACR_VALUE) */
+
+#if !defined(CONFIG_SYS_TLB_FOR_BOOT_FLASH)
+#define CONFIG_SYS_TLB_FOR_BOOT_FLASH 0 /* use TLB 0 as default */
+#endif
+
+#define function_prolog(func_name) .text; \
+ .align 2; \
+ .globl func_name; \
+ func_name:
+#define function_epilog(func_name) .type func_name,@function; \
+ .size func_name,.-func_name
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME ) /* Machine Check */
+
+
+ .extern ext_bus_cntlr_init
+#ifdef CONFIG_NAND_U_BOOT
+ .extern reconfig_tlb0
+#endif
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r12 to access the GOT
+ */
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
+ START_GOT
+ GOT_ENTRY(_GOT2_TABLE_)
+ GOT_ENTRY(_FIXUP_TABLE_)
+
+ GOT_ENTRY(_start)
+ GOT_ENTRY(_start_of_vectors)
+ GOT_ENTRY(_end_of_vectors)
+ GOT_ENTRY(transfer_to_handler)
+
+ GOT_ENTRY(__init_end)
+ GOT_ENTRY(__bss_end)
+ GOT_ENTRY(__bss_start)
+ END_GOT
+#endif /* CONFIG_NAND_SPL */
+
+#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL) && \
+ !defined(CONFIG_SPL_BUILD)
+ /*
+ * NAND U-Boot image is started from offset 0
+ */
+ .text
+#if defined(CONFIG_440)
+ bl reconfig_tlb0
+#endif
+ GET_GOT
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
+ bl board_init_f
+ /* NOTREACHED - board_init_f() does not return */
+#endif
+
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_BOOT_FROM_XMD)
+ /*
+ * 4xx RAM-booting U-Boot image is started from offset 0
+ */
+ .text
+ bl _start_440
+#endif
+
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+ /*
+ * This is the entry of the real U-Boot from a board port
+ * that supports SPL booting on the PPC4xx. We only need
+ * to call board_init_f() here. Everything else has already
+ * been done in the SPL u-boot version.
+ */
+ GET_GOT /* initialize GOT access */
+ bl board_init_f /* run 1st part of board init code (in Flash)*/
+ /* NOTREACHED - board_init_f() does not return */
+#endif
+
+/*
+ * 440 Startup -- on reset only the top 4k of the effective
+ * address space is mapped in by an entry in the instruction
+ * and data shadow TLB. The .bootpg section is located in the
+ * top 4k & does only what's necessary to map in the the rest
+ * of the boot rom. Once the boot rom is mapped in we can
+ * proceed with normal startup.
+ *
+ * NOTE: CS0 only covers the top 2MB of the effective address
+ * space after reset.
+ */
+
+#if defined(CONFIG_440)
+#if !defined(CONFIG_NAND_SPL)
+ .section .bootpg,"ax"
+#endif
+ .globl _start_440
+
+/**************************************************************************/
+_start_440:
+ /*--------------------------------------------------------------------+
+ | 440EPX BUP Change - Hardware team request
+ +--------------------------------------------------------------------*/
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+ sync
+ nop
+ nop
+#endif
+ /*----------------------------------------------------------------+
+ | Core bug fix. Clear the esr
+ +-----------------------------------------------------------------*/
+ li r0,0
+ mtspr SPRN_ESR,r0
+ /*----------------------------------------------------------------*/
+ /* Clear and set up some registers. */
+ /*----------------------------------------------------------------*/
+ iccci r0,r0 /* NOTE: operands not used for 440 */
+ dccci r0,r0 /* NOTE: operands not used for 440 */
+ sync
+ li r0,0
+ mtspr SPRN_SRR0,r0
+ mtspr SPRN_SRR1,r0
+ mtspr SPRN_CSRR0,r0
+ mtspr SPRN_CSRR1,r0
+ /* NOTE: 440GX adds machine check status regs */
+#if defined(CONFIG_440) && !defined(CONFIG_440GP)
+ mtspr SPRN_MCSRR0,r0
+ mtspr SPRN_MCSRR1,r0
+ mfspr r1,SPRN_MCSR
+ mtspr SPRN_MCSR,r1
+#endif
+
+ /*----------------------------------------------------------------*/
+ /* CCR0 init */
+ /*----------------------------------------------------------------*/
+ /* Disable store gathering & broadcast, guarantee inst/data
+ * cache block touch, force load/store alignment
+ * (see errata 1.12: 440_33)
+ */
+ lis r1,0x0030 /* store gathering & broadcast disable */
+ ori r1,r1,0x6000 /* cache touch */
+ mtspr SPRN_CCR0,r1
+
+ /*----------------------------------------------------------------*/
+ /* Initialize debug */
+ /*----------------------------------------------------------------*/
+ mfspr r1,SPRN_DBCR0
+ andis. r1, r1, 0x8000 /* test DBCR0[EDM] bit */
+ bne skip_debug_init /* if set, don't clear debug register */
+ mfspr r1,SPRN_CCR0
+ ori r1,r1,CCR0_DTB@l /* Disable Trace Broadcast */
+ mtspr SPRN_CCR0,r1
+ mtspr SPRN_DBCR0,r0
+ mtspr SPRN_DBCR1,r0
+ mtspr SPRN_DBCR2,r0
+ mtspr SPRN_IAC1,r0
+ mtspr SPRN_IAC2,r0
+ mtspr SPRN_IAC3,r0
+ mtspr SPRN_DAC1,r0
+ mtspr SPRN_DAC2,r0
+ mtspr SPRN_DVC1,r0
+ mtspr SPRN_DVC2,r0
+
+ mfspr r1,SPRN_DBSR
+ mtspr SPRN_DBSR,r1 /* Clear all valid bits */
+skip_debug_init:
+
+#if defined (CONFIG_440SPE)
+ /*----------------------------------------------------------------+
+ | Initialize Core Configuration Reg1.
+ | a. ICDPEI: Record even parity. Normal operation.
+ | b. ICTPEI: Record even parity. Normal operation.
+ | c. DCTPEI: Record even parity. Normal operation.
+ | d. DCDPEI: Record even parity. Normal operation.
+ | e. DCUPEI: Record even parity. Normal operation.
+ | f. DCMPEI: Record even parity. Normal operation.
+ | g. FCOM: Normal operation
+ | h. MMUPEI: Record even parity. Normal operation.
+ | i. FFF: Flush only as much data as necessary.
+ | j. TCS: Timebase increments from CPU clock.
+ +-----------------------------------------------------------------*/
+ li r0,0
+ mtspr SPRN_CCR1, r0
+
+ /*----------------------------------------------------------------+
+ | Reset the timebase.
+ | The previous write to CCR1 sets the timebase source.
+ +-----------------------------------------------------------------*/
+ mtspr SPRN_TBWL, r0
+ mtspr SPRN_TBWU, r0
+#endif
+
+ /*----------------------------------------------------------------*/
+ /* Setup interrupt vectors */
+ /*----------------------------------------------------------------*/
+ mtspr SPRN_IVPR,r0 /* Vectors start at 0x0000_0000 */
+ li r1,0x0100
+ mtspr SPRN_IVOR0,r1 /* Critical input */
+ li r1,0x0200
+ mtspr SPRN_IVOR1,r1 /* Machine check */
+ li r1,0x0300
+ mtspr SPRN_IVOR2,r1 /* Data storage */
+ li r1,0x0400
+ mtspr SPRN_IVOR3,r1 /* Instruction storage */
+ li r1,0x0500
+ mtspr SPRN_IVOR4,r1 /* External interrupt */
+ li r1,0x0600
+ mtspr SPRN_IVOR5,r1 /* Alignment */
+ li r1,0x0700
+ mtspr SPRN_IVOR6,r1 /* Program check */
+ li r1,0x0800
+ mtspr SPRN_IVOR7,r1 /* Floating point unavailable */
+ li r1,0x0c00
+ mtspr SPRN_IVOR8,r1 /* System call */
+ li r1,0x0a00
+ mtspr SPRN_IVOR9,r1 /* Auxiliary Processor unavailable */
+ li r1,0x0900
+ mtspr SPRN_IVOR10,r1 /* Decrementer */
+ li r1,0x1300
+ mtspr SPRN_IVOR13,r1 /* Data TLB error */
+ li r1,0x1400
+ mtspr SPRN_IVOR14,r1 /* Instr TLB error */
+ li r1,0x2000
+ mtspr SPRN_IVOR15,r1 /* Debug */
+
+ /*----------------------------------------------------------------*/
+ /* Configure cache regions */
+ /*----------------------------------------------------------------*/
+ mtspr SPRN_INV0,r0
+ mtspr SPRN_INV1,r0
+ mtspr SPRN_INV2,r0
+ mtspr SPRN_INV3,r0
+ mtspr SPRN_DNV0,r0
+ mtspr SPRN_DNV1,r0
+ mtspr SPRN_DNV2,r0
+ mtspr SPRN_DNV3,r0
+ mtspr SPRN_ITV0,r0
+ mtspr SPRN_ITV1,r0
+ mtspr SPRN_ITV2,r0
+ mtspr SPRN_ITV3,r0
+ mtspr SPRN_DTV0,r0
+ mtspr SPRN_DTV1,r0
+ mtspr SPRN_DTV2,r0
+ mtspr SPRN_DTV3,r0
+
+ /*----------------------------------------------------------------*/
+ /* Cache victim limits */
+ /*----------------------------------------------------------------*/
+ /* floors 0, ceiling max to use the entire cache -- nothing locked
+ */
+ lis r1,0x0001
+ ori r1,r1,0xf800
+ mtspr SPRN_IVLIM,r1
+ mtspr SPRN_DVLIM,r1
+
+ /*----------------------------------------------------------------+
+ |Initialize MMUCR[STID] = 0.
+ +-----------------------------------------------------------------*/
+ mfspr r0,SPRN_MMUCR
+ addis r1,0,0xFFFF
+ ori r1,r1,0xFF00
+ and r0,r0,r1
+ mtspr SPRN_MMUCR,r0
+
+ /*----------------------------------------------------------------*/
+ /* Clear all TLB entries -- TID = 0, TS = 0 */
+ /*----------------------------------------------------------------*/
+ addis r0,0,0x0000
+#ifdef CONFIG_SYS_RAMBOOT
+ li r4,0 /* Start with TLB #0 */
+#else
+ li r4,1 /* Start with TLB #1 */
+#endif
+ li r1,64 /* 64 TLB entries */
+ sub r1,r1,r4 /* calculate last TLB # */
+ mtctr r1
+rsttlb:
+#ifdef CONFIG_SYS_RAMBOOT
+ tlbre r3,r4,0 /* Read contents from TLB word #0 to get EPN */
+ rlwinm. r3,r3,0,0xfffffc00 /* Mask EPN */
+ beq tlbnxt /* Skip EPN=0 TLB, this is the SDRAM TLB */
+#endif
+ tlbwe r0,r4,0 /* Invalidate all entries (V=0)*/
+ tlbwe r0,r4,1
+ tlbwe r0,r4,2
+tlbnxt: addi r4,r4,1 /* Next TLB */
+ bdnz rsttlb
+
+ /*----------------------------------------------------------------*/
+ /* TLB entry setup -- step thru tlbtab */
+ /*----------------------------------------------------------------*/
+#if defined(CONFIG_440SPE_REVA)
+ /*----------------------------------------------------------------*/
+ /* We have different TLB tables for revA and rev B of 440SPe */
+ /*----------------------------------------------------------------*/
+ mfspr r1, PVR
+ lis r0,0x5342
+ ori r0,r0,0x1891
+ cmpw r7,r1,r0
+ bne r7,..revA
+ bl tlbtabB
+ b ..goon
+..revA:
+ bl tlbtabA
+..goon:
+#else
+ bl tlbtab /* Get tlbtab pointer */
+#endif
+ mr r5,r0
+ li r1,0x003f /* 64 TLB entries max */
+ mtctr r1
+ li r4,0 /* TLB # */
+
+ addi r5,r5,-4
+1:
+#ifdef CONFIG_SYS_RAMBOOT
+ tlbre r3,r4,0 /* Read contents from TLB word #0 */
+ rlwinm. r3,r3,0,0x00000200 /* Mask V (valid) bit */
+ bne tlbnx2 /* Skip V=1 TLB, this is the SDRAM TLB */
+#endif
+ lwzu r0,4(r5)
+ cmpwi r0,0
+ beq 2f /* 0 marks end */
+ lwzu r1,4(r5)
+ lwzu r2,4(r5)
+ tlbwe r0,r4,0 /* TLB Word 0 */
+ tlbwe r1,r4,1 /* TLB Word 1 */
+ tlbwe r2,r4,2 /* TLB Word 2 */
+tlbnx2: addi r4,r4,1 /* Next TLB */
+ bdnz 1b
+
+ /*----------------------------------------------------------------*/
+ /* Continue from 'normal' start */
+ /*----------------------------------------------------------------*/
+2:
+ bl 3f
+ b _start
+
+3: li r0,0
+ mtspr SPRN_SRR1,r0 /* Keep things disabled for now */
+ mflr r1
+ mtspr SPRN_SRR0,r1
+ rfi
+#endif /* CONFIG_440 */
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
+ .text
+ .long 0x27051956 /* U-Boot Magic Number */
+ .globl version_string
+version_string:
+ .ascii U_BOOT_VERSION_STRING, "\0"
+
+ . = EXC_OFF_SYS_RESET
+ .globl _start_of_vectors
+_start_of_vectors:
+
+/* Critical input. */
+ CRIT_EXCEPTION(0x100, CritcalInput, UnknownException)
+
+#ifdef CONFIG_440
+/* Machine check */
+ MCK_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+#else
+ CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+#endif /* CONFIG_440 */
+
+/* Data Storage exception. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE)
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG(SRR0, SRR1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException,
+ MSR_KERNEL, COPY_EE)
+
+#ifdef CONFIG_440
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+ STD_EXCEPTION(0x900, Decrementer, DecrementerPITException)
+ STD_EXCEPTION(0xa00, APU, UnknownException)
+#endif
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+
+#ifdef CONFIG_440
+ STD_EXCEPTION(0x1300, DataTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, InstructionTLBError, UnknownException)
+#else
+ STD_EXCEPTION(0x1000, PIT, DecrementerPITException)
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+#endif
+ CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
+
+ .globl _end_of_vectors
+_end_of_vectors:
+ . = _START_OFFSET
+#endif
+ .globl _start
+_start:
+
+#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
+ /*
+ * This is the entry of the real U-Boot from a board port
+ * that supports SPL booting on the PPC4xx. We only need
+ * to call board_init_f() here. Everything else has already
+ * been done in the SPL u-boot version.
+ */
+ GET_GOT /* initialize GOT access */
+ bl board_init_f /* run 1st part of board init code (in Flash)*/
+ /* NOTREACHED - board_init_f() does not return */
+#endif
+
+/*****************************************************************************/
+#if defined(CONFIG_440)
+
+ /*----------------------------------------------------------------*/
+ /* Clear and set up some registers. */
+ /*----------------------------------------------------------------*/
+ li r0,0x0000
+ lis r1,0xffff
+ mtspr SPRN_DEC,r0 /* prevent dec exceptions */
+ mtspr SPRN_TBWL,r0 /* prevent fit & wdt exceptions */
+ mtspr SPRN_TBWU,r0
+ mtspr SPRN_TSR,r1 /* clear all timer exception status */
+ mtspr SPRN_TCR,r0 /* disable all */
+ mtspr SPRN_ESR,r0 /* clear exception syndrome register */
+ mtxer r0 /* clear integer exception register */
+
+ /*----------------------------------------------------------------*/
+ /* Debug setup -- some (not very good) ice's need an event*/
+ /* to establish control :-( Define CONFIG_SYS_INIT_DBCR to the dbsr */
+ /* value you need in this case 0x8cff 0000 should do the trick */
+ /*----------------------------------------------------------------*/
+#if defined(CONFIG_SYS_INIT_DBCR)
+ lis r1,0xffff
+ ori r1,r1,0xffff
+ mtspr SPRN_DBSR,r1 /* Clear all status bits */
+ lis r0,CONFIG_SYS_INIT_DBCR@h
+ ori r0,r0,CONFIG_SYS_INIT_DBCR@l
+ mtspr SPRN_DBCR0,r0
+ isync
+#endif
+
+ /*----------------------------------------------------------------*/
+ /* Setup the internal SRAM */
+ /*----------------------------------------------------------------*/
+ li r0,0
+
+#ifdef CONFIG_SYS_INIT_RAM_DCACHE
+ /* Clear Dcache to use as RAM */
+ addis r3,r0,CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3,r3,CONFIG_SYS_INIT_RAM_ADDR@l
+ addis r4,r0,CONFIG_SYS_INIT_RAM_SIZE@h
+ ori r4,r4,CONFIG_SYS_INIT_RAM_SIZE@l
+ rlwinm. r5,r4,0,27,31
+ rlwinm r5,r4,27,5,31
+ beq ..d_ran
+ addi r5,r5,0x0001
+..d_ran:
+ mtctr r5
+..d_ag:
+ dcbz r0,r3
+ addi r3,r3,32
+ bdnz ..d_ag
+
+ /*
+ * Lock the init-ram/stack in d-cache, so that other regions
+ * may use d-cache as well
+ * Note, that this current implementation locks exactly 4k
+ * of d-cache, so please make sure that you don't define a
+ * bigger init-ram area. Take a look at the lwmon5 440EPx
+ * implementation as a reference.
+ */
+ msync
+ isync
+ /* 8. set TFLOOR/NFLOOR to 8 (-> 8*16*32 bytes locked -> 4k) */
+ lis r1,0x0201
+ ori r1,r1,0xf808
+ mtspr SPRN_DVLIM,r1
+ lis r1,0x0808
+ ori r1,r1,0x0808
+ mtspr SPRN_DNV0,r1
+ mtspr SPRN_DNV1,r1
+ mtspr SPRN_DNV2,r1
+ mtspr SPRN_DNV3,r1
+ mtspr SPRN_DTV0,r1
+ mtspr SPRN_DTV1,r1
+ mtspr SPRN_DTV2,r1
+ mtspr SPRN_DTV3,r1
+ msync
+ isync
+#endif /* CONFIG_SYS_INIT_RAM_DCACHE */
+
+ /* 440EP & 440GR are only 440er PPC's without internal SRAM */
+#if !defined(CONFIG_440EP) && !defined(CONFIG_440GR)
+ /* not all PPC's have internal SRAM usable as L2-cache */
+#if defined(CONFIG_440GX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460SX)
+ mtdcr L2_CACHE_CFG,r0 /* Ensure L2 Cache is off */
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_APM821XX)
+ lis r1, 0x0000
+ ori r1,r1,0x0008 /* Set L2_CACHE_CFG[RDBW]=1 */
+ mtdcr L2_CACHE_CFG,r1
+#endif
+
+ lis r2,0x7fff
+ ori r2,r2,0xffff
+ mfdcr r1,ISRAM0_DPC
+ and r1,r1,r2 /* Disable parity check */
+ mtdcr ISRAM0_DPC,r1
+ mfdcr r1,ISRAM0_PMEG
+ and r1,r1,r2 /* Disable pwr mgmt */
+ mtdcr ISRAM0_PMEG,r1
+
+ lis r1,0x8000 /* BAS = 8000_0000 */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SP)
+ ori r1,r1,0x0980 /* first 64k */
+ mtdcr ISRAM0_SB0CR,r1
+ lis r1,0x8001
+ ori r1,r1,0x0980 /* second 64k */
+ mtdcr ISRAM0_SB1CR,r1
+ lis r1, 0x8002
+ ori r1,r1, 0x0980 /* third 64k */
+ mtdcr ISRAM0_SB2CR,r1
+ lis r1, 0x8003
+ ori r1,r1, 0x0980 /* fourth 64k */
+ mtdcr ISRAM0_SB3CR,r1
+#elif defined(CONFIG_440SPE) || defined(CONFIG_460EX) || \
+ defined(CONFIG_460GT) || defined(CONFIG_APM821XX)
+ lis r1,0x0000 /* BAS = X_0000_0000 */
+ ori r1,r1,0x0984 /* first 64k */
+ mtdcr ISRAM0_SB0CR,r1
+ lis r1,0x0001
+ ori r1,r1,0x0984 /* second 64k */
+ mtdcr ISRAM0_SB1CR,r1
+ lis r1, 0x0002
+ ori r1,r1, 0x0984 /* third 64k */
+ mtdcr ISRAM0_SB2CR,r1
+ lis r1, 0x0003
+ ori r1,r1, 0x0984 /* fourth 64k */
+ mtdcr ISRAM0_SB3CR,r1
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_APM821XX)
+ lis r2,0x7fff
+ ori r2,r2,0xffff
+ mfdcr r1,ISRAM1_DPC
+ and r1,r1,r2 /* Disable parity check */
+ mtdcr ISRAM1_DPC,r1
+ mfdcr r1,ISRAM1_PMEG
+ and r1,r1,r2 /* Disable pwr mgmt */
+ mtdcr ISRAM1_PMEG,r1
+
+ lis r1,0x0004 /* BAS = 4_0004_0000 */
+ ori r1,r1,ISRAM1_SIZE /* ocm size */
+ mtdcr ISRAM1_SB0CR,r1
+#endif
+#elif defined(CONFIG_460SX)
+ lis r1,0x0000 /* BAS = 0000_0000 */
+ ori r1,r1,0x0B84 /* first 128k */
+ mtdcr ISRAM0_SB0CR,r1
+ lis r1,0x0001
+ ori r1,r1,0x0B84 /* second 128k */
+ mtdcr ISRAM0_SB1CR,r1
+ lis r1, 0x0002
+ ori r1,r1, 0x0B84 /* third 128k */
+ mtdcr ISRAM0_SB2CR,r1
+ lis r1, 0x0003
+ ori r1,r1, 0x0B84 /* fourth 128k */
+ mtdcr ISRAM0_SB3CR,r1
+#elif defined(CONFIG_440GP)
+ ori r1,r1,0x0380 /* 8k rw */
+ mtdcr ISRAM0_SB0CR,r1
+ mtdcr ISRAM0_SB1CR,r0 /* Disable bank 1 */
+#endif
+#endif /* #if !defined(CONFIG_440EP) && !defined(CONFIG_440GR) */
+
+ /*----------------------------------------------------------------*/
+ /* Setup the stack in internal SRAM */
+ /*----------------------------------------------------------------*/
+ lis r1,CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET@l
+ li r0,0
+ stwu r0,-4(r1)
+ stwu r0,-4(r1) /* Terminate call chain */
+
+ stwu r1,-8(r1) /* Save back chain and move SP */
+ lis r0,RESET_VECTOR@h /* Address of reset vector */
+ ori r0,r0, RESET_VECTOR@l
+ stwu r1,-8(r1) /* Save back chain and move SP */
+ stw r0,+12(r1) /* Save return addr (underflow vect) */
+
+#ifdef CONFIG_NAND_SPL
+ bl nand_boot_common /* will not return */
+#else
+#ifndef CONFIG_SPL_BUILD
+ GET_GOT
+#endif
+
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
+ bl board_init_f
+ /* NOTREACHED - board_init_f() does not return */
+#endif
+
+#endif /* CONFIG_440 */
+
+/*****************************************************************************/
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \
+ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \
+ defined(CONFIG_405EX) || defined(CONFIG_405)
+ /*----------------------------------------------------------------------- */
+ /* Clear and set up some registers. */
+ /*----------------------------------------------------------------------- */
+ addi r4,r0,0x0000
+#if !defined(CONFIG_405EX)
+ mtspr SPRN_SGR,r4
+#else
+ /*
+ * On 405EX, completely clearing the SGR leads to PPC hangup
+ * upon PCIe configuration access. The PCIe memory regions
+ * need to be guarded!
+ */
+ lis r3,0x0000
+ ori r3,r3,0x7FFC
+ mtspr SPRN_SGR,r3
+#endif
+ mtspr SPRN_DCWR,r4
+ mtesr r4 /* clear Exception Syndrome Reg */
+ mttcr r4 /* clear Timer Control Reg */
+ mtxer r4 /* clear Fixed-Point Exception Reg */
+ mtevpr r4 /* clear Exception Vector Prefix Reg */
+ addi r4,r0,(0xFFFF-0x10000) /* set r4 to 0xFFFFFFFF (status in the */
+ /* dbsr is cleared by setting bits to 1) */
+ mtdbsr r4 /* clear/reset the dbsr */
+
+ /* Invalidate the i- and d-caches. */
+ bl invalidate_icache
+ bl invalidate_dcache
+
+ /* Set-up icache cacheability. */
+ lis r4, CONFIG_SYS_ICACHE_SACR_VALUE@h
+ ori r4, r4, CONFIG_SYS_ICACHE_SACR_VALUE@l
+ mticcr r4
+ isync
+
+ /* Set-up dcache cacheability. */
+ lis r4, CONFIG_SYS_DCACHE_SACR_VALUE@h
+ ori r4, r4, CONFIG_SYS_DCACHE_SACR_VALUE@l
+ mtdccr r4
+
+#if !(defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR))\
+ && !defined (CONFIG_XILINX_405)
+ /*----------------------------------------------------------------------- */
+ /* Tune the speed and size for flash CS0 */
+ /*----------------------------------------------------------------------- */
+ bl ext_bus_cntlr_init
+#endif
+
+#if !(defined(CONFIG_SYS_INIT_DCACHE_CS) || defined(CONFIG_SYS_TEMP_STACK_OCM))
+ /*
+ * For boards that don't have OCM and can't use the data cache
+ * for their primordial stack, setup stack here directly after the
+ * SDRAM is initialized in ext_bus_cntlr_init.
+ */
+ lis r1, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r1,r1,CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in SDRAM */
+
+ li r0, 0 /* Make room for stack frame header and */
+ stwu r0, -4(r1) /* clear final stack frame so that */
+ stwu r0, -4(r1) /* stack backtraces terminate cleanly */
+ /*
+ * Set up a dummy frame to store reset vector as return address.
+ * this causes stack underflow to reset board.
+ */
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ lis r0, RESET_VECTOR@h /* Address of reset vector */
+ ori r0, r0, RESET_VECTOR@l
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ stw r0, +12(r1) /* Save return addr (underflow vect) */
+#endif /* !(CONFIG_SYS_INIT_DCACHE_CS || !CONFIG_SYS_TEM_STACK_OCM) */
+
+#if defined(CONFIG_405EP)
+ /*----------------------------------------------------------------------- */
+ /* DMA Status, clear to come up clean */
+ /*----------------------------------------------------------------------- */
+ addis r3,r0, 0xFFFF /* Clear all existing DMA status */
+ ori r3,r3, 0xFFFF
+ mtdcr DMASR, r3
+
+ bl ppc405ep_init /* do ppc405ep specific init */
+#endif /* CONFIG_405EP */
+
+#if defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE)
+#if defined(CONFIG_405EZ)
+ /********************************************************************
+ * Setup OCM - On Chip Memory - PPC405EZ uses OCM Controller V2
+ *******************************************************************/
+ /*
+ * We can map the OCM on the PLB3, so map it at
+ * CONFIG_SYS_OCM_DATA_ADDR + 0x8000
+ */
+ lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */
+ ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l
+ ori r3,r3,0x0270 /* 16K for Bank 1, R/W/Enable */
+ mtdcr OCM0_PLBCR1,r3 /* Set PLB Access */
+ ori r3,r3,0x4000 /* Add 0x4000 for bank 2 */
+ mtdcr OCM0_PLBCR2,r3 /* Set PLB Access */
+ isync
+
+ lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */
+ ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l
+ ori r3,r3,0x0270 /* 16K for Bank 1, R/W/Enable */
+ mtdcr OCM0_DSRC1, r3 /* Set Data Side */
+ mtdcr OCM0_ISRC1, r3 /* Set Instruction Side */
+ ori r3,r3,0x4000 /* Add 0x4000 for bank 2 */
+ mtdcr OCM0_DSRC2, r3 /* Set Data Side */
+ mtdcr OCM0_ISRC2, r3 /* Set Instruction Side */
+ addis r3,0,0x0800 /* OCM Data Parity Disable - 1 Wait State */
+ mtdcr OCM0_DISDPC,r3
+
+ isync
+#else /* CONFIG_405EZ */
+ /********************************************************************
+ * Setup OCM - On Chip Memory
+ *******************************************************************/
+ /* Setup OCM */
+ lis r0, 0x7FFF
+ ori r0, r0, 0xFFFF
+ mfdcr r3, OCM0_ISCNTL /* get instr-side IRAM config */
+ mfdcr r4, OCM0_DSCNTL /* get data-side IRAM config */
+ and r3, r3, r0 /* disable data-side IRAM */
+ and r4, r4, r0 /* disable data-side IRAM */
+ mtdcr OCM0_ISCNTL, r3 /* set instr-side IRAM config */
+ mtdcr OCM0_DSCNTL, r4 /* set data-side IRAM config */
+ isync
+
+ lis r3,CONFIG_SYS_OCM_DATA_ADDR@h /* OCM location */
+ ori r3,r3,CONFIG_SYS_OCM_DATA_ADDR@l
+ mtdcr OCM0_DSARC, r3
+ addis r4, 0, 0xC000 /* OCM data area enabled */
+ mtdcr OCM0_DSCNTL, r4
+ isync
+#endif /* CONFIG_405EZ */
+#endif
+
+ /*----------------------------------------------------------------------- */
+ /* Setup temporary stack in DCACHE or OCM if needed for SDRAM SPD. */
+ /*----------------------------------------------------------------------- */
+#ifdef CONFIG_SYS_INIT_DCACHE_CS
+ li r4, PBxAP
+ mtdcr EBC0_CFGADDR, r4
+ lis r4, CONFIG_SYS_INIT_DCACHE_PBxAR@h
+ ori r4, r4, CONFIG_SYS_INIT_DCACHE_PBxAR@l
+ mtdcr EBC0_CFGDATA, r4
+
+ addi r4, 0, PBxCR
+ mtdcr EBC0_CFGADDR, r4
+ lis r4, CONFIG_SYS_INIT_DCACHE_PBxCR@h
+ ori r4, r4, CONFIG_SYS_INIT_DCACHE_PBxCR@l
+ mtdcr EBC0_CFGDATA, r4
+
+ /*
+ * Enable the data cache for the 128MB storage access control region
+ * at CONFIG_SYS_INIT_RAM_ADDR.
+ */
+ mfdccr r4
+ oris r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h
+ ori r4, r4, PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l
+ mtdccr r4
+
+ /*
+ * Preallocate data cache lines to be used to avoid a subsequent
+ * cache miss and an ensuing machine check exception when exceptions
+ * are enabled.
+ */
+ li r0, 0
+
+ lis r3, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+
+ lis r4, CONFIG_SYS_INIT_RAM_SIZE@h
+ ori r4, r4, CONFIG_SYS_INIT_RAM_SIZE@l
+
+ /*
+ * Convert the size, in bytes, to the number of cache lines/blocks
+ * to preallocate.
+ */
+ clrlwi. r5, r4, (32 - L1_CACHE_SHIFT)
+ srwi r5, r4, L1_CACHE_SHIFT
+ beq ..load_counter
+ addi r5, r5, 0x0001
+..load_counter:
+ mtctr r5
+
+ /* Preallocate the computed number of cache blocks. */
+..alloc_dcache_block:
+ dcba r0, r3
+ addi r3, r3, L1_CACHE_BYTES
+ bdnz ..alloc_dcache_block
+ sync
+
+ /*
+ * Load the initial stack pointer and data area and convert the size,
+ * in bytes, to the number of words to initialize to a known value.
+ */
+ lis r1, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r1, r1, CONFIG_SYS_INIT_SP_OFFSET@l
+
+ lis r4, (CONFIG_SYS_INIT_RAM_SIZE >> 2)@h
+ ori r4, r4, (CONFIG_SYS_INIT_RAM_SIZE >> 2)@l
+ mtctr r4
+
+ lis r2, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r2, r2, CONFIG_SYS_INIT_RAM_SIZE@l
+
+ lis r4, CONFIG_SYS_INIT_RAM_PATTERN@h
+ ori r4, r4, CONFIG_SYS_INIT_RAM_PATTERN@l
+
+..stackloop:
+ stwu r4, -4(r2)
+ bdnz ..stackloop
+
+ /*
+ * Make room for stack frame header and clear final stack frame so
+ * that stack backtraces terminate cleanly.
+ */
+ stwu r0, -4(r1)
+ stwu r0, -4(r1)
+
+ /*
+ * Set up a dummy frame to store reset vector as return address.
+ * this causes stack underflow to reset board.
+ */
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ addis r0, 0, RESET_VECTOR@h /* Address of reset vector */
+ ori r0, r0, RESET_VECTOR@l
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ stw r0, +12(r1) /* Save return addr (underflow vect) */
+
+#elif defined(CONFIG_SYS_TEMP_STACK_OCM) && \
+ (defined(CONFIG_SYS_OCM_DATA_ADDR) && defined(CONFIG_SYS_OCM_DATA_SIZE))
+ /*
+ * Stack in OCM.
+ */
+
+ /* Set up Stack at top of OCM */
+ lis r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@h
+ ori r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)@l
+
+ /* Set up a zeroized stack frame so that backtrace works right */
+ li r0, 0
+ stwu r0, -4(r1)
+ stwu r0, -4(r1)
+
+ /*
+ * Set up a dummy frame to store reset vector as return address.
+ * this causes stack underflow to reset board.
+ */
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ lis r0, RESET_VECTOR@h /* Address of reset vector */
+ ori r0, r0, RESET_VECTOR@l
+ stwu r1, -8(r1) /* Save back chain and move SP */
+ stw r0, +12(r1) /* Save return addr (underflow vect) */
+#endif /* CONFIG_SYS_INIT_DCACHE_CS */
+
+#ifdef CONFIG_NAND_SPL
+ bl nand_boot_common /* will not return */
+#else
+ GET_GOT /* initialize GOT access */
+
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
+
+ bl board_init_f /* run first part of init code (from Flash) */
+ /* NOTREACHED - board_init_f() does not return */
+
+#endif /* CONFIG_NAND_SPL */
+
+#endif /* CONFIG_405GP || CONFIG_405CR || CONFIG_405 || CONFIG_405EP */
+ /*----------------------------------------------------------------------- */
+
+
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+crit_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SPRN_CSRR0,r2
+ mtspr SPRN_CSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfci
+
+#ifdef CONFIG_440
+mck_return:
+ mfmsr r28 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r28,r28,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r28
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SPRN_MCSRR0,r2
+ mtspr SPRN_MCSRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfmci
+#endif /* CONFIG_440 */
+
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16 */
+/* Description: Output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16
+out16:
+ sth r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out16r */
+/* Description: Byte reverse and output 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out16r
+out16r:
+ sthbrx r4,r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32r */
+/* Description: Byte reverse and output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32r
+out32r:
+ stwbrx r4,r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in16 */
+/* Description: Input 16 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in16
+in16:
+ lhz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in16r */
+/* Description: Input 16 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+ .globl in16r
+in16r:
+ lhbrx r3,r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in32r */
+/* Description: Input 32 bits and byte reverse */
+/*------------------------------------------------------------------------------- */
+ .globl in32r
+in32r:
+ lwbrx r3,r0,r3
+ blr
+
+#if !defined(CONFIG_SPL_BUILD)
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = Relocated stack pointer
+ * r4 = Relocated global data pointer
+ * r5 = Relocated text pointer
+ */
+ .globl relocate_code
+relocate_code:
+#if defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS)
+ /*
+ * We need to flush the initial global data (gd_t) and bd_info
+ * before the dcache will be invalidated.
+ */
+
+ /* Save registers */
+ mr r9, r3
+ mr r10, r4
+ mr r11, r5
+
+ /*
+ * Flush complete dcache, this is faster than flushing the
+ * ranges for global_data and bd_info instead.
+ */
+ bl flush_dcache
+
+#if defined(CONFIG_SYS_INIT_DCACHE_CS)
+ /*
+ * Undo the earlier data cache set-up for the primordial stack and
+ * data area. First, invalidate the data cache and then disable data
+ * cacheability for that area. Finally, restore the EBC values, if
+ * any.
+ */
+
+ /* Invalidate the primordial stack and data area in cache */
+ lis r3, CONFIG_SYS_INIT_RAM_ADDR@h
+ ori r3, r3, CONFIG_SYS_INIT_RAM_ADDR@l
+
+ lis r4, CONFIG_SYS_INIT_RAM_SIZE@h
+ ori r4, r4, CONFIG_SYS_INIT_RAM_SIZE@l
+ add r4, r4, r3
+
+ bl invalidate_dcache_range
+
+ /* Disable cacheability for the region */
+ mfdccr r3
+ lis r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@h
+ ori r4, r4, ~PPC_128MB_SACR_VALUE(CONFIG_SYS_INIT_RAM_ADDR)@l
+ and r3, r3, r4
+ mtdccr r3
+
+ /* Restore the EBC parameters */
+ li r3, PBxAP
+ mtdcr EBC0_CFGADDR, r3
+ lis r3, PBxAP_VAL@h
+ ori r3, r3, PBxAP_VAL@l
+ mtdcr EBC0_CFGDATA, r3
+
+ li r3, PBxCR
+ mtdcr EBC0_CFGADDR, r3
+ lis r3, PBxCR_VAL@h
+ ori r3, r3, PBxCR_VAL@l
+ mtdcr EBC0_CFGDATA, r3
+#endif /* defined(CONFIG_SYS_INIT_DCACHE_CS) */
+
+ /* Restore registers */
+ mr r3, r9
+ mr r4, r10
+ mr r5, r11
+#endif /* defined(CONFIG_4xx_DCACHE) || defined(CONFIG_SYS_INIT_DCACHE_CS) */
+
+#ifdef CONFIG_SYS_INIT_RAM_DCACHE
+ /*
+ * Unlock the previously locked d-cache
+ */
+ msync
+ isync
+ /* set TFLOOR/NFLOOR to 0 again */
+ lis r6,0x0001
+ ori r6,r6,0xf800
+ mtspr SPRN_DVLIM,r6
+ lis r6,0x0000
+ ori r6,r6,0x0000
+ mtspr SPRN_DNV0,r6
+ mtspr SPRN_DNV1,r6
+ mtspr SPRN_DNV2,r6
+ mtspr SPRN_DNV3,r6
+ mtspr SPRN_DTV0,r6
+ mtspr SPRN_DTV1,r6
+ mtspr SPRN_DTV2,r6
+ mtspr SPRN_DTV3,r6
+ msync
+ isync
+
+ /* Invalidate data cache, now no longer our stack */
+ dccci 0,0
+ sync
+ isync
+#endif /* CONFIG_SYS_INIT_RAM_DCACHE */
+
+ /*
+ * On some 440er platforms the cache is enabled in the first TLB (Boot-CS)
+ * to speed up the boot process. Now this cache needs to be disabled.
+ */
+#if defined(CONFIG_440)
+ /* Clear all potential pending exceptions */
+ mfspr r1,SPRN_MCSR
+ mtspr SPRN_MCSR,r1
+ addi r1,r0,CONFIG_SYS_TLB_FOR_BOOT_FLASH /* Use defined TLB */
+ tlbre r0,r1,0x0002 /* Read contents */
+ ori r0,r0,0x0c00 /* Or in the inhibit, write through bit */
+ tlbwe r0,r1,0x0002 /* Save it out */
+ sync
+ isync
+#endif /* defined(CONFIG_440) */
+ mr r1, r3 /* Set new stack pointer */
+ mr r9, r4 /* Save copy of Init Data pointer */
+ mr r10, r5 /* Save copy of Destination Address */
+
+ GET_GOT
+ mr r3, r5 /* Destination Address */
+ lis r4, CONFIG_SYS_MONITOR_BASE@h /* Source Address */
+ ori r4, r4, CONFIG_SYS_MONITOR_BASE@l
+ lwz r5, GOT(__init_end)
+ sub r5, r5, r4
+ li r6, L1_CACHE_BYTES /* Cache Line Size */
+
+ /*
+ * Fix GOT pointer:
+ *
+ * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
+ *
+ * Offset:
+ */
+ sub r15, r10, r4
+
+ /* First our own GOT */
+ add r12, r12, r15
+ /* then the one used by the C code */
+ add r30, r30, r15
+
+ /*
+ * Now relocate code
+ */
+
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: dcbst 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: icbi 0,r4
+ add r4,r4,r6
+ cmplw r4,r5
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+ addi r0, r10, in_ram - _start + _START_OFFSET
+ mtlr r0
+ blr /* NEVER RETURNS! */
+
+in_ram:
+
+ /*
+ * Relocation Function, r12 point to got2+0x8000
+ *
+ * Adjust got2 pointers, no need to check for 0, this code
+ * already puts a few entries in the table.
+ */
+ li r0,__got2_entries@sectoff@l
+ la r3,GOT(_GOT2_TABLE_)
+ lwz r11,GOT(_GOT2_TABLE_)
+ mtctr r0
+ sub r11,r3,r11
+ addi r3,r3,-4
+1: lwzu r0,4(r3)
+ cmpwi r0,0
+ beq- 2f
+ add r0,r0,r11
+ stw r0,0(r3)
+2: bdnz 1b
+
+ /*
+ * Now adjust the fixups and the pointers to the fixups
+ * in case we need to move ourselves again.
+ */
+ li r0,__fixup_entries@sectoff@l
+ lwz r3,GOT(_FIXUP_TABLE_)
+ cmpwi r0,0
+ mtctr r0
+ addi r3,r3,-4
+ beq 4f
+3: lwzu r4,4(r3)
+ lwzux r0,r4,r11
+ cmpwi r0,0
+ add r0,r0,r11
+ stw r4,0(r3)
+ beq- 5f
+ stw r0,0(r4)
+5: bdnz 3b
+4:
+clear_bss:
+ /*
+ * Now clear BSS segment
+ */
+ lwz r3,GOT(__bss_start)
+ lwz r4,GOT(__bss_end)
+
+ cmplw 0, r3, r4
+ beq 7f
+
+ li r0, 0
+
+ andi. r5, r4, 3
+ beq 6f
+ sub r4, r4, r5
+ mtctr r5
+ mr r5, r4
+5: stb r0, 0(r5)
+ addi r5, r5, 1
+ bdnz 5b
+6:
+ stw r0, 0(r3)
+ addi r3, r3, 4
+ cmplw 0, r3, r4
+ bne 6b
+
+7:
+ mr r3, r9 /* Init Data pointer */
+ mr r4, r10 /* Destination Address */
+ bl board_init_r
+
+ /*
+ * Copy exception vector code to low memory
+ *
+ * r3: dest_addr
+ * r7: source address, r8: end address, r9: target address
+ */
+ .globl trap_init
+trap_init:
+ mflr r4 /* save link register */
+ GET_GOT
+ lwz r7, GOT(_start_of_vectors)
+ lwz r8, GOT(_end_of_vectors)
+
+ li r9, 0x100 /* reset vector always at 0x100 */
+
+ cmplw 0, r7, r8
+ bgelr /* return if r7>=r8 - just in case */
+1:
+ lwz r0, 0(r7)
+ stw r0, 0(r9)
+ addi r7, r7, 4
+ addi r9, r9, 4
+ cmplw 0, r7, r8
+ bne 1b
+
+ /*
+ * relocate `hdlr' and `int_return' entries
+ */
+ li r7, .L_MachineCheck - _start + _START_OFFSET
+ li r8, Alignment - _start + _START_OFFSET
+2:
+ bl trap_reloc
+ addi r7, r7, 0x100 /* next exception vector */
+ cmplw 0, r7, r8
+ blt 2b
+
+ li r7, .L_Alignment - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_ProgramCheck - _start + _START_OFFSET
+ bl trap_reloc
+
+#ifdef CONFIG_440
+ li r7, .L_FPUnavailable - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_Decrementer - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_APU - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_InstructionTLBError - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_DataTLBError - _start + _START_OFFSET
+ bl trap_reloc
+#else /* CONFIG_440 */
+ li r7, .L_PIT - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_InstructionTLBMiss - _start + _START_OFFSET
+ bl trap_reloc
+
+ li r7, .L_DataTLBMiss - _start + _START_OFFSET
+ bl trap_reloc
+#endif /* CONFIG_440 */
+
+ li r7, .L_DebugBreakpoint - _start + _START_OFFSET
+ bl trap_reloc
+
+#if !defined(CONFIG_440)
+ addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */
+ oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */
+ mtmsr r7 /* change MSR */
+#else
+ bl __440_msr_set
+ b __440_msr_continue
+
+__440_msr_set:
+ addi r7,r0,0x1000 /* set ME bit (Machine Exceptions) */
+ oris r7,r7,0x0002 /* set CE bit (Critical Exceptions) */
+ mtspr SPRN_SRR1,r7
+ mflr r7
+ mtspr SPRN_SRR0,r7
+ rfi
+__440_msr_continue:
+#endif
+
+ mtlr r4 /* restore link register */
+ blr
+#endif /* CONFIG_SPL_BUILD */
+
+#if defined(CONFIG_440)
+/*----------------------------------------------------------------------------+
+| dcbz_area.
++----------------------------------------------------------------------------*/
+ function_prolog(dcbz_area)
+ rlwinm. r5,r4,0,27,31
+ rlwinm r5,r4,27,5,31
+ beq ..d_ra2
+ addi r5,r5,0x0001
+..d_ra2:mtctr r5
+..d_ag2:dcbz r0,r3
+ addi r3,r3,32
+ bdnz ..d_ag2
+ sync
+ blr
+ function_epilog(dcbz_area)
+#endif /* CONFIG_440 */
+#endif /* CONFIG_NAND_SPL */
+
+/*------------------------------------------------------------------------------- */
+/* Function: in8 */
+/* Description: Input 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in8
+in8:
+ lbz r3,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out8 */
+/* Description: Output 8 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out8
+out8:
+ stb r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: out32 */
+/* Description: Output 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl out32
+out32:
+ stw r4,0x0000(r3)
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: in32 */
+/* Description: Input 32 bits */
+/*------------------------------------------------------------------------------- */
+ .globl in32
+in32:
+ lwz 3,0x0000(3)
+ blr
+
+/**************************************************************************/
+/* PPC405EP specific stuff */
+/**************************************************************************/
+#ifdef CONFIG_405EP
+ppc405ep_init:
+
+#ifdef CONFIG_BUBINGA
+ /*
+ * Initialize EBC chip selects 1 & 4 and GPIO pins (for alternate
+ * function) to support FPGA and NVRAM accesses below.
+ */
+
+ lis r3,GPIO0_OSRH@h /* config GPIO output select */
+ ori r3,r3,GPIO0_OSRH@l
+ lis r4,CONFIG_SYS_GPIO0_OSRH@h
+ ori r4,r4,CONFIG_SYS_GPIO0_OSRH@l
+ stw r4,0(r3)
+ lis r3,GPIO0_OSRL@h
+ ori r3,r3,GPIO0_OSRL@l
+ lis r4,CONFIG_SYS_GPIO0_OSRL@h
+ ori r4,r4,CONFIG_SYS_GPIO0_OSRL@l
+ stw r4,0(r3)
+
+ lis r3,GPIO0_ISR1H@h /* config GPIO input select */
+ ori r3,r3,GPIO0_ISR1H@l
+ lis r4,CONFIG_SYS_GPIO0_ISR1H@h
+ ori r4,r4,CONFIG_SYS_GPIO0_ISR1H@l
+ stw r4,0(r3)
+ lis r3,GPIO0_ISR1L@h
+ ori r3,r3,GPIO0_ISR1L@l
+ lis r4,CONFIG_SYS_GPIO0_ISR1L@h
+ ori r4,r4,CONFIG_SYS_GPIO0_ISR1L@l
+ stw r4,0(r3)
+
+ lis r3,GPIO0_TSRH@h /* config GPIO three-state select */
+ ori r3,r3,GPIO0_TSRH@l
+ lis r4,CONFIG_SYS_GPIO0_TSRH@h
+ ori r4,r4,CONFIG_SYS_GPIO0_TSRH@l
+ stw r4,0(r3)
+ lis r3,GPIO0_TSRL@h
+ ori r3,r3,GPIO0_TSRL@l
+ lis r4,CONFIG_SYS_GPIO0_TSRL@h
+ ori r4,r4,CONFIG_SYS_GPIO0_TSRL@l
+ stw r4,0(r3)
+
+ lis r3,GPIO0_TCR@h /* config GPIO driver output enables */
+ ori r3,r3,GPIO0_TCR@l
+ lis r4,CONFIG_SYS_GPIO0_TCR@h
+ ori r4,r4,CONFIG_SYS_GPIO0_TCR@l
+ stw r4,0(r3)
+
+ li r3,PB1AP /* program EBC bank 1 for RTC access */
+ mtdcr EBC0_CFGADDR,r3
+ lis r3,CONFIG_SYS_EBC_PB1AP@h
+ ori r3,r3,CONFIG_SYS_EBC_PB1AP@l
+ mtdcr EBC0_CFGDATA,r3
+ li r3,PB1CR
+ mtdcr EBC0_CFGADDR,r3
+ lis r3,CONFIG_SYS_EBC_PB1CR@h
+ ori r3,r3,CONFIG_SYS_EBC_PB1CR@l
+ mtdcr EBC0_CFGDATA,r3
+
+ li r3,PB1AP /* program EBC bank 1 for RTC access */
+ mtdcr EBC0_CFGADDR,r3
+ lis r3,CONFIG_SYS_EBC_PB1AP@h
+ ori r3,r3,CONFIG_SYS_EBC_PB1AP@l
+ mtdcr EBC0_CFGDATA,r3
+ li r3,PB1CR
+ mtdcr EBC0_CFGADDR,r3
+ lis r3,CONFIG_SYS_EBC_PB1CR@h
+ ori r3,r3,CONFIG_SYS_EBC_PB1CR@l
+ mtdcr EBC0_CFGDATA,r3
+
+ li r3,PB4AP /* program EBC bank 4 for FPGA access */
+ mtdcr EBC0_CFGADDR,r3
+ lis r3,CONFIG_SYS_EBC_PB4AP@h
+ ori r3,r3,CONFIG_SYS_EBC_PB4AP@l
+ mtdcr EBC0_CFGDATA,r3
+ li r3,PB4CR
+ mtdcr EBC0_CFGADDR,r3
+ lis r3,CONFIG_SYS_EBC_PB4CR@h
+ ori r3,r3,CONFIG_SYS_EBC_PB4CR@l
+ mtdcr EBC0_CFGDATA,r3
+#endif
+
+ /*
+ !-----------------------------------------------------------------------
+ ! Check to see if chip is in bypass mode.
+ ! If so, write stored CPC0_PLLMR0 and CPC0_PLLMR1 values and perform a
+ ! CPU reset Otherwise, skip this step and keep going.
+ ! Note: Running BIOS in bypass mode is not supported since PLB speed
+ ! will not be fast enough for the SDRAM (min 66MHz)
+ !-----------------------------------------------------------------------
+ */
+ mfdcr r5, CPC0_PLLMR1
+ rlwinm r4,r5,1,0x1 /* get system clock source (SSCS) */
+ cmpi cr0,0,r4,0x1
+
+ beq pll_done /* if SSCS =b'1' then PLL has */
+ /* already been set */
+ /* and CPU has been reset */
+ /* so skip to next section */
+
+#ifdef CONFIG_BUBINGA
+ /*
+ !-----------------------------------------------------------------------
+ ! Read NVRAM to get value to write in PLLMR.
+ ! If value has not been correctly saved, write default value
+ ! Default config values (assuming on-board 33MHz SYS_CLK) are above.
+ ! See CPU_DEFAULT_200 and CPU_DEFAULT_266 above.
+ !
+ ! WARNING: This code assumes the first three words in the nvram_t
+ ! structure in openbios.h. Changing the beginning of
+ ! the structure will break this code.
+ !
+ !-----------------------------------------------------------------------
+ */
+ addis r3,0,NVRAM_BASE@h
+ addi r3,r3,NVRAM_BASE@l
+
+ lwz r4, 0(r3)
+ addis r5,0,NVRVFY1@h
+ addi r5,r5,NVRVFY1@l
+ cmp cr0,0,r4,r5 /* Compare 1st NVRAM Magic number*/
+ bne ..no_pllset
+ addi r3,r3,4
+ lwz r4, 0(r3)
+ addis r5,0,NVRVFY2@h
+ addi r5,r5,NVRVFY2@l
+ cmp cr0,0,r4,r5 /* Compare 2 NVRAM Magic number */
+ bne ..no_pllset
+ addi r3,r3,8 /* Skip over conf_size */
+ lwz r4, 4(r3) /* Load PLLMR1 value from NVRAM */
+ lwz r3, 0(r3) /* Load PLLMR0 value from NVRAM */
+ rlwinm r5,r4,1,0x1 /* get system clock source (SSCS) */
+ cmpi cr0,0,r5,1 /* See if PLL is locked */
+ beq pll_write
+..no_pllset:
+#endif /* CONFIG_BUBINGA */
+
+#ifdef CONFIG_TAIHU
+ mfdcr r4, CPC0_BOOT
+ andi. r5, r4, CPC0_BOOT_SEP@l
+ bne strap_1 /* serial eeprom present */
+ addis r5,0,CPLD_REG0_ADDR@h
+ ori r5,r5,CPLD_REG0_ADDR@l
+ andi. r5, r5, 0x10
+ bne _pci_66mhz
+#endif /* CONFIG_TAIHU */
+
+#if defined(CONFIG_ZEUS)
+ mfdcr r4, CPC0_BOOT
+ andi. r5, r4, CPC0_BOOT_SEP@l
+ bne strap_1 /* serial eeprom present */
+ lis r3,0x0000
+ addi r3,r3,0x3030
+ lis r4,0x8042
+ addi r4,r4,0x223e
+ b 1f
+strap_1:
+ mfdcr r3, CPC0_PLLMR0
+ mfdcr r4, CPC0_PLLMR1
+ b 1f
+#endif
+
+ addis r3,0,PLLMR0_DEFAULT@h /* PLLMR0 default value */
+ ori r3,r3,PLLMR0_DEFAULT@l /* */
+ addis r4,0,PLLMR1_DEFAULT@h /* PLLMR1 default value */
+ ori r4,r4,PLLMR1_DEFAULT@l /* */
+
+#ifdef CONFIG_TAIHU
+ b 1f
+_pci_66mhz:
+ addis r3,0,PLLMR0_DEFAULT_PCI66@h
+ ori r3,r3,PLLMR0_DEFAULT_PCI66@l
+ addis r4,0,PLLMR1_DEFAULT_PCI66@h
+ ori r4,r4,PLLMR1_DEFAULT_PCI66@l
+ b 1f
+strap_1:
+ mfdcr r3, CPC0_PLLMR0
+ mfdcr r4, CPC0_PLLMR1
+#endif /* CONFIG_TAIHU */
+
+1:
+ b pll_write /* Write the CPC0_PLLMR with new value */
+
+pll_done:
+ /*
+ !-----------------------------------------------------------------------
+ ! Clear Soft Reset Register
+ ! This is needed to enable PCI if not booting from serial EPROM
+ !-----------------------------------------------------------------------
+ */
+ addi r3, 0, 0x0
+ mtdcr CPC0_SRR, r3
+
+ addis r3,0,0x0010
+ mtctr r3
+pci_wait:
+ bdnz pci_wait
+
+ blr /* return to main code */
+
+/*
+!-----------------------------------------------------------------------------
+! Function: pll_write
+! Description: Updates the value of the CPC0_PLLMR according to CMOS27E documentation
+! That is:
+! 1. Pll is first disabled (de-activated by putting in bypass mode)
+! 2. PLL is reset
+! 3. Clock dividers are set while PLL is held in reset and bypassed
+! 4. PLL Reset is cleared
+! 5. Wait 100us for PLL to lock
+! 6. A core reset is performed
+! Input: r3 = Value to write to CPC0_PLLMR0
+! Input: r4 = Value to write to CPC0_PLLMR1
+! Output r3 = none
+!-----------------------------------------------------------------------------
+*/
+ .globl pll_write
+pll_write:
+ mfdcr r5, CPC0_UCR
+ andis. r5,r5,0xFFFF
+ ori r5,r5,0x0101 /* Stop the UART clocks */
+ mtdcr CPC0_UCR,r5 /* Before changing PLL */
+
+ mfdcr r5, CPC0_PLLMR1
+ rlwinm r5,r5,0,0x7FFFFFFF /* Disable PLL */
+ mtdcr CPC0_PLLMR1,r5
+ oris r5,r5,0x4000 /* Set PLL Reset */
+ mtdcr CPC0_PLLMR1,r5
+
+ mtdcr CPC0_PLLMR0,r3 /* Set clock dividers */
+ rlwinm r5,r4,0,0x3FFFFFFF /* Reset & Bypass new PLL dividers */
+ oris r5,r5,0x4000 /* Set PLL Reset */
+ mtdcr CPC0_PLLMR1,r5 /* Set clock dividers */
+ rlwinm r5,r5,0,0xBFFFFFFF /* Clear PLL Reset */
+ mtdcr CPC0_PLLMR1,r5
+
+ /*
+ ! Wait min of 100us for PLL to lock.
+ ! See CMOS 27E databook for more info.
+ ! At 200MHz, that means waiting 20,000 instructions
+ */
+ addi r3,0,20000 /* 2000 = 0x4e20 */
+ mtctr r3
+pll_wait:
+ bdnz pll_wait
+
+ oris r5,r5,0x8000 /* Enable PLL */
+ mtdcr CPC0_PLLMR1,r5 /* Engage */
+
+ /*
+ * Reset CPU to guarantee timings are OK
+ * Not sure if this is needed...
+ */
+ addis r3,0,0x1000
+ mtspr SPRN_DBCR0,r3 /* This will cause a CPU core reset, and */
+ /* execution will continue from the poweron */
+ /* vector of 0xfffffffc */
+#endif /* CONFIG_405EP */
+
+#if defined(CONFIG_440)
+/*----------------------------------------------------------------------------+
+| mttlb3.
++----------------------------------------------------------------------------*/
+ function_prolog(mttlb3)
+ TLBWE(4,3,2)
+ blr
+ function_epilog(mttlb3)
+
+/*----------------------------------------------------------------------------+
+| mftlb3.
++----------------------------------------------------------------------------*/
+ function_prolog(mftlb3)
+ TLBRE(3,3,2)
+ blr
+ function_epilog(mftlb3)
+
+/*----------------------------------------------------------------------------+
+| mttlb2.
++----------------------------------------------------------------------------*/
+ function_prolog(mttlb2)
+ TLBWE(4,3,1)
+ blr
+ function_epilog(mttlb2)
+
+/*----------------------------------------------------------------------------+
+| mftlb2.
++----------------------------------------------------------------------------*/
+ function_prolog(mftlb2)
+ TLBRE(3,3,1)
+ blr
+ function_epilog(mftlb2)
+
+/*----------------------------------------------------------------------------+
+| mttlb1.
++----------------------------------------------------------------------------*/
+ function_prolog(mttlb1)
+ TLBWE(4,3,0)
+ blr
+ function_epilog(mttlb1)
+
+/*----------------------------------------------------------------------------+
+| mftlb1.
++----------------------------------------------------------------------------*/
+ function_prolog(mftlb1)
+ TLBRE(3,3,0)
+ blr
+ function_epilog(mftlb1)
+#endif /* CONFIG_440 */
+
+#if defined(CONFIG_NAND_SPL)
+/*
+ * void nand_boot_relocate(dst, src, bytes)
+ *
+ * r3 = Destination address to copy code to (in SDRAM)
+ * r4 = Source address to copy code from
+ * r5 = size to copy in bytes
+ */
+nand_boot_relocate:
+ mr r6,r3
+ mr r7,r4
+ mflr r8
+
+ /*
+ * Copy SPL from icache into SDRAM
+ */
+ subi r3,r3,4
+ subi r4,r4,4
+ srwi r5,r5,2
+ mtctr r5
+..spl_loop:
+ lwzu r0,4(r4)
+ stwu r0,4(r3)
+ bdnz ..spl_loop
+
+ /*
+ * Calculate "corrected" link register, so that we "continue"
+ * in execution in destination range
+ */
+ sub r3,r7,r6 /* r3 = src - dst */
+ sub r8,r8,r3 /* r8 = link-reg - (src - dst) */
+ mtlr r8
+ blr
+
+nand_boot_common:
+ /*
+ * First initialize SDRAM. It has to be available *before* calling
+ * nand_boot().
+ */
+ lis r3,CONFIG_SYS_SDRAM_BASE@h
+ ori r3,r3,CONFIG_SYS_SDRAM_BASE@l
+ bl initdram
+
+ /*
+ * Now copy the 4k SPL code into SDRAM and continue execution
+ * from there.
+ */
+ lis r3,CONFIG_SYS_NAND_BOOT_SPL_DST@h
+ ori r3,r3,CONFIG_SYS_NAND_BOOT_SPL_DST@l
+ lis r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@h
+ ori r4,r4,CONFIG_SYS_NAND_BOOT_SPL_SRC@l
+ lis r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@h
+ ori r5,r5,CONFIG_SYS_NAND_BOOT_SPL_SIZE@l
+ bl nand_boot_relocate
+
+ /*
+ * We're running from SDRAM now!!!
+ *
+ * It is necessary for 4xx systems to relocate from running at
+ * the original location (0xfffffxxx) to somewhere else (SDRAM
+ * preferably). This is because CS0 needs to be reconfigured for
+ * NAND access. And we can't reconfigure this CS when currently
+ * "running" from it.
+ */
+
+ /*
+ * Finally call nand_boot() to load main NAND U-Boot image from
+ * NAND and jump to it.
+ */
+ bl nand_boot /* will not return */
+#endif /* CONFIG_NAND_SPL */
diff --git a/arch/powerpc/cpu/ppc4xx/tlb.c b/arch/powerpc/cpu/ppc4xx/tlb.c
new file mode 100644
index 0000000..684da92
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/tlb.c
@@ -0,0 +1,352 @@
+/*
+ * (C) Copyright 2007
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_440)
+
+#include <asm/ppc440.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+
+typedef struct region {
+ u64 base;
+ u32 size;
+ u32 tlb_word2_i_value;
+} region_t;
+
+void remove_tlb(u32 vaddr, u32 size)
+{
+ int i;
+ u32 tlb_word0_value;
+ u32 tlb_vaddr;
+ u32 tlb_size = 0;
+
+ for (i=0; i<PPC4XX_TLB_SIZE; i++) {
+ tlb_word0_value = mftlb1(i);
+ tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value);
+ if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) &&
+ (tlb_vaddr >= vaddr)) {
+ /*
+ * TLB is enabled and start address is lower or equal
+ * than the area we are looking for. Now we only have
+ * to check the size/end address for a match.
+ */
+ switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) {
+ case TLB_WORD0_SIZE_1KB:
+ tlb_size = 1 << 10;
+ break;
+ case TLB_WORD0_SIZE_4KB:
+ tlb_size = 4 << 10;
+ break;
+ case TLB_WORD0_SIZE_16KB:
+ tlb_size = 16 << 10;
+ break;
+ case TLB_WORD0_SIZE_64KB:
+ tlb_size = 64 << 10;
+ break;
+ case TLB_WORD0_SIZE_256KB:
+ tlb_size = 256 << 10;
+ break;
+ case TLB_WORD0_SIZE_1MB:
+ tlb_size = 1 << 20;
+ break;
+ case TLB_WORD0_SIZE_16MB:
+ tlb_size = 16 << 20;
+ break;
+ case TLB_WORD0_SIZE_256MB:
+ tlb_size = 256 << 20;
+ break;
+ }
+
+ /*
+ * Now check the end-address if it's in the range
+ */
+ if ((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1))
+ /*
+ * Found a TLB in the range.
+ * Disable it by writing 0 to tlb0 word.
+ */
+ mttlb1(i, 0);
+ }
+ }
+
+ /* Execute an ISYNC instruction so that the new TLB entry takes effect */
+ asm("isync");
+}
+
+/*
+ * Change the I attribute (cache inhibited) of a TLB or multiple TLB's.
+ * This function is used to either turn cache on or off in a specific
+ * memory area.
+ */
+void change_tlb(u32 vaddr, u32 size, u32 tlb_word2_i_value)
+{
+ int i;
+ u32 tlb_word0_value;
+ u32 tlb_word2_value;
+ u32 tlb_vaddr;
+ u32 tlb_size = 0;
+
+ for (i=0; i<PPC4XX_TLB_SIZE; i++) {
+ tlb_word0_value = mftlb1(i);
+ tlb_vaddr = TLB_WORD0_EPN_DECODE(tlb_word0_value);
+ if (((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_ENABLE) &&
+ (tlb_vaddr >= vaddr)) {
+ /*
+ * TLB is enabled and start address is lower or equal
+ * than the area we are looking for. Now we only have
+ * to check the size/end address for a match.
+ */
+ switch (tlb_word0_value & TLB_WORD0_SIZE_MASK) {
+ case TLB_WORD0_SIZE_1KB:
+ tlb_size = 1 << 10;
+ break;
+ case TLB_WORD0_SIZE_4KB:
+ tlb_size = 4 << 10;
+ break;
+ case TLB_WORD0_SIZE_16KB:
+ tlb_size = 16 << 10;
+ break;
+ case TLB_WORD0_SIZE_64KB:
+ tlb_size = 64 << 10;
+ break;
+ case TLB_WORD0_SIZE_256KB:
+ tlb_size = 256 << 10;
+ break;
+ case TLB_WORD0_SIZE_1MB:
+ tlb_size = 1 << 20;
+ break;
+ case TLB_WORD0_SIZE_16MB:
+ tlb_size = 16 << 20;
+ break;
+ case TLB_WORD0_SIZE_256MB:
+ tlb_size = 256 << 20;
+ break;
+ }
+
+ /*
+ * Now check the end-address if it's in the range
+ */
+ if (((tlb_vaddr + tlb_size - 1) <= (vaddr + size - 1)) ||
+ ((tlb_vaddr < (vaddr + size - 1)) &&
+ ((tlb_vaddr + tlb_size - 1) > (vaddr + size - 1)))) {
+ /*
+ * Found a TLB in the range.
+ * Change cache attribute in tlb2 word.
+ */
+ tlb_word2_value =
+ TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE |
+ TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE |
+ TLB_WORD2_W_DISABLE | tlb_word2_i_value |
+ TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE |
+ TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE |
+ TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE |
+ TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE |
+ TLB_WORD2_SR_ENABLE;
+
+ /*
+ * Now either flush or invalidate the dcache
+ */
+ if (tlb_word2_i_value)
+ flush_dcache();
+ else
+ invalidate_dcache();
+
+ mttlb3(i, tlb_word2_value);
+ asm("iccci 0,0");
+ }
+ }
+ }
+
+ /* Execute an ISYNC instruction so that the new TLB entry takes effect */
+ asm("isync");
+}
+
+static int add_tlb_entry(u64 phys_addr,
+ u32 virt_addr,
+ u32 tlb_word0_size_value,
+ u32 tlb_word2_i_value)
+{
+ int i;
+ unsigned long tlb_word0_value;
+ unsigned long tlb_word1_value;
+ unsigned long tlb_word2_value;
+
+ /* First, find the index of a TLB entry not being used */
+ for (i=0; i<PPC4XX_TLB_SIZE; i++) {
+ tlb_word0_value = mftlb1(i);
+ if ((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_DISABLE)
+ break;
+ }
+ if (i >= PPC4XX_TLB_SIZE)
+ return -1;
+
+ /* Second, create the TLB entry */
+ tlb_word0_value = TLB_WORD0_EPN_ENCODE(virt_addr) | TLB_WORD0_V_ENABLE |
+ TLB_WORD0_TS_0 | tlb_word0_size_value;
+ tlb_word1_value = TLB_WORD1_RPN_ENCODE((u32)phys_addr) |
+ TLB_WORD1_ERPN_ENCODE(phys_addr >> 32);
+ tlb_word2_value = TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE |
+ TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE |
+ TLB_WORD2_W_DISABLE | tlb_word2_i_value |
+ TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE |
+ TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE |
+ TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE |
+ TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE |
+ TLB_WORD2_SR_ENABLE;
+
+ /* Wait for all memory accesses to complete */
+ sync();
+
+ /* Third, add the TLB entries */
+ mttlb1(i, tlb_word0_value);
+ mttlb2(i, tlb_word1_value);
+ mttlb3(i, tlb_word2_value);
+
+ /* Execute an ISYNC instruction so that the new TLB entry takes effect */
+ asm("isync");
+
+ return 0;
+}
+
+static void program_tlb_addr(u64 phys_addr,
+ u32 virt_addr,
+ u32 mem_size,
+ u32 tlb_word2_i_value)
+{
+ int rc;
+ int tlb_i;
+
+ tlb_i = tlb_word2_i_value;
+ while (mem_size != 0) {
+ rc = 0;
+ /* Add the TLB entries in to map the region. */
+ if (((phys_addr & TLB_256MB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_256MB_SIZE)) {
+ /* Add a 256MB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_256MB, tlb_i)) == 0) {
+ mem_size -= TLB_256MB_SIZE;
+ phys_addr += TLB_256MB_SIZE;
+ virt_addr += TLB_256MB_SIZE;
+ }
+ } else if (((phys_addr & TLB_16MB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_16MB_SIZE)) {
+ /* Add a 16MB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_16MB, tlb_i)) == 0) {
+ mem_size -= TLB_16MB_SIZE;
+ phys_addr += TLB_16MB_SIZE;
+ virt_addr += TLB_16MB_SIZE;
+ }
+ } else if (((phys_addr & TLB_1MB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_1MB_SIZE)) {
+ /* Add a 1MB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_1MB, tlb_i)) == 0) {
+ mem_size -= TLB_1MB_SIZE;
+ phys_addr += TLB_1MB_SIZE;
+ virt_addr += TLB_1MB_SIZE;
+ }
+ } else if (((phys_addr & TLB_256KB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_256KB_SIZE)) {
+ /* Add a 256KB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_256KB, tlb_i)) == 0) {
+ mem_size -= TLB_256KB_SIZE;
+ phys_addr += TLB_256KB_SIZE;
+ virt_addr += TLB_256KB_SIZE;
+ }
+ } else if (((phys_addr & TLB_64KB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_64KB_SIZE)) {
+ /* Add a 64KB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_64KB, tlb_i)) == 0) {
+ mem_size -= TLB_64KB_SIZE;
+ phys_addr += TLB_64KB_SIZE;
+ virt_addr += TLB_64KB_SIZE;
+ }
+ } else if (((phys_addr & TLB_16KB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_16KB_SIZE)) {
+ /* Add a 16KB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_16KB, tlb_i)) == 0) {
+ mem_size -= TLB_16KB_SIZE;
+ phys_addr += TLB_16KB_SIZE;
+ virt_addr += TLB_16KB_SIZE;
+ }
+ } else if (((phys_addr & TLB_4KB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_4KB_SIZE)) {
+ /* Add a 4KB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_4KB, tlb_i)) == 0) {
+ mem_size -= TLB_4KB_SIZE;
+ phys_addr += TLB_4KB_SIZE;
+ virt_addr += TLB_4KB_SIZE;
+ }
+ } else if (((phys_addr & TLB_1KB_ALIGN_MASK) == phys_addr) &&
+ (mem_size >= TLB_1KB_SIZE)) {
+ /* Add a 1KB TLB entry */
+ if ((rc = add_tlb_entry(phys_addr, virt_addr,
+ TLB_WORD0_SIZE_1KB, tlb_i)) == 0) {
+ mem_size -= TLB_1KB_SIZE;
+ phys_addr += TLB_1KB_SIZE;
+ virt_addr += TLB_1KB_SIZE;
+ }
+ } else {
+ printf("ERROR: no TLB size exists for the base address 0x%llx.\n",
+ phys_addr);
+ }
+
+ if (rc != 0)
+ printf("ERROR: no TLB entries available for the base addr 0x%llx.\n",
+ phys_addr);
+ }
+
+ return;
+}
+
+/*
+ * Program one (or multiple) TLB entries for one memory region
+ *
+ * Common usage for boards with SDRAM DIMM modules to dynamically
+ * configure the TLB's for the SDRAM
+ */
+void program_tlb(u64 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value)
+{
+ region_t region_array;
+
+ region_array.base = phys_addr;
+ region_array.size = size;
+ region_array.tlb_word2_i_value = tlb_word2_i_value; /* en-/disable cache */
+
+ /* Call the routine to add in the tlb entries for the memory regions */
+ program_tlb_addr(region_array.base, virt_addr, region_array.size,
+ region_array.tlb_word2_i_value);
+
+ return;
+}
+
+#endif /* CONFIG_440 */
diff --git a/arch/powerpc/cpu/ppc4xx/traps.c b/arch/powerpc/cpu/ppc4xx/traps.c
new file mode 100644
index 0000000..dae19cb
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/traps.c
@@ -0,0 +1,408 @@
+/*
+ * linux/arch/powerpc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/processor.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+ */
+#define END_OF_MEM (gd->bd->bi_memstart + gd->bd->bi_memsize)
+
+static __inline__ unsigned long get_esr(void)
+{
+ unsigned long val;
+
+#if defined(CONFIG_440)
+ asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
+#else
+ asm volatile("mfesr %0" : "=r" (val) :);
+#endif
+ return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+#if defined(CONFIG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/*
+ * Trap & Exception support
+ */
+
+static void print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DEAR: %08lX\n",
+ regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0) {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7) {
+ printf("\n");
+ }
+ }
+}
+
+
+static void _exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception");
+}
+
+void MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup, val;
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+ u32 value2;
+ int corr_ecc = 0;
+ int uncorr_ecc = 0;
+#endif
+
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ val = mfspr(MCSR);
+ /* Clear MCSR */
+ mtspr(SPRN_MCSR, val);
+ return;
+ }
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Machine Check Exception.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ", regs);
+
+ val = get_esr();
+
+#if !defined(CONFIG_440) && !defined(CONFIG_405EX)
+ if (val& ESR_IMCP) {
+ printf("Instruction");
+ mtspr(ESR, val & ~ESR_IMCP);
+ } else {
+ printf("Data");
+ }
+ printf(" machine check.\n");
+
+#elif defined(CONFIG_440) || defined(CONFIG_405EX)
+ if (val& ESR_IMCP){
+ printf("Instruction Synchronous Machine Check exception\n");
+ mtspr(SPRN_ESR, val & ~ESR_IMCP);
+ } else {
+ val = mfspr(MCSR);
+ if (val & MCSR_IB)
+ printf("Instruction Read PLB Error\n");
+#if defined(CONFIG_440)
+ if (val & MCSR_DRB)
+ printf("Data Read PLB Error\n");
+ if (val & MCSR_DWB)
+ printf("Data Write PLB Error\n");
+#else
+ if (val & MCSR_DB)
+ printf("Data PLB Error\n");
+#endif
+ if (val & MCSR_TLBP)
+ printf("TLB Parity Error\n");
+ if (val & MCSR_ICP){
+ /*flush_instruction_cache(); */
+ printf("I-Cache Parity Error\n");
+ }
+ if (val & MCSR_DCSP)
+ printf("D-Cache Search Parity Error\n");
+ if (val & MCSR_DCFP)
+ printf("D-Cache Flush Parity Error\n");
+ if (val & MCSR_IMPE)
+ printf("Machine Check exception is imprecise\n");
+
+ /* Clear MCSR */
+ mtspr(SPRN_MCSR, val);
+ }
+
+#if defined(CONFIG_DDR_ECC) && defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+ /*
+ * Read and print ECC status register/info:
+ * The faulting address is only known upon uncorrectable ECC
+ * errors.
+ */
+ mfsdram(SDRAM_ECCES, val);
+ if (val & SDRAM_ECCES_CE)
+ printf("ECC: Correctable error\n");
+ if (val & SDRAM_ECCES_UE) {
+ printf("ECC: Uncorrectable error at 0x%02x%08x\n",
+ mfdcr(SDRAM_ERRADDULL), mfdcr(SDRAM_ERRADDLLL));
+ }
+#endif /* CONFIG_DDR_ECC ... */
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+ mfsdram(DDR0_00, val) ;
+ printf("DDR0: DDR0_00 %lx\n", val);
+ val = (val >> 16) & 0xff;
+ if (val & 0x80)
+ printf("DDR0: At least one interrupt active\n");
+ if (val & 0x40)
+ printf("DDR0: DRAM initialization complete.\n");
+ if (val & 0x20) {
+ printf("DDR0: Multiple uncorrectable ECC events.\n");
+ uncorr_ecc = 1;
+ }
+ if (val & 0x10) {
+ printf("DDR0: Single uncorrectable ECC event.\n");
+ uncorr_ecc = 1;
+ }
+ if (val & 0x08) {
+ printf("DDR0: Multiple correctable ECC events.\n");
+ corr_ecc = 1;
+ }
+ if (val & 0x04) {
+ printf("DDR0: Single correctable ECC event.\n");
+ corr_ecc = 1;
+ }
+ if (val & 0x02)
+ printf("Multiple accesses outside the defined"
+ " physical memory space detected\n");
+ if (val & 0x01)
+ printf("DDR0: Single access outside the defined"
+ " physical memory space detected.\n");
+
+ mfsdram(DDR0_01, val);
+ val = (val >> 8) & 0x7;
+ switch (val ) {
+ case 0:
+ printf("DDR0: Write Out-of-Range command\n");
+ break;
+ case 1:
+ printf("DDR0: Read Out-of-Range command\n");
+ break;
+ case 2:
+ printf("DDR0: Masked write Out-of-Range command\n");
+ break;
+ case 4:
+ printf("DDR0: Wrap write Out-of-Range command\n");
+ break;
+ case 5:
+ printf("DDR0: Wrap read Out-of-Range command\n");
+ break;
+ default:
+ mfsdram(DDR0_01, value2);
+ printf("DDR0: No DDR0 error know 0x%lx %x\n", val, value2);
+ }
+ mfsdram(DDR0_23, val);
+ if (((val >> 16) & 0xff) && corr_ecc)
+ printf("DDR0: Syndrome for correctable ECC event 0x%lx\n",
+ (val >> 16) & 0xff);
+ mfsdram(DDR0_23, val);
+ if (((val >> 8) & 0xff) && uncorr_ecc)
+ printf("DDR0: Syndrome for uncorrectable ECC event 0x%lx\n",
+ (val >> 8) & 0xff);
+ mfsdram(DDR0_33, val);
+ if (val)
+ printf("DDR0: Address of command that caused an "
+ "Out-of-Range interrupt %lx\n", val);
+ mfsdram(DDR0_34, val);
+ if (val && uncorr_ecc)
+ printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
+ mfsdram(DDR0_35, val);
+ if (val && uncorr_ecc)
+ printf("DDR0: Address of uncorrectable ECC event %lx\n", val);
+ mfsdram(DDR0_36, val);
+ if (val && uncorr_ecc)
+ printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
+ mfsdram(DDR0_37, val);
+ if (val && uncorr_ecc)
+ printf("DDR0: Data of uncorrectable ECC event 0x%08lx\n", val);
+ mfsdram(DDR0_38, val);
+ if (val && corr_ecc)
+ printf("DDR0: Address of correctable ECC event %lx\n", val);
+ mfsdram(DDR0_39, val);
+ if (val && corr_ecc)
+ printf("DDR0: Address of correctable ECC event %lx\n", val);
+ mfsdram(DDR0_40, val);
+ if (val && corr_ecc)
+ printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
+ mfsdram(DDR0_41, val);
+ if (val && corr_ecc)
+ printf("DDR0: Data of correctable ECC event 0x%08lx\n", val);
+#endif /* CONFIG_440EPX */
+#endif /* CONFIG_440 */
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void AlignmentException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void ProgramCheckException(struct pt_regs *regs)
+{
+ long esr_val;
+
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+
+ esr_val = get_esr();
+ if( esr_val & ESR_PIL )
+ printf( "** Illegal Instruction **\n" );
+ else if( esr_val & ESR_PPR )
+ printf( "** Privileged Instruction **\n" );
+ else if( esr_val & ESR_PTR )
+ printf( "** Trap Instruction **\n" );
+
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void DecrementerPITException(struct pt_regs *regs)
+{
+ /*
+ * Reset PIT interrupt
+ */
+ mtspr(SPRN_TSR, 0x08000000);
+
+ /*
+ * Call timer_interrupt routine in interrupts.c
+ */
+ timer_interrupt(NULL);
+}
+
+
+void UnknownException(struct pt_regs *regs)
+{
+#if defined(CONFIG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+void DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if defined(CONFIG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
diff --git a/arch/powerpc/cpu/ppc4xx/u-boot-spl.lds b/arch/powerpc/cpu/ppc4xx/u-boot-spl.lds
new file mode 100644
index 0000000..ae1df17
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/u-boot-spl.lds
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012-2013 Stefan Roese <sr@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+MEMORY
+{
+ sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR,
+ LENGTH = CONFIG_SPL_BSS_MAX_SIZE
+ flash : ORIGIN = CONFIG_SPL_TEXT_BASE,
+ LENGTH = CONFIG_SYS_SPL_MAX_LEN
+}
+
+OUTPUT_ARCH(powerpc)
+ENTRY(_start)
+SECTIONS
+{
+#ifdef CONFIG_440
+ .bootpg 0xfffff000 :
+ {
+ arch/powerpc/cpu/ppc4xx/start.o (.bootpg)
+
+ /*
+ * PPC440 board need a board specific object with the
+ * TLB definitions. This needs to get included right after
+ * start.o, since the first shadow TLB only covers 4k
+ * of address space.
+ */
+ CONFIG_BOARDDIR/init.o (.bootpg)
+ } > flash
+#endif
+
+ .resetvec 0xFFFFFFFC :
+ {
+ KEEP(*(.resetvec))
+ } > flash
+
+ .text :
+ {
+ __start = .;
+ arch/powerpc/cpu/ppc4xx/start.o (.text)
+ CONFIG_BOARDDIR/init.o (.text)
+ *(.text*)
+ } > flash
+
+ . = ALIGN(4);
+ .data : { *(SORT_BY_ALIGNMENT(.data*)) } > flash
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } > flash
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start = .;
+ *(.bss*)
+ . = ALIGN(4);
+ __bss_end = .;
+ } > sdram
+}
diff --git a/arch/powerpc/cpu/ppc4xx/u-boot.lds b/arch/powerpc/cpu/ppc4xx/u-boot.lds
new file mode 100644
index 0000000..e994f02
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/u-boot.lds
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2007-2009 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "config.h" /* CONFIG_BOARDDIR */
+
+#ifndef RESET_VECTOR_ADDRESS
+#ifdef CONFIG_RESET_VECTOR_ADDRESS
+#define RESET_VECTOR_ADDRESS CONFIG_RESET_VECTOR_ADDRESS
+#else
+#define RESET_VECTOR_ADDRESS 0xfffffffc
+#endif
+#endif
+
+OUTPUT_ARCH(powerpc)
+
+PHDRS
+{
+ text PT_LOAD;
+ bss PT_LOAD;
+}
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .text :
+ {
+ *(.text*)
+ } :text
+ _etext = .;
+ PROVIDE (etext = .);
+ .rodata :
+ {
+ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
+ } :text
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x00FF) & 0xFFFFFF00;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ _GOT2_TABLE_ = .;
+ KEEP(*(.got2))
+ KEEP(*(.got))
+ PROVIDE(_GLOBAL_OFFSET_TABLE_ = . + 4);
+ _FIXUP_TABLE_ = .;
+ KEEP(*(.fixup))
+ }
+ __got2_entries = ((_GLOBAL_OFFSET_TABLE_ - _GOT2_TABLE_) >> 2) - 1;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data*)
+ *(.sdata*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ . = .;
+
+ . = ALIGN(4);
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list*)));
+ }
+
+ . = .;
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(256);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(256);
+ __init_end = .;
+
+#ifndef CONFIG_SPL
+#ifdef CONFIG_440
+ .bootpg RESET_VECTOR_ADDRESS - 0xffc :
+ {
+ arch/powerpc/cpu/ppc4xx/start.o (.bootpg)
+
+ /*
+ * PPC440 board need a board specific object with the
+ * TLB definitions. This needs to get included right after
+ * start.o, since the first shadow TLB only covers 4k
+ * of address space.
+ */
+#ifdef CONFIG_INIT_TLB
+ CONFIG_INIT_TLB (.bootpg)
+#else
+ CONFIG_BOARDDIR/init.o (.bootpg)
+#endif
+ } :text = 0xffff
+#endif
+
+ .resetvec RESET_VECTOR_ADDRESS :
+ {
+ KEEP(*(.resetvec))
+ } :text = 0xffff
+
+ . = RESET_VECTOR_ADDRESS + 0x4;
+
+ /*
+ * Make sure that the bss segment isn't linked at 0x0, otherwise its
+ * address won't be updated during relocation fixups. Note that
+ * this is a temporary fix. Code to dynamically the fixup the bss
+ * location will be added in the future. When the bss relocation
+ * fixup code is present this workaround should be removed.
+ */
+#if (RESET_VECTOR_ADDRESS == 0xfffffffc)
+ . |= 0x10;
+#endif
+#endif /* CONFIG_SPL */
+
+ __bss_start = .;
+ .bss (NOLOAD) :
+ {
+ *(.bss*)
+ *(.sbss*)
+ *(COMMON)
+ } :bss
+
+ . = ALIGN(4);
+ __bss_end = . ;
+ PROVIDE (end = .);
+}
diff --git a/arch/powerpc/cpu/ppc4xx/uic.c b/arch/powerpc/cpu/ppc4xx/uic.c
new file mode 100644
index 0000000..324f0e9
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/uic.c
@@ -0,0 +1,180 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2002 (440 port)
+ * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com
+ *
+ * (C) Copyright 2003 (440GX port)
+ * Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+ *
+ * (C) Copyright 2008 (PPC440X05 port for Virtex 5 FX)
+ * Ricardo Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * Work supported by Qtechnology (htpp://qtec.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <asm/ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+
+#if (UIC_MAX > 3)
+#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
+ UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI) | \
+ UIC_MASK(VECNUM_UIC3CI) | UIC_MASK(VECNUM_UIC3NCI))
+#elif (UIC_MAX > 2)
+#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI) | \
+ UIC_MASK(VECNUM_UIC2CI) | UIC_MASK(VECNUM_UIC2NCI))
+#elif (UIC_MAX > 1)
+#define UICB0_ALL (UIC_MASK(VECNUM_UIC1CI) | UIC_MASK(VECNUM_UIC1NCI))
+#else
+#define UICB0_ALL 0
+#endif
+
+u32 get_dcr(u16);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void pic_enable(void)
+{
+#if (UIC_MAX > 1)
+ /* Install the UIC1 handlers */
+ irq_install_handler(VECNUM_UIC1NCI, (void *)(void *)external_interrupt, 0);
+ irq_install_handler(VECNUM_UIC1CI, (void *)(void *)external_interrupt, 0);
+#endif
+#if (UIC_MAX > 2)
+ irq_install_handler(VECNUM_UIC2NCI, (void *)(void *)external_interrupt, 0);
+ irq_install_handler(VECNUM_UIC2CI, (void *)(void *)external_interrupt, 0);
+#endif
+#if (UIC_MAX > 3)
+ irq_install_handler(VECNUM_UIC3NCI, (void *)(void *)external_interrupt, 0);
+ irq_install_handler(VECNUM_UIC3CI, (void *)(void *)external_interrupt, 0);
+#endif
+}
+
+/* Handler for UIC interrupt */
+static void uic_interrupt(u32 uic_base, int vec_base)
+{
+ u32 uic_msr;
+ u32 msr_shift;
+ int vec;
+
+ /*
+ * Read masked interrupt status register to determine interrupt source
+ */
+ uic_msr = get_dcr(uic_base + UIC_MSR);
+ msr_shift = uic_msr;
+ vec = vec_base;
+
+ while (msr_shift != 0) {
+ if (msr_shift & 0x80000000)
+ interrupt_run_handler(vec);
+ /*
+ * Shift msr to next position and increment vector
+ */
+ msr_shift <<= 1;
+ vec++;
+ }
+}
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+ u32 uic_msr;
+
+ /*
+ * Read masked interrupt status register to determine interrupt source
+ */
+ uic_msr = mfdcr(UIC0MSR);
+
+#if (UIC_MAX > 1)
+ if ((UIC_MASK(VECNUM_UIC1CI) & uic_msr) ||
+ (UIC_MASK(VECNUM_UIC1NCI) & uic_msr))
+ uic_interrupt(UIC1_DCR_BASE, 32);
+#endif
+
+#if (UIC_MAX > 2)
+ if ((UIC_MASK(VECNUM_UIC2CI) & uic_msr) ||
+ (UIC_MASK(VECNUM_UIC2NCI) & uic_msr))
+ uic_interrupt(UIC2_DCR_BASE, 64);
+#endif
+
+#if (UIC_MAX > 3)
+ if ((UIC_MASK(VECNUM_UIC3CI) & uic_msr) ||
+ (UIC_MASK(VECNUM_UIC3NCI) & uic_msr))
+ uic_interrupt(UIC3_DCR_BASE, 96);
+#endif
+
+ mtdcr(UIC0SR, (uic_msr & UICB0_ALL));
+
+ if (uic_msr & ~(UICB0_ALL))
+ uic_interrupt(UIC0_DCR_BASE, 0);
+
+ return;
+}
+
+void pic_irq_ack(unsigned int vec)
+{
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(UIC0SR, UIC_MASK(vec));
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(UIC1SR, UIC_MASK(vec));
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(UIC2SR, UIC_MASK(vec));
+ else if (vec >= 96)
+ mtdcr(UIC3SR, UIC_MASK(vec));
+}
+
+/*
+ * Install and free a interrupt handler.
+ */
+void pic_irq_enable(unsigned int vec)
+{
+
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(UIC0ER, mfdcr(UIC0ER) | UIC_MASK(vec));
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(UIC1ER, mfdcr(UIC1ER) | UIC_MASK(vec));
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(UIC2ER, mfdcr(UIC2ER) | UIC_MASK(vec));
+ else if (vec >= 96)
+ mtdcr(UIC3ER, mfdcr(UIC3ER) | UIC_MASK(vec));
+
+ debug("Install interrupt vector %d\n", vec);
+}
+
+void pic_irq_disable(unsigned int vec)
+{
+ if ((vec >= 0) && (vec < 32))
+ mtdcr(UIC0ER, mfdcr(UIC0ER) & ~UIC_MASK(vec));
+ else if ((vec >= 32) && (vec < 64))
+ mtdcr(UIC1ER, mfdcr(UIC1ER) & ~UIC_MASK(vec));
+ else if ((vec >= 64) && (vec < 96))
+ mtdcr(UIC2ER, mfdcr(UIC2ER) & ~UIC_MASK(vec));
+ else if (vec >= 96)
+ mtdcr(UIC3ER, mfdcr(UIC3ER) & ~UIC_MASK(vec));
+}
diff --git a/arch/powerpc/cpu/ppc4xx/usb.c b/arch/powerpc/cpu/ppc4xx/usb.c
new file mode 100644
index 0000000..8c71f75
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usb.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2007
+ * Markus Klotzbuecher, DENX Software Engineering <mk@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT)
+
+#ifdef CONFIG_4xx_DCACHE
+#include <asm/mmu.h>
+DECLARE_GLOBAL_DATA_PTR;
+#endif
+
+int usb_cpu_init(void)
+{
+#ifdef CONFIG_4xx_DCACHE
+ /* disable cache */
+ change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE);
+#endif
+
+ return 0;
+}
+
+int usb_cpu_stop(void)
+{
+#ifdef CONFIG_4xx_DCACHE
+ /* enable cache */
+ change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0);
+#endif
+ return 0;
+}
+
+int usb_cpu_init_fail(void)
+{
+#ifdef CONFIG_4xx_DCACHE
+ /* enable cache */
+ change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0);
+#endif
+ return 0;
+}
+
+#endif /* defined(CONFIG_USB_OHCI) && defined(CONFIG_SYS_USB_OHCI_CPU_INIT) */
diff --git a/arch/powerpc/cpu/ppc4xx/usb_ohci.c b/arch/powerpc/cpu/ppc4xx/usb_ohci.c
new file mode 100644
index 0000000..f820c37
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usb_ohci.c
@@ -0,0 +1,1639 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB on the PPC440EP.
+ *
+ * (C) Copyright 2003-2004
+ * Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
+ *
+ * (C) Copyright 2004
+ * Pierre Aubert, Staubli Faverges <p.aubert@staubli.com>
+ *
+ * Note: Much of this code has been derived from Linux 2.4
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+/*
+ * IMPORTANT NOTES
+ * 1 - this driver is intended for use with USB Mass Storage Devices
+ * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes!
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_USB_OHCI
+
+#include <malloc.h>
+#include <usb.h>
+#include "usb_ohci.h"
+
+#define OHCI_USE_NPS /* force NoPowerSwitching mode */
+#undef OHCI_VERBOSE_DEBUG /* not always helpful */
+#undef DEBUG
+#undef SHOW_INFO
+#undef OHCI_FILL_TRACE
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT \
+ (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
+
+#define readl(a) (*((volatile u32 *)(a)))
+#define writel(a, b) (*((volatile u32 *)(b)) = ((volatile u32)a))
+
+#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+
+#ifdef DEBUG
+#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while(0)
+#endif /* DEBUG */
+#define err(format, arg...) printf("ERROR: " format "\n", ## arg)
+#ifdef SHOW_INFO
+#define info(format, arg...) printf("INFO: " format "\n", ## arg)
+#else
+#define info(format, arg...) do {} while(0)
+#endif
+
+#define m16_swap(x) swap_16(x)
+#define m32_swap(x) swap_32(x)
+
+#if defined(CONFIG_405EZ) || defined(CONFIG_440EP) || defined(CONFIG_440EPX)
+#define ohci_cpu_to_le16(x) (x)
+#define ohci_cpu_to_le32(x) (x)
+#else
+#define ohci_cpu_to_le16(x) swap_16(x)
+#define ohci_cpu_to_le32(x) swap_32(x)
+#endif
+
+/* global ohci_t */
+static ohci_t gohci;
+/* this must be aligned to a 256 byte boundary */
+struct ohci_hcca ghcca[1];
+/* a pointer to the aligned storage */
+struct ohci_hcca *phcca;
+/* this allocates EDs for all possible endpoints */
+struct ohci_device ohci_dev;
+/* urb_priv */
+urb_priv_t urb_priv;
+/* RHSC flag */
+int got_rhsc;
+/* device which was disconnected */
+struct usb_device *devgone;
+/* flag guarding URB transation */
+int urb_finished = 0;
+
+/*-------------------------------------------------------------------------*/
+
+/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
+ * The erratum (#4) description is incorrect. AMD's workaround waits
+ * till some bits (mostly reserved) are clear; ok for all revs.
+ */
+#define OHCI_QUIRK_AMD756 0xabcd
+#define read_roothub(hc, register, mask) ({ \
+ u32 temp = readl (&hc->regs->roothub.register); \
+ if (hc->flags & OHCI_QUIRK_AMD756) \
+ while (temp & mask) \
+ temp = readl (&hc->regs->roothub.register); \
+ temp; })
+
+static u32 roothub_a (struct ohci *hc)
+ { return read_roothub (hc, a, 0xfc0fe000); }
+static inline u32 roothub_b (struct ohci *hc)
+ { return readl (&hc->regs->roothub.b); }
+static inline u32 roothub_status (struct ohci *hc)
+ { return readl (&hc->regs->roothub.status); }
+static u32 roothub_portstatus (struct ohci *hc, int i)
+ { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
+
+
+/* forward declaration */
+static int hc_interrupt (void);
+static void
+td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval);
+
+/*-------------------------------------------------------------------------*
+ * URB support functions
+ *-------------------------------------------------------------------------*/
+
+/* free HCD-private data associated with this URB */
+
+static void urb_free_priv (urb_priv_t * urb)
+{
+ int i;
+ int last;
+ struct td * td;
+
+ last = urb->length - 1;
+ if (last >= 0) {
+ for (i = 0; i <= last; i++) {
+ td = urb->td[i];
+ if (td) {
+ td->usb_dev = NULL;
+ urb->td[i] = NULL;
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+static int sohci_get_current_frame_number (struct usb_device * dev);
+
+/* debug| print the main components of an URB
+ * small: 0) header + data packets 1) just header */
+
+static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer,
+ int transfer_len, struct devrequest * setup, char * str, int small)
+{
+ urb_priv_t * purb = &urb_priv;
+
+ dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx",
+ str,
+ sohci_get_current_frame_number (dev),
+ usb_pipedevice (pipe),
+ usb_pipeendpoint (pipe),
+ usb_pipeout (pipe)? 'O': 'I',
+ usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"):
+ (usb_pipecontrol (pipe)? "CTRL": "BULK"),
+ purb->actual_length,
+ transfer_len, dev->status);
+#ifdef OHCI_VERBOSE_DEBUG
+ if (!small) {
+ int i, len;
+
+ if (usb_pipecontrol (pipe)) {
+ printf (__FILE__ ": cmd(8):");
+ for (i = 0; i < 8 ; i++)
+ printf (" %02x", ((__u8 *) setup) [i]);
+ printf ("\n");
+ }
+ if (transfer_len > 0 && buffer) {
+ printf (__FILE__ ": data(%d/%d):",
+ purb->actual_length,
+ transfer_len);
+ len = usb_pipeout (pipe)?
+ transfer_len: purb->actual_length;
+ for (i = 0; i < 16 && i < len; i++)
+ printf (" %02x", ((__u8 *) buffer) [i]);
+ printf ("%s\n", i < len? "...": "");
+ }
+ }
+#endif
+}
+
+/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/
+void ep_print_int_eds (ohci_t *ohci, char * str) {
+ int i, j;
+ __u32 * ed_p;
+ for (i= 0; i < 32; i++) {
+ j = 5;
+ ed_p = &(ohci->hcca->int_table [i]);
+ if (*ed_p == 0)
+ continue;
+ printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i);
+ while (*ed_p != 0 && j--) {
+ ed_t *ed = (ed_t *)ohci_cpu_to_le32(ed_p);
+ printf (" ed: %4x;", ed->hwINFO);
+ ed_p = &ed->hwNextED;
+ }
+ printf ("\n");
+ }
+}
+
+static void ohci_dump_intr_mask (char *label, __u32 mask)
+{
+ dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s",
+ label,
+ mask,
+ (mask & OHCI_INTR_MIE) ? " MIE" : "",
+ (mask & OHCI_INTR_OC) ? " OC" : "",
+ (mask & OHCI_INTR_RHSC) ? " RHSC" : "",
+ (mask & OHCI_INTR_FNO) ? " FNO" : "",
+ (mask & OHCI_INTR_UE) ? " UE" : "",
+ (mask & OHCI_INTR_RD) ? " RD" : "",
+ (mask & OHCI_INTR_SF) ? " SF" : "",
+ (mask & OHCI_INTR_WDH) ? " WDH" : "",
+ (mask & OHCI_INTR_SO) ? " SO" : ""
+ );
+}
+
+static void maybe_print_eds (char *label, __u32 value)
+{
+ ed_t *edp = (ed_t *)value;
+
+ if (value) {
+ dbg ("%s %08x", label, value);
+ dbg ("%08x", edp->hwINFO);
+ dbg ("%08x", edp->hwTailP);
+ dbg ("%08x", edp->hwHeadP);
+ dbg ("%08x", edp->hwNextED);
+ }
+}
+
+static char * hcfs2string (int state)
+{
+ switch (state) {
+ case OHCI_USB_RESET: return "reset";
+ case OHCI_USB_RESUME: return "resume";
+ case OHCI_USB_OPER: return "operational";
+ case OHCI_USB_SUSPEND: return "suspend";
+ }
+ return "?";
+}
+
+/* dump control and status registers */
+static void ohci_dump_status (ohci_t *controller)
+{
+ struct ohci_regs *regs = controller->regs;
+ __u32 temp;
+
+ temp = readl (&regs->revision) & 0xff;
+ if (temp != 0x10)
+ dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f));
+
+ temp = readl (&regs->control);
+ dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp,
+ (temp & OHCI_CTRL_RWE) ? " RWE" : "",
+ (temp & OHCI_CTRL_RWC) ? " RWC" : "",
+ (temp & OHCI_CTRL_IR) ? " IR" : "",
+ hcfs2string (temp & OHCI_CTRL_HCFS),
+ (temp & OHCI_CTRL_BLE) ? " BLE" : "",
+ (temp & OHCI_CTRL_CLE) ? " CLE" : "",
+ (temp & OHCI_CTRL_IE) ? " IE" : "",
+ (temp & OHCI_CTRL_PLE) ? " PLE" : "",
+ temp & OHCI_CTRL_CBSR
+ );
+
+ temp = readl (&regs->cmdstatus);
+ dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp,
+ (temp & OHCI_SOC) >> 16,
+ (temp & OHCI_OCR) ? " OCR" : "",
+ (temp & OHCI_BLF) ? " BLF" : "",
+ (temp & OHCI_CLF) ? " CLF" : "",
+ (temp & OHCI_HCR) ? " HCR" : ""
+ );
+
+ ohci_dump_intr_mask ("intrstatus", readl (&regs->intrstatus));
+ ohci_dump_intr_mask ("intrenable", readl (&regs->intrenable));
+
+ maybe_print_eds ("ed_periodcurrent", readl (&regs->ed_periodcurrent));
+
+ maybe_print_eds ("ed_controlhead", readl (&regs->ed_controlhead));
+ maybe_print_eds ("ed_controlcurrent", readl (&regs->ed_controlcurrent));
+
+ maybe_print_eds ("ed_bulkhead", readl (&regs->ed_bulkhead));
+ maybe_print_eds ("ed_bulkcurrent", readl (&regs->ed_bulkcurrent));
+
+ maybe_print_eds ("donehead", readl (&regs->donehead));
+}
+
+static void ohci_dump_roothub (ohci_t *controller, int verbose)
+{
+ __u32 temp, ndp, i;
+
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+
+ if (verbose) {
+ dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp,
+ ((temp & RH_A_POTPGT) >> 24) & 0xff,
+ (temp & RH_A_NOCP) ? " NOCP" : "",
+ (temp & RH_A_OCPM) ? " OCPM" : "",
+ (temp & RH_A_DT) ? " DT" : "",
+ (temp & RH_A_NPS) ? " NPS" : "",
+ (temp & RH_A_PSM) ? " PSM" : "",
+ ndp
+ );
+ temp = roothub_b (controller);
+ dbg ("roothub.b: %08x PPCM=%04x DR=%04x",
+ temp,
+ (temp & RH_B_PPCM) >> 16,
+ (temp & RH_B_DR)
+ );
+ temp = roothub_status (controller);
+ dbg ("roothub.status: %08x%s%s%s%s%s%s",
+ temp,
+ (temp & RH_HS_CRWE) ? " CRWE" : "",
+ (temp & RH_HS_OCIC) ? " OCIC" : "",
+ (temp & RH_HS_LPSC) ? " LPSC" : "",
+ (temp & RH_HS_DRWE) ? " DRWE" : "",
+ (temp & RH_HS_OCI) ? " OCI" : "",
+ (temp & RH_HS_LPS) ? " LPS" : ""
+ );
+ }
+
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s",
+ i,
+ temp,
+ (temp & RH_PS_PRSC) ? " PRSC" : "",
+ (temp & RH_PS_OCIC) ? " OCIC" : "",
+ (temp & RH_PS_PSSC) ? " PSSC" : "",
+ (temp & RH_PS_PESC) ? " PESC" : "",
+ (temp & RH_PS_CSC) ? " CSC" : "",
+
+ (temp & RH_PS_LSDA) ? " LSDA" : "",
+ (temp & RH_PS_PPS) ? " PPS" : "",
+ (temp & RH_PS_PRS) ? " PRS" : "",
+ (temp & RH_PS_POCI) ? " POCI" : "",
+ (temp & RH_PS_PSS) ? " PSS" : "",
+
+ (temp & RH_PS_PES) ? " PES" : "",
+ (temp & RH_PS_CCS) ? " CCS" : ""
+ );
+ }
+}
+
+static void ohci_dump (ohci_t *controller, int verbose)
+{
+ dbg ("OHCI controller usb-%s state", controller->slot_name);
+
+ /* dumps some of the state we know about */
+ ohci_dump_status (controller);
+ if (verbose)
+ ep_print_int_eds (controller, "hcca");
+ dbg ("hcca frame #%04x", controller->hcca->frame_no);
+ ohci_dump_roothub (controller, 1);
+}
+
+
+#endif /* DEBUG */
+
+/*-------------------------------------------------------------------------*
+ * Interface functions (URB)
+ *-------------------------------------------------------------------------*/
+
+/* get a transfer request */
+
+int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, int interval)
+{
+ ohci_t *ohci;
+ ed_t * ed;
+ urb_priv_t *purb_priv;
+ int i, size = 0;
+
+ ohci = &gohci;
+
+ /* when controller's hung, permit only roothub cleanup attempts
+ * such as powering down ports */
+ if (ohci->disabled) {
+ err("sohci_submit_job: EPIPE");
+ return -1;
+ }
+
+ /* if we have an unfinished URB from previous transaction let's
+ * fail and scream as quickly as possible so as not to corrupt
+ * further communication */
+ if (!urb_finished) {
+ err("sohci_submit_job: URB NOT FINISHED");
+ return -1;
+ }
+ /* we're about to begin a new transaction here so mark the URB unfinished */
+ urb_finished = 0;
+
+ /* every endpoint has a ed, locate and fill it */
+ if (!(ed = ep_add_ed (dev, pipe))) {
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+
+ /* for the private part of the URB we need the number of TDs (size) */
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK: /* one TD for every 4096 Byte */
+ size = (transfer_len - 1) / 4096 + 1;
+ break;
+ case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */
+ size = (transfer_len == 0)? 2:
+ (transfer_len - 1) / 4096 + 3;
+ break;
+ }
+
+ if (size >= (N_URB_TD - 1)) {
+ err("need %d TDs, only have %d", size, N_URB_TD);
+ return -1;
+ }
+ purb_priv = &urb_priv;
+ purb_priv->pipe = pipe;
+
+ /* fill the private part of the URB */
+ purb_priv->length = size;
+ purb_priv->ed = ed;
+ purb_priv->actual_length = 0;
+
+ /* allocate the TDs */
+ /* note that td[0] was allocated in ep_add_ed */
+ for (i = 0; i < size; i++) {
+ purb_priv->td[i] = td_alloc (dev);
+ if (!purb_priv->td[i]) {
+ purb_priv->length = i;
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: ENOMEM");
+ return -1;
+ }
+ }
+
+ if (ed->state == ED_NEW || (ed->state & ED_DEL)) {
+ urb_free_priv (purb_priv);
+ err("sohci_submit_job: EINVAL");
+ return -1;
+ }
+
+ /* link the ed into a chain if is not already */
+ if (ed->state != ED_OPER)
+ ep_link (ohci, ed);
+
+ /* fill the TDs and link it to the ed */
+ td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef DEBUG
+/* tell us the current USB frame number */
+
+static int sohci_get_current_frame_number (struct usb_device *usb_dev)
+{
+ ohci_t *ohci = &gohci;
+
+ return ohci_cpu_to_le16 (ohci->hcca->frame_no);
+}
+#endif
+
+/*-------------------------------------------------------------------------*
+ * ED handling functions
+ *-------------------------------------------------------------------------*/
+
+/* link an ed into one of the HC chains */
+
+static int ep_link (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+
+ ed->state = ED_OPER;
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ ed->hwNextED = 0;
+ if (ohci->ed_controltail == NULL) {
+ writel (ed, &ohci->regs->ed_controlhead);
+ } else {
+ ohci->ed_controltail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_controltail;
+ if (!ohci->ed_controltail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_controltail = edi;
+ break;
+
+ case PIPE_BULK:
+ ed->hwNextED = 0;
+ if (ohci->ed_bulktail == NULL) {
+ writel (ed, &ohci->regs->ed_bulkhead);
+ } else {
+ ohci->ed_bulktail->hwNextED = ohci_cpu_to_le32 ((unsigned long)ed);
+ }
+ ed->ed_prev = ohci->ed_bulktail;
+ if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] &&
+ !ohci->ed_rm_list[1] && !ohci->sleeping) {
+ ohci->hc_control |= OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ ohci->ed_bulktail = edi;
+ break;
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* unlink an ed from one of the HC chains.
+ * just the link to the ed is unlinked.
+ * the link from the ed still points to another operational ed or 0
+ * so the HC can eventually finish the processing of the unlinked ed */
+
+static int ep_unlink (ohci_t *ohci, ed_t *edi)
+{
+ volatile ed_t *ed = edi;
+
+ ed->hwINFO |= ohci_cpu_to_le32 (OHCI_ED_SKIP);
+
+ switch (ed->type) {
+ case PIPE_CONTROL:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_CLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_controltail == ed) {
+ ohci->ed_controltail = ed->ed_prev;
+ } else {
+ ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+
+ case PIPE_BULK:
+ if (ed->ed_prev == NULL) {
+ if (!ed->hwNextED) {
+ ohci->hc_control &= ~OHCI_CTRL_BLE;
+ writel (ohci->hc_control, &ohci->regs->control);
+ }
+ writel (ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead);
+ } else {
+ ed->ed_prev->hwNextED = ed->hwNextED;
+ }
+ if (ohci->ed_bulktail == ed) {
+ ohci->ed_bulktail = ed->ed_prev;
+ } else {
+ ((ed_t *)ohci_cpu_to_le32 (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev;
+ }
+ break;
+ }
+ ed->state = ED_UNLINK;
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* add/reinit an endpoint; this should be done once at the usb_set_configuration command,
+ * but the USB stack is a little bit stateless so we do it at every transaction
+ * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK
+ * in all other cases the state is left unchanged
+ * the ed info fields are setted anyway even though most of them should not change */
+
+static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
+{
+ td_t *td;
+ ed_t *ed_ret;
+ volatile ed_t *ed;
+
+ ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) |
+ (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))];
+
+ if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) {
+ err("ep_add_ed: pending delete");
+ /* pending delete request */
+ return NULL;
+ }
+
+ if (ed->state == ED_NEW) {
+ ed->hwINFO = ohci_cpu_to_le32 (OHCI_ED_SKIP); /* skip ed */
+ /* dummy td; end of td list for ed */
+ td = td_alloc (usb_dev);
+ ed->hwTailP = ohci_cpu_to_le32 ((unsigned long)td);
+ ed->hwHeadP = ed->hwTailP;
+ ed->state = ED_UNLINK;
+ ed->type = usb_pipetype (pipe);
+ ohci_dev.ed_cnt++;
+ }
+
+ ed->hwINFO = ohci_cpu_to_le32 (usb_pipedevice (pipe)
+ | usb_pipeendpoint (pipe) << 7
+ | (usb_pipeisoc (pipe)? 0x8000: 0)
+ | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
+ | (usb_dev->speed == USB_SPEED_LOW) << 13
+ | usb_maxpacket (usb_dev, pipe) << 16);
+
+ return ed_ret;
+}
+
+/*-------------------------------------------------------------------------*
+ * TD handling functions
+ *-------------------------------------------------------------------------*/
+
+/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
+
+static void td_fill (ohci_t *ohci, unsigned int info,
+ void *data, int len,
+ struct usb_device *dev, int index, urb_priv_t *urb_priv)
+{
+ volatile td_t *td, *td_pt;
+#ifdef OHCI_FILL_TRACE
+ int i;
+#endif
+
+ if (index > urb_priv->length) {
+ err("index > length");
+ return;
+ }
+ /* use this td as the next dummy */
+ td_pt = urb_priv->td [index];
+ td_pt->hwNextTD = 0;
+
+ /* fill the old dummy TD */
+ td = urb_priv->td [index] = (td_t *)(ohci_cpu_to_le32 (urb_priv->ed->hwTailP) & ~0xf);
+
+ td->ed = urb_priv->ed;
+ td->next_dl_td = NULL;
+ td->index = index;
+ td->data = (__u32)data;
+#ifdef OHCI_FILL_TRACE
+ if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) {
+ for (i = 0; i < len; i++)
+ printf("td->data[%d] %#2x ",i, ((unsigned char *)td->data)[i]);
+ printf("\n");
+ }
+#endif
+ if (!len)
+ data = 0;
+
+ td->hwINFO = ohci_cpu_to_le32 (info);
+ td->hwCBP = ohci_cpu_to_le32 ((unsigned long)data);
+ if (data)
+ td->hwBE = ohci_cpu_to_le32 ((unsigned long)(data + len - 1));
+ else
+ td->hwBE = 0;
+ td->hwNextTD = ohci_cpu_to_le32 ((unsigned long)td_pt);
+
+ /* append to queue */
+ td->ed->hwTailP = td->hwNextTD;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* prepare all TDs of a transfer */
+static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval)
+{
+ ohci_t *ohci = &gohci;
+ int data_len = transfer_len;
+ void *data;
+ int cnt = 0;
+ __u32 info = 0;
+ unsigned int toggle = 0;
+
+ /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */
+ if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) {
+ toggle = TD_T_TOGGLE;
+ } else {
+ toggle = TD_T_DATA0;
+ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
+ }
+ urb->td_cnt = 0;
+ if (data_len)
+ data = buffer;
+ else
+ data = 0;
+
+ switch (usb_pipetype (pipe)) {
+ case PIPE_BULK:
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
+ while(data_len > 4096) {
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb);
+ data += 4096; data_len -= 4096; cnt++;
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
+ td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb);
+ cnt++;
+
+ if (!ohci->sleeping)
+ writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+ break;
+
+ case PIPE_CONTROL:
+ info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
+ td_fill (ohci, info, setup, 8, dev, cnt++, urb);
+ if (data_len > 0) {
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
+ /* NOTE: mishandles transfers >8K, some >4K */
+ td_fill (ohci, info, data, data_len, dev, cnt++, urb);
+ }
+ info = usb_pipeout (pipe)?
+ TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
+ td_fill (ohci, info, data, 0, dev, cnt++, urb);
+ if (!ohci->sleeping)
+ writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+ break;
+ }
+ if (urb->length != cnt)
+ dbg("TD LENGTH %d != CNT %d", urb->length, cnt);
+}
+
+/*-------------------------------------------------------------------------*
+ * Done List handling functions
+ *-------------------------------------------------------------------------*/
+
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+ __u32 tdBE, tdCBP;
+ urb_priv_t *lurb_priv = &urb_priv;
+
+ tdBE = ohci_cpu_to_le32 (td->hwBE);
+ tdCBP = ohci_cpu_to_le32 (td->hwCBP);
+
+
+ if (!(usb_pipecontrol(lurb_priv->pipe) &&
+ ((td->index == 0) || (td->index == lurb_priv->length - 1)))) {
+ if (tdBE != 0) {
+ if (td->hwCBP == 0)
+ lurb_priv->actual_length += tdBE - td->data + 1;
+ else
+ lurb_priv->actual_length += tdCBP - td->data;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+
+static td_t * dl_reverse_done_list (ohci_t *ohci)
+{
+ __u32 td_list_hc;
+ td_t *td_rev = NULL;
+ td_t *td_list = NULL;
+ urb_priv_t *lurb_priv = NULL;
+
+ td_list_hc = ohci_cpu_to_le32 (ohci->hcca->done_head) & 0xfffffff0;
+ ohci->hcca->done_head = 0;
+
+ while (td_list_hc) {
+ td_list = (td_t *)td_list_hc;
+
+ if (TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO))) {
+ lurb_priv = &urb_priv;
+ dbg(" USB-error/status: %x : %p",
+ TD_CC_GET (ohci_cpu_to_le32 (td_list->hwINFO)), td_list);
+ if (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x1)) {
+ if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) {
+ td_list->ed->hwHeadP =
+ (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & ohci_cpu_to_le32 (0xfffffff0)) |
+ (td_list->ed->hwHeadP & ohci_cpu_to_le32 (0x2));
+ lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1;
+ } else
+ td_list->ed->hwHeadP &= ohci_cpu_to_le32 (0xfffffff2);
+ }
+#ifdef CONFIG_MPC5200
+ td_list->hwNextTD = 0;
+#endif
+ }
+
+ td_list->next_dl_td = td_rev;
+ td_rev = td_list;
+ td_list_hc = ohci_cpu_to_le32 (td_list->hwNextTD) & 0xfffffff0;
+ }
+ return td_list;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* td done list */
+static int dl_done_list (ohci_t *ohci, td_t *td_list)
+{
+ td_t *td_list_next = NULL;
+ ed_t *ed;
+ int cc = 0;
+ int stat = 0;
+ /* urb_t *urb; */
+ urb_priv_t *lurb_priv;
+ __u32 tdINFO, edHeadP, edTailP;
+
+ while (td_list) {
+ td_list_next = td_list->next_dl_td;
+
+ lurb_priv = &urb_priv;
+ tdINFO = ohci_cpu_to_le32 (td_list->hwINFO);
+
+ ed = td_list->ed;
+
+ dl_transfer_length(td_list);
+
+ /* error code of transfer */
+ cc = TD_CC_GET (tdINFO);
+ if (++(lurb_priv->td_cnt) == lurb_priv->length) {
+ if ((ed->state & (ED_OPER | ED_UNLINK))
+ && (lurb_priv->state != URB_DEL)) {
+ dbg("ConditionCode %#x", cc);
+ stat = cc_to_error[cc];
+ urb_finished = 1;
+ }
+ }
+
+ if (ed->state != ED_NEW) {
+ edHeadP = ohci_cpu_to_le32 (ed->hwHeadP) & 0xfffffff0;
+ edTailP = ohci_cpu_to_le32 (ed->hwTailP);
+
+ /* unlink eds if they are not busy */
+ if ((edHeadP == edTailP) && (ed->state == ED_OPER))
+ ep_unlink (ohci, ed);
+ }
+
+ td_list = td_list_next;
+ }
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] =
+{
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x01, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+ 28, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'O', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'C', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'I', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+/* Hub class-specific descriptor is constructed dynamically */
+
+
+/*-------------------------------------------------------------------------*/
+
+#define OK(x) len = (x); break
+#ifdef DEBUG
+#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);}
+#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);}
+#else
+#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status)
+#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1])
+#endif
+#define RD_RH_STAT roothub_status(&gohci)
+#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1)
+
+/* request to virtual root hub */
+
+int rh_check_port_status(ohci_t *controller)
+{
+ __u32 temp, ndp, i;
+ int res;
+
+ res = -1;
+ temp = roothub_a (controller);
+ ndp = (temp & RH_A_NDP);
+ for (i = 0; i < ndp; i++) {
+ temp = roothub_portstatus (controller, i);
+ /* check for a device disconnect */
+ if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+ (RH_PS_PESC | RH_PS_CSC)) &&
+ ((temp & RH_PS_CCS) == 0)) {
+ res = i;
+ break;
+ }
+ }
+ return res;
+}
+
+static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len, struct devrequest *cmd)
+{
+ void * data = buffer;
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ __u32 datab[4];
+ __u8 *data_buf = (__u8 *)datab;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wIndex;
+ __u16 wLength;
+
+#ifdef DEBUG
+urb_priv.actual_length = 0;
+pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
+#endif
+ if (usb_pipeint(pipe)) {
+ info("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = m16_swap (cmd->value);
+ wIndex = m16_swap (cmd->index);
+ wLength = m16_swap (cmd->length);
+
+ info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x",
+ dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
+
+ switch (bmRType_bReq) {
+ /* Request Destination:
+ without flags: Device,
+ RH_INTERFACE: interface,
+ RH_ENDPOINT: endpoint,
+ RH_CLASS means HUB here,
+ RH_OTHER | RH_CLASS almost ever means HUB_PORT here
+ */
+
+ case RH_GET_STATUS:
+ *(__u16 *) data_buf = m16_swap (1); OK (2);
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *) data_buf = m16_swap (0); OK (2);
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *) data_buf = m16_swap (0); OK (2);
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *) data_buf = m32_swap (
+ RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
+ OK (4);
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4);
+
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ switch (wValue) {
+ case (RH_ENDPOINT_STALL): OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ switch (wValue) {
+ case RH_C_HUB_LOCAL_POWER:
+ OK(0);
+ case (RH_C_HUB_OVER_CURRENT):
+ WR_RH_STAT(RH_HS_OCIC); OK (0);
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_CCS ); OK (0);
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_POCI); OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_LSDA); OK (0);
+ case (RH_C_PORT_CONNECTION):
+ WR_RH_PORTSTAT (RH_PS_CSC ); OK (0);
+ case (RH_C_PORT_ENABLE):
+ WR_RH_PORTSTAT (RH_PS_PESC); OK (0);
+ case (RH_C_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSSC); OK (0);
+ case (RH_C_PORT_OVER_CURRENT):
+ WR_RH_PORTSTAT (RH_PS_OCIC); OK (0);
+ case (RH_C_PORT_RESET):
+ WR_RH_PORTSTAT (RH_PS_PRSC); OK (0);
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ WR_RH_PORTSTAT (RH_PS_PSS ); OK (0);
+ case (RH_PORT_RESET): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PRS);
+ OK (0);
+ case (RH_PORT_POWER):
+ WR_RH_PORTSTAT (RH_PS_PPS ); OK (0);
+ case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
+ if (RD_RH_PORTSTAT & RH_PS_CCS)
+ WR_RH_PORTSTAT (RH_PS_PES );
+ OK (0);
+ }
+ break;
+
+ case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0);
+
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_dev_des),
+ wLength));
+ data_buf = root_hub_dev_des; OK(len);
+ case (0x02): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_config_des),
+ wLength));
+ data_buf = root_hub_config_des; OK(len);
+ case (0x03): /* string descriptors */
+ if(wValue==0x0300) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index0),
+ wLength));
+ data_buf = root_hub_str_index0;
+ OK(len);
+ }
+ if(wValue==0x0301) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof (root_hub_str_index1),
+ wLength));
+ data_buf = root_hub_str_index1;
+ OK(len);
+ }
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ {
+ __u32 temp = roothub_a (&gohci);
+
+ data_buf [0] = 9; /* min length; */
+ data_buf [1] = 0x29;
+ data_buf [2] = temp & RH_A_NDP;
+ data_buf [3] = 0;
+ if (temp & RH_A_PSM) /* per-port power switching? */
+ data_buf [3] |= 0x1;
+ if (temp & RH_A_NOCP) /* no overcurrent reporting? */
+ data_buf [3] |= 0x10;
+ else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */
+ data_buf [3] |= 0x8;
+
+ /* corresponds to data_buf[4-7] */
+ datab [1] = 0;
+ data_buf [5] = (temp & RH_A_POTPGT) >> 24;
+ temp = roothub_b (&gohci);
+ data_buf [7] = temp & RH_B_DR;
+ if (data_buf [2] < 7) {
+ data_buf [8] = 0xff;
+ } else {
+ data_buf [0] += 2;
+ data_buf [8] = (temp & RH_B_DR) >> 8;
+ data_buf [10] = data_buf [9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data_buf [0], wLength));
+ OK (len);
+ }
+
+ case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1);
+
+ case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0);
+
+ default:
+ dbg ("unsupported root hub command");
+ stat = USB_ST_STALLED;
+ }
+
+#ifdef DEBUG
+ ohci_dump_roothub (&gohci, 1);
+#endif
+
+ len = min_t(int, len, leni);
+ if (data != data_buf)
+ memcpy (data, data_buf, len);
+ dev->act_len = len;
+ dev->status = stat;
+
+#ifdef DEBUG
+ if (transfer_len)
+ urb_priv.actual_length = transfer_len;
+ pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
+#endif
+
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* common code for handling submit messages - used for all but root hub */
+/* accesses. */
+int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup, int interval)
+{
+ int stat = 0;
+ int maxsize = usb_maxpacket(dev, pipe);
+ int timeout;
+
+ /* device pulled? Shortcut the action. */
+ if (devgone == dev) {
+ dev->status = USB_ST_CRC_ERR;
+ return 0;
+ }
+
+#ifdef DEBUG
+ urb_priv.actual_length = 0;
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+ if (!maxsize) {
+ err("submit_common_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+
+ if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) {
+ err("sohci_submit_job failed");
+ return -1;
+ }
+
+ /* allow more time for a BULK device to react - some are slow */
+#define BULK_TO 5000 /* timeout in milliseconds */
+ if (usb_pipebulk(pipe))
+ timeout = BULK_TO;
+ else
+ timeout = 100;
+
+ /* wait for it to complete */
+ for (;;) {
+ /* check whether the controller is done */
+ stat = hc_interrupt();
+ if (stat < 0) {
+ stat = USB_ST_CRC_ERR;
+ break;
+ }
+
+ /* NOTE: since we are not interrupt driven in U-Boot and always
+ * handle only one URB at a time, we cannot assume the
+ * transaction finished on the first successful return from
+ * hc_interrupt().. unless the flag for current URB is set,
+ * meaning that all TD's to/from device got actually
+ * transferred and processed. If the current URB is not
+ * finished we need to re-iterate this loop so as
+ * hc_interrupt() gets called again as there needs to be some
+ * more TD's to process still */
+ if ((stat >= 0) && (stat != 0xff) && (urb_finished)) {
+ /* 0xff is returned for an SF-interrupt */
+ break;
+ }
+
+ if (--timeout) {
+ mdelay(1);
+ if (!urb_finished)
+ dbg("\%");
+
+ } else {
+ err("CTL:TIMEOUT ");
+ dbg("submit_common_msg: TO status %x\n", stat);
+ stat = USB_ST_CRC_ERR;
+ urb_finished = 1;
+ break;
+ }
+ }
+#if 0
+ /* we got an Root Hub Status Change interrupt */
+ if (got_rhsc) {
+#ifdef DEBUG
+ ohci_dump_roothub (&gohci, 1);
+#endif
+ got_rhsc = 0;
+ /* abuse timeout */
+ timeout = rh_check_port_status(&gohci);
+ if (timeout >= 0) {
+#if 0 /* this does nothing useful, but leave it here in case that changes */
+ /* the called routine adds 1 to the passed value */
+ usb_hub_port_connect_change(gohci.rh.dev, timeout - 1);
+#endif
+ /*
+ * XXX
+ * This is potentially dangerous because it assumes
+ * that only one device is ever plugged in!
+ */
+ devgone = dev;
+ }
+ }
+#endif
+
+ dev->status = stat;
+ dev->act_len = transfer_len;
+
+#ifdef DEBUG
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
+#endif
+
+ /* free TDs in urb_priv */
+ urb_free_priv (&urb_priv);
+ return 0;
+}
+
+/* submit routines called from usb.c */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len)
+{
+ info("submit_bulk_msg");
+ return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0);
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *setup)
+{
+ int maxsize = usb_maxpacket(dev, pipe);
+
+ info("submit_control_msg");
+#ifdef DEBUG
+ urb_priv.actual_length = 0;
+ pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
+#endif
+ if (!maxsize) {
+ err("submit_control_message: pipesize for pipe %lx is zero",
+ pipe);
+ return -1;
+ }
+ if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) {
+ gohci.rh.dev = dev;
+ /* root hub - redirect */
+ return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len,
+ setup);
+ }
+
+ return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int transfer_len, int interval)
+{
+ info("submit_int_msg");
+ return -1;
+}
+
+/*-------------------------------------------------------------------------*
+ * HC functions
+ *-------------------------------------------------------------------------*/
+
+/* reset the HC and BUS */
+
+static int hc_reset (ohci_t *ohci)
+{
+ int timeout = 30;
+ int smm_timeout = 50; /* 0,5 sec */
+
+ if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */
+ writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
+ info("USB HC TakeOver from SMM");
+ while (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
+ mdelay (10);
+ if (--smm_timeout == 0) {
+ err("USB HC TakeOver failed!");
+ return -1;
+ }
+ }
+ }
+
+ /* Disable HC interrupts */
+ writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
+
+ dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;",
+ ohci->slot_name,
+ readl (&ohci->regs->control));
+
+ /* Reset USB (needed by some controllers) */
+ ohci->hc_control = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* HC Reset requires max 10 us delay */
+ writel (OHCI_HCR, &ohci->regs->cmdstatus);
+ while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
+ if (--timeout == 0) {
+ err("USB HC reset timed out!");
+ return -1;
+ }
+ udelay (1);
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* Start an OHCI controller, set the BUS operational
+ * enable interrupts
+ * connect the virtual root hub */
+
+static int hc_start (ohci_t * ohci)
+{
+ __u32 mask;
+ unsigned int fminterval;
+
+ ohci->disabled = 1;
+
+ /* Tell the controller where the control and bulk lists are
+ * The lists are empty now. */
+
+ writel (0, &ohci->regs->ed_controlhead);
+ writel (0, &ohci->regs->ed_bulkhead);
+
+ writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
+
+ fminterval = 0x2edf;
+ writel ((fminterval * 9) / 10, &ohci->regs->periodicstart);
+ fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
+ writel (fminterval, &ohci->regs->fminterval);
+ writel (0x628, &ohci->regs->lsthresh);
+
+ /* start controller operations */
+ ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
+ ohci->disabled = 0;
+ writel (ohci->hc_control, &ohci->regs->control);
+
+ /* disable all interrupts */
+ mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
+ OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
+ OHCI_INTR_OC | OHCI_INTR_MIE);
+ writel (mask, &ohci->regs->intrdisable);
+ /* clear all interrupts */
+ mask &= ~OHCI_INTR_MIE;
+ writel (mask, &ohci->regs->intrstatus);
+ /* Choose the interrupts we care about now - but w/o MIE */
+ mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO;
+ writel (mask, &ohci->regs->intrenable);
+
+#ifdef OHCI_USE_NPS
+ /* required for AMD-756 and some Mac platforms */
+ writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM,
+ &ohci->regs->roothub.a);
+ writel (RH_HS_LPSC, &ohci->regs->roothub.status);
+#endif /* OHCI_USE_NPS */
+
+ /* POTPGT delay is bits 24-31, in 2 ms units. */
+ mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+
+ /* connect the virtual root hub */
+ ohci->rh.devnum = 0;
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* an interrupt happens */
+
+static int
+hc_interrupt (void)
+{
+ ohci_t *ohci = &gohci;
+ struct ohci_regs *regs = ohci->regs;
+ int ints;
+ int stat = -1;
+
+ if ((ohci->hcca->done_head != 0) &&
+ !(ohci_cpu_to_le32(ohci->hcca->done_head) & 0x01)) {
+
+ ints = OHCI_INTR_WDH;
+
+ } else if ((ints = readl (&regs->intrstatus)) == ~(u32)0) {
+ ohci->disabled++;
+ err ("%s device removed!", ohci->slot_name);
+ return -1;
+
+ } else if ((ints &= readl (&regs->intrenable)) == 0) {
+ dbg("hc_interrupt: returning..\n");
+ return 0xff;
+ }
+
+ /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */
+
+ if (ints & OHCI_INTR_RHSC) {
+ got_rhsc = 1;
+ stat = 0xff;
+ }
+
+ if (ints & OHCI_INTR_UE) {
+ ohci->disabled++;
+ err ("OHCI Unrecoverable Error, controller usb-%s disabled",
+ ohci->slot_name);
+ /* e.g. due to PCI Master/Target Abort */
+
+#ifdef DEBUG
+ ohci_dump (ohci, 1);
+#endif
+ /* FIXME: be optimistic, hope that bug won't repeat often. */
+ /* Make some non-interrupt context restart the controller. */
+ /* Count and limit the retries though; either hardware or */
+ /* software errors can go forever... */
+ hc_reset (ohci);
+ return -1;
+ }
+
+ if (ints & OHCI_INTR_WDH) {
+ writel (OHCI_INTR_WDH, &regs->intrdisable);
+ stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci));
+ writel (OHCI_INTR_WDH, &regs->intrenable);
+ }
+
+ if (ints & OHCI_INTR_SO) {
+ dbg("USB Schedule overrun\n");
+ writel (OHCI_INTR_SO, &regs->intrenable);
+ stat = -1;
+ }
+
+ /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
+ if (ints & OHCI_INTR_SF) {
+ unsigned int frame = ohci_cpu_to_le16 (ohci->hcca->frame_no) & 1;
+ mdelay(1);
+ writel (OHCI_INTR_SF, &regs->intrdisable);
+ if (ohci->ed_rm_list[frame] != NULL)
+ writel (OHCI_INTR_SF, &regs->intrenable);
+ stat = 0xff;
+ }
+
+ writel (ints, &regs->intrstatus);
+ return stat;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+
+/* De-allocate all resources.. */
+
+static void hc_release_ohci (ohci_t *ohci)
+{
+ dbg ("USB HC release ohci usb-%s", ohci->slot_name);
+
+ if (!ohci->disabled)
+ hc_reset (ohci);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * low level initalisation routine, called from usb.c
+ */
+static char ohci_inited = 0;
+
+int usb_lowlevel_init(int index, void **controller)
+{
+ memset (&gohci, 0, sizeof (ohci_t));
+ memset (&urb_priv, 0, sizeof (urb_priv_t));
+
+ /* align the storage */
+ if ((__u32)&ghcca[0] & 0xff) {
+ err("HCCA not aligned!!");
+ return -1;
+ }
+ phcca = &ghcca[0];
+ info("aligned ghcca %p", phcca);
+ memset(&ohci_dev, 0, sizeof(struct ohci_device));
+ if ((__u32)&ohci_dev.ed[0] & 0x7) {
+ err("EDs not aligned!!");
+ return -1;
+ }
+ memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1));
+ if ((__u32)gtd & 0x7) {
+ err("TDs not aligned!!");
+ return -1;
+ }
+ ptd = gtd;
+ gohci.hcca = phcca;
+ memset (phcca, 0, sizeof (struct ohci_hcca));
+
+ gohci.disabled = 1;
+ gohci.sleeping = 0;
+ gohci.irq = -1;
+#if defined(CONFIG_440EP)
+ gohci.regs = (struct ohci_regs *)(CONFIG_SYS_PERIPHERAL_BASE | 0x1000);
+#elif defined(CONFIG_440EPX) || defined(CONFIG_SYS_USB_HOST)
+ gohci.regs = (struct ohci_regs *)(CONFIG_SYS_USB_HOST);
+#endif
+
+ gohci.flags = 0;
+ gohci.slot_name = "ppc440";
+
+ if (hc_reset (&gohci) < 0) {
+ hc_release_ohci (&gohci);
+ return -1;
+ }
+
+ if (hc_start (&gohci) < 0) {
+ err ("can't start usb-%s", gohci.slot_name);
+ hc_release_ohci (&gohci);
+ return -1;
+ }
+
+#ifdef DEBUG
+ ohci_dump (&gohci, 1);
+#endif
+ ohci_inited = 1;
+ urb_finished = 1;
+
+ return 0;
+}
+
+int usb_lowlevel_stop(int index)
+{
+ /* this gets called really early - before the controller has */
+ /* even been initialized! */
+ if (!ohci_inited)
+ return 0;
+ /* TODO release any interrupts, etc. */
+ /* call hc_release_ohci() here ? */
+ hc_reset (&gohci);
+ return 0;
+}
+
+#endif /* CONFIG_USB_OHCI */
diff --git a/arch/powerpc/cpu/ppc4xx/usb_ohci.h b/arch/powerpc/cpu/ppc4xx/usb_ohci.h
new file mode 100644
index 0000000..2c3dc4f
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/usb_ohci.h
@@ -0,0 +1,410 @@
+/*
+ * URB OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * usb-ohci.h
+ */
+
+static int cc_to_error[16] = {
+
+/* mapping of the OHCI CC status to error codes */
+ /* No Error */ 0,
+ /* CRC Error */ USB_ST_CRC_ERR,
+ /* Bit Stuff */ USB_ST_BIT_ERR,
+ /* Data Togg */ USB_ST_CRC_ERR,
+ /* Stall */ USB_ST_STALLED,
+ /* DevNotResp */ -1,
+ /* PIDCheck */ USB_ST_BIT_ERR,
+ /* UnExpPID */ USB_ST_BIT_ERR,
+ /* DataOver */ USB_ST_BUF_ERR,
+ /* DataUnder */ USB_ST_BUF_ERR,
+ /* reservd */ -1,
+ /* reservd */ -1,
+ /* BufferOver */ USB_ST_BUF_ERR,
+ /* BuffUnder */ USB_ST_BUF_ERR,
+ /* Not Access */ -1,
+ /* Not Access */ -1
+};
+
+/* ED States */
+
+#define ED_NEW 0x00
+#define ED_UNLINK 0x01
+#define ED_OPER 0x02
+#define ED_DEL 0x04
+#define ED_URB_DEL 0x08
+
+/* usb_ohci_ed */
+struct ed {
+ __u32 hwINFO;
+ __u32 hwTailP;
+ __u32 hwHeadP;
+ __u32 hwNextED;
+
+ struct ed *ed_prev;
+ __u8 int_period;
+ __u8 int_branch;
+ __u8 int_load;
+ __u8 int_interval;
+ __u8 state;
+ __u8 type;
+ __u16 last_iso;
+ struct ed *ed_rm_list;
+
+ struct usb_device *usb_dev;
+ __u32 unused[3];
+} __attribute__((aligned(16)));
+typedef struct ed ed_t;
+
+/* TD info field */
+#define TD_CC 0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
+#define TD_EC 0x0C000000
+#define TD_T 0x03000000
+#define TD_T_DATA0 0x02000000
+#define TD_T_DATA1 0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R 0x00040000
+#define TD_DI 0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP 0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN 0x00100000
+#define TD_DP_OUT 0x00080000
+
+#define TD_ISO 0x00010000
+#define TD_DEL 0x00020000
+
+/* CC Codes */
+#define TD_CC_NOERROR 0x00
+#define TD_CC_CRC 0x01
+#define TD_CC_BITSTUFFING 0x02
+#define TD_CC_DATATOGGLEM 0x03
+#define TD_CC_STALL 0x04
+#define TD_DEVNOTRESP 0x05
+#define TD_PIDCHECKFAIL 0x06
+#define TD_UNEXPECTEDPID 0x07
+#define TD_DATAOVERRUN 0x08
+#define TD_DATAUNDERRUN 0x09
+#define TD_BUFFEROVERRUN 0x0C
+#define TD_BUFFERUNDERRUN 0x0D
+#define TD_NOTACCESSED 0x0F
+
+#define MAXPSW 1
+
+struct td {
+ __u32 hwINFO;
+ __u32 hwCBP; /* Current Buffer Pointer */
+ __u32 hwNextTD; /* Next TD Pointer */
+ __u32 hwBE; /* Memory Buffer End Pointer */
+
+ __u16 hwPSW[MAXPSW];
+ __u8 unused;
+ __u8 index;
+ struct ed *ed;
+ struct td *next_dl_td;
+ struct usb_device *usb_dev;
+ int transfer_len;
+ __u32 data;
+
+ __u32 unused2[2];
+} __attribute__((aligned(32)));
+typedef struct td td_t;
+
+#define OHCI_ED_SKIP (1 << 14)
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of. It must be 256-byte aligned.
+ */
+
+#define NUM_INTS 32 /* part of the OHCI standard */
+struct ohci_hcca {
+ __u32 int_table[NUM_INTS]; /* Interrupt ED table */
+#if defined(CONFIG_MPC5200)
+ __u16 pad1; /* set to 0 on each frame_no change */
+ __u16 frame_no; /* current frame number */
+#else
+ __u16 frame_no; /* current frame number */
+ __u16 pad1; /* set to 0 on each frame_no change */
+#endif
+ __u32 done_head; /* info returned for an interrupt */
+ u8 reserved_for_hc[116];
+} __attribute__((aligned(256)));
+
+/*
+ * Maximum number of root hub ports.
+ */
+#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region. This is Memory Mapped I/O. You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+ /* control and status registers */
+ __u32 revision;
+ __u32 control;
+ __u32 cmdstatus;
+ __u32 intrstatus;
+ __u32 intrenable;
+ __u32 intrdisable;
+ /* memory pointers */
+ __u32 hcca;
+ __u32 ed_periodcurrent;
+ __u32 ed_controlhead;
+ __u32 ed_controlcurrent;
+ __u32 ed_bulkhead;
+ __u32 ed_bulkcurrent;
+ __u32 donehead;
+ /* frame counters */
+ __u32 fminterval;
+ __u32 fmremaining;
+ __u32 fmnumber;
+ __u32 periodicstart;
+ __u32 lsthresh;
+ /* Root hub ports */
+ struct ohci_roothub_regs {
+ __u32 a;
+ __u32 b;
+ __u32 status;
+ __u32 portstatus[MAX_ROOT_PORTS];
+ } roothub;
+} __attribute__((aligned(32)));
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
+#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
+#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
+#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
+#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
+#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
+#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
+#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
+#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+# define OHCI_USB_RESET (0 << 6)
+# define OHCI_USB_RESUME (1 << 6)
+# define OHCI_USB_OPER (2 << 6)
+# define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR (1 << 0) /* host controller reset */
+#define OHCI_CLF (1 << 1) /* control list filled */
+#define OHCI_BLF (1 << 2) /* bulk list filled */
+#define OHCI_OCR (1 << 3) /* ownership change request */
+#define OHCI_SOC (3 << 16) /* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
+#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
+#define OHCI_INTR_SF (1 << 2) /* start frame */
+#define OHCI_INTR_RD (1 << 3) /* resume detect */
+#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
+#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
+#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
+#define OHCI_INTR_OC (1 << 30) /* ownership change */
+#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
+
+/* Virtual Root HUB */
+struct virt_root_hub {
+ int devnum; /* Address of Root Hub endpoint */
+ void *dev; /* was urb */
+ void *int_addr;
+ int send;
+ int interval;
+};
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */
+
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status */
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS 0x00000001 /* local power status */
+#define RH_HS_OCI 0x00000002 /* over current indicator */
+#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
+#define RH_HS_LPSC 0x00010000 /* local power status change */
+#define RH_HS_OCIC 0x00020000 /* over current indicator change */
+#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+/* urb */
+#define N_URB_TD 48
+typedef struct {
+ ed_t *ed;
+ __u16 length; /* number of tds associated with this request */
+ __u16 td_cnt; /* number of tds already serviced */
+ int state;
+ unsigned long pipe;
+ int actual_length;
+ td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */
+} urb_priv_t;
+#define URB_DEL 1
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+typedef struct ohci {
+ struct ohci_hcca *hcca; /* hcca */
+ /*dma_addr_t hcca_dma; */
+
+ int irq;
+ int disabled; /* e.g. got a UE, we're hung */
+ int sleeping;
+ unsigned long flags; /* for HC bugs */
+
+ struct ohci_regs *regs; /* OHCI controller's memory */
+
+ ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */
+ ed_t *ed_bulktail; /* last endpoint of bulk list */
+ ed_t *ed_controltail; /* last endpoint of control list */
+ int intrstatus;
+ __u32 hc_control; /* copy of the hc control reg */
+ struct usb_device *dev[32];
+ struct virt_root_hub rh;
+
+ const char *slot_name;
+} ohci_t;
+
+#define NUM_EDS 8 /* num of preallocated endpoint descriptors */
+
+struct ohci_device {
+ ed_t ed[NUM_EDS];
+ int ed_cnt;
+};
+
+/* hcd */
+/* endpoint */
+static int ep_link(ohci_t * ohci, ed_t * ed);
+static int ep_unlink(ohci_t * ohci, ed_t * ed);
+static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe);
+
+/*-------------------------------------------------------------------------*/
+
+/* we need more TDs than EDs */
+#define NUM_TD 64
+
+/* +1 so we can align the storage */
+td_t gtd[NUM_TD + 1];
+/* pointers to aligned storage */
+td_t *ptd;
+
+/* TDs ... */
+static inline struct td *td_alloc(struct usb_device *usb_dev)
+{
+ int i;
+ struct td *td;
+
+ td = NULL;
+ for (i = 0; i < NUM_TD; i++) {
+ if (ptd[i].usb_dev == NULL) {
+ td = &ptd[i];
+ td->usb_dev = usb_dev;
+ break;
+ }
+ }
+
+ return td;
+}
+
+static inline void ed_free(struct ed *ed)
+{
+ ed->usb_dev = NULL;
+}
diff --git a/arch/powerpc/cpu/ppc4xx/xilinx_irq.c b/arch/powerpc/cpu/ppc4xx/xilinx_irq.c
new file mode 100644
index 0000000..eaa3de2
--- /dev/null
+++ b/arch/powerpc/cpu/ppc4xx/xilinx_irq.c
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/interrupt.h>
+#include <asm/ppc4xx.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+#include <asm/io.h>
+#include <asm/xilinx_irq.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void pic_enable(void)
+{
+ debug("Xilinx PIC at 0x%8x\n", intc);
+
+ /*
+ * Disable all external interrupts until they are
+ * explicitly requested.
+ */
+ out_be32((u32 *) IER, 0);
+
+ /* Acknowledge any pending interrupts just in case. */
+ out_be32((u32 *) IAR, 0xffffffff);
+
+ /* Turn on the Master Enable. */
+ out_be32((u32 *) MER, 0x3UL);
+
+ return;
+}
+
+int xilinx_pic_irq_get(void)
+{
+ u32 irq;
+ irq = in_be32((u32 *) IVR);
+
+ /* If no interrupt is pending then all bits of the IVR are set to 1. As
+ * the IVR is as many bits wide as numbers of inputs are available.
+ * Therefore, if all bits of the IVR are set to one, its content will
+ * be bigger than XPAR_INTC_MAX_NUM_INTR_INPUTS.
+ */
+ if (irq >= XPAR_INTC_MAX_NUM_INTR_INPUTS)
+ irq = -1; /* report no pending interrupt. */
+
+ debug("get_irq: %d\n", irq);
+ return (irq);
+}
+
+void pic_irq_enable(unsigned int irq)
+{
+ u32 mask = IRQ_MASK(irq);
+ debug("enable: %d\n", irq);
+ out_be32((u32 *) SIE, mask);
+}
+
+void pic_irq_disable(unsigned int irq)
+{
+ u32 mask = IRQ_MASK(irq);
+ debug("disable: %d\n", irq);
+ out_be32((u32 *) CIE, mask);
+}
+
+void pic_irq_ack(unsigned int irq)
+{
+ u32 mask = IRQ_MASK(irq);
+ debug("ack: %d\n", irq);
+ out_be32((u32 *) IAR, mask);
+}
+
+void external_interrupt(struct pt_regs *regs)
+{
+ int irq;
+
+ irq = xilinx_pic_irq_get();
+ if (irq < 0)
+ return;
+
+ interrupt_run_handler(irq);
+
+ return;
+}
diff --git a/arch/powerpc/include/asm/4xx_pci.h b/arch/powerpc/include/asm/4xx_pci.h
new file mode 100644
index 0000000..f686e7c
--- /dev/null
+++ b/arch/powerpc/include/asm/4xx_pci.h
@@ -0,0 +1,60 @@
+#ifndef _405GP_PCI_H
+#define _405GP_PCI_H
+
+#include <pci.h>
+
+/*----------------------------------------------------------------------------+
+| 405GP PCI core memory map defines.
++----------------------------------------------------------------------------*/
+#define MIN_PCI_MEMADDR1 0x80000000
+#define MIN_PCI_MEMADDR2 0x00000000
+#define MIN_PLB_PCI_IOADDR 0xE8000000 /* PLB side of PCI I/O address space */
+#define MIN_PCI_PCI_IOADDR 0x00000000 /* PCI side of PCI I/O address space */
+#define MAX_PCI_DEVICES 32
+
+/*----------------------------------------------------------------------------+
+| Defines for the 405GP PCI Config address and data registers followed by
+| defines for the standard PCI device configuration header.
++----------------------------------------------------------------------------*/
+#define PCICFGADR 0xEEC00000
+#define PCICFGDATA 0xEEC00004
+
+#define PCIBUSNUM 0x40 /* 405GP specific parameters */
+#define PCISUBBUSNUM 0x41
+#define PCIDISCOUNT 0x42
+#define PCIBRDGOPT1 0x4A
+#define PCIBRDGOPT2 0x60
+
+/*----------------------------------------------------------------------------+
+| Defines for 405GP PCI Master local configuration regs.
++----------------------------------------------------------------------------*/
+#define PMM0LA 0xEF400000
+#define PMM0MA 0xEF400004
+#define PMM0PCILA 0xEF400008
+#define PMM0PCIHA 0xEF40000C
+#define PMM1LA 0xEF400010
+#define PMM1MA 0xEF400014
+#define PMM1PCILA 0xEF400018
+#define PMM1PCIHA 0xEF40001C
+#define PMM2LA 0xEF400020
+#define PMM2MA 0xEF400024
+#define PMM2PCILA 0xEF400028
+#define PMM2PCIHA 0xEF40002C
+
+/*----------------------------------------------------------------------------+
+| Defines for 405GP PCI Target local configuration regs.
++----------------------------------------------------------------------------*/
+#define PTM1MS 0xEF400030
+#define PTM1LA 0xEF400034
+#define PTM2MS 0xEF400038
+#define PTM2LA 0xEF40003C
+
+#define PCIDEVID_405GP 0x0
+
+void board_pci_fixup_irq(struct pci_controller *hose, pci_dev_t dev);
+int pci_arbiter_enabled(void);
+int __pci_pre_init(struct pci_controller *hose);
+void __pci_target_init(struct pci_controller *hose);
+void __pci_master_init(struct pci_controller *hose);
+
+#endif
diff --git a/arch/powerpc/include/asm/4xx_pcie.h b/arch/powerpc/include/asm/4xx_pcie.h
new file mode 100644
index 0000000..fbdc28e
--- /dev/null
+++ b/arch/powerpc/include/asm/4xx_pcie.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __4XX_PCIE_H
+#define __4XX_PCIE_H
+
+#include <asm/ppc4xx.h>
+#include <pci.h>
+
+#define DCRN_SDR0_CFGADDR 0x00e
+#define DCRN_SDR0_CFGDATA 0x00f
+
+#if defined(CONFIG_440SPE)
+#define CONFIG_SYS_PCIE_NR_PORTS 3
+
+#define CONFIG_SYS_PCIE_ADDR_HIGH 0x0000000d
+
+#define DCRN_PCIE0_BASE 0x100
+#define DCRN_PCIE1_BASE 0x120
+#define DCRN_PCIE2_BASE 0x140
+
+#define PCIE0_SDR 0x300
+#define PCIE1_SDR 0x340
+#define PCIE2_SDR 0x370
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define CONFIG_SYS_PCIE_NR_PORTS 2
+
+#define CONFIG_SYS_PCIE_ADDR_HIGH 0x0000000d
+
+#define DCRN_PCIE0_BASE 0x100
+#define DCRN_PCIE1_BASE 0x120
+
+#define PCIE0_SDR 0x300
+#define PCIE1_SDR 0x340
+#endif
+
+#if defined(CONFIG_405EX)
+#define CONFIG_SYS_PCIE_NR_PORTS 2
+
+#define CONFIG_SYS_PCIE_ADDR_HIGH 0x00000000
+
+#define DCRN_PCIE0_BASE 0x040
+#define DCRN_PCIE1_BASE 0x060
+
+#define PCIE0_SDR 0x400
+#define PCIE1_SDR 0x440
+#endif
+
+#define PCIE0 DCRN_PCIE0_BASE
+#define PCIE1 DCRN_PCIE1_BASE
+#define PCIE2 DCRN_PCIE2_BASE
+
+#define DCRN_PEGPL_CFGBAH(base) (base + 0x00)
+#define DCRN_PEGPL_CFGBAL(base) (base + 0x01)
+#define DCRN_PEGPL_CFGMSK(base) (base + 0x02)
+#define DCRN_PEGPL_MSGBAH(base) (base + 0x03)
+#define DCRN_PEGPL_MSGBAL(base) (base + 0x04)
+#define DCRN_PEGPL_MSGMSK(base) (base + 0x05)
+#define DCRN_PEGPL_OMR1BAH(base) (base + 0x06)
+#define DCRN_PEGPL_OMR1BAL(base) (base + 0x07)
+#define DCRN_PEGPL_OMR1MSKH(base) (base + 0x08)
+#define DCRN_PEGPL_OMR1MSKL(base) (base + 0x09)
+#define DCRN_PEGPL_REGBAH(base) (base + 0x12)
+#define DCRN_PEGPL_REGBAL(base) (base + 0x13)
+#define DCRN_PEGPL_REGMSK(base) (base + 0x14)
+#define DCRN_PEGPL_SPECIAL(base) (base + 0x15)
+#define DCRN_PEGPL_CFG(base) (base + 0x16)
+
+/*
+ * System DCRs (SDRs)
+ */
+#define PESDR0_PLLLCT1 0x03a0
+#define PESDR0_PLLLCT2 0x03a1
+#define PESDR0_PLLLCT3 0x03a2
+
+/* common regs, at for all 4xx with PCIe core */
+#define SDRN_PESDR_UTLSET1(n) (sdr_base(n) + 0x00)
+#define SDRN_PESDR_UTLSET2(n) (sdr_base(n) + 0x01)
+#define SDRN_PESDR_DLPSET(n) (sdr_base(n) + 0x02)
+#define SDRN_PESDR_LOOP(n) (sdr_base(n) + 0x03)
+#define SDRN_PESDR_RCSSET(n) (sdr_base(n) + 0x04)
+#define SDRN_PESDR_RCSSTS(n) (sdr_base(n) + 0x05)
+
+#if defined(CONFIG_440SPE)
+#define SDRN_PESDR_HSSL0SET1(n) (sdr_base(n) + 0x06)
+#define SDRN_PESDR_HSSL0SET2(n) (sdr_base(n) + 0x07)
+#define SDRN_PESDR_HSSL0STS(n) (sdr_base(n) + 0x08)
+#define SDRN_PESDR_HSSL1SET1(n) (sdr_base(n) + 0x09)
+#define SDRN_PESDR_HSSL1SET2(n) (sdr_base(n) + 0x0a)
+#define SDRN_PESDR_HSSL1STS(n) (sdr_base(n) + 0x0b)
+#define SDRN_PESDR_HSSL2SET1(n) (sdr_base(n) + 0x0c)
+#define SDRN_PESDR_HSSL2SET2(n) (sdr_base(n) + 0x0d)
+#define SDRN_PESDR_HSSL2STS(n) (sdr_base(n) + 0x0e)
+#define SDRN_PESDR_HSSL3SET1(n) (sdr_base(n) + 0x0f)
+#define SDRN_PESDR_HSSL3SET2(n) (sdr_base(n) + 0x10)
+#define SDRN_PESDR_HSSL3STS(n) (sdr_base(n) + 0x11)
+
+#define PESDR0_UTLSET1 0x0300
+#define PESDR0_UTLSET2 0x0301
+#define PESDR0_DLPSET 0x0302
+#define PESDR0_LOOP 0x0303
+#define PESDR0_RCSSET 0x0304
+#define PESDR0_RCSSTS 0x0305
+#define PESDR0_HSSL0SET1 0x0306
+#define PESDR0_HSSL0SET2 0x0307
+#define PESDR0_HSSL0STS 0x0308
+#define PESDR0_HSSL1SET1 0x0309
+#define PESDR0_HSSL1SET2 0x030a
+#define PESDR0_HSSL1STS 0x030b
+#define PESDR0_HSSL2SET1 0x030c
+#define PESDR0_HSSL2SET2 0x030d
+#define PESDR0_HSSL2STS 0x030e
+#define PESDR0_HSSL3SET1 0x030f
+#define PESDR0_HSSL3SET2 0x0310
+#define PESDR0_HSSL3STS 0x0311
+#define PESDR0_HSSL4SET1 0x0312
+#define PESDR0_HSSL4SET2 0x0313
+#define PESDR0_HSSL4STS 0x0314
+#define PESDR0_HSSL5SET1 0x0315
+#define PESDR0_HSSL5SET2 0x0316
+#define PESDR0_HSSL5STS 0x0317
+#define PESDR0_HSSL6SET1 0x0318
+#define PESDR0_HSSL6SET2 0x0319
+#define PESDR0_HSSL6STS 0x031a
+#define PESDR0_HSSL7SET1 0x031b
+#define PESDR0_HSSL7SET2 0x031c
+#define PESDR0_HSSL7STS 0x031d
+#define PESDR0_HSSCTLSET 0x031e
+#define PESDR0_LANE_ABCD 0x031f
+#define PESDR0_LANE_EFGH 0x0320
+
+#define PESDR1_UTLSET1 0x0340
+#define PESDR1_UTLSET2 0x0341
+#define PESDR1_DLPSET 0x0342
+#define PESDR1_LOOP 0x0343
+#define PESDR1_RCSSET 0x0344
+#define PESDR1_RCSSTS 0x0345
+#define PESDR1_HSSL0SET1 0x0346
+#define PESDR1_HSSL0SET2 0x0347
+#define PESDR1_HSSL0STS 0x0348
+#define PESDR1_HSSL1SET1 0x0349
+#define PESDR1_HSSL1SET2 0x034a
+#define PESDR1_HSSL1STS 0x034b
+#define PESDR1_HSSL2SET1 0x034c
+#define PESDR1_HSSL2SET2 0x034d
+#define PESDR1_HSSL2STS 0x034e
+#define PESDR1_HSSL3SET1 0x034f
+#define PESDR1_HSSL3SET2 0x0350
+#define PESDR1_HSSL3STS 0x0351
+#define PESDR1_HSSCTLSET 0x0352
+#define PESDR1_LANE_ABCD 0x0353
+
+#define PESDR2_UTLSET1 0x0370
+#define PESDR2_UTLSET2 0x0371
+#define PESDR2_DLPSET 0x0372
+#define PESDR2_LOOP 0x0373
+#define PESDR2_RCSSET 0x0374
+#define PESDR2_RCSSTS 0x0375
+#define PESDR2_HSSL0SET1 0x0376
+#define PESDR2_HSSL0SET2 0x0377
+#define PESDR2_HSSL0STS 0x0378
+#define PESDR2_HSSL1SET1 0x0379
+#define PESDR2_HSSL1SET2 0x037a
+#define PESDR2_HSSL1STS 0x037b
+#define PESDR2_HSSL2SET1 0x037c
+#define PESDR2_HSSL2SET2 0x037d
+#define PESDR2_HSSL2STS 0x037e
+#define PESDR2_HSSL3SET1 0x037f
+#define PESDR2_HSSL3SET2 0x0380
+#define PESDR2_HSSL3STS 0x0381
+#define PESDR2_HSSCTLSET 0x0382
+#define PESDR2_LANE_ABCD 0x0383
+
+#elif defined(CONFIG_405EX)
+
+#define SDRN_PESDR_PHYSET1(n) (sdr_base(n) + 0x06)
+#define SDRN_PESDR_PHYSET2(n) (sdr_base(n) + 0x07)
+#define SDRN_PESDR_BIST(n) (sdr_base(n) + 0x08)
+#define SDRN_PESDR_LPB(n) (sdr_base(n) + 0x0b)
+#define SDRN_PESDR_PHYSTA(n) (sdr_base(n) + 0x0c)
+
+#define PESDR0_UTLSET1 0x0400
+#define PESDR0_UTLSET2 0x0401
+#define PESDR0_DLPSET 0x0402
+#define PESDR0_LOOP 0x0403
+#define PESDR0_RCSSET 0x0404
+#define PESDR0_RCSSTS 0x0405
+#define PESDR0_PHYSET1 0x0406
+#define PESDR0_PHYSET2 0x0407
+#define PESDR0_BIST 0x0408
+#define PESDR0_LPB 0x040B
+#define PESDR0_PHYSTA 0x040C
+
+#define PESDR1_UTLSET1 0x0440
+#define PESDR1_UTLSET2 0x0441
+#define PESDR1_DLPSET 0x0442
+#define PESDR1_LOOP 0x0443
+#define PESDR1_RCSSET 0x0444
+#define PESDR1_RCSSTS 0x0445
+#define PESDR1_PHYSET1 0x0446
+#define PESDR1_PHYSET2 0x0447
+#define PESDR1_BIST 0x0448
+#define PESDR1_LPB 0x044B
+#define PESDR1_PHYSTA 0x044C
+
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+
+#define PESDR0_L0BIST 0x0308 /* PE0 L0 built in self test */
+#define PESDR0_L0BISTSTS 0x0309 /* PE0 L0 built in self test status */
+#define PESDR0_L0CDRCTL 0x030A /* PE0 L0 CDR control */
+#define PESDR0_L0DRV 0x030B /* PE0 L0 drive */
+#define PESDR0_L0REC 0x030C /* PE0 L0 receiver */
+#define PESDR0_L0LPB 0x030D /* PE0 L0 loopback */
+#define PESDR0_L0CLK 0x030E /* PE0 L0 clocking */
+#define PESDR0_PHY_CTL_RST 0x030F /* PE0 PHY control reset */
+#define PESDR0_RSTSTA 0x0310 /* PE0 reset status */
+#define PESDR0_OBS 0x0311 /* PE0 observation register */
+#define PESDR0_L0ERRC 0x0320 /* PE0 L0 error counter */
+
+#define PESDR1_L0BIST 0x0348 /* PE1 L0 built in self test */
+#define PESDR1_L1BIST 0x0349 /* PE1 L1 built in self test */
+#define PESDR1_L2BIST 0x034A /* PE1 L2 built in self test */
+#define PESDR1_L3BIST 0x034B /* PE1 L3 built in self test */
+#define PESDR1_L0BISTSTS 0x034C /* PE1 L0 built in self test status */
+#define PESDR1_L1BISTSTS 0x034D /* PE1 L1 built in self test status */
+#define PESDR1_L2BISTSTS 0x034E /* PE1 L2 built in self test status */
+#define PESDR1_L3BISTSTS 0x034F /* PE1 L3 built in self test status */
+#define PESDR1_L0CDRCTL 0x0350 /* PE1 L0 CDR control */
+#define PESDR1_L1CDRCTL 0x0351 /* PE1 L1 CDR control */
+#define PESDR1_L2CDRCTL 0x0352 /* PE1 L2 CDR control */
+#define PESDR1_L3CDRCTL 0x0353 /* PE1 L3 CDR control */
+#define PESDR1_L0DRV 0x0354 /* PE1 L0 drive */
+#define PESDR1_L1DRV 0x0355 /* PE1 L1 drive */
+#define PESDR1_L2DRV 0x0356 /* PE1 L2 drive */
+#define PESDR1_L3DRV 0x0357 /* PE1 L3 drive */
+#define PESDR1_L0REC 0x0358 /* PE1 L0 receiver */
+#define PESDR1_L1REC 0x0359 /* PE1 L1 receiver */
+#define PESDR1_L2REC 0x035A /* PE1 L2 receiver */
+#define PESDR1_L3REC 0x035B /* PE1 L3 receiver */
+#define PESDR1_L0LPB 0x035C /* PE1 L0 loopback */
+#define PESDR1_L1LPB 0x035D /* PE1 L1 loopback */
+#define PESDR1_L2LPB 0x035E /* PE1 L2 loopback */
+#define PESDR1_L3LPB 0x035F /* PE1 L3 loopback */
+#define PESDR1_L0CLK 0x0360 /* PE1 L0 clocking */
+#define PESDR1_L1CLK 0x0361 /* PE1 L1 clocking */
+#define PESDR1_L2CLK 0x0362 /* PE1 L2 clocking */
+#define PESDR1_L3CLK 0x0363 /* PE1 L3 clocking */
+#define PESDR1_PHY_CTL_RST 0x0364 /* PE1 PHY control reset */
+#define PESDR1_RSTSTA 0x0365 /* PE1 reset status */
+#define PESDR1_OBS 0x0366 /* PE1 observation register */
+#define PESDR1_L0ERRC 0x0368 /* PE1 L0 error counter */
+#define PESDR1_L1ERRC 0x0369 /* PE1 L1 error counter */
+#define PESDR1_L2ERRC 0x036A /* PE1 L2 error counter */
+#define PESDR1_L3ERRC 0x036B /* PE1 L3 error counter */
+#define PESDR0_IHS1 0x036C /* PE interrupt handler interfact setting 1 */
+#define PESDR0_IHS2 0x036D /* PE interrupt handler interfact setting 2 */
+
+#endif
+
+/* SDR Bit Mappings */
+#define PESDRx_RCSSET_HLDPLB 0x10000000
+#define PESDRx_RCSSET_RSTGU 0x01000000
+#define PESDRx_RCSSET_RDY 0x00100000
+#define PESDRx_RCSSET_RSTDL 0x00010000
+#define PESDRx_RCSSET_RSTPYN 0x00001000
+
+#define PESDRx_RCSSTS_PLBIDL 0x10000000
+#define PESDRx_RCSSTS_HRSTRQ 0x01000000
+#define PESDRx_RCSSTS_PGRST 0x00100000
+#define PESDRx_RCSSTS_VC0ACT 0x00010000
+#define PESDRx_RCSSTS_BMEN 0x00000100
+
+/*
+ * UTL register offsets
+ */
+#define PEUTL_PBCTL 0x00
+#define PEUTL_PBBSZ 0x20
+#define PEUTL_OPDBSZ 0x68
+#define PEUTL_IPHBSZ 0x70
+#define PEUTL_IPDBSZ 0x78
+#define PEUTL_OUTTR 0x90
+#define PEUTL_INTR 0x98
+#define PEUTL_PCTL 0xa0
+#define PEUTL_RCSTA 0xb0
+#define PEUTL_RCIRQEN 0xb8
+
+/*
+ * Config space register offsets
+ */
+#define PECFG_BAR0LMPA 0x210
+#define PECFG_BAR0HMPA 0x214
+#define PECFG_BAR1MPA 0x218
+#define PECFG_BAR2LMPA 0x220
+#define PECFG_BAR2HMPA 0x224
+
+#define PECFG_PIMEN 0x33c
+#define PECFG_PIM0LAL 0x340
+#define PECFG_PIM0LAH 0x344
+#define PECFG_PIM1LAL 0x348
+#define PECFG_PIM1LAH 0x34c
+#define PECFG_PIM01SAL 0x350
+#define PECFG_PIM01SAH 0x354
+
+#define PECFG_POM0LAL 0x380
+#define PECFG_POM0LAH 0x384
+
+#define SDR_READ(offset) ({\
+ mtdcr(DCRN_SDR0_CFGADDR, offset); \
+ mfdcr(DCRN_SDR0_CFGDATA);})
+
+#define SDR_WRITE(offset, data) ({\
+ mtdcr(DCRN_SDR0_CFGADDR, offset); \
+ mtdcr(DCRN_SDR0_CFGDATA,data);})
+
+#define GPL_DMER_MASK_DISA 0x02000000
+
+#define U64_TO_U32_LOW(val) ((u32)((val) & 0x00000000ffffffffULL))
+#define U64_TO_U32_HIGH(val) ((u32)((val) >> 32))
+
+/*
+ * Prototypes
+ */
+int ppc4xx_init_pcie(void);
+int ppc4xx_init_pcie_rootport(int port);
+int ppc4xx_init_pcie_endport(int port);
+void ppc4xx_setup_pcie_rootpoint(struct pci_controller *hose, int port);
+int ppc4xx_setup_pcie_endpoint(struct pci_controller *hose, int port);
+int pcie_hose_scan(struct pci_controller *hose, int bus);
+
+/*
+ * Function to determine root port or endport from env variable.
+ */
+static inline int is_end_point(int port)
+{
+ char s[10], *tk;
+ char *pcie_mode = getenv("pcie_mode");
+
+ if (pcie_mode == NULL)
+ return 0;
+
+ strcpy(s, pcie_mode);
+ tk = strtok(s, ":");
+
+ switch (port) {
+ case 0:
+ if (tk != NULL) {
+ if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+
+ case 1:
+ tk = strtok(NULL, ":");
+ if (tk != NULL) {
+ if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+
+ case 2:
+ tk = strtok(NULL, ":");
+ if (tk != NULL)
+ tk = strtok(NULL, ":");
+ if (tk != NULL) {
+ if (!(strcmp(tk, "ep") && strcmp(tk, "EP")))
+ return 1;
+ else
+ return 0;
+ }
+ else
+ return 0;
+ }
+
+ return 0;
+}
+
+#if defined(PCIE0_SDR)
+static inline u32 sdr_base(int port)
+{
+ switch (port) {
+ default: /* to satisfy compiler */
+ case 0:
+ return PCIE0_SDR;
+ case 1:
+ return PCIE1_SDR;
+#if CONFIG_SYS_PCIE_NR_PORTS > 2
+ case 2:
+ return PCIE2_SDR;
+#endif
+ }
+}
+#endif /* defined(PCIE0_SDR) */
+
+#endif /* __4XX_PCIE_H */
diff --git a/arch/powerpc/include/asm/5xx_immap.h b/arch/powerpc/include/asm/5xx_immap.h
new file mode 100644
index 0000000..72cbab4
--- /dev/null
+++ b/arch/powerpc/include/asm/5xx_immap.h
@@ -0,0 +1,439 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File: 5xx_immap.h
+ *
+ * Discription: MPC555 Internal Memory Map
+ *
+ */
+
+#ifndef __IMMAP_5XX__
+#define __IMMAP_5XX__
+
+/* System Configuration Registers.
+*/
+typedef struct sys_conf {
+ uint sc_siumcr;
+ uint sc_sypcr;
+ char res1[6];
+ ushort sc_swsr;
+ uint sc_sipend;
+ uint sc_simask;
+ uint sc_siel;
+ uint sc_sivec;
+ uint sc_tesr;
+ uint sc_sgpiodt1;
+ uint sc_sgpiodt2;
+ uint sc_sgpiocr;
+ uint sc_emcr;
+ uint sc_res1aa;
+ uint sc_res1ab;
+ uint sc_pdmcr;
+ char res3[192];
+} sysconf5xx_t;
+
+
+/* Memory Controller Registers.
+*/
+typedef struct mem_ctlr {
+ uint memc_br0;
+ uint memc_or0;
+ uint memc_br1;
+ uint memc_or1;
+ uint memc_br2;
+ uint memc_or2;
+ uint memc_br3;
+ uint memc_or3;
+ char res1[32];
+ uint memc_dmbr;
+ uint memc_dmor;
+ char res2[48];
+ ushort memc_mstat;
+ ushort memc_res4a;
+ char res3[132];
+} memctl5xx_t;
+
+/* System Integration Timers.
+*/
+typedef struct sys_int_timers {
+ ushort sit_tbscr;
+ char res1[2];
+ uint sit_tbref0;
+ uint sit_tbref1;
+ char res2[20];
+ ushort sit_rtcsc;
+ char res3[2];
+ uint sit_rtc;
+ uint sit_rtsec;
+ uint sit_rtcal;
+ char res4[16];
+ ushort sit_piscr;
+ char res5[2];
+ uint sit_pitc;
+ uint sit_pitr;
+ char res6[52];
+} sit5xx_t;
+
+/* Clocks and Reset
+*/
+typedef struct clk_and_reset {
+ uint car_sccr;
+ uint car_plprcr;
+ ushort car_rsr;
+ ushort car_res7a;
+ ushort car_colir;
+ ushort car_res7b;
+ ushort car_vsrmcr;
+ ushort car_res7c;
+ char res1[108];
+
+} car5xx_t;
+
+#define TBSCR_TBE ((ushort)0x0001)
+
+/* System Integration Timer Keys
+*/
+typedef struct sitk {
+ uint sitk_tbscrk;
+ uint sitk_tbref0k;
+ uint sitk_tbref1k;
+ uint sitk_tbk;
+ char res1[16];
+ uint sitk_rtcsck;
+ uint sitk_rtck;
+ uint sitk_rtseck;
+ uint sitk_rtcalk;
+ char res2[16];
+ uint sitk_piscrk;
+ uint sitk_pitck;
+ char res3[56];
+} sitk5xx_t;
+
+/* Clocks and Reset Keys.
+*/
+typedef struct cark {
+ uint cark_sccrk;
+ uint cark_plprcrk;
+ uint cark_rsrk;
+ char res1[1140];
+} cark8xx_t;
+
+/* The key to unlock registers maintained by keep-alive power.
+*/
+#define KAPWR_KEY ((unsigned int)0x55ccaa33)
+
+/* Flash Configuration
+*/
+typedef struct fl {
+ uint fl_cmfmcr;
+ uint fl_cmftst;
+ uint fl_cmfctl;
+ char res1[52];
+} fl5xx_t;
+
+/* Dpram Control
+*/
+typedef struct dprc {
+ ushort dprc_dptmcr;
+ ushort dprc_ramtst;
+ ushort dprc_rambar;
+ ushort dprc_misrh;
+ ushort dprc_misrl;
+ ushort dprc_miscnt;
+} dprc5xx_t;
+
+/* Time Processor Unit
+*/
+typedef struct tpu {
+ ushort tpu_tpumcr;
+ ushort tpu_tcr;
+ ushort tpu_dscr;
+ ushort tpu_dssr;
+ ushort tpu_ticr;
+ ushort tpu_cier;
+ ushort tpu_cfsr0;
+ ushort tpu_cfsr1;
+ ushort tpu_cfsr2;
+ ushort tpu_cfsr3;
+ ushort tpu_hsqr0;
+ ushort tpu_hsqr1;
+ ushort tpu_hsrr0;
+ ushort tpu_hsrr1;
+ ushort tpu_cpr0;
+ ushort tpu_cpr1;
+ ushort tpu_cisr;
+ ushort tpu_lr;
+ ushort tpu_sglr;
+ ushort tpu_dcnr;
+ ushort tpu_tpumcr2;
+ ushort tpu_tpumcr3;
+ ushort tpu_isdr;
+ ushort tpu_iscr;
+ char res1[208];
+ char tpu[16][16];
+ char res2[512];
+} tpu5xx_t;
+
+/* QADC
+*/
+typedef struct qadc {
+ ushort qadc_64mcr;
+ ushort qadc_64test;
+ ushort qadc_64int;
+ u_char qadc_portqa;
+ u_char qadc_portqb;
+ ushort qadc_ddrqa;
+ ushort qadc_qacr0;
+ ushort qadc_qacr1;
+ ushort qadc_qacr2;
+ ushort qadc_qasr0;
+ ushort qadc_qasr1;
+ char res1[492];
+ /* command convertion word table */
+ ushort qadc_ccw[64];
+ /* result word table, unsigned right justified */
+ ushort qadc_rjurr[64];
+ /* result word table, signed left justified */
+ ushort qadc_ljsrr[64];
+ /* result word table, unsigned left justified */
+ ushort qadc_ljurr[64];
+} qadc5xx_t;
+
+/* QSMCM
+*/
+typedef struct qsmcm {
+ ushort qsmcm_qsmcr;
+ ushort qsmcm_qtest;
+ ushort qsmcm_qdsci_il;
+ ushort qsmcm_qspi_il;
+ ushort qsmcm_scc1r0;
+ ushort qsmcm_scc1r1;
+ ushort qsmcm_sc1sr;
+ ushort qsmcm_sc1dr;
+ char res1[2];
+ char res2[2];
+ ushort qsmcm_portqs;
+ u_char qsmcm_pqspar;
+ u_char qsmcm_ddrqs;
+ ushort qsmcm_spcr0;
+ ushort qsmcm_spcr1;
+ ushort qsmcm_spcr2;
+ u_char qsmcm_spcr3;
+ u_char qsmcm_spsr;
+ ushort qsmcm_scc2r0;
+ ushort qsmcm_scc2r1;
+ ushort qsmcm_sc2sr;
+ ushort qsmcm_sc2dr;
+ ushort qsmcm_qsci1cr;
+ ushort qsmcm_qsci1sr;
+ ushort qsmcm_sctq[16];
+ ushort qsmcm_scrq[16];
+ char res3[212];
+ ushort qsmcm_recram[32];
+ ushort qsmcm_tranram[32];
+ u_char qsmcm_comdram[32];
+ char res[3616];
+} qsmcm5xx_t;
+
+
+/* MIOS
+*/
+
+typedef struct mios {
+ ushort mios_mpwmsm0perr; /* mpwmsm0 */
+ ushort mios_mpwmsm0pulr;
+ ushort mios_mpwmsm0cntr;
+ ushort mios_mpwmsm0scr;
+ ushort mios_mpwmsm1perr; /* mpwmsm1 */
+ ushort mios_mpwmsm1pulr;
+ ushort mios_mpwmsm1cntr;
+ ushort mios_mpwmsm1scr;
+ ushort mios_mpwmsm2perr; /* mpwmsm2 */
+ ushort mios_mpwmsm2pulr;
+ ushort mios_mpwmsm2cntr;
+ ushort mios_mpwmsm2scr;
+ ushort mios_mpwmsm3perr; /* mpwmsm3 */
+ ushort mios_mpwmsm3pulr;
+ ushort mios_mpwmsm3cntr;
+ ushort mios_mpwmsm3scr;
+ char res1[16];
+ ushort mios_mmcsm6cnt; /* mmcsm6 */
+ ushort mios_mmcsm6mlr;
+ ushort mios_mmcsm6scrd, mmcsm6scr;
+ char res2[32];
+ ushort mios_mdasm11ar; /* mdasm11 */
+ ushort mios_mdasm11br;
+ ushort mios_mdasm11scrd, mdasm11scr;
+ ushort mios_mdasm12ar; /* mdasm12 */
+ ushort mios_mdasm12br;
+ ushort mios_mdasm12scrd, mdasm12scr;
+ ushort mios_mdasm13ar; /* mdasm13 */
+ ushort mios_mdasm13br;
+ ushort mios_mdasm13scrd, mdasm13scr;
+ ushort mios_mdasm14ar; /* mdasm14 */
+ ushort mios_mdasm14br;
+ ushort mios_mdasm14scrd, mdasm14scr;
+ ushort mios_mdasm15ar; /* mdasm15 */
+ ushort mios_mdasm15br;
+ ushort mios_mdasm15scrd, mdasm15scr;
+ ushort mios_mpwmsm16perr; /* mpwmsm16 */
+ ushort mios_mpwmsm16pulr;
+ ushort mios_mpwmsm16cntr;
+ ushort mios_mpwmsm16scr;
+ ushort mios_mpwmsm17perr; /* mpwmsm17 */
+ ushort mios_mpwmsm17pulr;
+ ushort mios_mpwmsm17cntr;
+ ushort mios_mpwmsm17scr;
+ ushort mios_mpwmsm18perr; /* mpwmsm18 */
+ ushort mios_mpwmsm18pulr;
+ ushort mios_mpwmsm18cntr;
+ ushort mios_mpwmsm18scr;
+ ushort mios_mpwmsm19perr; /* mpwmsm19 */
+ ushort mios_mpwmsm19pulr;
+ ushort mios_mpwmsm19cntr;
+ ushort mios_mpwmsm19scr;
+ char res3[16];
+ ushort mios_mmcsm22cnt; /* mmcsm22 */
+ ushort mios_mmcsm22mlr;
+ ushort mios_mmcsm22scrd, mmcsm22scr;
+ char res4[32];
+ ushort mios_mdasm27ar; /* mdasm27 */
+ ushort mios_mdasm27br;
+ ushort mios_mdasm27scrd, mdasm27scr;
+ ushort mios_mdasm28ar; /*mdasm28 */
+ ushort mios_mdasm28br;
+ ushort mios_mdasm28scrd, mdasm28scr;
+ ushort mios_mdasm29ar; /* mdasm29 */
+ ushort mios_mdasm29br;
+ ushort mios_mdasm29scrd, mdasm29scr;
+ ushort mios_mdasm30ar; /* mdasm30 */
+ ushort mios_mdasm30br;
+ ushort mios_mdasm30scrd, mdasm30scr;
+ ushort mios_mdasm31ar; /* mdasm31 */
+ ushort mios_mdasm31br;
+ ushort mios_mdasm31scrd, mdasm31scr;
+ ushort mios_mpiosm32dr;
+ ushort mios_mpiosm32ddr;
+ char res5[1788];
+ ushort mios_mios1tpcr;
+ char mios_res13[2];
+ ushort mios_mios1vnr;
+ ushort mios_mios1mcr;
+ char res6[12];
+ ushort mios_res42z;
+ ushort mios_mcpsmscr;
+ char res7[1000];
+ ushort mios_mios1sr0;
+ char res12[2];
+ ushort mios_mios1er0;
+ ushort mios_mios1rpr0;
+ char res8[40];
+ ushort mios_mios1lvl0;
+ char res9[14];
+ ushort mios_mios1sr1;
+ char res10[2];
+ ushort mios_mios1er1;
+ ushort mios_mios1rpr1;
+ char res11[40];
+ ushort mios_mios1lvl1;
+ char res13[1038];
+} mios5xx_t;
+
+/* Toucan Module
+*/
+typedef struct tcan {
+ ushort tcan_tcnmcr;
+ ushort tcan_cantcr;
+ ushort tcan_canicr;
+ u_char tcan_canctrl0;
+ u_char tcan_canctrl1;
+ u_char tcan_presdiv;
+ u_char tcan_canctrl2;
+ ushort tcan_timer;
+ char res1[4];
+ ushort tcan_rxgmskhi;
+ ushort tcan_rxgmsklo;
+ ushort tcan_rx14mskhi;
+ ushort tcan_rx14msklo;
+ ushort tcan_rx15mskhi;
+ ushort tcan_rx15msklo;
+ char res2[4];
+ ushort tcan_estat;
+ ushort tcan_imask;
+ ushort tcan_iflag;
+ u_char tcan_rxectr;
+ u_char tcan_txectr;
+ char res3[88];
+ struct {
+ ushort scr;
+ ushort id_high;
+ ushort id_low;
+ u_char data[8];
+ char res4[2];
+ } tcan_mbuff[16];
+ char res5[640];
+} tcan5xx_t;
+
+/* UIMB
+*/
+typedef struct uimb {
+ uint uimb_umcr;
+ char res1[12];
+ uint uimb_utstcreg;
+ char res2[12];
+ uint uimb_uipend;
+} uimb5xx_t;
+
+
+/* Internal Memory Map MPC555
+*/
+typedef struct immap {
+ char res1[262144]; /* CMF Flash A 256 Kbytes */
+ char res2[196608]; /* CMF Flash B 192 Kbytes */
+ char res3[2670592]; /* Reserved for Flash */
+ sysconf5xx_t im_siu_conf; /* SIU Configuration */
+ memctl5xx_t im_memctl; /* Memory Controller */
+ sit5xx_t im_sit; /* System Integration Timers */
+ car5xx_t im_clkrst; /* Clocks and Reset */
+ sitk5xx_t im_sitk; /* System Integration Timer Keys*/
+ cark8xx_t im_clkrstk; /* Clocks and Resert Keys */
+ fl5xx_t im_fla; /* Flash Module A */
+ fl5xx_t im_flb; /* Flash Module B */
+ char res4[14208]; /* Reserved for SIU */
+ dprc5xx_t im_dprc; /* Dpram Control Register */
+ char res5[8180]; /* Reserved */
+ char dptram[6144]; /* Dptram */
+ char res6[2048]; /* Reserved */
+ tpu5xx_t im_tpua; /* Time Proessing Unit A */
+ tpu5xx_t im_tpub; /* Time Processing Unit B */
+ qadc5xx_t im_qadca; /* QADC A */
+ qadc5xx_t im_qadcb; /* QADC B */
+ qsmcm5xx_t im_qsmcm; /* SCI and SPI */
+ mios5xx_t im_mios; /* MIOS */
+ tcan5xx_t im_tcana; /* Toucan A */
+ tcan5xx_t im_tcanb; /* Toucan B */
+ char res7[1792]; /* Reserved */
+ uimb5xx_t im_uimb; /* UIMB */
+} immap_t;
+
+#endif /* __IMMAP_5XX__ */
diff --git a/arch/powerpc/include/asm/8xx_immap.h b/arch/powerpc/include/asm/8xx_immap.h
new file mode 100644
index 0000000..01129ed
--- /dev/null
+++ b/arch/powerpc/include/asm/8xx_immap.h
@@ -0,0 +1,516 @@
+
+/*
+ * MPC8xx Internal Memory Map
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * The I/O on the MPC860 is comprised of blocks of special registers
+ * and the dual port ram for the Communication Processor Module.
+ * Within this space are functional units such as the SIU, memory
+ * controller, system timers, and other control functions. It is
+ * a combination that I found difficult to separate into logical
+ * functional files.....but anyone else is welcome to try. -- Dan
+ */
+#ifndef __IMMAP_8XX__
+#define __IMMAP_8XX__
+
+/* System configuration registers.
+*/
+typedef struct sys_conf {
+ uint sc_siumcr;
+ uint sc_sypcr;
+ uint sc_swt;
+ char res1[2];
+ ushort sc_swsr;
+ uint sc_sipend;
+ uint sc_simask;
+ uint sc_siel;
+ uint sc_sivec;
+ uint sc_tesr;
+ char res2[0xc];
+ uint sc_sdcr;
+ char res3[0x4c];
+} sysconf8xx_t;
+
+/* PCMCIA configuration registers.
+*/
+typedef struct pcmcia_conf {
+ uint pcmc_pbr0;
+ uint pcmc_por0;
+ uint pcmc_pbr1;
+ uint pcmc_por1;
+ uint pcmc_pbr2;
+ uint pcmc_por2;
+ uint pcmc_pbr3;
+ uint pcmc_por3;
+ uint pcmc_pbr4;
+ uint pcmc_por4;
+ uint pcmc_pbr5;
+ uint pcmc_por5;
+ uint pcmc_pbr6;
+ uint pcmc_por6;
+ uint pcmc_pbr7;
+ uint pcmc_por7;
+ char res1[0x20];
+ uint pcmc_pgcra;
+ uint pcmc_pgcrb;
+ uint pcmc_pscr;
+ char res2[4];
+ uint pcmc_pipr;
+ char res3[4];
+ uint pcmc_per;
+ char res4[4];
+} pcmconf8xx_t;
+
+/* Memory controller registers.
+*/
+typedef struct mem_ctlr {
+ uint memc_br0;
+ uint memc_or0;
+ uint memc_br1;
+ uint memc_or1;
+ uint memc_br2;
+ uint memc_or2;
+ uint memc_br3;
+ uint memc_or3;
+ uint memc_br4;
+ uint memc_or4;
+ uint memc_br5;
+ uint memc_or5;
+ uint memc_br6;
+ uint memc_or6;
+ uint memc_br7;
+ uint memc_or7;
+ char res1[0x24];
+ uint memc_mar;
+ uint memc_mcr;
+ char res2[4];
+ uint memc_mamr;
+ uint memc_mbmr;
+ ushort memc_mstat;
+ ushort memc_mptpr;
+ uint memc_mdr;
+ char res3[0x80];
+} memctl8xx_t;
+
+/* System Integration Timers.
+*/
+typedef struct sys_int_timers {
+ ushort sit_tbscr;
+ char res0[0x02];
+ uint sit_tbreff0;
+ uint sit_tbreff1;
+ char res1[0x14];
+ ushort sit_rtcsc;
+ char res2[0x02];
+ uint sit_rtc;
+ uint sit_rtsec;
+ uint sit_rtcal;
+ char res3[0x10];
+ ushort sit_piscr;
+ char res4[2];
+ uint sit_pitc;
+ uint sit_pitr;
+ char res5[0x34];
+} sit8xx_t;
+
+#define TBSCR_TBIRQ_MASK ((ushort)0xff00)
+#define TBSCR_REFA ((ushort)0x0080)
+#define TBSCR_REFB ((ushort)0x0040)
+#define TBSCR_REFAE ((ushort)0x0008)
+#define TBSCR_REFBE ((ushort)0x0004)
+#define TBSCR_TBF ((ushort)0x0002)
+#define TBSCR_TBE ((ushort)0x0001)
+
+#define RTCSC_RTCIRQ_MASK ((ushort)0xff00)
+#define RTCSC_SEC ((ushort)0x0080)
+#define RTCSC_ALR ((ushort)0x0040)
+#define RTCSC_38K ((ushort)0x0010)
+#define RTCSC_SIE ((ushort)0x0008)
+#define RTCSC_ALE ((ushort)0x0004)
+#define RTCSC_RTF ((ushort)0x0002)
+#define RTCSC_RTE ((ushort)0x0001)
+
+#define PISCR_PIRQ_MASK ((ushort)0xff00)
+#define PISCR_PS ((ushort)0x0080)
+#define PISCR_PIE ((ushort)0x0004)
+#define PISCR_PTF ((ushort)0x0002)
+#define PISCR_PTE ((ushort)0x0001)
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+ uint car_sccr;
+ uint car_plprcr;
+ uint car_rsr;
+ char res[0x74]; /* Reserved area */
+} car8xx_t;
+
+/* System Integration Timers keys.
+*/
+typedef struct sitk {
+ uint sitk_tbscrk;
+ uint sitk_tbreff0k;
+ uint sitk_tbreff1k;
+ uint sitk_tbk;
+ char res1[0x10];
+ uint sitk_rtcsck;
+ uint sitk_rtck;
+ uint sitk_rtseck;
+ uint sitk_rtcalk;
+ char res2[0x10];
+ uint sitk_piscrk;
+ uint sitk_pitck;
+ char res3[0x38];
+} sitk8xx_t;
+
+/* Clocks and reset keys.
+*/
+typedef struct cark {
+ uint cark_sccrk;
+ uint cark_plprcrk;
+ uint cark_rsrk;
+ char res[0x474];
+} cark8xx_t;
+
+/* The key to unlock registers maintained by keep-alive power.
+*/
+#define KAPWR_KEY ((unsigned int)0x55ccaa33)
+
+/* Video interface. MPC823 Only.
+*/
+typedef struct vid823 {
+ ushort vid_vccr;
+ ushort res1;
+ u_char vid_vsr;
+ u_char res2;
+ u_char vid_vcmr;
+ u_char res3;
+ uint vid_vbcb;
+ uint res4;
+ uint vid_vfcr0;
+ uint vid_vfaa0;
+ uint vid_vfba0;
+ uint vid_vfcr1;
+ uint vid_vfaa1;
+ uint vid_vfba1;
+ u_char res5[0x18];
+} vid823_t;
+
+/* LCD interface. 823 Only.
+*/
+typedef struct lcd {
+ uint lcd_lccr;
+ uint lcd_lchcr;
+ uint lcd_lcvcr;
+ char res1[4];
+ uint lcd_lcfaa;
+ uint lcd_lcfba;
+ char lcd_lcsr;
+ char res2[0x7];
+} lcd823_t;
+
+/* I2C
+*/
+typedef struct i2c {
+ u_char i2c_i2mod;
+ char res1[3];
+ u_char i2c_i2add;
+ char res2[3];
+ u_char i2c_i2brg;
+ char res3[3];
+ u_char i2c_i2com;
+ char res4[3];
+ u_char i2c_i2cer;
+ char res5[3];
+ u_char i2c_i2cmr;
+ char res6[0x8b];
+} i2c8xx_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+ char res1[4];
+ uint sdma_sdar;
+ u_char sdma_sdsr;
+ char res3[3];
+ u_char sdma_sdmr;
+ char res4[3];
+ u_char sdma_idsr1;
+ char res5[3];
+ u_char sdma_idmr1;
+ char res6[3];
+ u_char sdma_idsr2;
+ char res7[3];
+ u_char sdma_idmr2;
+ char res8[0x13];
+} sdma8xx_t;
+
+/* Communication Processor Module Interrupt Controller.
+*/
+typedef struct cpm_ic {
+ ushort cpic_civr;
+ char res[0xe];
+ uint cpic_cicr;
+ uint cpic_cipr;
+ uint cpic_cimr;
+ uint cpic_cisr;
+} cpic8xx_t;
+
+/* Input/Output Port control/status registers.
+*/
+typedef struct io_port {
+ ushort iop_padir;
+ ushort iop_papar;
+ ushort iop_paodr;
+ ushort iop_padat;
+ char res1[8];
+ ushort iop_pcdir;
+ ushort iop_pcpar;
+ ushort iop_pcso;
+ ushort iop_pcdat;
+ ushort iop_pcint;
+ char res2[6];
+ ushort iop_pddir;
+ ushort iop_pdpar;
+ char res3[2];
+ ushort iop_pddat;
+ uint utmode;
+ char res4[4];
+} iop8xx_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+ ushort cpmt_tgcr;
+ char res1[0xe];
+ ushort cpmt_tmr1;
+ ushort cpmt_tmr2;
+ ushort cpmt_trr1;
+ ushort cpmt_trr2;
+ ushort cpmt_tcr1;
+ ushort cpmt_tcr2;
+ ushort cpmt_tcn1;
+ ushort cpmt_tcn2;
+ ushort cpmt_tmr3;
+ ushort cpmt_tmr4;
+ ushort cpmt_trr3;
+ ushort cpmt_trr4;
+ ushort cpmt_tcr3;
+ ushort cpmt_tcr4;
+ ushort cpmt_tcn3;
+ ushort cpmt_tcn4;
+ ushort cpmt_ter1;
+ ushort cpmt_ter2;
+ ushort cpmt_ter3;
+ ushort cpmt_ter4;
+ char res2[8];
+} cpmtimer8xx_t;
+
+/* Finally, the Communication Processor stuff.....
+*/
+typedef struct scc { /* Serial communication channels */
+ uint scc_gsmrl;
+ uint scc_gsmrh;
+ ushort scc_psmr;
+ char res1[2];
+ ushort scc_todr;
+ ushort scc_dsr;
+ ushort scc_scce;
+ char res2[2];
+ ushort scc_sccm;
+ char res3;
+ u_char scc_sccs;
+ char res4[8];
+} scc_t;
+
+typedef struct smc { /* Serial management channels */
+ char res1[2];
+ ushort smc_smcmr;
+ char res2[2];
+ u_char smc_smce;
+ char res3[3];
+ u_char smc_smcm;
+ char res4[5];
+} smc_t;
+
+/* MPC860T Fast Ethernet Controller. It isn't part of the CPM, but
+ * it fits within the address space.
+ */
+
+typedef struct fec {
+ uint fec_addr_low; /* lower 32 bits of station address */
+ ushort fec_addr_high; /* upper 16 bits of station address */
+ ushort res1; /* reserved */
+ uint fec_hash_table_high; /* upper 32-bits of hash table */
+ uint fec_hash_table_low; /* lower 32-bits of hash table */
+ uint fec_r_des_start; /* beginning of Rx descriptor ring */
+ uint fec_x_des_start; /* beginning of Tx descriptor ring */
+ uint fec_r_buff_size; /* Rx buffer size */
+ uint res2[9]; /* reserved */
+ uint fec_ecntrl; /* ethernet control register */
+ uint fec_ievent; /* interrupt event register */
+ uint fec_imask; /* interrupt mask register */
+ uint fec_ivec; /* interrupt level and vector status */
+ uint fec_r_des_active; /* Rx ring updated flag */
+ uint fec_x_des_active; /* Tx ring updated flag */
+ uint res3[10]; /* reserved */
+ uint fec_mii_data; /* MII data register */
+ uint fec_mii_speed; /* MII speed control register */
+ uint res4[17]; /* reserved */
+ uint fec_r_bound; /* end of RAM (read-only) */
+ uint fec_r_fstart; /* Rx FIFO start address */
+ uint res5[6]; /* reserved */
+ uint fec_x_fstart; /* Tx FIFO start address */
+ uint res6[17]; /* reserved */
+ uint fec_fun_code; /* fec SDMA function code */
+ uint res7[3]; /* reserved */
+ uint fec_r_cntrl; /* Rx control register */
+ uint fec_r_hash; /* Rx hash register */
+ uint res8[14]; /* reserved */
+ uint fec_x_cntrl; /* Tx control register */
+ uint res9[0x1e]; /* reserved */
+} fec_t;
+
+/* The FEC and LCD color map share the same address space....
+ * I guess we will never see an 823T :-).
+ */
+union fec_lcd {
+ fec_t fl_un_fec;
+ u_char fl_un_cmap[0x200];
+};
+
+typedef struct comm_proc {
+ /* General control and status registers.
+ */
+ ushort cp_cpcr;
+ u_char res1[2];
+ ushort cp_rccr;
+ u_char res2;
+ u_char cp_rmds;
+ u_char res3[4];
+ ushort cp_cpmcr1;
+ ushort cp_cpmcr2;
+ ushort cp_cpmcr3;
+ ushort cp_cpmcr4;
+ u_char res4[2];
+ ushort cp_rter;
+ u_char res5[2];
+ ushort cp_rtmr;
+ u_char res6[0x14];
+
+ /* Baud rate generators.
+ */
+ uint cp_brgc1;
+ uint cp_brgc2;
+ uint cp_brgc3;
+ uint cp_brgc4;
+
+ /* Serial Communication Channels.
+ */
+ scc_t cp_scc[4];
+
+ /* Serial Management Channels.
+ */
+ smc_t cp_smc[2];
+
+ /* Serial Peripheral Interface.
+ */
+ ushort cp_spmode;
+ u_char res7[4];
+ u_char cp_spie;
+ u_char res8[3];
+ u_char cp_spim;
+ u_char res9[2];
+ u_char cp_spcom;
+ u_char res10[2];
+
+ /* Parallel Interface Port.
+ */
+ u_char res11[2];
+ ushort cp_pipc;
+ u_char res12[2];
+ ushort cp_ptpr;
+ uint cp_pbdir;
+ uint cp_pbpar;
+ u_char res13[2];
+ ushort cp_pbodr;
+ uint cp_pbdat;
+
+ /* Port E - MPC87x/88x only.
+ */
+ uint cp_pedir;
+ uint cp_pepar;
+ uint cp_peso;
+ uint cp_peodr;
+ uint cp_pedat;
+
+ /* Communications Processor Timing Register -
+ Contains RMII Timing for the FECs on MPC87x/88x only.
+ */
+ uint cp_cptr;
+
+ /* Serial Interface and Time Slot Assignment.
+ */
+ uint cp_simode;
+ u_char cp_sigmr;
+ u_char res15;
+ u_char cp_sistr;
+ u_char cp_sicmr;
+ u_char res16[4];
+ uint cp_sicr;
+ uint cp_sirp;
+ u_char res17[0xc];
+
+ /* 256 bytes of MPC823 video controller RAM array.
+ */
+ u_char cp_vcram[0x100];
+ u_char cp_siram[0x200];
+
+ /* The fast ethernet controller is not really part of the CPM,
+ * but it resides in the address space.
+ * The LCD color map is also here.
+ */
+ union fec_lcd fl_un;
+#define cp_fec fl_un.fl_un_fec
+#define lcd_cmap fl_un.fl_un_cmap
+ char res18[0xE00];
+
+ /* The MPC885 family has a second FEC here */
+ fec_t cp_fec2;
+#define cp_fec1 cp_fec /* consistency macro */
+
+ /* Dual Ported RAM follows.
+ * There are many different formats for this memory area
+ * depending upon the devices used and options chosen.
+ * Some processors don't have all of it populated.
+ */
+ u_char cp_dpmem[0x1C00]; /* BD / Data / ucode */
+
+ /* Parameter RAM */
+ union {
+ u_char cp_dparam[0x400];
+ u16 cp_dparam16[0x200];
+ };
+} cpm8xx_t;
+
+/* Internal memory map.
+*/
+typedef struct immap {
+ sysconf8xx_t im_siu_conf; /* SIU Configuration */
+ pcmconf8xx_t im_pcmcia; /* PCMCIA Configuration */
+ memctl8xx_t im_memctl; /* Memory Controller */
+ sit8xx_t im_sit; /* System integration timers */
+ car8xx_t im_clkrst; /* Clocks and reset */
+ sitk8xx_t im_sitk; /* Sys int timer keys */
+ cark8xx_t im_clkrstk; /* Clocks and reset keys */
+ vid823_t im_vid; /* Video (823 only) */
+ lcd823_t im_lcd; /* LCD (823 only) */
+ i2c8xx_t im_i2c; /* I2C control/status */
+ sdma8xx_t im_sdma; /* SDMA control/status */
+ cpic8xx_t im_cpic; /* CPM Interrupt Controller */
+ iop8xx_t im_ioport; /* IO Port control/status */
+ cpmtimer8xx_t im_cpmtimer; /* CPM timers */
+ cpm8xx_t im_cpm; /* Communication processor */
+} immap_t;
+
+#endif /* __IMMAP_8XX__ */
diff --git a/arch/powerpc/include/asm/apm821xx.h b/arch/powerpc/include/asm/apm821xx.h
new file mode 100644
index 0000000..8841bc9
--- /dev/null
+++ b/arch/powerpc/include/asm/apm821xx.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, Applied Micro Circuits Corporation
+ * Author: Tirumala R Marri <tmarri@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _APM821XX_H_
+#define _APM821XX_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
+
+/* Memory mapped registers */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xEF600000
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0200)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+#define SDR0_SRST0_DMC 0x00200000
+#define SDR0_SRST1_AHB 0x00000040 /* PLB4XAHB bridge */
+
+/* AHB config. */
+#define AHB_TOP 0xA4
+#define AHB_BOT 0xA5
+
+/* clk divisors */
+#define PLLSYS0_FWD_DIV_A_MASK 0x000000f0 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x0000000f /* Fwd Div B */
+#define PLLSYS0_FB_DIV_MASK 0x0000ff00 /* Feedback divisor */
+#define PLLSYS0_OPB_DIV_MASK 0x0c000000 /* OPB Divisor */
+#define PLLSYS0_EPB_DIV_MASK 0x00000300 /* EPB divisor */
+#define PLLSYS0_EXTSL_MASK 0x00000080 /* PerClk feedback path */
+#define PLLSYS0_PLBEDV0_DIV_MASK 0xe0000000/* PLB Early Clk Div*/
+#define PLLSYS0_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS0_SEL_MASK 0x18000000 /* 0 = PLL, 1 = PerClk */
+
+/*
+ + * Clocking Controller
+ + */
+#define CPR0_CLKUPD 0x0020
+#define CPR0_PLLC 0x0040
+#define CPR0_PLLC_SEL(pllc) (((pllc) & 0x01000000) >> 24)
+#define CPR0_PLLD 0x0060
+#define CPR0_PLLD_FDV(plld) (((plld) & 0xff000000) >> 24)
+#define CPR0_PLLD_FWDVA(plld) (((plld) & 0x000f0000) >> 16)
+#define CPR0_CPUD 0x0080
+#define CPR0_CPUD_CPUDV(cpud) (((cpud) & 0x07000000) >> 24)
+#define CPR0_PLB2D 0x00a0
+#define CPR0_PLB2D_PLB2DV(plb2d) (((plb2d) & 0x06000000) >> 25)
+#define CPR0_OPBD 0x00c0
+#define CPR0_OPBD_OPBDV(opbd) (((opbd) & 0x03000000) >> 24)
+#define CPR0_PERD 0x00e0
+#define CPR0_PERD_PERDV(perd) (((perd) & 0x03000000) >> 24)
+#define CPR0_DDR2D 0x0100
+#define CPR0_DDR2D_DDR2DV(ddr2d) (((ddr2d) & 0x06000000) >> 25)
+#define CLK_ICFG 0x0140
+
+#endif /* _APM821XX_H_ */
diff --git a/arch/powerpc/include/asm/arch-mpc83xx/gpio.h b/arch/powerpc/include/asm/arch-mpc83xx/gpio.h
new file mode 100644
index 0000000..036f51e
--- /dev/null
+++ b/arch/powerpc/include/asm/arch-mpc83xx/gpio.h
@@ -0,0 +1,38 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _MPC83XX_GPIO_H_
+#define _MPC83XX_GPIO_H_
+
+/*
+ * The MCP83xx's 1-2 GPIO controllers each with 32 bits.
+ */
+#if defined(CONFIG_MPC8313) || defined(CONFIG_MPC8308) || \
+ defined(CONFIG_MPC8315)
+#define MPC83XX_GPIO_CTRLRS 1
+#elif defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+#define MPC83XX_GPIO_CTRLRS 2
+#else
+#define MPC83XX_GPIO_CTRLRS 0
+#endif
+
+#define MAX_NUM_GPIOS (32 * MPC83XX_GPIO_CTRLRS)
+
+void mpc83xx_gpio_init_f(void);
+void mpc83xx_gpio_init_r(void);
+
+#endif /* MPC83XX_GPIO_H_ */
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
new file mode 100644
index 0000000..23f22df
--- /dev/null
+++ b/arch/powerpc/include/asm/atomic.h
@@ -0,0 +1,95 @@
+/*
+ * PowerPC atomic operations
+ */
+
+#ifndef _ASM_PPC_ATOMIC_H_
+#define _ASM_PPC_ATOMIC_H_
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+typedef struct { volatile int counter; } atomic_t;
+#else
+typedef struct { int counter; } atomic_t;
+#endif
+
+#define ATOMIC_INIT(i) { (i) }
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
+extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
+
+extern __inline__ int atomic_add_return(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%3\n\
+ add %0,%2,%0\n\
+ stwcx. %0,0,%3\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (a), "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+extern __inline__ int atomic_sub_return(int a, atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%3\n\
+ subf %0,%2,%0\n\
+ stwcx. %0,0,%3\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (a), "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+extern __inline__ int atomic_inc_return(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%2\n\
+ addic %0,%0,1\n\
+ stwcx. %0,0,%2\n\
+ bne- 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+extern __inline__ int atomic_dec_return(atomic_t *v)
+{
+ int t;
+
+ __asm__ __volatile__("\n\
+1: lwarx %0,0,%2\n\
+ addic %0,%0,-1\n\
+ stwcx. %0,0,%2\n\
+ bne 1b"
+ : "=&r" (t), "=m" (*v)
+ : "r" (v), "m" (*v)
+ : "cc");
+
+ return t;
+}
+
+#define atomic_add(a, v) ((void) atomic_add_return((a), (v)))
+#define atomic_sub(a, v) ((void) atomic_sub_return((a), (v)))
+#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
+#define atomic_inc(v) ((void) atomic_inc_return((v)))
+#define atomic_dec(v) ((void) atomic_dec_return((v)))
+#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)
+
+#endif /* _ASM_PPC_ATOMIC_H_ */
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
new file mode 100644
index 0000000..adaf091
--- /dev/null
+++ b/arch/powerpc/include/asm/bitops.h
@@ -0,0 +1,387 @@
+/*
+ * bitops.h: Bit string operations on the ppc
+ */
+
+#ifndef _PPC_BITOPS_H
+#define _PPC_BITOPS_H
+
+#include <linux/config.h>
+#include <asm/byteorder.h>
+
+extern void set_bit(int nr, volatile void *addr);
+extern void clear_bit(int nr, volatile void *addr);
+extern void change_bit(int nr, volatile void *addr);
+extern int test_and_set_bit(int nr, volatile void *addr);
+extern int test_and_clear_bit(int nr, volatile void *addr);
+extern int test_and_change_bit(int nr, volatile void *addr);
+
+/*
+ * Arguably these bit operations don't imply any memory barrier or
+ * SMP ordering, but in fact a lot of drivers expect them to imply
+ * both, since they do on x86 cpus.
+ */
+#ifdef CONFIG_SMP
+#define SMP_WMB "eieio\n"
+#define SMP_MB "\nsync"
+#else
+#define SMP_WMB
+#define SMP_MB
+#endif /* CONFIG_SMP */
+
+#define __INLINE_BITOPS 1
+
+#if __INLINE_BITOPS
+/*
+ * These used to be if'd out here because using : "cc" as a constraint
+ * resulted in errors from egcs. Things may be OK with gcc-2.95.
+ */
+extern __inline__ void set_bit(int nr, volatile void * addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%3\n\
+ or %0,%0,%2\n\
+ stwcx. %0,0,%3\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc" );
+}
+
+extern __inline__ void clear_bit(int nr, volatile void *addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%3\n\
+ andc %0,%0,%2\n\
+ stwcx. %0,0,%3\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+extern __inline__ void change_bit(int nr, volatile void *addr)
+{
+ unsigned long old;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%3\n\
+ xor %0,%0,%2\n\
+ stwcx. %0,0,%3\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+}
+
+extern __inline__ int test_and_set_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4\n\
+ or %1,%0,%3\n\
+ stwcx. %1,0,%4\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+extern __inline__ int test_and_clear_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4\n\
+ andc %1,%0,%3\n\
+ stwcx. %1,0,%4\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+
+extern __inline__ int test_and_change_bit(int nr, volatile void *addr)
+{
+ unsigned int old, t;
+ unsigned int mask = 1 << (nr & 0x1f);
+ volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
+
+ __asm__ __volatile__(SMP_WMB "\
+1: lwarx %0,0,%4\n\
+ xor %1,%0,%3\n\
+ stwcx. %1,0,%4\n\
+ bne 1b"
+ SMP_MB
+ : "=&r" (old), "=&r" (t), "=m" (*p)
+ : "r" (mask), "r" (p), "m" (*p)
+ : "cc");
+
+ return (old & mask) != 0;
+}
+#endif /* __INLINE_BITOPS */
+
+extern __inline__ int test_bit(int nr, __const__ volatile void *addr)
+{
+ __const__ unsigned int *p = (__const__ unsigned int *) addr;
+
+ return ((p[nr >> 5] >> (nr & 0x1f)) & 1) != 0;
+}
+
+/* Return the bit position of the most significant 1 bit in a word */
+/* - the result is undefined when x == 0 */
+extern __inline__ int __ilog2(unsigned int x)
+{
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+ return 31 - lz;
+}
+
+extern __inline__ int ffz(unsigned int x)
+{
+ if ((x = ~x) == 0)
+ return 32;
+ return __ilog2(x & -x);
+}
+
+/*
+ * fls: find last (most-significant) bit set.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ *
+ * On powerpc, __ilog2(0) returns -1, but this is not safe in general
+ */
+static __inline__ int fls(unsigned int x)
+{
+ return __ilog2(x) + 1;
+}
+#define PLATFORM_FLS
+
+/**
+ * fls64 - find last set bit in a 64-bit word
+ * @x: the word to search
+ *
+ * This is defined in a similar way as the libc and compiler builtin
+ * ffsll, but returns the position of the most significant set bit.
+ *
+ * fls64(value) returns 0 if value is 0 or the position of the last
+ * set bit if value is nonzero. The last (most significant) bit is
+ * at position 64.
+ */
+#if BITS_PER_LONG == 32
+static inline int fls64(__u64 x)
+{
+ __u32 h = x >> 32;
+ if (h)
+ return fls(h) + 32;
+ return fls(x);
+}
+#elif BITS_PER_LONG == 64
+static inline int fls64(__u64 x)
+{
+ if (x == 0)
+ return 0;
+ return __ilog2(x) + 1;
+}
+#else
+#error BITS_PER_LONG not 32 or 64
+#endif
+
+static inline int __ilog2_u64(u64 n)
+{
+ return fls64(n) - 1;
+}
+
+static inline int ffs64(u64 x)
+{
+ return __ilog2_u64(x & -x) + 1ull;
+}
+
+#ifdef __KERNEL__
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+extern __inline__ int ffs(int x)
+{
+ return __ilog2(x & -x) + 1;
+}
+#define PLATFORM_FFS
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+/*
+ * This implementation of find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h.
+ */
+#define find_first_zero_bit(addr, size) \
+ find_next_zero_bit((addr), (size), 0)
+
+extern __inline__ unsigned long find_next_zero_bit(void * addr,
+ unsigned long size, unsigned long offset)
+{
+ unsigned int * p = ((unsigned int *) addr) + (offset >> 5);
+ unsigned int result = offset & ~31UL;
+ unsigned int tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 31UL;
+ if (offset) {
+ tmp = *p++;
+ tmp |= ~0UL >> (32-offset);
+ if (size < 32)
+ goto found_first;
+ if (tmp != ~0U)
+ goto found_middle;
+ size -= 32;
+ result += 32;
+ }
+ while (size >= 32) {
+ if ((tmp = *p++) != ~0U)
+ goto found_middle;
+ result += 32;
+ size -= 32;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+found_first:
+ tmp |= ~0UL << size;
+found_middle:
+ return result + ffz(tmp);
+}
+
+
+#define _EXT2_HAVE_ASM_BITOPS_
+
+#ifdef __KERNEL__
+/*
+ * test_and_{set,clear}_bit guarantee atomicity without
+ * disabling interrupts.
+ */
+#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr)
+#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr)
+
+#else
+extern __inline__ int ext2_set_bit(int nr, void * addr)
+{
+ int mask;
+ unsigned char *ADDR = (unsigned char *) addr;
+ int oldbit;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ oldbit = (*ADDR & mask) ? 1 : 0;
+ *ADDR |= mask;
+ return oldbit;
+}
+
+extern __inline__ int ext2_clear_bit(int nr, void * addr)
+{
+ int mask;
+ unsigned char *ADDR = (unsigned char *) addr;
+ int oldbit;
+
+ ADDR += nr >> 3;
+ mask = 1 << (nr & 0x07);
+ oldbit = (*ADDR & mask) ? 1 : 0;
+ *ADDR = *ADDR & ~mask;
+ return oldbit;
+}
+#endif /* __KERNEL__ */
+
+extern __inline__ int ext2_test_bit(int nr, __const__ void * addr)
+{
+ __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
+
+ return (ADDR[nr >> 3] >> (nr & 7)) & 1;
+}
+
+/*
+ * This implementation of ext2_find_{first,next}_zero_bit was stolen from
+ * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
+ */
+
+#define ext2_find_first_zero_bit(addr, size) \
+ ext2_find_next_zero_bit((addr), (size), 0)
+
+static __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
+ unsigned long size, unsigned long offset)
+{
+ unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+ unsigned int result = offset & ~31UL;
+ unsigned int tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 31UL;
+ if (offset) {
+ tmp = cpu_to_le32p(p++);
+ tmp |= ~0UL >> (32-offset);
+ if (size < 32)
+ goto found_first;
+ if (tmp != ~0U)
+ goto found_middle;
+ size -= 32;
+ result += 32;
+ }
+ while (size >= 32) {
+ if ((tmp = cpu_to_le32p(p++)) != ~0U)
+ goto found_middle;
+ result += 32;
+ size -= 32;
+ }
+ if (!size)
+ return result;
+ tmp = cpu_to_le32p(p);
+found_first:
+ tmp |= ~0U << size;
+found_middle:
+ return result + ffz(tmp);
+}
+
+/* Bitmap functions for the minix filesystem. */
+#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
+#define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
+#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
+
+#endif /* _PPC_BITOPS_H */
diff --git a/arch/powerpc/include/asm/byteorder.h b/arch/powerpc/include/asm/byteorder.h
new file mode 100644
index 0000000..3f5bcf6
--- /dev/null
+++ b/arch/powerpc/include/asm/byteorder.h
@@ -0,0 +1,84 @@
+#ifndef _PPC_BYTEORDER_H
+#define _PPC_BYTEORDER_H
+
+#include <asm/types.h>
+
+#ifdef __GNUC__
+
+extern __inline__ unsigned ld_le16(const volatile unsigned short *addr)
+{
+ unsigned val;
+
+ __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+
+extern __inline__ void st_le16(volatile unsigned short *addr, const unsigned val)
+{
+ __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+extern __inline__ unsigned ld_le32(const volatile unsigned *addr)
+{
+ unsigned val;
+
+ __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+
+extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val)
+{
+ __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+/* alas, egcs sounds like it has a bug in this code that doesn't use the
+ inline asm correctly, and can cause file corruption. Until I hear that
+ it's fixed, I can live without the extra speed. I hope. */
+#if !(__GNUC__ >= 2 && __GNUC_MINOR__ >= 90)
+#if 0
+# define __arch_swab16(x) ld_le16(&x)
+# define __arch_swab32(x) ld_le32(&x)
+#else
+static __inline__ __attribute__((const)) __u16 ___arch__swab16(__u16 value)
+{
+ __u16 result;
+
+ __asm__("rlwimi %0,%1,8,16,23"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 8));
+ return result;
+}
+
+static __inline__ __attribute__((const)) __u32 ___arch__swab32(__u32 value)
+{
+ __u32 result;
+
+ __asm__("rlwimi %0,%1,24,16,23\n\t"
+ "rlwimi %0,%1,8,8,15\n\t"
+ "rlwimi %0,%1,24,0,7"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 24));
+ return result;
+}
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+#endif /* 0 */
+
+#endif
+
+/* The same, but returns converted value from the location pointer by addr. */
+#define __arch__swab16p(addr) ld_le16(addr)
+#define __arch__swab32p(addr) ld_le32(addr)
+
+/* The same, but do the conversion in situ, ie. put the value back to addr. */
+#define __arch__swab16s(addr) st_le16(addr,*addr)
+#define __arch__swab32s(addr) st_le32(addr,*addr)
+
+#endif /* __GNUC__ */
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define __BYTEORDER_HAS_U64__
+#endif
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _PPC_BYTEORDER_H */
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h
new file mode 100644
index 0000000..5f9c640
--- /dev/null
+++ b/arch/powerpc/include/asm/cache.h
@@ -0,0 +1,107 @@
+/*
+ * include/asm-ppc/cache.h
+ */
+#ifndef __ARCH_PPC_CACHE_H
+#define __ARCH_PPC_CACHE_H
+
+#include <linux/config.h>
+#include <asm/processor.h>
+
+/* bytes per L1 cache line */
+#if defined(CONFIG_8xx)
+#define L1_CACHE_SHIFT 4
+#elif defined(CONFIG_PPC64BRIDGE)
+#define L1_CACHE_SHIFT 7
+#elif defined(CONFIG_E500MC)
+#define L1_CACHE_SHIFT 6
+#else
+#define L1_CACHE_SHIFT 5
+#endif
+
+#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+
+/*
+ * Use the L1 data cache line size value for the minimum DMA buffer alignment
+ * on PowerPC.
+ */
+#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
+
+/*
+ * For compatibility reasons support the CONFIG_SYS_CACHELINE_SIZE too
+ */
+#ifndef CONFIG_SYS_CACHELINE_SIZE
+#define CONFIG_SYS_CACHELINE_SIZE L1_CACHE_BYTES
+#endif
+
+#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+#define L1_CACHE_PAGES 8
+
+#define SMP_CACHE_BYTES L1_CACHE_BYTES
+
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned \
+ __attribute__((__aligned__(L1_CACHE_BYTES), \
+ __section__(".data.cacheline_aligned")))
+#endif
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+extern void flush_dcache_range(unsigned long start, unsigned long stop);
+extern void clean_dcache_range(unsigned long start, unsigned long stop);
+extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
+extern void flush_dcache(void);
+extern void invalidate_dcache(void);
+extern void invalidate_icache(void);
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+extern void unlock_ram_in_cache(void);
+#endif /* CONFIG_SYS_INIT_RAM_LOCK */
+#endif /* __ASSEMBLY__ */
+
+/* prep registers for L2 */
+#define CACHECRBA 0x80000823 /* Cache configuration register address */
+#define L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */
+#define L2CACHE_512KB 0x00 /* 512KB */
+#define L2CACHE_256KB 0x01 /* 256KB */
+#define L2CACHE_1MB 0x02 /* 1MB */
+#define L2CACHE_NONE 0x03 /* NONE */
+#define L2CACHE_PARITY 0x08 /* Mask for L2 Cache Parity Protected bit */
+
+#ifdef CONFIG_8xx
+/* Cache control on the MPC8xx is provided through some additional
+ * special purpose registers.
+ */
+#define IC_CST 560 /* Instruction cache control/status */
+#define IC_ADR 561 /* Address needed for some commands */
+#define IC_DAT 562 /* Read-only data register */
+#define DC_CST 568 /* Data cache control/status */
+#define DC_ADR 569 /* Address needed for some commands */
+#define DC_DAT 570 /* Read-only data register */
+
+/* Commands. Only the first few are available to the instruction cache.
+*/
+#define IDC_ENABLE 0x02000000 /* Cache enable */
+#define IDC_DISABLE 0x04000000 /* Cache disable */
+#define IDC_LDLCK 0x06000000 /* Load and lock */
+#define IDC_UNLINE 0x08000000 /* Unlock line */
+#define IDC_UNALL 0x0a000000 /* Unlock all */
+#define IDC_INVALL 0x0c000000 /* Invalidate all */
+
+#define DC_FLINE 0x0e000000 /* Flush data cache line */
+#define DC_SFWT 0x01000000 /* Set forced writethrough mode */
+#define DC_CFWT 0x03000000 /* Clear forced writethrough mode */
+#define DC_SLES 0x05000000 /* Set little endian swap mode */
+#define DC_CLES 0x07000000 /* Clear little endian swap mode */
+
+/* Status.
+*/
+#define IDC_ENABLED 0x80000000 /* Cache is enabled */
+#define IDC_CERR1 0x00200000 /* Cache error 1 */
+#define IDC_CERR2 0x00100000 /* Cache error 2 */
+#define IDC_CERR3 0x00080000 /* Cache error 3 */
+
+#define DC_DFWT 0x40000000 /* Data cache is forced write through */
+#define DC_LES 0x20000000 /* Caches are little endian mode */
+#endif /* CONFIG_8xx */
+
+#endif
diff --git a/arch/powerpc/include/asm/config.h b/arch/powerpc/include/asm/config.h
new file mode 100644
index 0000000..67cea01
--- /dev/null
+++ b/arch/powerpc/include/asm/config.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _ASM_CONFIG_H_
+#define _ASM_CONFIG_H_
+
+#ifdef CONFIG_MPC85xx
+#include <asm/config_mpc85xx.h>
+#endif
+
+#ifdef CONFIG_MPC86xx
+#include <asm/config_mpc86xx.h>
+#endif
+
+#ifndef HWCONFIG_BUFFER_SIZE
+ #define HWCONFIG_BUFFER_SIZE 256
+#endif
+
+/* CONFIG_HARD_SPI triggers SPI bus initialization in PowerPC */
+#if defined(CONFIG_MPC8XXX_SPI) || defined(CONFIG_FSL_ESPI)
+# ifndef CONFIG_HARD_SPI
+# define CONFIG_HARD_SPI
+# endif
+#endif
+
+#define CONFIG_LMB
+#define CONFIG_SYS_BOOT_RAMDISK_HIGH
+#define CONFIG_SYS_BOOT_GET_CMDLINE
+#define CONFIG_SYS_BOOT_GET_KBD
+
+#ifndef CONFIG_MAX_MEM_MAPPED
+#if defined(CONFIG_4xx) || \
+ defined(CONFIG_E500) || \
+ defined(CONFIG_MPC86xx) || \
+ defined(CONFIG_E300)
+#define CONFIG_MAX_MEM_MAPPED ((phys_size_t)2 << 30)
+#else
+#define CONFIG_MAX_MEM_MAPPED (256 << 20)
+#endif
+#endif
+
+/* Check if boards need to enable FSL DMA engine for SDRAM init */
+#if !defined(CONFIG_FSL_DMA) && defined(CONFIG_DDR_ECC)
+#if (defined(CONFIG_MPC83xx) && defined(CONFIG_DDR_ECC_INIT_VIA_DMA)) || \
+ ((defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)) && \
+ !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER))
+#define CONFIG_FSL_DMA
+#endif
+#endif
+
+#ifndef CONFIG_MAX_CPUS
+#define CONFIG_MAX_CPUS 1
+#endif
+
+/*
+ * Provide a default boot page translation virtual address that lines up with
+ * Freescale's default e500 reset page.
+ */
+#if (defined(CONFIG_E500) && defined(CONFIG_MP))
+#ifndef CONFIG_BPTR_VIRT_ADDR
+#define CONFIG_BPTR_VIRT_ADDR 0xfffff000
+#endif
+#endif
+
+/*
+ * SEC (crypto unit) major compatible version determination
+ */
+#if defined(CONFIG_MPC83xx)
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#endif
+
+/* Since so many PPC SOCs have a semi-common LBC, define this here */
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) || \
+ defined(CONFIG_MPC83xx)
+#if !defined(CONFIG_FSL_IFC)
+#define CONFIG_FSL_LBC
+#endif
+#endif
+
+/* The TSEC driver uses the PHYLIB infrastructure */
+#ifndef CONFIG_PHYLIB
+#if defined(CONFIG_TSEC_ENET)
+#define CONFIG_PHYLIB
+
+#include <config_phylib_all_drivers.h>
+#endif /* TSEC_ENET */
+#endif /* !CONFIG_PHYLIB */
+
+/* The FMAN driver uses the PHYLIB infrastructure */
+#if defined(CONFIG_FMAN_ENET)
+#define CONFIG_PHYLIB
+#endif
+
+/* All PPC boards must swap IDE bytes */
+#define CONFIG_IDE_SWAP_IO
+
+#endif /* _ASM_CONFIG_H_ */
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
new file mode 100644
index 0000000..1d46b14
--- /dev/null
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -0,0 +1,643 @@
+/*
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _ASM_MPC85xx_CONFIG_H_
+#define _ASM_MPC85xx_CONFIG_H_
+
+/* SoC specific defines for Freescale MPC85xx (PQ3) and QorIQ processors */
+
+#ifdef CONFIG_SYS_CCSRBAR_DEFAULT
+#error "Do not define CONFIG_SYS_CCSRBAR_DEFAULT in the board header file."
+#endif
+
+/*
+ * This macro should be removed when we no longer care about backwards
+ * compatibility with older operating systems.
+ */
+#define CONFIG_PPC_SPINTABLE_COMPATIBLE
+
+#define FSL_DDR_VER_4_7 47
+
+/* Number of TLB CAM entries we have on FSL Book-E chips */
+#if defined(CONFIG_E500MC)
+#define CONFIG_SYS_NUM_TLBCAMS 64
+#elif defined(CONFIG_E500)
+#define CONFIG_SYS_NUM_TLBCAMS 16
+#endif
+
+#if defined(CONFIG_MPC8536)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 1
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+
+#elif defined(CONFIG_MPC8540)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 8
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+
+#elif defined(CONFIG_MPC8541)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 8
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+
+#elif defined(CONFIG_MPC8544)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 10
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 0
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+
+#elif defined(CONFIG_MPC8548)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 10
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 0
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_NMG_DDR120
+#define CONFIG_SYS_FSL_ERRATUM_NMG_LBC103
+#define CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 1
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_RMU
+#define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM 2
+
+#elif defined(CONFIG_MPC8555)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 8
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+
+#elif defined(CONFIG_MPC8560)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 8
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+
+#elif defined(CONFIG_MPC8568)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 10
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define QE_MURAM_SIZE 0x10000UL
+#define MAX_QE_RISC 2
+#define QE_NUM_OF_SNUM 28
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 1
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_RMU
+#define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM 2
+
+#elif defined(CONFIG_MPC8569)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 10
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define QE_MURAM_SIZE 0x20000UL
+#define MAX_QE_RISC 4
+#define QE_NUM_OF_SNUM 46
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 1
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_RMU
+#define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM 2
+
+#elif defined(CONFIG_MPC8572)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_DDR_115
+#define CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
+
+#elif defined(CONFIG_P1010)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_FSL_SDHC_V2_3
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 3
+#define CONFIG_TSECV2
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_IFC_A002769
+#define CONFIG_SYS_FSL_ERRATUM_P1010_A003549
+#define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
+
+/* P1011 is single core version of P1020 */
+#elif defined(CONFIG_P1011)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_FSL_PCIE_DISABLE_ASPM
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+
+/* P1012 is single core version of P1021 */
+#elif defined(CONFIG_P1012)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_FSL_PCIE_DISABLE_ASPM
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define QE_MURAM_SIZE 0x6000UL
+#define MAX_QE_RISC 1
+#define QE_NUM_OF_SNUM 28
+
+/* P1013 is single core version of P1022 */
+#elif defined(CONFIG_P1013)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_FSL_SATA_ERRATUM_A001
+
+#elif defined(CONFIG_P1014)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_FSL_SDHC_V2_3
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 3
+#define CONFIG_TSECV2
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_IFC_A002769
+#define CONFIG_SYS_FSL_ERRATUM_P1010_A003549
+#define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
+
+/* P1017 is single core version of P1023 */
+#elif defined(CONFIG_P1017)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 1
+#define CONFIG_SYS_NUM_FM1_DTSEC 2
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_QMAN_NUM_PORTALS 3
+#define CONFIG_SYS_BMAN_NUM_PORTALS 3
+#define CONFIG_SYS_FM_MURAM_SIZE 0x10000
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff600000
+
+#elif defined(CONFIG_P1020)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_FSL_PCIE_DISABLE_ASPM
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+
+#elif defined(CONFIG_P1021)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_FSL_PCIE_DISABLE_ASPM
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define QE_MURAM_SIZE 0x6000UL
+#define MAX_QE_RISC 1
+#define QE_NUM_OF_SNUM 28
+
+#elif defined(CONFIG_P1022)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_FSL_SATA_ERRATUM_A001
+
+#elif defined(CONFIG_P1023)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 1
+#define CONFIG_SYS_NUM_FM1_DTSEC 2
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_QMAN_NUM_PORTALS 3
+#define CONFIG_SYS_BMAN_NUM_PORTALS 3
+#define CONFIG_SYS_FM_MURAM_SIZE 0x10000
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff600000
+
+/* P1024 is lower end variant of P1020 */
+#elif defined(CONFIG_P1024)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_FSL_PCIE_DISABLE_ASPM
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+
+/* P1025 is lower end variant of P1021 */
+#elif defined(CONFIG_P1025)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_TSECV2
+#define CONFIG_FSL_PCIE_DISABLE_ASPM
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define QE_MURAM_SIZE 0x6000UL
+#define MAX_QE_RISC 1
+#define QE_NUM_OF_SNUM 28
+
+/* P2010 is single core version of P2020 */
+#elif defined(CONFIG_P2010)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
+
+#elif defined(CONFIG_P2020)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
+#define CONFIG_SYS_FSL_SEC_COMPAT 2
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_RMU
+#define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM 2
+
+#elif defined(CONFIG_PPC_P2041) /* also supports P2040 */
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS1
+#define CONFIG_MAX_CPUS 4
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 32
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 1
+#define CONFIG_SYS_NUM_FM1_DTSEC 5
+#define CONFIG_SYS_NUM_FM1_10GEC 1
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_FM_MURAM_SIZE 0x28000
+#define CONFIG_SYS_FSL_TBCLK_DIV 32
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB2_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+#define CONFIG_SYS_FSL_ERRATUM_USB14
+#define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_ERRATUM_A004510
+#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
+#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 0x11
+#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
+#define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+#define CONFIG_SYS_FSL_ERRATUM_A004849
+
+#elif defined(CONFIG_PPC_P3041)
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS1
+#define CONFIG_MAX_CPUS 4
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 32
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 1
+#define CONFIG_SYS_NUM_FM1_DTSEC 5
+#define CONFIG_SYS_NUM_FM1_10GEC 1
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_FM_MURAM_SIZE 0x28000
+#define CONFIG_SYS_FSL_TBCLK_DIV 32
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB2_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+#define CONFIG_SYS_FSL_ERRATUM_USB14
+#define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_ERRATUM_A004510
+#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
+#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV2 0x11
+#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
+#define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+#define CONFIG_SYS_FSL_ERRATUM_A004849
+
+#elif defined(CONFIG_PPC_P4080) /* also supports P4040 */
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS1
+#define CONFIG_MAX_CPUS 8
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 4
+#define CONFIG_SYS_FSL_NUM_LAWS 32
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 2
+#define CONFIG_SYS_NUM_FM1_DTSEC 4
+#define CONFIG_SYS_NUM_FM2_DTSEC 4
+#define CONFIG_SYS_NUM_FM1_10GEC 1
+#define CONFIG_SYS_NUM_FM2_10GEC 1
+#define CONFIG_NUM_DDR_CONTROLLERS 2
+#define CONFIG_SYS_FM_MURAM_SIZE 0x28000
+#define CONFIG_SYS_FSL_TBCLK_DIV 16
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,p4080-pcie"
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+#define CONFIG_SYS_FSL_ERRATUM_CPC_A002
+#define CONFIG_SYS_FSL_ERRATUM_CPC_A003
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
+#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC135
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC13
+#define CONFIG_SYS_P4080_ERRATUM_CPU22
+#define CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+#define CONFIG_SYS_P4080_ERRATUM_SERDES8
+#define CONFIG_SYS_P4080_ERRATUM_SERDES9
+#define CONFIG_SYS_P4080_ERRATUM_SERDES_A001
+#define CONFIG_SYS_P4080_ERRATUM_SERDES_A005
+#define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_RMU
+#define CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM 2
+#define CONFIG_SYS_FSL_ERRATUM_A004510
+#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x20
+#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xff000000
+#define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+#define CONFIG_SYS_FSL_ERRATUM_A004849
+#define CONFIG_SYS_FSL_ERRATUM_A004580
+#define CONFIG_SYS_P4080_ERRATUM_PCIE_A003
+
+#elif defined(CONFIG_PPC_P5020) /* also supports P5010 */
+#define CONFIG_SYS_PPC64 /* 64-bit core */
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS1
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 32
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 1
+#define CONFIG_SYS_NUM_FM1_DTSEC 5
+#define CONFIG_SYS_NUM_FM1_10GEC 1
+#define CONFIG_NUM_DDR_CONTROLLERS 2
+#define CONFIG_SYS_FM_MURAM_SIZE 0x28000
+#define CONFIG_SYS_FSL_TBCLK_DIV 32
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2"
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB2_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_USB14
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_ERRATUM_A004510
+#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
+#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xc0000000
+#define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
+
+#elif defined(CONFIG_PPC_P5040)
+#define CONFIG_SYS_PPC64
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS1
+#define CONFIG_MAX_CPUS 4
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 3
+#define CONFIG_SYS_FSL_NUM_LAWS 32
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 2
+#define CONFIG_SYS_NUM_FM1_DTSEC 5
+#define CONFIG_SYS_NUM_FM1_10GEC 1
+#define CONFIG_SYS_NUM_FM2_DTSEC 5
+#define CONFIG_SYS_NUM_FM2_10GEC 1
+#define CONFIG_NUM_DDR_CONTROLLERS 2
+#define CONFIG_SYS_FM_MURAM_SIZE 0x28000
+#define CONFIG_SYS_FSL_TBCLK_DIV 16
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.4"
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB2_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_USB14
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
+#define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
+#define CONFIG_SYS_FSL_ERRATUM_A004699
+#define CONFIG_SYS_FSL_ERRATUM_A004510
+#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
+#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
+
+#elif defined(CONFIG_BSC9131)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_FSL_SDHC_V2_3
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_TSECV2
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_FSL_DSP_M2_RAM_ADDR 0xb0000000
+#define CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT 0xff600000
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT 3
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_NAND_FSL_IFC
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+
+#elif defined(CONFIG_BSC9132)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_PPC_E500_DEBUG_TLB 3
+#define CONFIG_FSL_SDHC_V2_3
+#define CONFIG_SYS_FSL_NUM_LAWS 12
+#define CONFIG_TSECV2
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_NUM_DDR_CONTROLLERS 2
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT 3
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
+#define CONFIG_NAND_FSL_IFC
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ESDHC_P1010_BROKEN_SDCLK
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.2"
+
+#elif defined(CONFIG_PPC_T4240) || defined(CONFIG_PPC_T4160)
+#define CONFIG_E6500
+#define CONFIG_SYS_PPC64 /* 64-bit core */
+#define CONFIG_FSL_CORENET /* Freescale CoreNet platform */
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS2 /* Freescale Chassis generation 2 */
+#define CONFIG_SYS_FSL_CORES_PER_CLUSTER 4
+#define CONFIG_SYS_FSL_QMAN_V3 /* QMAN version 3 */
+#ifdef CONFIG_PPC_T4240
+#define CONFIG_MAX_CPUS 12
+#define CONFIG_SYS_NUM_FM1_DTSEC 8
+#define CONFIG_SYS_NUM_FM1_10GEC 2
+#define CONFIG_SYS_NUM_FM2_DTSEC 8
+#define CONFIG_SYS_NUM_FM2_10GEC 2
+#define CONFIG_NUM_DDR_CONTROLLERS 3
+#else
+#define CONFIG_MAX_CPUS 8
+#define CONFIG_SYS_NUM_FM1_DTSEC 7
+#define CONFIG_SYS_NUM_FM1_10GEC 1
+#define CONFIG_SYS_NUM_FM2_DTSEC 7
+#define CONFIG_SYS_NUM_FM2_10GEC 1
+#define CONFIG_NUM_DDR_CONTROLLERS 2
+#endif
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 5
+#define CONFIG_SYS_FSL_NUM_LAWS 32
+#define CONFIG_SYS_FSL_SRDS_3
+#define CONFIG_SYS_FSL_SRDS_4
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 2
+#define CONFIG_SYS_FSL_DDR_VER FSL_DDR_VER_4_7
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT 8
+#define CONFIG_SYS_FMAN_V3
+#define CONFIG_SYS_FM_MURAM_SIZE 0x60000
+#define CONFIG_SYS_FSL_TBCLK_DIV 16
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v3.0"
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_FSL_ERRATUM_A004468
+#define CONFIG_SYS_FSL_ERRATUM_A_004934
+#define CONFIG_SYS_FSL_ERRATUM_A005871
+#define CONFIG_SYS_FSL_ERRATUM_A006593
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+#define CONFIG_SYS_FSL_PCI_VER_3_X
+
+#elif defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_B4420)
+#define CONFIG_E6500
+#define CONFIG_SYS_PPC64 /* 64-bit core */
+#define CONFIG_FSL_CORENET /* Freescale CoreNet platform */
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS2 /* Freescale Chassis generation 2 */
+#define CONFIG_SYS_FSL_QMAN_V3 /* QMAN version 3 */
+#define CONFIG_SYS_FSL_NUM_LAWS 32
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 1
+#define CONFIG_SYS_FSL_DDR_VER FSL_DDR_VER_4_7
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
+#define CONFIG_SYS_FMAN_V3
+#define CONFIG_SYS_FM_MURAM_SIZE 0x60000
+#define CONFIG_SYS_FSL_TBCLK_DIV 16
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.4"
+#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
+#define CONFIG_SYS_FSL_ERRATUM_A_004934
+#define CONFIG_SYS_FSL_ERRATUM_A005871
+#define CONFIG_SYS_FSL_ERRATUM_A006593
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+
+#ifdef CONFIG_PPC_B4860
+#define CONFIG_SYS_FSL_CORES_PER_CLUSTER 4
+#define CONFIG_MAX_CPUS 4
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 4
+#define CONFIG_SYS_NUM_FM1_DTSEC 6
+#define CONFIG_SYS_NUM_FM1_10GEC 2
+#define CONFIG_NUM_DDR_CONTROLLERS 2
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#else
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_CORES_PER_CLUSTER 2
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 4
+#define CONFIG_SYS_NUM_FM1_DTSEC 4
+#define CONFIG_SYS_NUM_FM1_10GEC 0
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#endif
+
+#elif defined(CONFIG_PPC_T1040)
+#define CONFIG_E5500
+#define CONFIG_FSL_CORENET /* Freescale CoreNet platform */
+#define CONFIG_SYS_FSL_QORIQ_CHASSIS2 /* Freescale Chassis generation 2 */
+#define CONFIG_SYS_FSL_CORES_PER_CLUSTER 1
+#define CONFIG_SYS_FSL_QMAN_V3 /* QMAN version 3 */
+#define CONFIG_MAX_CPUS 4
+#define CONFIG_SYS_FSL_NUM_CC_PLLS 5
+#define CONFIG_SYS_FSL_NUM_LAWS 16
+#define CONFIG_SYS_FSL_SEC_COMPAT 4
+#define CONFIG_SYS_NUM_FMAN 1
+#define CONFIG_SYS_NUM_FM1_DTSEC 5
+#define CONFIG_NUM_DDR_CONTROLLERS 1
+#define CONFIG_SYS_FSL_DDR_VER FSL_DDR_VER_4_7
+#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
+#define CONFIG_SYS_FMAN_V3
+#define CONFIG_SYS_FM_MURAM_SIZE 0x28000
+#define CONFIG_SYS_FSL_TBCLK_DIV 32
+#define CONFIG_SYS_FSL_PCIE_COMPAT "fsl,qoriq-pcie-v2.4"
+#define CONFIG_SYS_FSL_SRIO_MAX_PORTS 2
+#define CONFIG_SYS_FSL_SRIO_OB_WIN_NUM 9
+#define CONFIG_SYS_FSL_SRIO_IB_WIN_NUM 5
+#define CONFIG_SYS_FSL_USB1_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB2_PHY_ENABLE
+#define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
+#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
+
+#else
+#error Processor type not defined for this platform
+#endif
+
+#ifndef CONFIG_SYS_CCSRBAR_DEFAULT
+#error "CONFIG_SYS_CCSRBAR_DEFAULT is not defined for this platform."
+#endif
+
+#ifdef CONFIG_E6500
+#define CONFIG_SYS_FSL_THREADS_PER_CORE 2
+#else
+#define CONFIG_SYS_FSL_THREADS_PER_CORE 1
+#endif
+
+#endif /* _ASM_MPC85xx_CONFIG_H_ */
diff --git a/arch/powerpc/include/asm/config_mpc86xx.h b/arch/powerpc/include/asm/config_mpc86xx.h
new file mode 100644
index 0000000..54ae398
--- /dev/null
+++ b/arch/powerpc/include/asm/config_mpc86xx.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _ASM_MPC86xx_CONFIG_H_
+#define _ASM_MPC86xx_CONFIG_H_
+
+/* SoC specific defines for Freescale MPC86xx processors */
+
+#if defined(CONFIG_MPC8610)
+#define CONFIG_MAX_CPUS 1
+#define CONFIG_SYS_FSL_NUM_LAWS 10
+
+#elif defined(CONFIG_MPC8641)
+#define CONFIG_MAX_CPUS 2
+#define CONFIG_SYS_FSL_NUM_LAWS 10
+
+#else
+#error Processor type not defined for this platform
+#endif
+
+#endif /* _ASM_MPC85xx_CONFIG_H_ */
diff --git a/arch/powerpc/include/asm/cpm_8260.h b/arch/powerpc/include/asm/cpm_8260.h
new file mode 100644
index 0000000..6a4a51a
--- /dev/null
+++ b/arch/powerpc/include/asm/cpm_8260.h
@@ -0,0 +1,796 @@
+
+/*
+ * MPC8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the MPC8260 internal
+ * memory map. See immap.h for details.
+ */
+#ifndef __CPM_82XX__
+#define __CPM_82XX__
+
+#include <asm/immap_8260.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST ((uint)0x80000000)
+#define CPM_CR_PAGE ((uint)0x7c000000)
+#define CPM_CR_SBLOCK ((uint)0x03e00000)
+#define CPM_CR_FLG ((uint)0x00010000)
+#define CPM_CR_MCN ((uint)0x00003fc0)
+#define CPM_CR_OPCODE ((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK (0x04)
+#define CPM_CR_SCC2_SBLOCK (0x05)
+#define CPM_CR_SCC3_SBLOCK (0x06)
+#define CPM_CR_SCC4_SBLOCK (0x07)
+#define CPM_CR_SMC1_SBLOCK (0x08)
+#define CPM_CR_SMC2_SBLOCK (0x09)
+#define CPM_CR_SPI_SBLOCK (0x0a)
+#define CPM_CR_I2C_SBLOCK (0x0b)
+#define CPM_CR_TIMER_SBLOCK (0x0f)
+#define CPM_CR_RAND_SBLOCK (0x0e)
+#define CPM_CR_FCC1_SBLOCK (0x10)
+#define CPM_CR_FCC2_SBLOCK (0x11)
+#define CPM_CR_FCC3_SBLOCK (0x12)
+#define CPM_CR_IDMA1_SBLOCK (0x14)
+#define CPM_CR_IDMA2_SBLOCK (0x15)
+#define CPM_CR_IDMA3_SBLOCK (0x16)
+#define CPM_CR_IDMA4_SBLOCK (0x17)
+#define CPM_CR_MCC1_SBLOCK (0x1c)
+
+#define CPM_CR_SCC1_PAGE (0x00)
+#define CPM_CR_SCC2_PAGE (0x01)
+#define CPM_CR_SCC3_PAGE (0x02)
+#define CPM_CR_SCC4_PAGE (0x03)
+#define CPM_CR_SMC1_PAGE (0x07)
+#define CPM_CR_SMC2_PAGE (0x08)
+#define CPM_CR_SPI_PAGE (0x09)
+#define CPM_CR_I2C_PAGE (0x0a)
+#define CPM_CR_TIMER_PAGE (0x0a)
+#define CPM_CR_RAND_PAGE (0x0a)
+#define CPM_CR_FCC1_PAGE (0x04)
+#define CPM_CR_FCC2_PAGE (0x05)
+#define CPM_CR_FCC3_PAGE (0x06)
+#define CPM_CR_IDMA1_PAGE (0x07)
+#define CPM_CR_IDMA2_PAGE (0x08)
+#define CPM_CR_IDMA3_PAGE (0x09)
+#define CPM_CR_IDMA4_PAGE (0x0a)
+#define CPM_CR_MCC1_PAGE (0x07)
+#define CPM_CR_MCC2_PAGE (0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX ((ushort)0x0000)
+#define CPM_CR_INIT_RX ((ushort)0x0001)
+#define CPM_CR_INIT_TX ((ushort)0x0002)
+#define CPM_CR_HUNT_MODE ((ushort)0x0003)
+#define CPM_CR_STOP_TX ((ushort)0x0004)
+#define CPM_CR_RESTART_TX ((ushort)0x0006)
+#define CPM_CR_SET_GADDR ((ushort)0x0008)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+ ((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses. The first 16K is available for almost
+ * any CPM use, so we put the BDs there. The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that. All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE ((uint)128)
+#define CPM_DP_NOSPACE ((uint)0x7fffffff)
+#ifndef CONFIG_MPC8272_FAMILY
+#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE ((uint)0x0000b000)
+#else /* 8247/48/71/72 */
+#define CPM_DATAONLY_SIZE ((uint)(4 * 1024) - CPM_DATAONLY_BASE)
+#define CPM_FCC_SPECIAL_BASE ((uint)0x00009000)
+#endif /* !CONFIG_MPC8272_FAMILY */
+
+/* The number of pages of host memory we allocate for CPM. This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES 2
+
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+extern cpm8260_t *cpmp; /* Pointer to comm processor */
+uint m8260_cpm_dpalloc(uint size, uint align);
+uint m8260_cpm_hostalloc(uint size, uint align);
+void m8260_cpm_setbrg(uint brg, uint rate);
+void m8260_cpm_fastbrg(uint brg, uint rate, int div16);
+void m8260_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+ ushort cbd_sc; /* Status and Control */
+ ushort cbd_datlen; /* Data length in buffer */
+ uint cbd_bufaddr; /* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */
+#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */
+#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */
+#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */
+#define BD_SC_LAST ((ushort)0x0800) /* Last buffer in frame */
+#define BD_SC_CM ((ushort)0x0200) /* Continous mode */
+#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */
+#define BD_SC_P ((ushort)0x0100) /* xmt preamble */
+#define BD_SC_BR ((ushort)0x0020) /* Break received */
+#define BD_SC_FR ((ushort)0x0010) /* Framing error */
+#define BD_SC_PR ((ushort)0x0008) /* Parity error */
+#define BD_SC_OV ((ushort)0x0002) /* Overrun */
+#define BD_SC_CD ((ushort)0x0001) /* ?? */
+
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */
+#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */
+#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */
+#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */
+#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */
+
+/* Parameter RAM offsets from the base.
+*/
+#ifndef CONFIG_SYS_CPM_POST_WORD_ADDR
+#define CPM_POST_WORD_ADDR 0x80FC /* steal a long at the end of SCC1 */
+#else
+#define CPM_POST_WORD_ADDR CONFIG_SYS_CPM_POST_WORD_ADDR
+#endif
+
+#ifndef CONFIG_SYS_CPM_BOOTCOUNT_ADDR
+#define CPM_BOOTCOUNT_ADDR (CPM_POST_WORD_ADDR - 2*sizeof(ulong))
+#else
+#define CPM_BOOTCOUNT_ADDR CONFIG_SYS_CPM_BOOTCOUNT_ADDR
+#endif
+
+#define PROFF_SCC1 ((uint)0x8000)
+#define PROFF_SCC2 ((uint)0x8100)
+#define PROFF_SCC3 ((uint)0x8200)
+#define PROFF_SCC4 ((uint)0x8300)
+#define PROFF_FCC1 ((uint)0x8400)
+#define PROFF_FCC2 ((uint)0x8500)
+#define PROFF_FCC3 ((uint)0x8600)
+#define PROFF_MCC1 ((uint)0x8700)
+#define PROFF_SMC1_BASE ((uint)0x87fc)
+#define PROFF_IDMA1_BASE ((uint)0x87fe)
+#define PROFF_MCC2 ((uint)0x8800)
+#define PROFF_SMC2_BASE ((uint)0x88fc)
+#define PROFF_IDMA2_BASE ((uint)0x88fe)
+#define PROFF_SPI_BASE ((uint)0x89fc)
+#define PROFF_IDMA3_BASE ((uint)0x89fe)
+#define PROFF_TIMERS ((uint)0x8ae0)
+#define PROFF_REVNUM ((uint)0x8af0)
+#define PROFF_RAND ((uint)0x8af8)
+#define PROFF_I2C_BASE ((uint)0x8afc)
+#define PROFF_IDMA4_BASE ((uint)0x8afe)
+
+/* The SMCs are relocated to any of the first eight DPRAM pages.
+ * We will fix these at the first locations of DPRAM, until we
+ * get some microcode patches :-).
+ * The parameter ram space for the SMCs is fifty-some bytes, and
+ * they are required to start on a 64 byte boundary.
+ */
+#define PROFF_SMC1 (0)
+#define PROFF_SMC2 (64)
+#define PROFF_SPI ((16*1024) - 128)
+
+/* Define enough so I can at least use the serial port as a UART.
+ */
+typedef struct smc_uart {
+ ushort smc_rbase; /* Rx Buffer descriptor base address */
+ ushort smc_tbase; /* Tx Buffer descriptor base address */
+ u_char smc_rfcr; /* Rx function code */
+ u_char smc_tfcr; /* Tx function code */
+ ushort smc_mrblr; /* Max receive buffer length */
+ uint smc_rstate; /* Internal */
+ uint smc_idp; /* Internal */
+ ushort smc_rbptr; /* Internal */
+ ushort smc_ibc; /* Internal */
+ uint smc_rxtmp; /* Internal */
+ uint smc_tstate; /* Internal */
+ uint smc_tdp; /* Internal */
+ ushort smc_tbptr; /* Internal */
+ ushort smc_tbc; /* Internal */
+ uint smc_txtmp; /* Internal */
+ ushort smc_maxidl; /* Maximum idle characters */
+ ushort smc_tmpidl; /* Temporary idle counter */
+ ushort smc_brklen; /* Last received break length */
+ ushort smc_brkec; /* rcv'd break condition counter */
+ ushort smc_brkcr; /* xmt break count register */
+ ushort smc_rmask; /* Temporary bit mask */
+ uint smc_stmp; /* SDMA Temp */
+} smc_uart_t;
+
+/* SMC uart mode register (Internal memory map).
+*/
+#define SMCMR_REN ((ushort)0x0001)
+#define SMCMR_TEN ((ushort)0x0002)
+#define SMCMR_DM ((ushort)0x000c)
+#define SMCMR_SM_GCI ((ushort)0x0000)
+#define SMCMR_SM_UART ((ushort)0x0020)
+#define SMCMR_SM_TRANS ((ushort)0x0030)
+#define SMCMR_SM_MASK ((ushort)0x0030)
+#define SMCMR_PM_EVEN ((ushort)0x0100) /* Even parity, else odd */
+#define SMCMR_REVD SMCMR_PM_EVEN
+#define SMCMR_PEN ((ushort)0x0200) /* Parity enable */
+#define SMCMR_BS SMCMR_PEN
+#define SMCMR_SL ((ushort)0x0400) /* Two stops, else one */
+#define SMCR_CLEN_MASK ((ushort)0x7800) /* Character length */
+#define smcr_mk_clen(C) (((C) << 11) & SMCR_CLEN_MASK)
+
+/* SMC Event and Mask register.
+*/
+#define SMCM_TXE ((unsigned char)0x10)
+#define SMCM_BSY ((unsigned char)0x04)
+#define SMCM_TX ((unsigned char)0x02)
+#define SMCM_RX ((unsigned char)0x01)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST ((uint)0x00020000)
+#define CPM_BRG_EN ((uint)0x00010000)
+#define CPM_BRG_EXTC_INT ((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9 ((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15 ((uint)0x00008000)
+#define CPM_BRG_ATB ((uint)0x00002000)
+#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
+#define CPM_BRG_DIV16 ((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP ((uint)0x00040000)
+#define SCC_GSMRH_GDE ((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT ((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC ((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC ((uint)0x00000000)
+#define SCC_GSMRH_REVD ((uint)0x00002000)
+#define SCC_GSMRH_TRX ((uint)0x00001000)
+#define SCC_GSMRH_TTX ((uint)0x00000800)
+#define SCC_GSMRH_CDP ((uint)0x00000400)
+#define SCC_GSMRH_CTSP ((uint)0x00000200)
+#define SCC_GSMRH_CDS ((uint)0x00000100)
+#define SCC_GSMRH_CTSS ((uint)0x00000080)
+#define SCC_GSMRH_TFL ((uint)0x00000040)
+#define SCC_GSMRH_RFW ((uint)0x00000020)
+#define SCC_GSMRH_TXSY ((uint)0x00000010)
+#define SCC_GSMRH_SYNL16 ((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8 ((uint)0x00000008)
+#define SCC_GSMRH_SYNL4 ((uint)0x00000004)
+#define SCC_GSMRH_RTSM ((uint)0x00000002)
+#define SCC_GSMRH_RSYN ((uint)0x00000001)
+
+#define SCC_GSMRL_SIR ((uint)0x80000000) /* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE ((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG ((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS ((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH ((uint)0x00000000)
+#define SCC_GSMRL_TCI ((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3 ((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4 ((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14 ((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF ((uint)0x00000000)
+#define SCC_GSMRL_RINV ((uint)0x02000000)
+#define SCC_GSMRL_TINV ((uint)0x01000000)
+#define SCC_GSMRL_TPL_128 ((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64 ((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48 ((uint)0x00800000)
+#define SCC_GSMRL_TPL_32 ((uint)0x00600000)
+#define SCC_GSMRL_TPL_16 ((uint)0x00400000)
+#define SCC_GSMRL_TPL_8 ((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE ((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1 ((uint)0x00180000)
+#define SCC_GSMRL_TPP_01 ((uint)0x00100000)
+#define SCC_GSMRL_TPP_10 ((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS ((uint)0x00000000)
+#define SCC_GSMRL_TEND ((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32 ((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16 ((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8 ((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1 ((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32 ((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16 ((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8 ((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1 ((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN ((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH ((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0 ((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI ((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ ((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN ((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH ((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0 ((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI ((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ ((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE ((uint)0x000000c0) /* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO ((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP ((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM ((uint)0x00000000)
+#define SCC_GSMRL_ENR ((uint)0x00000020)
+#define SCC_GSMRL_ENT ((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET ((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP ((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC ((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14 ((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC ((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS ((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART ((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7 ((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK ((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC ((uint)0x00000000)
+
+#define SCC_TODR_TOD ((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define SCCM_TXE ((unsigned char)0x10)
+#define SCCM_BSY ((unsigned char)0x04)
+#define SCCM_TX ((unsigned char)0x02)
+#define SCCM_RX ((unsigned char)0x01)
+
+typedef struct scc_param {
+ ushort scc_rbase; /* Rx Buffer descriptor base address */
+ ushort scc_tbase; /* Tx Buffer descriptor base address */
+ u_char scc_rfcr; /* Rx function code */
+ u_char scc_tfcr; /* Tx function code */
+ ushort scc_mrblr; /* Max receive buffer length */
+ uint scc_rstate; /* Internal */
+ uint scc_idp; /* Internal */
+ ushort scc_rbptr; /* Internal */
+ ushort scc_ibc; /* Internal */
+ uint scc_rxtmp; /* Internal */
+ uint scc_tstate; /* Internal */
+ uint scc_tdp; /* Internal */
+ ushort scc_tbptr; /* Internal */
+ ushort scc_tbc; /* Internal */
+ uint scc_txtmp; /* Internal */
+ uint scc_rcrc; /* Internal */
+ uint scc_tcrc; /* Internal */
+} sccp_t;
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+ sccp_t sen_genscc;
+ uint sen_cpres; /* Preset CRC */
+ uint sen_cmask; /* Constant mask for CRC */
+ uint sen_crcec; /* CRC Error counter */
+ uint sen_alec; /* alignment error counter */
+ uint sen_disfc; /* discard frame counter */
+ ushort sen_pads; /* Tx short frame pad character */
+ ushort sen_retlim; /* Retry limit threshold */
+ ushort sen_retcnt; /* Retry limit counter */
+ ushort sen_maxflr; /* maximum frame length register */
+ ushort sen_minflr; /* minimum frame length register */
+ ushort sen_maxd1; /* maximum DMA1 length */
+ ushort sen_maxd2; /* maximum DMA2 length */
+ ushort sen_maxd; /* Rx max DMA */
+ ushort sen_dmacnt; /* Rx DMA counter */
+ ushort sen_maxb; /* Max BD byte count */
+ ushort sen_gaddr1; /* Group address filter */
+ ushort sen_gaddr2;
+ ushort sen_gaddr3;
+ ushort sen_gaddr4;
+ uint sen_tbuf0data0; /* Save area 0 - current frame */
+ uint sen_tbuf0data1; /* Save area 1 - current frame */
+ uint sen_tbuf0rba; /* Internal */
+ uint sen_tbuf0crc; /* Internal */
+ ushort sen_tbuf0bcnt; /* Internal */
+ ushort sen_paddrh; /* physical address (MSB) */
+ ushort sen_paddrm;
+ ushort sen_paddrl; /* physical address (LSB) */
+ ushort sen_pper; /* persistence */
+ ushort sen_rfbdptr; /* Rx first BD pointer */
+ ushort sen_tfbdptr; /* Tx first BD pointer */
+ ushort sen_tlbdptr; /* Tx last BD pointer */
+ uint sen_tbuf1data0; /* Save area 0 - current frame */
+ uint sen_tbuf1data1; /* Save area 1 - current frame */
+ uint sen_tbuf1rba; /* Internal */
+ uint sen_tbuf1crc; /* Internal */
+ ushort sen_tbuf1bcnt; /* Internal */
+ ushort sen_txlen; /* Tx Frame length counter */
+ ushort sen_iaddr1; /* Individual address filter */
+ ushort sen_iaddr2;
+ ushort sen_iaddr3;
+ ushort sen_iaddr4;
+ ushort sen_boffcnt; /* Backoff counter */
+
+ /* NOTE: Some versions of the manual have the following items
+ * incorrectly documented. Below is the proper order.
+ */
+ ushort sen_taddrh; /* temp address (MSB) */
+ ushort sen_taddrm;
+ ushort sen_taddrl; /* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */
+#define SCCE_ENET_TXE ((ushort)0x0010) /* Transmit Error */
+#define SCCE_ENET_RXF ((ushort)0x0008) /* Full frame received */
+#define SCCE_ENET_BSY ((ushort)0x0004) /* All incoming buffers full */
+#define SCCE_ENET_TXB ((ushort)0x0002) /* A buffer was transmitted */
+#define SCCE_ENET_RXB ((ushort)0x0001) /* A buffer was received */
+
+/* SCC Mode Register (PSMR) as used by Ethernet.
+*/
+#define SCC_PSMR_HBC ((ushort)0x8000) /* Enable heartbeat */
+#define SCC_PSMR_FC ((ushort)0x4000) /* Force collision */
+#define SCC_PSMR_RSH ((ushort)0x2000) /* Receive short frames */
+#define SCC_PSMR_IAM ((ushort)0x1000) /* Check individual hash */
+#define SCC_PSMR_ENCRC ((ushort)0x0800) /* Ethernet CRC mode */
+#define SCC_PSMR_PRO ((ushort)0x0200) /* Promiscuous mode */
+#define SCC_PSMR_BRO ((ushort)0x0100) /* Catch broadcast pkts */
+#define SCC_PSMR_SBT ((ushort)0x0080) /* Special backoff timer */
+#define SCC_PSMR_LPB ((ushort)0x0040) /* Set Loopback mode */
+#define SCC_PSMR_SIP ((ushort)0x0020) /* Sample Input Pins */
+#define SCC_PSMR_LCW ((ushort)0x0010) /* Late collision window */
+#define SCC_PSMR_NIB22 ((ushort)0x000a) /* Start frame search */
+#define SCC_PSMR_FDE ((ushort)0x0001) /* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_RX_EMPTY ((ushort)0x8000)
+#define BD_ENET_RX_WRAP ((ushort)0x2000)
+#define BD_ENET_RX_INTR ((ushort)0x1000)
+#define BD_ENET_RX_LAST ((ushort)0x0800)
+#define BD_ENET_RX_FIRST ((ushort)0x0400)
+#define BD_ENET_RX_MISS ((ushort)0x0100)
+#define BD_ENET_RX_BC ((ushort)0x0080) /* FCC Only */
+#define BD_ENET_RX_MC ((ushort)0x0040) /* FCC Only */
+#define BD_ENET_RX_LG ((ushort)0x0020)
+#define BD_ENET_RX_NO ((ushort)0x0010)
+#define BD_ENET_RX_SH ((ushort)0x0008)
+#define BD_ENET_RX_CR ((ushort)0x0004)
+#define BD_ENET_RX_OV ((ushort)0x0002)
+#define BD_ENET_RX_CL ((ushort)0x0001)
+#define BD_ENET_RX_STATS ((ushort)0x01ff) /* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_TX_READY ((ushort)0x8000)
+#define BD_ENET_TX_PAD ((ushort)0x4000)
+#define BD_ENET_TX_WRAP ((ushort)0x2000)
+#define BD_ENET_TX_INTR ((ushort)0x1000)
+#define BD_ENET_TX_LAST ((ushort)0x0800)
+#define BD_ENET_TX_TC ((ushort)0x0400)
+#define BD_ENET_TX_DEF ((ushort)0x0200)
+#define BD_ENET_TX_HB ((ushort)0x0100)
+#define BD_ENET_TX_LC ((ushort)0x0080)
+#define BD_ENET_TX_RL ((ushort)0x0040)
+#define BD_ENET_TX_RCMASK ((ushort)0x003c)
+#define BD_ENET_TX_UN ((ushort)0x0002)
+#define BD_ENET_TX_CSL ((ushort)0x0001)
+#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+ sccp_t scc_genscc;
+ uint scc_res1; /* Reserved */
+ uint scc_res2; /* Reserved */
+ ushort scc_maxidl; /* Maximum idle chars */
+ ushort scc_idlc; /* temp idle counter */
+ ushort scc_brkcr; /* Break count register */
+ ushort scc_parec; /* receive parity error counter */
+ ushort scc_frmec; /* receive framing error counter */
+ ushort scc_nosec; /* receive noise counter */
+ ushort scc_brkec; /* receive break condition counter */
+ ushort scc_brkln; /* last received break length */
+ ushort scc_uaddr1; /* UART address character 1 */
+ ushort scc_uaddr2; /* UART address character 2 */
+ ushort scc_rtemp; /* Temp storage */
+ ushort scc_toseq; /* Transmit out of sequence char */
+ ushort scc_char1; /* control character 1 */
+ ushort scc_char2; /* control character 2 */
+ ushort scc_char3; /* control character 3 */
+ ushort scc_char4; /* control character 4 */
+ ushort scc_char5; /* control character 5 */
+ ushort scc_char6; /* control character 6 */
+ ushort scc_char7; /* control character 7 */
+ ushort scc_char8; /* control character 8 */
+ ushort scc_rccm; /* receive control character mask */
+ ushort scc_rccr; /* receive control character register */
+ ushort scc_rlbc; /* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR ((ushort)0x1000)
+#define UART_SCCM_GLT ((ushort)0x0800)
+#define UART_SCCM_AB ((ushort)0x0200)
+#define UART_SCCM_IDL ((ushort)0x0100)
+#define UART_SCCM_GRA ((ushort)0x0080)
+#define UART_SCCM_BRKE ((ushort)0x0040)
+#define UART_SCCM_BRKS ((ushort)0x0020)
+#define UART_SCCM_CCR ((ushort)0x0008)
+#define UART_SCCM_BSY ((ushort)0x0004)
+#define UART_SCCM_TX ((ushort)0x0002)
+#define UART_SCCM_RX ((ushort)0x0001)
+
+/* The SCC PSMR when used as a UART.
+*/
+#define SCU_PSMR_FLC ((ushort)0x8000)
+#define SCU_PSMR_SL ((ushort)0x4000)
+#define SCU_PSMR_CL ((ushort)0x3000)
+#define SCU_PSMR_UM ((ushort)0x0c00)
+#define SCU_PSMR_FRZ ((ushort)0x0200)
+#define SCU_PSMR_RZS ((ushort)0x0100)
+#define SCU_PSMR_SYN ((ushort)0x0080)
+#define SCU_PSMR_DRT ((ushort)0x0040)
+#define SCU_PSMR_PEN ((ushort)0x0010)
+#define SCU_PSMR_RPM ((ushort)0x000c)
+#define SCU_PSMR_REVP ((ushort)0x0008)
+#define SCU_PSMR_TPM ((ushort)0x0003)
+#define SCU_PSMR_TEVP ((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+ sccp_t st_genscc;
+ uint st_cpres; /* Preset CRC */
+ uint st_cmask; /* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST ((ushort)0x0800)
+
+/* SCC as HDLC controller - taken from commproc.h
+ */
+typedef struct scc_hdlc {
+ sccp_t sh_genscc;
+ /*
+ * HDLC specific parameter RAM
+ */
+ uchar res[4]; /* reserved */
+ ulong sh_cmask; /* CRC constant */
+ ulong sh_cpres; /* CRC preset */
+ ushort sh_disfc; /* discarded frame counter */
+ ushort sh_crcec; /* CRC error counter */
+ ushort sh_abtsc; /* abort sequence counter */
+ ushort sh_nmarc; /* nonmatching address rx cnt */
+ ushort sh_retrc; /* frame retransmission cnt */
+ ushort sh_mflr; /* maximum frame length reg */
+ ushort sh_maxcnt; /* maximum length counter */
+ ushort sh_rfthr; /* received frames threshold */
+ ushort sh_rfcnt; /* received frames count */
+ ushort sh_hmask; /* user defined frm addr mask */
+ ushort sh_haddr1; /* user defined frm address 1 */
+ ushort sh_haddr2; /* user defined frm address 2 */
+ ushort sh_haddr3; /* user defined frm address 3 */
+ ushort sh_haddr4; /* user defined frm address 4 */
+ ushort tmp; /* temp */
+ ushort tmp_mb; /* temp */
+} scc_hdlc_t;
+
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM ((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE ((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE ((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE ((uint)0xc0000000)
+#define FCC_GFMR_TCI ((uint)0x20000000)
+#define FCC_GFMR_TRX ((uint)0x10000000)
+#define FCC_GFMR_TTX ((uint)0x08000000)
+#define FCC_GFMR_TTX ((uint)0x08000000)
+#define FCC_GFMR_CDP ((uint)0x04000000)
+#define FCC_GFMR_CTSP ((uint)0x02000000)
+#define FCC_GFMR_CDS ((uint)0x01000000)
+#define FCC_GFMR_CTSS ((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE ((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO ((uint)0x00004000)
+#define FCC_GFMR_SYNL_8 ((uint)0x00008000)
+#define FCC_GFMR_SYNL_16 ((uint)0x0000c000)
+#define FCC_GFMR_RTSM ((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ ((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI ((uint)0x00000800)
+#define FCC_GFMR_REVD ((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ ((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI ((uint)0x00000100)
+#define FCC_GFMR_TCRC_16 ((uint)0x00000000)
+#define FCC_GFMR_TCRC_32 ((uint)0x00000080)
+#define FCC_GFMR_ENR ((uint)0x00000020)
+#define FCC_GFMR_ENT ((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET ((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM ((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC ((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+ ushort fcc_riptr; /* Rx Internal temp pointer */
+ ushort fcc_tiptr; /* Tx Internal temp pointer */
+ ushort fcc_res1;
+ ushort fcc_mrblr; /* Max receive buffer length, mod 32 bytes */
+ uint fcc_rstate; /* Upper byte is Func code, must be set */
+ uint fcc_rbase; /* Receive BD base */
+ ushort fcc_rbdstat; /* RxBD status */
+ ushort fcc_rbdlen; /* RxBD down counter */
+ uint fcc_rdptr; /* RxBD internal data pointer */
+ uint fcc_tstate; /* Upper byte is Func code, must be set */
+ uint fcc_tbase; /* Transmit BD base */
+ ushort fcc_tbdstat; /* TxBD status */
+ ushort fcc_tbdlen; /* TxBD down counter */
+ uint fcc_tdptr; /* TxBD internal data pointer */
+ uint fcc_rbptr; /* Rx BD Internal buf pointer */
+ uint fcc_tbptr; /* Tx BD Internal buf pointer */
+ uint fcc_rcrc; /* Rx temp CRC */
+ uint fcc_res2;
+ uint fcc_tcrc; /* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+ fccp_t fen_genfcc;
+ uint fen_statbuf; /* Internal status buffer */
+ uint fen_camptr; /* CAM address */
+ uint fen_cmask; /* Constant mask for CRC */
+ uint fen_cpres; /* Preset CRC */
+ uint fen_crcec; /* CRC Error counter */
+ uint fen_alec; /* alignment error counter */
+ uint fen_disfc; /* discard frame counter */
+ ushort fen_retlim; /* Retry limit */
+ ushort fen_retcnt; /* Retry counter */
+ ushort fen_pper; /* Persistence */
+ ushort fen_boffcnt; /* backoff counter */
+ uint fen_gaddrh; /* Group address filter, high 32-bits */
+ uint fen_gaddrl; /* Group address filter, low 32-bits */
+ ushort fen_tfcstat; /* out of sequence TxBD */
+ ushort fen_tfclen;
+ uint fen_tfcptr;
+ ushort fen_mflr; /* Maximum frame length (1518) */
+ ushort fen_paddrh; /* MAC address */
+ ushort fen_paddrm;
+ ushort fen_paddrl;
+ ushort fen_ibdcount; /* Internal BD counter */
+ ushort fen_idbstart; /* Internal BD start pointer */
+ ushort fen_ibdend; /* Internal BD end pointer */
+ ushort fen_txlen; /* Internal Tx frame length counter */
+ uint fen_ibdbase[8]; /* Internal use */
+ uint fen_iaddrh; /* Individual address filter */
+ uint fen_iaddrl;
+ ushort fen_minflr; /* Minimum frame length (64) */
+ ushort fen_taddrh; /* Filter transfer MAC address */
+ ushort fen_taddrm;
+ ushort fen_taddrl;
+ ushort fen_padptr; /* Pointer to pad byte buffer */
+ ushort fen_cftype; /* control frame type */
+ ushort fen_cfrange; /* control frame range */
+ ushort fen_maxb; /* maximum BD count */
+ ushort fen_maxd1; /* Max DMA1 length (1520) */
+ ushort fen_maxd2; /* Max DMA2 length (1520) */
+ ushort fen_maxd; /* internal max DMA count */
+ ushort fen_dmacnt; /* internal DMA counter */
+ uint fen_octc; /* Total octect counter */
+ uint fen_colc; /* Total collision counter */
+ uint fen_broc; /* Total broadcast packet counter */
+ uint fen_mulc; /* Total multicast packet count */
+ uint fen_uspc; /* Total packets < 64 bytes */
+ uint fen_frgc; /* Total packets < 64 bytes with errors */
+ uint fen_ospc; /* Total packets > 1518 */
+ uint fen_jbrc; /* Total packets > 1518 with errors */
+ uint fen_p64c; /* Total packets == 64 bytes */
+ uint fen_p65c; /* Total packets 64 < bytes <= 127 */
+ uint fen_p128c; /* Total packets 127 < bytes <= 255 */
+ uint fen_p256c; /* Total packets 256 < bytes <= 511 */
+ uint fen_p512c; /* Total packets 512 < bytes <= 1023 */
+ uint fen_p1024c; /* Total packets 1024 < bytes <= 1518 */
+ uint fen_cambuf; /* Internal CAM buffer poiner */
+ ushort fen_rfthr; /* Received frames threshold */
+ ushort fen_rfcnt; /* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */
+#define FCC_ENET_RXC ((ushort)0x0040) /* Control Frame Received */
+#define FCC_ENET_TXC ((ushort)0x0020) /* Out of seq. Tx sent */
+#define FCC_ENET_TXE ((ushort)0x0010) /* Transmit Error */
+#define FCC_ENET_RXF ((ushort)0x0008) /* Full frame received */
+#define FCC_ENET_BSY ((ushort)0x0004) /* Busy. Rx Frame dropped */
+#define FCC_ENET_TXB ((ushort)0x0002) /* A buffer was transmitted */
+#define FCC_ENET_RXB ((ushort)0x0001) /* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC ((uint)0x80000000) /* Enable heartbeat */
+#define FCC_PSMR_FC ((uint)0x40000000) /* Force Collision */
+#define FCC_PSMR_SBT ((uint)0x20000000) /* Stop backoff timer */
+#define FCC_PSMR_LPB ((uint)0x10000000) /* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW ((uint)0x08000000) /* Late collision select */
+#define FCC_PSMR_FDE ((uint)0x04000000) /* Full Duplex Enable */
+#define FCC_PSMR_MON ((uint)0x02000000) /* RMON Enable */
+#define FCC_PSMR_PRO ((uint)0x00400000) /* Promiscuous Enable */
+#define FCC_PSMR_FCE ((uint)0x00200000) /* Flow Control Enable */
+#define FCC_PSMR_RSH ((uint)0x00100000) /* Receive Short Frames */
+#define FCC_PSMR_RMII ((uint)0x00020000) /* Use RMII interface */
+#define FCC_PSMR_CAM ((uint)0x00000400) /* CAM enable */
+#define FCC_PSMR_BRO ((uint)0x00000200) /* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC ((uint)0x00000080) /* Use 32-bit CRC */
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+ ushort iic_rbase; /* Rx Buffer descriptor base address */
+ ushort iic_tbase; /* Tx Buffer descriptor base address */
+ u_char iic_rfcr; /* Rx function code */
+ u_char iic_tfcr; /* Tx function code */
+ ushort iic_mrblr; /* Max receive buffer length */
+ uint iic_rstate; /* Internal */
+ uint iic_rdp; /* Internal */
+ ushort iic_rbptr; /* Internal */
+ ushort iic_rbc; /* Internal */
+ uint iic_rxtmp; /* Internal */
+ uint iic_tstate; /* Internal */
+ uint iic_tdp; /* Internal */
+ ushort iic_tbptr; /* Internal */
+ ushort iic_tbc; /* Internal */
+ uint iic_txtmp; /* Internal */
+} iic_t;
+
+/* SPI parameter RAM.
+*/
+typedef struct spi {
+ ushort spi_rbase; /* Rx Buffer descriptor base address */
+ ushort spi_tbase; /* Tx Buffer descriptor base address */
+ u_char spi_rfcr; /* Rx function code */
+ u_char spi_tfcr; /* Tx function code */
+ ushort spi_mrblr; /* Max receive buffer length */
+ uint spi_rstate; /* Internal */
+ uint spi_rdp; /* Internal */
+ ushort spi_rbptr; /* Internal */
+ ushort spi_rbc; /* Internal */
+ uint spi_rxtmp; /* Internal */
+ uint spi_tstate; /* Internal */
+ uint spi_tdp; /* Internal */
+ ushort spi_tbptr; /* Internal */
+ ushort spi_tbc; /* Internal */
+ uint spi_txtmp; /* Internal */
+ uint spi_res; /* Tx temp. */
+ uint spi_res1[4]; /* SDMA temp. */
+} spi_t;
+
+/* SPI Mode register.
+*/
+#define SPMODE_LOOP ((ushort)0x4000) /* Loopback */
+#define SPMODE_CI ((ushort)0x2000) /* Clock Invert */
+#define SPMODE_CP ((ushort)0x1000) /* Clock Phase */
+#define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */
+#define SPMODE_REV ((ushort)0x0400) /* Reversed Data */
+#define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */
+#define SPMODE_EN ((ushort)0x0100) /* Enable */
+#define SPMODE_LENMSK ((ushort)0x00f0) /* character length */
+#define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */
+
+#define SPMODE_LEN(x) ((((x)-1)&0xF)<<4)
+#define SPMODE_PM(x) ((x) &0xF)
+
+/* SPI Event/Mask register.
+*/
+#define SPI_EMASK 0x37 /* Event Mask */
+#define SPI_MME 0x20 /* Multi-Master Error */
+#define SPI_TXE 0x10 /* Transmit Error */
+#define SPI_BSY 0x04 /* Busy */
+#define SPI_TXB 0x02 /* Tx Buffer Empty */
+#define SPI_RXB 0x01 /* RX Buffer full/closed */
+
+#define SPI_STR 0x80 /* SPCOM: Start transmit */
+
+#define SPI_EB ((u_char)0x10) /* big endian byte order */
+
+#define BD_IIC_START ((ushort)0x0400)
+
+#endif /* __CPM_82XX__ */
diff --git a/arch/powerpc/include/asm/cpm_85xx.h b/arch/powerpc/include/asm/cpm_85xx.h
new file mode 100644
index 0000000..1681ecd
--- /dev/null
+++ b/arch/powerpc/include/asm/cpm_85xx.h
@@ -0,0 +1,830 @@
+
+/*
+ * MPC85xx Communication Processor Module
+ * Copyright (c) 2003,Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ *
+ * MPC8260 Communication Processor Module.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * This file contains structures and information for the communication
+ * processor channels found in the dual port RAM or parameter RAM.
+ * All CPM control and status is available through the MPC8260 internal
+ * memory map. See immap.h for details.
+ */
+#ifndef __CPM_85XX__
+#define __CPM_85XX__
+
+#include <asm/immap_85xx.h>
+
+/* CPM Command register.
+*/
+#define CPM_CR_RST ((uint)0x80000000)
+#define CPM_CR_PAGE ((uint)0x7c000000)
+#define CPM_CR_SBLOCK ((uint)0x03e00000)
+#define CPM_CR_FLG ((uint)0x00010000)
+#define CPM_CR_MCN ((uint)0x00003fc0)
+#define CPM_CR_OPCODE ((uint)0x0000000f)
+
+/* Device sub-block and page codes.
+*/
+#define CPM_CR_SCC1_SBLOCK (0x04)
+#define CPM_CR_SCC2_SBLOCK (0x05)
+#define CPM_CR_SCC3_SBLOCK (0x06)
+#define CPM_CR_SCC4_SBLOCK (0x07)
+#define CPM_CR_SMC1_SBLOCK (0x08)
+#define CPM_CR_SMC2_SBLOCK (0x09)
+#define CPM_CR_SPI_SBLOCK (0x0a)
+#define CPM_CR_I2C_SBLOCK (0x0b)
+#define CPM_CR_TIMER_SBLOCK (0x0f)
+#define CPM_CR_RAND_SBLOCK (0x0e)
+#define CPM_CR_FCC1_SBLOCK (0x10)
+#define CPM_CR_FCC2_SBLOCK (0x11)
+#define CPM_CR_FCC3_SBLOCK (0x12)
+#define CPM_CR_MCC1_SBLOCK (0x1c)
+
+#define CPM_CR_SCC1_PAGE (0x00)
+#define CPM_CR_SCC2_PAGE (0x01)
+#define CPM_CR_SCC3_PAGE (0x02)
+#define CPM_CR_SCC4_PAGE (0x03)
+#define CPM_CR_SPI_PAGE (0x09)
+#define CPM_CR_I2C_PAGE (0x0a)
+#define CPM_CR_TIMER_PAGE (0x0a)
+#define CPM_CR_RAND_PAGE (0x0a)
+#define CPM_CR_FCC1_PAGE (0x04)
+#define CPM_CR_FCC2_PAGE (0x05)
+#define CPM_CR_FCC3_PAGE (0x06)
+#define CPM_CR_MCC1_PAGE (0x07)
+#define CPM_CR_MCC2_PAGE (0x08)
+
+/* Some opcodes (there are more...later)
+*/
+#define CPM_CR_INIT_TRX ((ushort)0x0000)
+#define CPM_CR_INIT_RX ((ushort)0x0001)
+#define CPM_CR_INIT_TX ((ushort)0x0002)
+#define CPM_CR_HUNT_MODE ((ushort)0x0003)
+#define CPM_CR_STOP_TX ((ushort)0x0004)
+#define CPM_CR_RESTART_TX ((ushort)0x0006)
+#define CPM_CR_SET_GADDR ((ushort)0x0008)
+
+#define mk_cr_cmd(PG, SBC, MCN, OP) \
+ ((PG << 26) | (SBC << 21) | (MCN << 6) | OP)
+
+/* Dual Port RAM addresses. The first 16K is available for almost
+ * any CPM use, so we put the BDs there. The first 128 bytes are
+ * used for SMC1 and SMC2 parameter RAM, so we start allocating
+ * BDs above that. All of this must change when we start
+ * downloading RAM microcode.
+ */
+#define CPM_DATAONLY_BASE ((uint)128)
+#define CPM_DP_NOSPACE ((uint)0x7FFFFFFF)
+#if defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555)
+#define CPM_FCC_SPECIAL_BASE ((uint)0x00009000)
+#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
+#else /* MPC8540, MPC8560 */
+#define CPM_FCC_SPECIAL_BASE ((uint)0x0000B000)
+#define CPM_DATAONLY_SIZE ((uint)(16 * 1024) - CPM_DATAONLY_BASE)
+#endif
+
+/* The number of pages of host memory we allocate for CPM. This is
+ * done early in kernel initialization to get physically contiguous
+ * pages.
+ */
+#define NUM_CPM_HOST_PAGES 2
+
+/* Export the base address of the communication processor registers
+ * and dual port ram.
+ */
+/*extern cpm8560_t *cpmp; Pointer to comm processor */
+uint m8560_cpm_dpalloc(uint size, uint align);
+uint m8560_cpm_hostalloc(uint size, uint align);
+void m8560_cpm_setbrg(uint brg, uint rate);
+void m8560_cpm_fastbrg(uint brg, uint rate, int div16);
+void m8560_cpm_extcbrg(uint brg, uint rate, uint extclk, int pinsel);
+
+/* Buffer descriptors used by many of the CPM protocols.
+*/
+typedef struct cpm_buf_desc {
+ ushort cbd_sc; /* Status and Control */
+ ushort cbd_datlen; /* Data length in buffer */
+ uint cbd_bufaddr; /* Buffer address in host memory */
+} cbd_t;
+
+#define BD_SC_EMPTY ((ushort)0x8000) /* Receive is empty */
+#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */
+#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */
+#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */
+#define BD_SC_LAST ((ushort)0x0800) /* Last buffer in frame */
+#define BD_SC_CM ((ushort)0x0200) /* Continous mode */
+#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */
+#define BD_SC_P ((ushort)0x0100) /* xmt preamble */
+#define BD_SC_BR ((ushort)0x0020) /* Break received */
+#define BD_SC_FR ((ushort)0x0010) /* Framing error */
+#define BD_SC_PR ((ushort)0x0008) /* Parity error */
+#define BD_SC_OV ((ushort)0x0002) /* Overrun */
+#define BD_SC_CD ((ushort)0x0001) /* ?? */
+
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */
+#define CPMFCR_EB ((u_char)0x10) /* Set big endian byte order */
+#define CPMFCR_TC2 ((u_char)0x04) /* Transfer code 2 value */
+#define CPMFCR_DTB ((u_char)0x02) /* Use local bus for data when set */
+#define CPMFCR_BDB ((u_char)0x01) /* Use local bus for BD when set */
+
+/* Parameter RAM offsets from the base.
+*/
+#define CPM_POST_WORD_ADDR 0x80FC /* steal a long at the end of SCC1 */
+#define PROFF_SCC1 ((uint)0x8000)
+#define PROFF_SCC2 ((uint)0x8100)
+#define PROFF_SCC3 ((uint)0x8200)
+#define PROFF_SCC4 ((uint)0x8300)
+#define PROFF_FCC1 ((uint)0x8400)
+#define PROFF_FCC2 ((uint)0x8500)
+#define PROFF_FCC3 ((uint)0x8600)
+#define PROFF_MCC1 ((uint)0x8700)
+#define PROFF_MCC2 ((uint)0x8800)
+#define PROFF_SPI_BASE ((uint)0x89fc)
+#define PROFF_TIMERS ((uint)0x8ae0)
+#define PROFF_REVNUM ((uint)0x8af0)
+#define PROFF_RAND ((uint)0x8af8)
+#define PROFF_I2C_BASE ((uint)0x8afc)
+
+/* Baud rate generators.
+*/
+#define CPM_BRG_RST ((uint)0x00020000)
+#define CPM_BRG_EN ((uint)0x00010000)
+#define CPM_BRG_EXTC_INT ((uint)0x00000000)
+#define CPM_BRG_EXTC_CLK3_9 ((uint)0x00004000)
+#define CPM_BRG_EXTC_CLK5_15 ((uint)0x00008000)
+#define CPM_BRG_ATB ((uint)0x00002000)
+#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
+#define CPM_BRG_DIV16 ((uint)0x00000001)
+
+/* SCCs.
+*/
+#define SCC_GSMRH_IRP ((uint)0x00040000)
+#define SCC_GSMRH_GDE ((uint)0x00010000)
+#define SCC_GSMRH_TCRC_CCITT ((uint)0x00008000)
+#define SCC_GSMRH_TCRC_BISYNC ((uint)0x00004000)
+#define SCC_GSMRH_TCRC_HDLC ((uint)0x00000000)
+#define SCC_GSMRH_REVD ((uint)0x00002000)
+#define SCC_GSMRH_TRX ((uint)0x00001000)
+#define SCC_GSMRH_TTX ((uint)0x00000800)
+#define SCC_GSMRH_CDP ((uint)0x00000400)
+#define SCC_GSMRH_CTSP ((uint)0x00000200)
+#define SCC_GSMRH_CDS ((uint)0x00000100)
+#define SCC_GSMRH_CTSS ((uint)0x00000080)
+#define SCC_GSMRH_TFL ((uint)0x00000040)
+#define SCC_GSMRH_RFW ((uint)0x00000020)
+#define SCC_GSMRH_TXSY ((uint)0x00000010)
+#define SCC_GSMRH_SYNL16 ((uint)0x0000000c)
+#define SCC_GSMRH_SYNL8 ((uint)0x00000008)
+#define SCC_GSMRH_SYNL4 ((uint)0x00000004)
+#define SCC_GSMRH_RTSM ((uint)0x00000002)
+#define SCC_GSMRH_RSYN ((uint)0x00000001)
+
+#define SCC_GSMRL_SIR ((uint)0x80000000) /* SCC2 only */
+#define SCC_GSMRL_EDGE_NONE ((uint)0x60000000)
+#define SCC_GSMRL_EDGE_NEG ((uint)0x40000000)
+#define SCC_GSMRL_EDGE_POS ((uint)0x20000000)
+#define SCC_GSMRL_EDGE_BOTH ((uint)0x00000000)
+#define SCC_GSMRL_TCI ((uint)0x10000000)
+#define SCC_GSMRL_TSNC_3 ((uint)0x0c000000)
+#define SCC_GSMRL_TSNC_4 ((uint)0x08000000)
+#define SCC_GSMRL_TSNC_14 ((uint)0x04000000)
+#define SCC_GSMRL_TSNC_INF ((uint)0x00000000)
+#define SCC_GSMRL_RINV ((uint)0x02000000)
+#define SCC_GSMRL_TINV ((uint)0x01000000)
+#define SCC_GSMRL_TPL_128 ((uint)0x00c00000)
+#define SCC_GSMRL_TPL_64 ((uint)0x00a00000)
+#define SCC_GSMRL_TPL_48 ((uint)0x00800000)
+#define SCC_GSMRL_TPL_32 ((uint)0x00600000)
+#define SCC_GSMRL_TPL_16 ((uint)0x00400000)
+#define SCC_GSMRL_TPL_8 ((uint)0x00200000)
+#define SCC_GSMRL_TPL_NONE ((uint)0x00000000)
+#define SCC_GSMRL_TPP_ALL1 ((uint)0x00180000)
+#define SCC_GSMRL_TPP_01 ((uint)0x00100000)
+#define SCC_GSMRL_TPP_10 ((uint)0x00080000)
+#define SCC_GSMRL_TPP_ZEROS ((uint)0x00000000)
+#define SCC_GSMRL_TEND ((uint)0x00040000)
+#define SCC_GSMRL_TDCR_32 ((uint)0x00030000)
+#define SCC_GSMRL_TDCR_16 ((uint)0x00020000)
+#define SCC_GSMRL_TDCR_8 ((uint)0x00010000)
+#define SCC_GSMRL_TDCR_1 ((uint)0x00000000)
+#define SCC_GSMRL_RDCR_32 ((uint)0x0000c000)
+#define SCC_GSMRL_RDCR_16 ((uint)0x00008000)
+#define SCC_GSMRL_RDCR_8 ((uint)0x00004000)
+#define SCC_GSMRL_RDCR_1 ((uint)0x00000000)
+#define SCC_GSMRL_RENC_DFMAN ((uint)0x00003000)
+#define SCC_GSMRL_RENC_MANCH ((uint)0x00002000)
+#define SCC_GSMRL_RENC_FM0 ((uint)0x00001000)
+#define SCC_GSMRL_RENC_NRZI ((uint)0x00000800)
+#define SCC_GSMRL_RENC_NRZ ((uint)0x00000000)
+#define SCC_GSMRL_TENC_DFMAN ((uint)0x00000600)
+#define SCC_GSMRL_TENC_MANCH ((uint)0x00000400)
+#define SCC_GSMRL_TENC_FM0 ((uint)0x00000200)
+#define SCC_GSMRL_TENC_NRZI ((uint)0x00000100)
+#define SCC_GSMRL_TENC_NRZ ((uint)0x00000000)
+#define SCC_GSMRL_DIAG_LE ((uint)0x000000c0) /* Loop and echo */
+#define SCC_GSMRL_DIAG_ECHO ((uint)0x00000080)
+#define SCC_GSMRL_DIAG_LOOP ((uint)0x00000040)
+#define SCC_GSMRL_DIAG_NORM ((uint)0x00000000)
+#define SCC_GSMRL_ENR ((uint)0x00000020)
+#define SCC_GSMRL_ENT ((uint)0x00000010)
+#define SCC_GSMRL_MODE_ENET ((uint)0x0000000c)
+#define SCC_GSMRL_MODE_DDCMP ((uint)0x00000009)
+#define SCC_GSMRL_MODE_BISYNC ((uint)0x00000008)
+#define SCC_GSMRL_MODE_V14 ((uint)0x00000007)
+#define SCC_GSMRL_MODE_AHDLC ((uint)0x00000006)
+#define SCC_GSMRL_MODE_PROFIBUS ((uint)0x00000005)
+#define SCC_GSMRL_MODE_UART ((uint)0x00000004)
+#define SCC_GSMRL_MODE_SS7 ((uint)0x00000003)
+#define SCC_GSMRL_MODE_ATALK ((uint)0x00000002)
+#define SCC_GSMRL_MODE_HDLC ((uint)0x00000000)
+
+#define SCC_TODR_TOD ((ushort)0x8000)
+
+/* SCC Event and Mask register.
+*/
+#define SCCM_TXE ((unsigned char)0x10)
+#define SCCM_BSY ((unsigned char)0x04)
+#define SCCM_TX ((unsigned char)0x02)
+#define SCCM_RX ((unsigned char)0x01)
+
+typedef struct scc_param {
+ ushort scc_rbase; /* Rx Buffer descriptor base address */
+ ushort scc_tbase; /* Tx Buffer descriptor base address */
+ u_char scc_rfcr; /* Rx function code */
+ u_char scc_tfcr; /* Tx function code */
+ ushort scc_mrblr; /* Max receive buffer length */
+ uint scc_rstate; /* Internal */
+ uint scc_idp; /* Internal */
+ ushort scc_rbptr; /* Internal */
+ ushort scc_ibc; /* Internal */
+ uint scc_rxtmp; /* Internal */
+ uint scc_tstate; /* Internal */
+ uint scc_tdp; /* Internal */
+ ushort scc_tbptr; /* Internal */
+ ushort scc_tbc; /* Internal */
+ uint scc_txtmp; /* Internal */
+ uint scc_rcrc; /* Internal */
+ uint scc_tcrc; /* Internal */
+} sccp_t;
+
+/* CPM Ethernet through SCC1.
+ */
+typedef struct scc_enet {
+ sccp_t sen_genscc;
+ uint sen_cpres; /* Preset CRC */
+ uint sen_cmask; /* Constant mask for CRC */
+ uint sen_crcec; /* CRC Error counter */
+ uint sen_alec; /* alignment error counter */
+ uint sen_disfc; /* discard frame counter */
+ ushort sen_pads; /* Tx short frame pad character */
+ ushort sen_retlim; /* Retry limit threshold */
+ ushort sen_retcnt; /* Retry limit counter */
+ ushort sen_maxflr; /* maximum frame length register */
+ ushort sen_minflr; /* minimum frame length register */
+ ushort sen_maxd1; /* maximum DMA1 length */
+ ushort sen_maxd2; /* maximum DMA2 length */
+ ushort sen_maxd; /* Rx max DMA */
+ ushort sen_dmacnt; /* Rx DMA counter */
+ ushort sen_maxb; /* Max BD byte count */
+ ushort sen_gaddr1; /* Group address filter */
+ ushort sen_gaddr2;
+ ushort sen_gaddr3;
+ ushort sen_gaddr4;
+ uint sen_tbuf0data0; /* Save area 0 - current frame */
+ uint sen_tbuf0data1; /* Save area 1 - current frame */
+ uint sen_tbuf0rba; /* Internal */
+ uint sen_tbuf0crc; /* Internal */
+ ushort sen_tbuf0bcnt; /* Internal */
+ ushort sen_paddrh; /* physical address (MSB) */
+ ushort sen_paddrm;
+ ushort sen_paddrl; /* physical address (LSB) */
+ ushort sen_pper; /* persistence */
+ ushort sen_rfbdptr; /* Rx first BD pointer */
+ ushort sen_tfbdptr; /* Tx first BD pointer */
+ ushort sen_tlbdptr; /* Tx last BD pointer */
+ uint sen_tbuf1data0; /* Save area 0 - current frame */
+ uint sen_tbuf1data1; /* Save area 1 - current frame */
+ uint sen_tbuf1rba; /* Internal */
+ uint sen_tbuf1crc; /* Internal */
+ ushort sen_tbuf1bcnt; /* Internal */
+ ushort sen_txlen; /* Tx Frame length counter */
+ ushort sen_iaddr1; /* Individual address filter */
+ ushort sen_iaddr2;
+ ushort sen_iaddr3;
+ ushort sen_iaddr4;
+ ushort sen_boffcnt; /* Backoff counter */
+
+ /* NOTE: Some versions of the manual have the following items
+ * incorrectly documented. Below is the proper order.
+ */
+ ushort sen_taddrh; /* temp address (MSB) */
+ ushort sen_taddrm;
+ ushort sen_taddrl; /* temp address (LSB) */
+} scc_enet_t;
+
+
+/* SCC Event register as used by Ethernet.
+*/
+#define SCCE_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */
+#define SCCE_ENET_TXE ((ushort)0x0010) /* Transmit Error */
+#define SCCE_ENET_RXF ((ushort)0x0008) /* Full frame received */
+#define SCCE_ENET_BSY ((ushort)0x0004) /* All incoming buffers full */
+#define SCCE_ENET_TXB ((ushort)0x0002) /* A buffer was transmitted */
+#define SCCE_ENET_RXB ((ushort)0x0001) /* A buffer was received */
+
+/* SCC Mode Register (PSMR) as used by Ethernet.
+*/
+#define SCC_PSMR_HBC ((ushort)0x8000) /* Enable heartbeat */
+#define SCC_PSMR_FC ((ushort)0x4000) /* Force collision */
+#define SCC_PSMR_RSH ((ushort)0x2000) /* Receive short frames */
+#define SCC_PSMR_IAM ((ushort)0x1000) /* Check individual hash */
+#define SCC_PSMR_ENCRC ((ushort)0x0800) /* Ethernet CRC mode */
+#define SCC_PSMR_PRO ((ushort)0x0200) /* Promiscuous mode */
+#define SCC_PSMR_BRO ((ushort)0x0100) /* Catch broadcast pkts */
+#define SCC_PSMR_SBT ((ushort)0x0080) /* Special backoff timer */
+#define SCC_PSMR_LPB ((ushort)0x0040) /* Set Loopback mode */
+#define SCC_PSMR_SIP ((ushort)0x0020) /* Sample Input Pins */
+#define SCC_PSMR_LCW ((ushort)0x0010) /* Late collision window */
+#define SCC_PSMR_NIB22 ((ushort)0x000a) /* Start frame search */
+#define SCC_PSMR_FDE ((ushort)0x0001) /* Full duplex enable */
+
+/* Buffer descriptor control/status used by Ethernet receive.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_RX_EMPTY ((ushort)0x8000)
+#define BD_ENET_RX_WRAP ((ushort)0x2000)
+#define BD_ENET_RX_INTR ((ushort)0x1000)
+#define BD_ENET_RX_LAST ((ushort)0x0800)
+#define BD_ENET_RX_FIRST ((ushort)0x0400)
+#define BD_ENET_RX_MISS ((ushort)0x0100)
+#define BD_ENET_RX_BC ((ushort)0x0080) /* FCC Only */
+#define BD_ENET_RX_MC ((ushort)0x0040) /* FCC Only */
+#define BD_ENET_RX_LG ((ushort)0x0020)
+#define BD_ENET_RX_NO ((ushort)0x0010)
+#define BD_ENET_RX_SH ((ushort)0x0008)
+#define BD_ENET_RX_CR ((ushort)0x0004)
+#define BD_ENET_RX_OV ((ushort)0x0002)
+#define BD_ENET_RX_CL ((ushort)0x0001)
+#define BD_ENET_RX_STATS ((ushort)0x01ff) /* All status bits */
+
+/* Buffer descriptor control/status used by Ethernet transmit.
+ * Common to SCC and FCC.
+ */
+#define BD_ENET_TX_READY ((ushort)0x8000)
+#define BD_ENET_TX_PAD ((ushort)0x4000)
+#define BD_ENET_TX_WRAP ((ushort)0x2000)
+#define BD_ENET_TX_INTR ((ushort)0x1000)
+#define BD_ENET_TX_LAST ((ushort)0x0800)
+#define BD_ENET_TX_TC ((ushort)0x0400)
+#define BD_ENET_TX_DEF ((ushort)0x0200)
+#define BD_ENET_TX_HB ((ushort)0x0100)
+#define BD_ENET_TX_LC ((ushort)0x0080)
+#define BD_ENET_TX_RL ((ushort)0x0040)
+#define BD_ENET_TX_RCMASK ((ushort)0x003c)
+#define BD_ENET_TX_UN ((ushort)0x0002)
+#define BD_ENET_TX_CSL ((ushort)0x0001)
+#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
+
+/* SCC as UART
+*/
+typedef struct scc_uart {
+ sccp_t scc_genscc;
+ uint scc_res1; /* Reserved */
+ uint scc_res2; /* Reserved */
+ ushort scc_maxidl; /* Maximum idle chars */
+ ushort scc_idlc; /* temp idle counter */
+ ushort scc_brkcr; /* Break count register */
+ ushort scc_parec; /* receive parity error counter */
+ ushort scc_frmec; /* receive framing error counter */
+ ushort scc_nosec; /* receive noise counter */
+ ushort scc_brkec; /* receive break condition counter */
+ ushort scc_brkln; /* last received break length */
+ ushort scc_uaddr1; /* UART address character 1 */
+ ushort scc_uaddr2; /* UART address character 2 */
+ ushort scc_rtemp; /* Temp storage */
+ ushort scc_toseq; /* Transmit out of sequence char */
+ ushort scc_char1; /* control character 1 */
+ ushort scc_char2; /* control character 2 */
+ ushort scc_char3; /* control character 3 */
+ ushort scc_char4; /* control character 4 */
+ ushort scc_char5; /* control character 5 */
+ ushort scc_char6; /* control character 6 */
+ ushort scc_char7; /* control character 7 */
+ ushort scc_char8; /* control character 8 */
+ ushort scc_rccm; /* receive control character mask */
+ ushort scc_rccr; /* receive control character register */
+ ushort scc_rlbc; /* receive last break character */
+} scc_uart_t;
+
+/* SCC Event and Mask registers when it is used as a UART.
+*/
+#define UART_SCCM_GLR ((ushort)0x1000)
+#define UART_SCCM_GLT ((ushort)0x0800)
+#define UART_SCCM_AB ((ushort)0x0200)
+#define UART_SCCM_IDL ((ushort)0x0100)
+#define UART_SCCM_GRA ((ushort)0x0080)
+#define UART_SCCM_BRKE ((ushort)0x0040)
+#define UART_SCCM_BRKS ((ushort)0x0020)
+#define UART_SCCM_CCR ((ushort)0x0008)
+#define UART_SCCM_BSY ((ushort)0x0004)
+#define UART_SCCM_TX ((ushort)0x0002)
+#define UART_SCCM_RX ((ushort)0x0001)
+
+/* The SCC PSMR when used as a UART.
+*/
+#define SCU_PSMR_FLC ((ushort)0x8000)
+#define SCU_PSMR_SL ((ushort)0x4000)
+#define SCU_PSMR_CL ((ushort)0x3000)
+#define SCU_PSMR_UM ((ushort)0x0c00)
+#define SCU_PSMR_FRZ ((ushort)0x0200)
+#define SCU_PSMR_RZS ((ushort)0x0100)
+#define SCU_PSMR_SYN ((ushort)0x0080)
+#define SCU_PSMR_DRT ((ushort)0x0040)
+#define SCU_PSMR_PEN ((ushort)0x0010)
+#define SCU_PSMR_RPM ((ushort)0x000c)
+#define SCU_PSMR_REVP ((ushort)0x0008)
+#define SCU_PSMR_TPM ((ushort)0x0003)
+#define SCU_PSMR_TEVP ((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+ sccp_t st_genscc;
+ uint st_cpres; /* Preset CRC */
+ uint st_cmask; /* Constant mask for CRC */
+} scc_trans_t;
+
+#define BD_SCC_TX_LAST ((ushort)0x0800)
+
+/* How about some FCCs.....
+*/
+#define FCC_GFMR_DIAG_NORM ((uint)0x00000000)
+#define FCC_GFMR_DIAG_LE ((uint)0x40000000)
+#define FCC_GFMR_DIAG_AE ((uint)0x80000000)
+#define FCC_GFMR_DIAG_ALE ((uint)0xc0000000)
+#define FCC_GFMR_TCI ((uint)0x20000000)
+#define FCC_GFMR_TRX ((uint)0x10000000)
+#define FCC_GFMR_TTX ((uint)0x08000000)
+#define FCC_GFMR_TTX ((uint)0x08000000)
+#define FCC_GFMR_CDP ((uint)0x04000000)
+#define FCC_GFMR_CTSP ((uint)0x02000000)
+#define FCC_GFMR_CDS ((uint)0x01000000)
+#define FCC_GFMR_CTSS ((uint)0x00800000)
+#define FCC_GFMR_SYNL_NONE ((uint)0x00000000)
+#define FCC_GFMR_SYNL_AUTO ((uint)0x00004000)
+#define FCC_GFMR_SYNL_8 ((uint)0x00008000)
+#define FCC_GFMR_SYNL_16 ((uint)0x0000c000)
+#define FCC_GFMR_RTSM ((uint)0x00002000)
+#define FCC_GFMR_RENC_NRZ ((uint)0x00000000)
+#define FCC_GFMR_RENC_NRZI ((uint)0x00000800)
+#define FCC_GFMR_REVD ((uint)0x00000400)
+#define FCC_GFMR_TENC_NRZ ((uint)0x00000000)
+#define FCC_GFMR_TENC_NRZI ((uint)0x00000100)
+#define FCC_GFMR_TCRC_16 ((uint)0x00000000)
+#define FCC_GFMR_TCRC_32 ((uint)0x00000080)
+#define FCC_GFMR_ENR ((uint)0x00000020)
+#define FCC_GFMR_ENT ((uint)0x00000010)
+#define FCC_GFMR_MODE_ENET ((uint)0x0000000c)
+#define FCC_GFMR_MODE_ATM ((uint)0x0000000a)
+#define FCC_GFMR_MODE_HDLC ((uint)0x00000000)
+
+/* Generic FCC parameter ram.
+*/
+typedef struct fcc_param {
+ ushort fcc_riptr; /* Rx Internal temp pointer */
+ ushort fcc_tiptr; /* Tx Internal temp pointer */
+ ushort fcc_res1;
+ ushort fcc_mrblr; /* Max receive buffer length, mod 32 bytes */
+ uint fcc_rstate; /* Upper byte is Func code, must be set */
+ uint fcc_rbase; /* Receive BD base */
+ ushort fcc_rbdstat; /* RxBD status */
+ ushort fcc_rbdlen; /* RxBD down counter */
+ uint fcc_rdptr; /* RxBD internal data pointer */
+ uint fcc_tstate; /* Upper byte is Func code, must be set */
+ uint fcc_tbase; /* Transmit BD base */
+ ushort fcc_tbdstat; /* TxBD status */
+ ushort fcc_tbdlen; /* TxBD down counter */
+ uint fcc_tdptr; /* TxBD internal data pointer */
+ uint fcc_rbptr; /* Rx BD Internal buf pointer */
+ uint fcc_tbptr; /* Tx BD Internal buf pointer */
+ uint fcc_rcrc; /* Rx temp CRC */
+ uint fcc_res2;
+ uint fcc_tcrc; /* Tx temp CRC */
+} fccp_t;
+
+
+/* Ethernet controller through FCC.
+*/
+typedef struct fcc_enet {
+ fccp_t fen_genfcc;
+ uint fen_statbuf; /* Internal status buffer */
+ uint fen_camptr; /* CAM address */
+ uint fen_cmask; /* Constant mask for CRC */
+ uint fen_cpres; /* Preset CRC */
+ uint fen_crcec; /* CRC Error counter */
+ uint fen_alec; /* alignment error counter */
+ uint fen_disfc; /* discard frame counter */
+ ushort fen_retlim; /* Retry limit */
+ ushort fen_retcnt; /* Retry counter */
+ ushort fen_pper; /* Persistence */
+ ushort fen_boffcnt; /* backoff counter */
+ uint fen_gaddrh; /* Group address filter, high 32-bits */
+ uint fen_gaddrl; /* Group address filter, low 32-bits */
+ ushort fen_tfcstat; /* out of sequence TxBD */
+ ushort fen_tfclen;
+ uint fen_tfcptr;
+ ushort fen_mflr; /* Maximum frame length (1518) */
+ ushort fen_paddrh; /* MAC address */
+ ushort fen_paddrm;
+ ushort fen_paddrl;
+ ushort fen_ibdcount; /* Internal BD counter */
+ ushort fen_ibdstart; /* Internal BD start pointer */
+ ushort fen_ibdend; /* Internal BD end pointer */
+ ushort fen_txlen; /* Internal Tx frame length counter */
+ uint fen_ibdbase[8]; /* Internal use */
+ uint fen_iaddrh; /* Individual address filter */
+ uint fen_iaddrl;
+ ushort fen_minflr; /* Minimum frame length (64) */
+ ushort fen_taddrh; /* Filter transfer MAC address */
+ ushort fen_taddrm;
+ ushort fen_taddrl;
+ ushort fen_padptr; /* Pointer to pad byte buffer */
+ ushort fen_cftype; /* control frame type */
+ ushort fen_cfrange; /* control frame range */
+ ushort fen_maxb; /* maximum BD count */
+ ushort fen_maxd1; /* Max DMA1 length (1520) */
+ ushort fen_maxd2; /* Max DMA2 length (1520) */
+ ushort fen_maxd; /* internal max DMA count */
+ ushort fen_dmacnt; /* internal DMA counter */
+ uint fen_octc; /* Total octect counter */
+ uint fen_colc; /* Total collision counter */
+ uint fen_broc; /* Total broadcast packet counter */
+ uint fen_mulc; /* Total multicast packet count */
+ uint fen_uspc; /* Total packets < 64 bytes */
+ uint fen_frgc; /* Total packets < 64 bytes with errors */
+ uint fen_ospc; /* Total packets > 1518 */
+ uint fen_jbrc; /* Total packets > 1518 with errors */
+ uint fen_p64c; /* Total packets == 64 bytes */
+ uint fen_p65c; /* Total packets 64 < bytes <= 127 */
+ uint fen_p128c; /* Total packets 127 < bytes <= 255 */
+ uint fen_p256c; /* Total packets 256 < bytes <= 511 */
+ uint fen_p512c; /* Total packets 512 < bytes <= 1023 */
+ uint fen_p1024c; /* Total packets 1024 < bytes <= 1518 */
+ uint fen_cambuf; /* Internal CAM buffer poiner */
+ ushort fen_rfthr; /* Received frames threshold */
+ ushort fen_rfcnt; /* Received frames count */
+} fcc_enet_t;
+
+/* FCC Event/Mask register as used by Ethernet.
+*/
+#define FCC_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */
+#define FCC_ENET_RXC ((ushort)0x0040) /* Control Frame Received */
+#define FCC_ENET_TXC ((ushort)0x0020) /* Out of seq. Tx sent */
+#define FCC_ENET_TXE ((ushort)0x0010) /* Transmit Error */
+#define FCC_ENET_RXF ((ushort)0x0008) /* Full frame received */
+#define FCC_ENET_BSY ((ushort)0x0004) /* Busy. Rx Frame dropped */
+#define FCC_ENET_TXB ((ushort)0x0002) /* A buffer was transmitted */
+#define FCC_ENET_RXB ((ushort)0x0001) /* A buffer was received */
+
+/* FCC Mode Register (FPSMR) as used by Ethernet.
+*/
+#define FCC_PSMR_HBC ((uint)0x80000000) /* Enable heartbeat */
+#define FCC_PSMR_FC ((uint)0x40000000) /* Force Collision */
+#define FCC_PSMR_SBT ((uint)0x20000000) /* Stop backoff timer */
+#define FCC_PSMR_LPB ((uint)0x10000000) /* Local protect. 1 = FDX */
+#define FCC_PSMR_LCW ((uint)0x08000000) /* Late collision select */
+#define FCC_PSMR_FDE ((uint)0x04000000) /* Full Duplex Enable */
+#define FCC_PSMR_MON ((uint)0x02000000) /* RMON Enable */
+#define FCC_PSMR_PRO ((uint)0x00400000) /* Promiscuous Enable */
+#define FCC_PSMR_FCE ((uint)0x00200000) /* Flow Control Enable */
+#define FCC_PSMR_RSH ((uint)0x00100000) /* Receive Short Frames */
+#define FCC_PSMR_CAM ((uint)0x00000400) /* CAM enable */
+#define FCC_PSMR_BRO ((uint)0x00000200) /* Broadcast pkt discard */
+#define FCC_PSMR_ENCRC ((uint)0x00000080) /* Use 32-bit CRC */
+
+/* IIC parameter RAM.
+*/
+typedef struct iic {
+ ushort iic_rbase; /* Rx Buffer descriptor base address */
+ ushort iic_tbase; /* Tx Buffer descriptor base address */
+ u_char iic_rfcr; /* Rx function code */
+ u_char iic_tfcr; /* Tx function code */
+ ushort iic_mrblr; /* Max receive buffer length */
+ uint iic_rstate; /* Internal */
+ uint iic_rdp; /* Internal */
+ ushort iic_rbptr; /* Internal */
+ ushort iic_rbc; /* Internal */
+ uint iic_rxtmp; /* Internal */
+ uint iic_tstate; /* Internal */
+ uint iic_tdp; /* Internal */
+ ushort iic_tbptr; /* Internal */
+ ushort iic_tbc; /* Internal */
+ uint iic_txtmp; /* Internal */
+} iic_t;
+
+/* SPI parameter RAM.
+*/
+typedef struct spi {
+ ushort spi_rbase; /* Rx Buffer descriptor base address */
+ ushort spi_tbase; /* Tx Buffer descriptor base address */
+ u_char spi_rfcr; /* Rx function code */
+ u_char spi_tfcr; /* Tx function code */
+ ushort spi_mrblr; /* Max receive buffer length */
+ uint spi_rstate; /* Internal */
+ uint spi_rdp; /* Internal */
+ ushort spi_rbptr; /* Internal */
+ ushort spi_rbc; /* Internal */
+ uint spi_rxtmp; /* Internal */
+ uint spi_tstate; /* Internal */
+ uint spi_tdp; /* Internal */
+ ushort spi_tbptr; /* Internal */
+ ushort spi_tbc; /* Internal */
+ uint spi_txtmp; /* Internal */
+ uint spi_res; /* Tx temp. */
+ uint spi_res1[4]; /* SDMA temp. */
+} spi_t;
+
+/* SPI Mode register.
+*/
+#define SPMODE_LOOP ((ushort)0x4000) /* Loopback */
+#define SPMODE_CI ((ushort)0x2000) /* Clock Invert */
+#define SPMODE_CP ((ushort)0x1000) /* Clock Phase */
+#define SPMODE_DIV16 ((ushort)0x0800) /* BRG/16 mode */
+#define SPMODE_REV ((ushort)0x0400) /* Reversed Data */
+#define SPMODE_MSTR ((ushort)0x0200) /* SPI Master */
+#define SPMODE_EN ((ushort)0x0100) /* Enable */
+#define SPMODE_LENMSK ((ushort)0x00f0) /* character length */
+#define SPMODE_PMMSK ((ushort)0x000f) /* prescale modulus */
+
+#define SPMODE_LEN(x) ((((x)-1)&0xF)<<4)
+#define SPMODE_PM(x) ((x) &0xF)
+
+#define SPI_EB ((u_char)0x10) /* big endian byte order */
+
+#define BD_IIC_START ((ushort)0x0400)
+
+/*-----------------------------------------------------------------------
+ * CMXFCR - CMX FCC Clock Route Register 15-12
+ */
+#define CMXFCR_FC1 0x40000000 /* FCC1 connection */
+#define CMXFCR_RF1CS_MSK 0x38000000 /* Receive FCC1 Clock Source Mask */
+#define CMXFCR_TF1CS_MSK 0x07000000 /* Transmit FCC1 Clock Source Mask */
+#define CMXFCR_FC2 0x00400000 /* FCC2 connection */
+#define CMXFCR_RF2CS_MSK 0x00380000 /* Receive FCC2 Clock Source Mask */
+#define CMXFCR_TF2CS_MSK 0x00070000 /* Transmit FCC2 Clock Source Mask */
+#define CMXFCR_FC3 0x00004000 /* FCC3 connection */
+#define CMXFCR_RF3CS_MSK 0x00003800 /* Receive FCC3 Clock Source Mask */
+#define CMXFCR_TF3CS_MSK 0x00000700 /* Transmit FCC3 Clock Source Mask */
+
+#define CMXFCR_RF1CS_BRG5 0x00000000 /* Receive FCC1 Clock Source is BRG5 */
+#define CMXFCR_RF1CS_BRG6 0x08000000 /* Receive FCC1 Clock Source is BRG6 */
+#define CMXFCR_RF1CS_BRG7 0x10000000 /* Receive FCC1 Clock Source is BRG7 */
+#define CMXFCR_RF1CS_BRG8 0x18000000 /* Receive FCC1 Clock Source is BRG8 */
+#define CMXFCR_RF1CS_CLK9 0x20000000 /* Receive FCC1 Clock Source is CLK9 */
+#define CMXFCR_RF1CS_CLK10 0x28000000 /* Receive FCC1 Clock Source is CLK10 */
+#define CMXFCR_RF1CS_CLK11 0x30000000 /* Receive FCC1 Clock Source is CLK11 */
+#define CMXFCR_RF1CS_CLK12 0x38000000 /* Receive FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_TF1CS_BRG5 0x00000000 /* Transmit FCC1 Clock Source is BRG5 */
+#define CMXFCR_TF1CS_BRG6 0x01000000 /* Transmit FCC1 Clock Source is BRG6 */
+#define CMXFCR_TF1CS_BRG7 0x02000000 /* Transmit FCC1 Clock Source is BRG7 */
+#define CMXFCR_TF1CS_BRG8 0x03000000 /* Transmit FCC1 Clock Source is BRG8 */
+#define CMXFCR_TF1CS_CLK9 0x04000000 /* Transmit FCC1 Clock Source is CLK9 */
+#define CMXFCR_TF1CS_CLK10 0x05000000 /* Transmit FCC1 Clock Source is CLK10 */
+#define CMXFCR_TF1CS_CLK11 0x06000000 /* Transmit FCC1 Clock Source is CLK11 */
+#define CMXFCR_TF1CS_CLK12 0x07000000 /* Transmit FCC1 Clock Source is CLK12 */
+
+#define CMXFCR_RF2CS_BRG5 0x00000000 /* Receive FCC2 Clock Source is BRG5 */
+#define CMXFCR_RF2CS_BRG6 0x00080000 /* Receive FCC2 Clock Source is BRG6 */
+#define CMXFCR_RF2CS_BRG7 0x00100000 /* Receive FCC2 Clock Source is BRG7 */
+#define CMXFCR_RF2CS_BRG8 0x00180000 /* Receive FCC2 Clock Source is BRG8 */
+#define CMXFCR_RF2CS_CLK13 0x00200000 /* Receive FCC2 Clock Source is CLK13 */
+#define CMXFCR_RF2CS_CLK14 0x00280000 /* Receive FCC2 Clock Source is CLK14 */
+#define CMXFCR_RF2CS_CLK15 0x00300000 /* Receive FCC2 Clock Source is CLK15 */
+#define CMXFCR_RF2CS_CLK16 0x00380000 /* Receive FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_TF2CS_BRG5 0x00000000 /* Transmit FCC2 Clock Source is BRG5 */
+#define CMXFCR_TF2CS_BRG6 0x00010000 /* Transmit FCC2 Clock Source is BRG6 */
+#define CMXFCR_TF2CS_BRG7 0x00020000 /* Transmit FCC2 Clock Source is BRG7 */
+#define CMXFCR_TF2CS_BRG8 0x00030000 /* Transmit FCC2 Clock Source is BRG8 */
+#define CMXFCR_TF2CS_CLK13 0x00040000 /* Transmit FCC2 Clock Source is CLK13 */
+#define CMXFCR_TF2CS_CLK14 0x00050000 /* Transmit FCC2 Clock Source is CLK14 */
+#define CMXFCR_TF2CS_CLK15 0x00060000 /* Transmit FCC2 Clock Source is CLK15 */
+#define CMXFCR_TF2CS_CLK16 0x00070000 /* Transmit FCC2 Clock Source is CLK16 */
+
+#define CMXFCR_RF3CS_BRG5 0x00000000 /* Receive FCC3 Clock Source is BRG5 */
+#define CMXFCR_RF3CS_BRG6 0x00000800 /* Receive FCC3 Clock Source is BRG6 */
+#define CMXFCR_RF3CS_BRG7 0x00001000 /* Receive FCC3 Clock Source is BRG7 */
+#define CMXFCR_RF3CS_BRG8 0x00001800 /* Receive FCC3 Clock Source is BRG8 */
+#define CMXFCR_RF3CS_CLK13 0x00002000 /* Receive FCC3 Clock Source is CLK13 */
+#define CMXFCR_RF3CS_CLK14 0x00002800 /* Receive FCC3 Clock Source is CLK14 */
+#define CMXFCR_RF3CS_CLK15 0x00003000 /* Receive FCC3 Clock Source is CLK15 */
+#define CMXFCR_RF3CS_CLK16 0x00003800 /* Receive FCC3 Clock Source is CLK16 */
+
+#define CMXFCR_TF3CS_BRG5 0x00000000 /* Transmit FCC3 Clock Source is BRG5 */
+#define CMXFCR_TF3CS_BRG6 0x00000100 /* Transmit FCC3 Clock Source is BRG6 */
+#define CMXFCR_TF3CS_BRG7 0x00000200 /* Transmit FCC3 Clock Source is BRG7 */
+#define CMXFCR_TF3CS_BRG8 0x00000300 /* Transmit FCC3 Clock Source is BRG8 */
+#define CMXFCR_TF3CS_CLK13 0x00000400 /* Transmit FCC3 Clock Source is CLK13 */
+#define CMXFCR_TF3CS_CLK14 0x00000500 /* Transmit FCC3 Clock Source is CLK14 */
+#define CMXFCR_TF3CS_CLK15 0x00000600 /* Transmit FCC3 Clock Source is CLK15 */
+#define CMXFCR_TF3CS_CLK16 0x00000700 /* Transmit FCC3 Clock Source is CLK16 */
+
+/*-----------------------------------------------------------------------
+ * CMXSCR - CMX SCC Clock Route Register 15-14
+ */
+#define CMXSCR_GR1 0x80000000 /* Grant Support of SCC1 */
+#define CMXSCR_SC1 0x40000000 /* SCC1 connection */
+#define CMXSCR_RS1CS_MSK 0x38000000 /* Receive SCC1 Clock Source Mask */
+#define CMXSCR_TS1CS_MSK 0x07000000 /* Transmit SCC1 Clock Source Mask */
+#define CMXSCR_GR2 0x00800000 /* Grant Support of SCC2 */
+#define CMXSCR_SC2 0x00400000 /* SCC2 connection */
+#define CMXSCR_RS2CS_MSK 0x00380000 /* Receive SCC2 Clock Source Mask */
+#define CMXSCR_TS2CS_MSK 0x00070000 /* Transmit SCC2 Clock Source Mask */
+#define CMXSCR_GR3 0x00008000 /* Grant Support of SCC3 */
+#define CMXSCR_SC3 0x00004000 /* SCC3 connection */
+#define CMXSCR_RS3CS_MSK 0x00003800 /* Receive SCC3 Clock Source Mask */
+#define CMXSCR_TS3CS_MSK 0x00000700 /* Transmit SCC3 Clock Source Mask */
+#define CMXSCR_GR4 0x00000080 /* Grant Support of SCC4 */
+#define CMXSCR_SC4 0x00000040 /* SCC4 connection */
+#define CMXSCR_RS4CS_MSK 0x00000038 /* Receive SCC4 Clock Source Mask */
+#define CMXSCR_TS4CS_MSK 0x00000007 /* Transmit SCC4 Clock Source Mask */
+
+#define CMXSCR_RS1CS_BRG1 0x00000000 /* SCC1 Rx Clock Source is BRG1 */
+#define CMXSCR_RS1CS_BRG2 0x08000000 /* SCC1 Rx Clock Source is BRG2 */
+#define CMXSCR_RS1CS_BRG3 0x10000000 /* SCC1 Rx Clock Source is BRG3 */
+#define CMXSCR_RS1CS_BRG4 0x18000000 /* SCC1 Rx Clock Source is BRG4 */
+#define CMXSCR_RS1CS_CLK11 0x20000000 /* SCC1 Rx Clock Source is CLK11 */
+#define CMXSCR_RS1CS_CLK12 0x28000000 /* SCC1 Rx Clock Source is CLK12 */
+#define CMXSCR_RS1CS_CLK3 0x30000000 /* SCC1 Rx Clock Source is CLK3 */
+#define CMXSCR_RS1CS_CLK4 0x38000000 /* SCC1 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS1CS_BRG1 0x00000000 /* SCC1 Tx Clock Source is BRG1 */
+#define CMXSCR_TS1CS_BRG2 0x01000000 /* SCC1 Tx Clock Source is BRG2 */
+#define CMXSCR_TS1CS_BRG3 0x02000000 /* SCC1 Tx Clock Source is BRG3 */
+#define CMXSCR_TS1CS_BRG4 0x03000000 /* SCC1 Tx Clock Source is BRG4 */
+#define CMXSCR_TS1CS_CLK11 0x04000000 /* SCC1 Tx Clock Source is CLK11 */
+#define CMXSCR_TS1CS_CLK12 0x05000000 /* SCC1 Tx Clock Source is CLK12 */
+#define CMXSCR_TS1CS_CLK3 0x06000000 /* SCC1 Tx Clock Source is CLK3 */
+#define CMXSCR_TS1CS_CLK4 0x07000000 /* SCC1 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS2CS_BRG1 0x00000000 /* SCC2 Rx Clock Source is BRG1 */
+#define CMXSCR_RS2CS_BRG2 0x00080000 /* SCC2 Rx Clock Source is BRG2 */
+#define CMXSCR_RS2CS_BRG3 0x00100000 /* SCC2 Rx Clock Source is BRG3 */
+#define CMXSCR_RS2CS_BRG4 0x00180000 /* SCC2 Rx Clock Source is BRG4 */
+#define CMXSCR_RS2CS_CLK11 0x00200000 /* SCC2 Rx Clock Source is CLK11 */
+#define CMXSCR_RS2CS_CLK12 0x00280000 /* SCC2 Rx Clock Source is CLK12 */
+#define CMXSCR_RS2CS_CLK3 0x00300000 /* SCC2 Rx Clock Source is CLK3 */
+#define CMXSCR_RS2CS_CLK4 0x00380000 /* SCC2 Rx Clock Source is CLK4 */
+
+#define CMXSCR_TS2CS_BRG1 0x00000000 /* SCC2 Tx Clock Source is BRG1 */
+#define CMXSCR_TS2CS_BRG2 0x00010000 /* SCC2 Tx Clock Source is BRG2 */
+#define CMXSCR_TS2CS_BRG3 0x00020000 /* SCC2 Tx Clock Source is BRG3 */
+#define CMXSCR_TS2CS_BRG4 0x00030000 /* SCC2 Tx Clock Source is BRG4 */
+#define CMXSCR_TS2CS_CLK11 0x00040000 /* SCC2 Tx Clock Source is CLK11 */
+#define CMXSCR_TS2CS_CLK12 0x00050000 /* SCC2 Tx Clock Source is CLK12 */
+#define CMXSCR_TS2CS_CLK3 0x00060000 /* SCC2 Tx Clock Source is CLK3 */
+#define CMXSCR_TS2CS_CLK4 0x00070000 /* SCC2 Tx Clock Source is CLK4 */
+
+#define CMXSCR_RS3CS_BRG1 0x00000000 /* SCC3 Rx Clock Source is BRG1 */
+#define CMXSCR_RS3CS_BRG2 0x00000800 /* SCC3 Rx Clock Source is BRG2 */
+#define CMXSCR_RS3CS_BRG3 0x00001000 /* SCC3 Rx Clock Source is BRG3 */
+#define CMXSCR_RS3CS_BRG4 0x00001800 /* SCC3 Rx Clock Source is BRG4 */
+#define CMXSCR_RS3CS_CLK5 0x00002000 /* SCC3 Rx Clock Source is CLK5 */
+#define CMXSCR_RS3CS_CLK6 0x00002800 /* SCC3 Rx Clock Source is CLK6 */
+#define CMXSCR_RS3CS_CLK7 0x00003000 /* SCC3 Rx Clock Source is CLK7 */
+#define CMXSCR_RS3CS_CLK8 0x00003800 /* SCC3 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS3CS_BRG1 0x00000000 /* SCC3 Tx Clock Source is BRG1 */
+#define CMXSCR_TS3CS_BRG2 0x00000100 /* SCC3 Tx Clock Source is BRG2 */
+#define CMXSCR_TS3CS_BRG3 0x00000200 /* SCC3 Tx Clock Source is BRG3 */
+#define CMXSCR_TS3CS_BRG4 0x00000300 /* SCC3 Tx Clock Source is BRG4 */
+#define CMXSCR_TS3CS_CLK5 0x00000400 /* SCC3 Tx Clock Source is CLK5 */
+#define CMXSCR_TS3CS_CLK6 0x00000500 /* SCC3 Tx Clock Source is CLK6 */
+#define CMXSCR_TS3CS_CLK7 0x00000600 /* SCC3 Tx Clock Source is CLK7 */
+#define CMXSCR_TS3CS_CLK8 0x00000700 /* SCC3 Tx Clock Source is CLK8 */
+
+#define CMXSCR_RS4CS_BRG1 0x00000000 /* SCC4 Rx Clock Source is BRG1 */
+#define CMXSCR_RS4CS_BRG2 0x00000008 /* SCC4 Rx Clock Source is BRG2 */
+#define CMXSCR_RS4CS_BRG3 0x00000010 /* SCC4 Rx Clock Source is BRG3 */
+#define CMXSCR_RS4CS_BRG4 0x00000018 /* SCC4 Rx Clock Source is BRG4 */
+#define CMXSCR_RS4CS_CLK5 0x00000020 /* SCC4 Rx Clock Source is CLK5 */
+#define CMXSCR_RS4CS_CLK6 0x00000028 /* SCC4 Rx Clock Source is CLK6 */
+#define CMXSCR_RS4CS_CLK7 0x00000030 /* SCC4 Rx Clock Source is CLK7 */
+#define CMXSCR_RS4CS_CLK8 0x00000038 /* SCC4 Rx Clock Source is CLK8 */
+
+#define CMXSCR_TS4CS_BRG1 0x00000000 /* SCC4 Tx Clock Source is BRG1 */
+#define CMXSCR_TS4CS_BRG2 0x00000001 /* SCC4 Tx Clock Source is BRG2 */
+#define CMXSCR_TS4CS_BRG3 0x00000002 /* SCC4 Tx Clock Source is BRG3 */
+#define CMXSCR_TS4CS_BRG4 0x00000003 /* SCC4 Tx Clock Source is BRG4 */
+#define CMXSCR_TS4CS_CLK5 0x00000004 /* SCC4 Tx Clock Source is CLK5 */
+#define CMXSCR_TS4CS_CLK6 0x00000005 /* SCC4 Tx Clock Source is CLK6 */
+#define CMXSCR_TS4CS_CLK7 0x00000006 /* SCC4 Tx Clock Source is CLK7 */
+#define CMXSCR_TS4CS_CLK8 0x00000007 /* SCC4 Tx Clock Source is CLK8 */
+
+#endif /* __CPM_85XX__ */
diff --git a/arch/powerpc/include/asm/e300.h b/arch/powerpc/include/asm/e300.h
new file mode 100644
index 0000000..bfef4df
--- /dev/null
+++ b/arch/powerpc/include/asm/e300.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2004 Freescale Semiconductor, Inc.
+ * Liberty Eran (liberty@freescale.com)
+ */
+
+#ifndef __E300_H__
+#define __E300_H__
+
+#define PVR_E300C1 0x80830000
+#define PVR_E300C2 0x80840000
+#define PVR_E300C3 0x80850000
+#define PVR_E300C4 0x80860000
+
+/*
+ * Hardware Implementation-Dependent Register 0 (HID0)
+ */
+
+/* #define HID0 1008 already defined in processor.h */
+#define HID0_MASK_MACHINE_CHECK 0x00000000
+#define HID0_ENABLE_MACHINE_CHECK 0x80000000
+
+#define HID0_DISABLE_CACHE_PARITY 0x00000000
+#define HID0_ENABLE_CACHE_PARITY 0x40000000
+
+#define HID0_DISABLE_ADDRESS_PARITY 0x00000000 /* on mpc8349ads must be disabled */
+#define HID0_ENABLE_ADDRESS_PARITY 0x20000000
+
+#define HID0_DISABLE_DATA_PARITY 0x00000000 /* on mpc8349ads must be disabled */
+#define HID0_ENABLE_DATE_PARITY 0x10000000
+
+#define HID0_CORE_CLK_OUT 0x00000000
+#define HID0_CORE_CLK_OUT_DIV_2 0x08000000
+
+#define HID0_ENABLE_ARTRY_OUT_PRECHARGE 0x00000000 /* on mpc8349ads must be enabled */
+#define HID0_DISABLE_ARTRY_OUT_PRECHARGE 0x01000000
+
+#define HID0_DISABLE_DOSE_MODE 0x00000000
+#define HID0_ENABLE_DOSE_MODE 0x00800000
+
+#define HID0_DISABLE_NAP_MODE 0x00000000
+#define HID0_ENABLE_NAP_MODE 0x00400000
+
+#define HID0_DISABLE_SLEEP_MODE 0x00000000
+#define HID0_ENABLE_SLEEP_MODE 0x00200000
+
+#define HID0_DISABLE_DYNAMIC_POWER_MANAGMENT 0x00000000
+#define HID0_ENABLE_DYNAMIC_POWER_MANAGMENT 0x00100000
+
+#define HID0_SOFT_RESET 0x00010000
+
+#define HID0_DISABLE_INSTRUCTION_CACHE 0x00000000
+#define HID0_ENABLE_INSTRUCTION_CACHE 0x00008000
+
+#define HID0_DISABLE_DATA_CACHE 0x00000000
+#define HID0_ENABLE_DATA_CACHE 0x00004000
+
+#define HID0_LOCK_INSTRUCTION_CACHE 0x00002000
+
+#define HID0_LOCK_DATA_CACHE 0x00001000
+
+#define HID0_INVALIDATE_INSTRUCTION_CACHE 0x00000800
+
+#define HID0_INVALIDATE_DATA_CACHE 0x00000400
+
+#define HID0_DISABLE_M_BIT 0x00000000
+#define HID0_ENABLE_M_BIT 0x00000080
+
+#define HID0_FBIOB 0x00000010
+
+#define HID0_DISABLE_ADDRESS_BROADCAST 0x00000000
+#define HID0_ENABLE_ADDRESS_BROADCAST 0x00000008
+
+#define HID0_ENABLE_NOOP_DCACHE_INSTRUCTION 0x00000000
+#define HID0_DISABLE_NOOP_DCACHE_INSTRUCTION 0x00000001
+
+/*
+ * Hardware Implementation-Dependent Register 2 (HID2)
+ */
+#define HID2 1011
+
+#define HID2_LET 0x08000000
+#define HID2_HBE 0x00040000
+#define HID2_IWLCK_000 0x00000000 /* no ways locked */
+#define HID2_IWLCK_001 0x00002000 /* way 0 locked */
+#define HID2_IWLCK_010 0x00004000 /* way 0 through way 1 locked */
+#define HID2_IWLCK_011 0x00006000 /* way 0 through way 2 locked */
+#define HID2_IWLCK_100 0x00008000 /* way 0 through way 3 locked */
+#define HID2_IWLCK_101 0x0000A000 /* way 0 through way 4 locked */
+#define HID2_IWLCK_110 0x0000C000 /* way 0 through way 5 locked */
+
+#endif /* __E300_H__ */
diff --git a/arch/powerpc/include/asm/errno.h b/arch/powerpc/include/asm/errno.h
new file mode 100644
index 0000000..4c82b50
--- /dev/null
+++ b/arch/powerpc/include/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/powerpc/include/asm/fsl_ddr_dimm_params.h b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
new file mode 100644
index 0000000..ffe4db8
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ddr_dimm_params.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef DDR2_DIMM_PARAMS_H
+#define DDR2_DIMM_PARAMS_H
+
+#define EDC_DATA_PARITY 1
+#define EDC_ECC 2
+#define EDC_AC_PARITY 4
+
+/* Parameters for a DDR2 dimm computed from the SPD */
+typedef struct dimm_params_s {
+
+ /* DIMM organization parameters */
+ char mpart[19]; /* guaranteed null terminated */
+
+ unsigned int n_ranks;
+ unsigned long long rank_density;
+ unsigned long long capacity;
+ unsigned int data_width;
+ unsigned int primary_sdram_width;
+ unsigned int ec_sdram_width;
+ unsigned int registered_dimm;
+
+ /* SDRAM device parameters */
+ unsigned int n_row_addr;
+ unsigned int n_col_addr;
+ unsigned int edc_config; /* 0 = none, 1 = parity, 2 = ECC */
+ unsigned int n_banks_per_sdram_device;
+ unsigned int burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */
+ unsigned int row_density;
+
+ /* used in computing base address of DIMMs */
+ unsigned long long base_address;
+ /* mirrored DIMMs */
+ unsigned int mirrored_dimm; /* only for ddr3 */
+
+ /* DIMM timing parameters */
+
+ unsigned int mtb_ps; /* medium timebase ps, only for ddr3 */
+ unsigned int ftb_10th_ps; /* fine timebase, in 1/10 ps, only for ddr3 */
+ unsigned int tAA_ps; /* minimum CAS latency time, only for ddr3 */
+ unsigned int tFAW_ps; /* four active window delay, only for ddr3 */
+
+ /*
+ * SDRAM clock periods
+ * The range for these are 1000-10000 so a short should be sufficient
+ */
+ unsigned int tCKmin_X_ps;
+ unsigned int tCKmin_X_minus_1_ps;
+ unsigned int tCKmin_X_minus_2_ps;
+ unsigned int tCKmax_ps;
+
+ /* SPD-defined CAS latencies */
+ unsigned int caslat_X;
+ unsigned int caslat_X_minus_1;
+ unsigned int caslat_X_minus_2;
+
+ unsigned int caslat_lowest_derated; /* Derated CAS latency */
+
+ /* basic timing parameters */
+ unsigned int tRCD_ps;
+ unsigned int tRP_ps;
+ unsigned int tRAS_ps;
+
+ unsigned int tWR_ps; /* maximum = 63750 ps */
+ unsigned int tWTR_ps; /* maximum = 63750 ps */
+ unsigned int tRFC_ps; /* max = 255 ns + 256 ns + .75 ns
+ = 511750 ps */
+
+ unsigned int tRRD_ps; /* maximum = 63750 ps */
+ unsigned int tRC_ps; /* maximum = 254 ns + .75 ns = 254750 ps */
+
+ unsigned int refresh_rate_ps;
+
+ /* DDR3 doesn't need these as below */
+ unsigned int tIS_ps; /* byte 32, spd->ca_setup */
+ unsigned int tIH_ps; /* byte 33, spd->ca_hold */
+ unsigned int tDS_ps; /* byte 34, spd->data_setup */
+ unsigned int tDH_ps; /* byte 35, spd->data_hold */
+ unsigned int tRTP_ps; /* byte 38, spd->trtp */
+ unsigned int tDQSQ_max_ps; /* byte 44, spd->tdqsq */
+ unsigned int tQHS_ps; /* byte 45, spd->tqhs */
+
+ /* DDR3 RDIMM */
+ unsigned char rcw[16]; /* Register Control Word 0-15 */
+} dimm_params_t;
+
+extern unsigned int ddr_compute_dimm_parameters(
+ const generic_spd_eeprom_t *spd,
+ dimm_params_t *pdimm,
+ unsigned int dimm_number);
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
new file mode 100644
index 0000000..640d329
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef FSL_DDR_MEMCTL_H
+#define FSL_DDR_MEMCTL_H
+
+/*
+ * Pick a basic DDR Technology.
+ */
+#include <ddr_spd.h>
+
+#define SDRAM_TYPE_DDR1 2
+#define SDRAM_TYPE_DDR2 3
+#define SDRAM_TYPE_LPDDR1 6
+#define SDRAM_TYPE_DDR3 7
+
+#define DDR_BL4 4 /* burst length 4 */
+#define DDR_BC4 DDR_BL4 /* burst chop for ddr3 */
+#define DDR_OTF 6 /* on-the-fly BC4 and BL8 */
+#define DDR_BL8 8 /* burst length 8 */
+
+#define DDR3_RTT_OFF 0
+#define DDR3_RTT_60_OHM 1 /* RTT_Nom = RZQ/4 */
+#define DDR3_RTT_120_OHM 2 /* RTT_Nom = RZQ/2 */
+#define DDR3_RTT_40_OHM 3 /* RTT_Nom = RZQ/6 */
+#define DDR3_RTT_20_OHM 4 /* RTT_Nom = RZQ/12 */
+#define DDR3_RTT_30_OHM 5 /* RTT_Nom = RZQ/8 */
+
+#define DDR2_RTT_OFF 0
+#define DDR2_RTT_75_OHM 1
+#define DDR2_RTT_150_OHM 2
+#define DDR2_RTT_50_OHM 3
+
+#if defined(CONFIG_FSL_DDR1)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (1)
+typedef ddr1_spd_eeprom_t generic_spd_eeprom_t;
+#ifndef CONFIG_FSL_SDRAM_TYPE
+#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR1
+#endif
+#elif defined(CONFIG_FSL_DDR2)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3)
+typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;
+#ifndef CONFIG_FSL_SDRAM_TYPE
+#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR2
+#endif
+#elif defined(CONFIG_FSL_DDR3)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3) /* FIXME */
+typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
+#ifndef CONFIG_FSL_SDRAM_TYPE
+#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR3
+#endif
+#endif /* #if defined(CONFIG_FSL_DDR1) */
+
+#define FSL_DDR_ODT_NEVER 0x0
+#define FSL_DDR_ODT_CS 0x1
+#define FSL_DDR_ODT_ALL_OTHER_CS 0x2
+#define FSL_DDR_ODT_OTHER_DIMM 0x3
+#define FSL_DDR_ODT_ALL 0x4
+#define FSL_DDR_ODT_SAME_DIMM 0x5
+#define FSL_DDR_ODT_CS_AND_OTHER_DIMM 0x6
+#define FSL_DDR_ODT_OTHER_CS_ONSAMEDIMM 0x7
+
+/* define bank(chip select) interleaving mode */
+#define FSL_DDR_CS0_CS1 0x40
+#define FSL_DDR_CS2_CS3 0x20
+#define FSL_DDR_CS0_CS1_AND_CS2_CS3 (FSL_DDR_CS0_CS1 | FSL_DDR_CS2_CS3)
+#define FSL_DDR_CS0_CS1_CS2_CS3 (FSL_DDR_CS0_CS1_AND_CS2_CS3 | 0x04)
+
+/* define memory controller interleaving mode */
+#define FSL_DDR_CACHE_LINE_INTERLEAVING 0x0
+#define FSL_DDR_PAGE_INTERLEAVING 0x1
+#define FSL_DDR_BANK_INTERLEAVING 0x2
+#define FSL_DDR_SUPERBANK_INTERLEAVING 0x3
+#define FSL_DDR_3WAY_1KB_INTERLEAVING 0xA
+#define FSL_DDR_3WAY_4KB_INTERLEAVING 0xC
+#define FSL_DDR_3WAY_8KB_INTERLEAVING 0xD
+/* placeholder for 4-way interleaving */
+#define FSL_DDR_4WAY_1KB_INTERLEAVING 0x1A
+#define FSL_DDR_4WAY_4KB_INTERLEAVING 0x1C
+#define FSL_DDR_4WAY_8KB_INTERLEAVING 0x1D
+
+#define SDRAM_CS_CONFIG_EN 0x80000000
+
+/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration
+ */
+#define SDRAM_CFG_MEM_EN 0x80000000
+#define SDRAM_CFG_SREN 0x40000000
+#define SDRAM_CFG_ECC_EN 0x20000000
+#define SDRAM_CFG_RD_EN 0x10000000
+#define SDRAM_CFG_SDRAM_TYPE_DDR1 0x02000000
+#define SDRAM_CFG_SDRAM_TYPE_DDR2 0x03000000
+#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000
+#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24
+#define SDRAM_CFG_DYN_PWR 0x00200000
+#define SDRAM_CFG_DBW_MASK 0x00180000
+#define SDRAM_CFG_DBW_SHIFT 19
+#define SDRAM_CFG_32_BE 0x00080000
+#define SDRAM_CFG_16_BE 0x00100000
+#define SDRAM_CFG_8_BE 0x00040000
+#define SDRAM_CFG_NCAP 0x00020000
+#define SDRAM_CFG_2T_EN 0x00008000
+#define SDRAM_CFG_BI 0x00000001
+
+#define SDRAM_CFG2_D_INIT 0x00000010
+#define SDRAM_CFG2_ODT_CFG_MASK 0x00600000
+#define SDRAM_CFG2_ODT_NEVER 0
+#define SDRAM_CFG2_ODT_ONLY_WRITE 1
+#define SDRAM_CFG2_ODT_ONLY_READ 2
+#define SDRAM_CFG2_ODT_ALWAYS 3
+
+#define TIMING_CFG_2_CPO_MASK 0x0F800000
+
+#if defined(CONFIG_P4080)
+#define RD_TO_PRE_MASK 0xf
+#define RD_TO_PRE_SHIFT 13
+#define WR_DATA_DELAY_MASK 0xf
+#define WR_DATA_DELAY_SHIFT 9
+#else
+#define RD_TO_PRE_MASK 0x7
+#define RD_TO_PRE_SHIFT 13
+#define WR_DATA_DELAY_MASK 0x7
+#define WR_DATA_DELAY_SHIFT 10
+#endif
+
+/* DDR_MD_CNTL */
+#define MD_CNTL_MD_EN 0x80000000
+#define MD_CNTL_CS_SEL_CS0 0x00000000
+#define MD_CNTL_CS_SEL_CS1 0x10000000
+#define MD_CNTL_CS_SEL_CS2 0x20000000
+#define MD_CNTL_CS_SEL_CS3 0x30000000
+#define MD_CNTL_CS_SEL_CS0_CS1 0x40000000
+#define MD_CNTL_CS_SEL_CS2_CS3 0x50000000
+#define MD_CNTL_MD_SEL_MR 0x00000000
+#define MD_CNTL_MD_SEL_EMR 0x01000000
+#define MD_CNTL_MD_SEL_EMR2 0x02000000
+#define MD_CNTL_MD_SEL_EMR3 0x03000000
+#define MD_CNTL_SET_REF 0x00800000
+#define MD_CNTL_SET_PRE 0x00400000
+#define MD_CNTL_CKE_CNTL_LOW 0x00100000
+#define MD_CNTL_CKE_CNTL_HIGH 0x00200000
+#define MD_CNTL_WRCW 0x00080000
+#define MD_CNTL_MD_VALUE(x) (x & 0x0000FFFF)
+
+/* DDR_CDR1 */
+#define DDR_CDR1_DHC_EN 0x80000000
+#define DDR_CDR1_ODT_SHIFT 17
+#define DDR_CDR1_ODT_MASK 0x6
+#define DDR_CDR2_ODT_MASK 0x1
+#define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT)
+#define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK)
+
+#if (defined(CONFIG_SYS_FSL_DDR_VER) && \
+ (CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7))
+#define DDR_CDR_ODT_OFF 0x0
+#define DDR_CDR_ODT_120ohm 0x1
+#define DDR_CDR_ODT_180ohm 0x2
+#define DDR_CDR_ODT_75ohm 0x3
+#define DDR_CDR_ODT_110ohm 0x4
+#define DDR_CDR_ODT_60hm 0x5
+#define DDR_CDR_ODT_70ohm 0x6
+#define DDR_CDR_ODT_47ohm 0x7
+#else
+#define DDR_CDR_ODT_75ohm 0x0
+#define DDR_CDR_ODT_55ohm 0x1
+#define DDR_CDR_ODT_60ohm 0x2
+#define DDR_CDR_ODT_50ohm 0x3
+#define DDR_CDR_ODT_150ohm 0x4
+#define DDR_CDR_ODT_43ohm 0x5
+#define DDR_CDR_ODT_120ohm 0x6
+#endif
+
+/* Record of register values computed */
+typedef struct fsl_ddr_cfg_regs_s {
+ struct {
+ unsigned int bnds;
+ unsigned int config;
+ unsigned int config_2;
+ } cs[CONFIG_CHIP_SELECTS_PER_CTRL];
+ unsigned int timing_cfg_3;
+ unsigned int timing_cfg_0;
+ unsigned int timing_cfg_1;
+ unsigned int timing_cfg_2;
+ unsigned int ddr_sdram_cfg;
+ unsigned int ddr_sdram_cfg_2;
+ unsigned int ddr_sdram_mode;
+ unsigned int ddr_sdram_mode_2;
+ unsigned int ddr_sdram_mode_3;
+ unsigned int ddr_sdram_mode_4;
+ unsigned int ddr_sdram_mode_5;
+ unsigned int ddr_sdram_mode_6;
+ unsigned int ddr_sdram_mode_7;
+ unsigned int ddr_sdram_mode_8;
+ unsigned int ddr_sdram_md_cntl;
+ unsigned int ddr_sdram_interval;
+ unsigned int ddr_data_init;
+ unsigned int ddr_sdram_clk_cntl;
+ unsigned int ddr_init_addr;
+ unsigned int ddr_init_ext_addr;
+ unsigned int timing_cfg_4;
+ unsigned int timing_cfg_5;
+ unsigned int ddr_zq_cntl;
+ unsigned int ddr_wrlvl_cntl;
+ unsigned int ddr_wrlvl_cntl_2;
+ unsigned int ddr_wrlvl_cntl_3;
+ unsigned int ddr_sr_cntr;
+ unsigned int ddr_sdram_rcw_1;
+ unsigned int ddr_sdram_rcw_2;
+ unsigned int ddr_eor;
+ unsigned int ddr_cdr1;
+ unsigned int ddr_cdr2;
+ unsigned int err_disable;
+ unsigned int err_int_en;
+ unsigned int debug[32];
+} fsl_ddr_cfg_regs_t;
+
+typedef struct memctl_options_partial_s {
+ unsigned int all_DIMMs_ECC_capable;
+ unsigned int all_DIMMs_tCKmax_ps;
+ unsigned int all_DIMMs_burst_lengths_bitmask;
+ unsigned int all_DIMMs_registered;
+ unsigned int all_DIMMs_unbuffered;
+ /* unsigned int lowest_common_SPD_caslat; */
+ unsigned int all_DIMMs_minimum_tRCD_ps;
+} memctl_options_partial_t;
+
+#define DDR_DATA_BUS_WIDTH_64 0
+#define DDR_DATA_BUS_WIDTH_32 1
+#define DDR_DATA_BUS_WIDTH_16 2
+/*
+ * Generalized parameters for memory controller configuration,
+ * might be a little specific to the FSL memory controller
+ */
+typedef struct memctl_options_s {
+ /*
+ * Memory organization parameters
+ *
+ * if DIMM is present in the system
+ * where DIMMs are with respect to chip select
+ * where chip selects are with respect to memory boundaries
+ */
+ unsigned int registered_dimm_en; /* use registered DIMM support */
+
+ /* Options local to a Chip Select */
+ struct cs_local_opts_s {
+ unsigned int auto_precharge;
+ unsigned int odt_rd_cfg;
+ unsigned int odt_wr_cfg;
+ unsigned int odt_rtt_norm;
+ unsigned int odt_rtt_wr;
+ } cs_local_opts[CONFIG_CHIP_SELECTS_PER_CTRL];
+
+ /* Special configurations for chip select */
+ unsigned int memctl_interleaving;
+ unsigned int memctl_interleaving_mode;
+ unsigned int ba_intlv_ctl;
+ unsigned int addr_hash;
+
+ /* Operational mode parameters */
+ unsigned int ECC_mode; /* Use ECC? */
+ /* Initialize ECC using memory controller? */
+ unsigned int ECC_init_using_memctl;
+ unsigned int DQS_config; /* Use DQS? maybe only with DDR2? */
+ /* SREN - self-refresh during sleep */
+ unsigned int self_refresh_in_sleep;
+ unsigned int dynamic_power; /* DYN_PWR */
+ /* memory data width to use (16-bit, 32-bit, 64-bit) */
+ unsigned int data_bus_width;
+ unsigned int burst_length; /* BL4, OTF and BL8 */
+ /* On-The-Fly Burst Chop enable */
+ unsigned int OTF_burst_chop_en;
+ /* mirrior DIMMs for DDR3 */
+ unsigned int mirrored_dimm;
+ unsigned int quad_rank_present;
+ unsigned int ap_en; /* address parity enable for RDIMM */
+
+ /* Global Timing Parameters */
+ unsigned int cas_latency_override;
+ unsigned int cas_latency_override_value;
+ unsigned int use_derated_caslat;
+ unsigned int additive_latency_override;
+ unsigned int additive_latency_override_value;
+
+ unsigned int clk_adjust; /* */
+ unsigned int cpo_override;
+ unsigned int write_data_delay; /* DQS adjust */
+
+ unsigned int wrlvl_override;
+ unsigned int wrlvl_sample; /* Write leveling */
+ unsigned int wrlvl_start;
+ unsigned int wrlvl_ctl_2;
+ unsigned int wrlvl_ctl_3;
+
+ unsigned int half_strength_driver_enable;
+ unsigned int twoT_en;
+ unsigned int threeT_en;
+ unsigned int bstopre;
+ unsigned int tCKE_clock_pulse_width_ps; /* tCKE */
+ unsigned int tFAW_window_four_activates_ps; /* tFAW -- FOUR_ACT */
+
+ /* Rtt impedance */
+ unsigned int rtt_override; /* rtt_override enable */
+ unsigned int rtt_override_value; /* that is Rtt_Nom for DDR3 */
+ unsigned int rtt_wr_override_value; /* this is Rtt_WR for DDR3 */
+
+ /* Automatic self refresh */
+ unsigned int auto_self_refresh_en;
+ unsigned int sr_it;
+ /* ZQ calibration */
+ unsigned int zq_en;
+ /* Write leveling */
+ unsigned int wrlvl_en;
+ /* RCW override for RDIMM */
+ unsigned int rcw_override;
+ unsigned int rcw_1;
+ unsigned int rcw_2;
+ /* control register 1 */
+ unsigned int ddr_cdr1;
+ unsigned int ddr_cdr2;
+
+ unsigned int trwt_override;
+ unsigned int trwt; /* read-to-write turnaround */
+} memctl_options_t;
+
+extern phys_size_t fsl_ddr_sdram(void);
+extern phys_size_t fsl_ddr_sdram_size(void);
+extern int fsl_use_spd(void);
+extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
+ unsigned int ctrl_num);
+u32 fsl_ddr_get_intl3r(void);
+
+/*
+ * The 85xx boards have a common prototype for fixed_sdram so put the
+ * declaration here.
+ */
+#ifdef CONFIG_MPC85xx
+extern phys_size_t fixed_sdram(void);
+#endif
+
+#if defined(CONFIG_DDR_ECC)
+extern void ddr_enable_ecc(unsigned int dram_size);
+#endif
+
+
+typedef struct fixed_ddr_parm{
+ int min_freq;
+ int max_freq;
+ fsl_ddr_cfg_regs_t *ddr_settings;
+} fixed_ddr_parm_t;
+#endif
diff --git a/arch/powerpc/include/asm/fsl_dma.h b/arch/powerpc/include/asm/fsl_dma.h
new file mode 100644
index 0000000..1164191
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_dma.h
@@ -0,0 +1,141 @@
+/*
+ * Freescale DMA Controller
+ *
+ * Copyright 2006 Freescale Semiconductor, Inc.
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_FSL_DMA_H_
+#define _ASM_FSL_DMA_H_
+
+#include <asm/types.h>
+
+#ifdef CONFIG_MPC83xx
+typedef struct fsl_dma {
+ uint mr; /* DMA mode register */
+#define FSL_DMA_MR_CS 0x00000001 /* Channel start */
+#define FSL_DMA_MR_CC 0x00000002 /* Channel continue */
+#define FSL_DMA_MR_CTM 0x00000004 /* Channel xfer mode */
+#define FSL_DMA_MR_CTM_DIRECT 0x00000004 /* Direct channel xfer mode */
+#define FSL_DMA_MR_EOTIE 0x00000080 /* End-of-transfer interrupt en */
+#define FSL_DMA_MR_PRC_MASK 0x00000c00 /* PCI read command */
+#define FSL_DMA_MR_SAHE 0x00001000 /* Source addr hold enable */
+#define FSL_DMA_MR_DAHE 0x00002000 /* Dest addr hold enable */
+#define FSL_DMA_MR_SAHTS_MASK 0x0000c000 /* Source addr hold xfer size */
+#define FSL_DMA_MR_DAHTS_MASK 0x00030000 /* Dest addr hold xfer size */
+#define FSL_DMA_MR_EMS_EN 0x00040000 /* Ext master start en */
+#define FSL_DMA_MR_IRQS 0x00080000 /* Interrupt steer */
+#define FSL_DMA_MR_DMSEN 0x00100000 /* Direct mode snooping en */
+#define FSL_DMA_MR_BWC_MASK 0x00e00000 /* Bandwidth/pause ctl */
+#define FSL_DMA_MR_DRCNT 0x0f000000 /* DMA request count */
+ uint sr; /* DMA status register */
+#define FSL_DMA_SR_EOCDI 0x00000001 /* End-of-chain/direct interrupt */
+#define FSL_DMA_SR_EOSI 0x00000002 /* End-of-segment interrupt */
+#define FSL_DMA_SR_CB 0x00000004 /* Channel busy */
+#define FSL_DMA_SR_TE 0x00000080 /* Transfer error */
+ uint cdar; /* DMA current descriptor address register */
+ char res0[4];
+ uint sar; /* DMA source address register */
+ char res1[4];
+ uint dar; /* DMA destination address register */
+ char res2[4];
+ uint bcr; /* DMA byte count register */
+ uint ndar; /* DMA next descriptor address register */
+ uint gsr; /* DMA general status register (DMA3 ONLY!) */
+ char res3[84];
+} fsl_dma_t;
+#else
+typedef struct fsl_dma {
+ uint mr; /* DMA mode register */
+#define FSL_DMA_MR_CS 0x00000001 /* Channel start */
+#define FSL_DMA_MR_CC 0x00000002 /* Channel continue */
+#define FSL_DMA_MR_CTM 0x00000004 /* Channel xfer mode */
+#define FSL_DMA_MR_CTM_DIRECT 0x00000004 /* Direct channel xfer mode */
+#define FSL_DMA_MR_CA 0x00000008 /* Channel abort */
+#define FSL_DMA_MR_CDSM 0x00000010
+#define FSL_DMA_MR_XFE 0x00000020 /* Extended features en */
+#define FSL_DMA_MR_EIE 0x00000040 /* Error interrupt en */
+#define FSL_DMA_MR_EOLSIE 0x00000080 /* End-of-lists interrupt en */
+#define FSL_DMA_MR_EOLNIE 0x00000100 /* End-of-links interrupt en */
+#define FSL_DMA_MR_EOSIE 0x00000200 /* End-of-seg interrupt en */
+#define FSL_DMA_MR_SRW 0x00000400 /* Single register write */
+#define FSL_DMA_MR_SAHE 0x00001000 /* Source addr hold enable */
+#define FSL_DMA_MR_DAHE 0x00002000 /* Dest addr hold enable */
+#define FSL_DMA_MR_SAHTS_MASK 0x0000c000 /* Source addr hold xfer size */
+#define FSL_DMA_MR_DAHTS_MASK 0x00030000 /* Dest addr hold xfer size */
+#define FSL_DMA_MR_EMS_EN 0x00040000 /* Ext master start en */
+#define FSL_DMA_MR_EMP_EN 0x00200000 /* Ext master pause en */
+#define FSL_DMA_MR_BWC_MASK 0x0f000000 /* Bandwidth/pause ctl */
+#define FSL_DMA_MR_BWC_DIS 0x0f000000 /* Bandwidth/pause ctl disable */
+ uint sr; /* DMA status register */
+#define FSL_DMA_SR_EOLSI 0x00000001 /* End-of-list interrupt */
+#define FSL_DMA_SR_EOSI 0x00000002 /* End-of-segment interrupt */
+#define FSL_DMA_SR_CB 0x00000004 /* Channel busy */
+#define FSL_DMA_SR_EOLNI 0x00000008 /* End-of-links interrupt */
+#define FSL_DMA_SR_PE 0x00000010 /* Programming error */
+#define FSL_DMA_SR_CH 0x00000020 /* Channel halted */
+#define FSL_DMA_SR_TE 0x00000080 /* Transfer error */
+ char res0[4];
+ uint clndar; /* DMA current link descriptor address register */
+ uint satr; /* DMA source attributes register */
+#define FSL_DMA_SATR_ESAD_MASK 0x000001ff /* Extended source addr */
+#define FSL_DMA_SATR_SREAD_NO_SNOOP 0x00040000 /* Read, don't snoop */
+#define FSL_DMA_SATR_SREAD_SNOOP 0x00050000 /* Read, snoop */
+#define FSL_DMA_SATR_SREAD_UNLOCK 0x00070000 /* Read, unlock l2 */
+#define FSL_DMA_SATR_STRAN_MASK 0x00f00000 /* Source interface */
+#define FSL_DMA_SATR_SSME 0x01000000 /* Source stride en */
+#define FSL_DMA_SATR_SPCIORDER 0x02000000 /* PCI transaction order */
+#define FSL_DMA_SATR_STFLOWLVL_MASK 0x0c000000 /* RIO flow level */
+#define FSL_DMA_SATR_SBPATRMU 0x20000000 /* Bypass ATMU */
+ uint sar; /* DMA source address register */
+ uint datr; /* DMA destination attributes register */
+#define FSL_DMA_DATR_EDAD_MASK 0x000001ff /* Extended dest addr */
+#define FSL_DMA_DATR_DWRITE_NO_SNOOP 0x00040000 /* Write, don't snoop */
+#define FSL_DMA_DATR_DWRITE_SNOOP 0x00050000 /* Write, snoop */
+#define FSL_DMA_DATR_DWRITE_ALLOC 0x00060000 /* Write, alloc l2 */
+#define FSL_DMA_DATR_DWRITE_LOCK 0x00070000 /* Write, lock l2 */
+#define FSL_DMA_DATR_DTRAN_MASK 0x00f00000 /* Dest interface */
+#define FSL_DMA_DATR_DSME 0x01000000 /* Dest stride en */
+#define FSL_DMA_DATR_DPCIORDER 0x02000000 /* PCI transaction order */
+#define FSL_DMA_DATR_DTFLOWLVL_MASK 0x0c000000 /* RIO flow level */
+#define FSL_DMA_DATR_DBPATRMU 0x20000000 /* Bypass ATMU */
+ uint dar; /* DMA destination address register */
+ uint bcr; /* DMA byte count register */
+ char res1[4];
+ uint nlndar; /* DMA next link descriptor address register */
+ char res2[8];
+ uint clabdar; /* DMA current List - alternate base descriptor address Register */
+ char res3[4];
+ uint nlsdar; /* DMA next list descriptor address register */
+ uint ssr; /* DMA source stride register */
+ uint dsr; /* DMA destination stride register */
+ char res4[56];
+} fsl_dma_t;
+#endif /* !CONFIG_MPC83xx */
+
+#ifdef CONFIG_FSL_DMA
+void dma_init(void);
+int dmacpy(phys_addr_t dest, phys_addr_t src, phys_size_t n);
+#if (defined(CONFIG_DDR_ECC) && !defined(CONFIG_ECC_INIT_VIA_DDRCONTROLLER))
+void dma_meminit(uint val, uint size);
+#endif
+#endif
+
+#endif /* _ASM_DMA_H_ */
diff --git a/arch/powerpc/include/asm/fsl_dtsec.h b/arch/powerpc/include/asm/fsl_dtsec.h
new file mode 100644
index 0000000..d1d993c
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_dtsec.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __DTSEC_H__
+#define __DTSEC_H__
+
+#include <asm/types.h>
+
+struct dtsec {
+ u32 tsec_id; /* controller ID and version */
+ u32 tsec_id2; /* controller ID and configuration */
+ u32 ievent; /* interrupt event */
+ u32 imask; /* interrupt mask */
+ u32 res0;
+ u32 ecntrl; /* ethernet control and configuration */
+ u32 ptv; /* pause time value */
+ u32 tbipa; /* TBI PHY address */
+ u32 res1[8];
+ u32 tctrl; /* Transmit control register */
+ u32 res2[3];
+ u32 rctrl; /* Receive control register */
+ u32 res3[11];
+ u32 igaddr[8]; /* Individual group address */
+ u32 gaddr[8]; /* group address */
+ u32 res4[16];
+ u32 maccfg1; /* MAC configuration register 1 */
+ u32 maccfg2; /* MAC configuration register 2 */
+ u32 ipgifg; /* inter-packet/inter-frame gap */
+ u32 hafdup; /* half-duplex control */
+ u32 maxfrm; /* Maximum frame size */
+ u32 res5[3];
+ u32 miimcfg; /* MII management configuration */
+ u32 miimcom; /* MII management command */
+ u32 miimadd; /* MII management address */
+ u32 miimcon; /* MII management control */
+ u32 miimstat; /* MII management status */
+ u32 miimind; /* MII management indicator */
+ u32 res6;
+ u32 ifstat; /* Interface status */
+ u32 macstnaddr1; /* MAC station address 1 */
+ u32 macstnaddr2; /* MAC station address 2 */
+ u32 res7[46];
+ /* transmit and receive counter */
+ u32 tr64; /* Tx and Rx 64 bytes frame */
+ u32 tr127; /* Tx and Rx 65 to 127 bytes frame */
+ u32 tr255; /* Tx and Rx 128 to 255 bytes frame */
+ u32 tr511; /* Tx and Rx 256 to 511 bytes frame */
+ u32 tr1k; /* Tx and Rx 512 to 1023 bytes frame */
+ u32 trmax; /* Tx and Rx 1024 to 1518 bytes frame */
+ u32 trmgv; /* Tx and Rx 1519 to 1522 good VLAN frame */
+ /* receive counters */
+ u32 rbyt; /* Receive byte counter */
+ u32 rpkt; /* Receive packet counter */
+ u32 rfcs; /* Receive FCS error */
+ u32 rmca; /* Receive multicast packet */
+ u32 rbca; /* Receive broadcast packet */
+ u32 rxcf; /* Receive control frame */
+ u32 rxpf; /* Receive pause frame */
+ u32 rxuo; /* Receive unknown OP code */
+ u32 raln; /* Receive alignment error */
+ u32 rflr; /* Receive frame length error */
+ u32 rcde; /* Receive code error */
+ u32 rcse; /* Receive carrier sense error */
+ u32 rund; /* Receive undersize packet */
+ u32 rovr; /* Receive oversize packet */
+ u32 rfrg; /* Receive fragments counter */
+ u32 rjbr; /* Receive jabber counter */
+ u32 rdrp; /* Receive drop counter */
+ /* transmit counters */
+ u32 tbyt; /* Transmit byte counter */
+ u32 tpkt; /* Transmit packet */
+ u32 tmca; /* Transmit multicast packet */
+ u32 tbca; /* Transmit broadcast packet */
+ u32 txpf; /* Transmit pause control frame */
+ u32 tdfr; /* Transmit deferral packet */
+ u32 tedf; /* Transmit excessive deferral pkt */
+ u32 tscl; /* Transmit single collision pkt */
+ u32 tmcl; /* Transmit multiple collision pkt */
+ u32 tlcl; /* Transmit late collision pkt */
+ u32 txcl; /* Transmit excessive collision */
+ u32 tncl; /* Transmit total collision */
+ u32 res8;
+ u32 tdrp; /* Transmit drop frame */
+ u32 tjbr; /* Transmit jabber frame */
+ u32 tfcs; /* Transmit FCS error */
+ u32 txcf; /* Transmit control frame */
+ u32 tovr; /* Transmit oversize frame */
+ u32 tund; /* Transmit undersize frame */
+ u32 tfrg; /* Transmit fragments frame */
+ /* counter controls */
+ u32 car1; /* carry register 1 */
+ u32 car2; /* carry register 2 */
+ u32 cam1; /* carry register 1 mask */
+ u32 cam2; /* carry register 2 mask */
+ u32 res9[80];
+};
+
+
+/* TBI register addresses */
+#define TBI_CR 0x00
+#define TBI_SR 0x01
+#define TBI_ANA 0x04
+#define TBI_ANLPBPA 0x05
+#define TBI_ANEX 0x06
+#define TBI_TBICON 0x11
+
+/* TBI MDIO register bit fields*/
+#define TBICON_CLK_SELECT 0x0020
+#define TBIANA_ASYMMETRIC_PAUSE 0x0100
+#define TBIANA_SYMMETRIC_PAUSE 0x0080
+#define TBIANA_HALF_DUPLEX 0x0040
+#define TBIANA_FULL_DUPLEX 0x0020
+#define TBICR_PHY_RESET 0x8000
+#define TBICR_ANEG_ENABLE 0x1000
+#define TBICR_RESTART_ANEG 0x0200
+#define TBICR_FULL_DUPLEX 0x0100
+#define TBICR_SPEED1_SET 0x0040
+
+/* IEVENT - interrupt events register */
+#define IEVENT_BABR 0x80000000 /* Babbling receive error */
+#define IEVENT_RXC 0x40000000 /* pause control frame received */
+#define IEVENT_MSRO 0x04000000 /* MIB counter overflow */
+#define IEVENT_GTSC 0x02000000 /* Graceful transmit stop complete */
+#define IEVENT_BABT 0x01000000 /* Babbling transmit error */
+#define IEVENT_TXC 0x00800000 /* control frame transmitted */
+#define IEVENT_TXE 0x00400000 /* Transmit channel error */
+#define IEVENT_LC 0x00040000 /* Late collision occurred */
+#define IEVENT_CRL 0x00020000 /* Collision retry exceed limit */
+#define IEVENT_XFUN 0x00010000 /* Transmit FIFO underrun */
+#define IEVENT_ABRT 0x00008000 /* Transmit packet abort */
+#define IEVENT_MMRD 0x00000400 /* MII management read complete */
+#define IEVENT_MMWR 0x00000200 /* MII management write complete */
+#define IEVENT_GRSC 0x00000100 /* Graceful stop complete */
+#define IEVENT_TDPE 0x00000002 /* Internal data parity error on Tx */
+#define IEVENT_RDPE 0x00000001 /* Internal data parity error on Rx */
+
+#define IEVENT_CLEAR_ALL 0xffffffff
+
+/* IMASK - interrupt mask register */
+#define IMASK_BREN 0x80000000 /* Babbling receive enable */
+#define IMASK_RXCEN 0x40000000 /* receive control enable */
+#define IMASK_MSROEN 0x04000000 /* MIB counter overflow enable */
+#define IMASK_GTSCEN 0x02000000 /* Graceful Tx stop complete enable */
+#define IMASK_BTEN 0x01000000 /* Babbling transmit error enable */
+#define IMASK_TXCEN 0x00800000 /* control frame transmitted enable */
+#define IMASK_TXEEN 0x00400000 /* Transmit channel error enable */
+#define IMASK_LCEN 0x00040000 /* Late collision interrupt enable */
+#define IMASK_CRLEN 0x00020000 /* Collision retry exceed limit */
+#define IMASK_XFUNEN 0x00010000 /* Transmit FIFO underrun enable */
+#define IMASK_ABRTEN 0x00008000 /* Transmit packet abort enable */
+#define IMASK_MMRDEN 0x00000400 /* MII management read complete enable */
+#define IMASK_MMWREN 0x00000200 /* MII management write complete enable */
+#define IMASK_GRSCEN 0x00000100 /* Graceful stop complete interrupt enable */
+#define IMASK_TDPEEN 0x00000002 /* Internal data parity error on Tx enable */
+#define IMASK_RDPEEN 0x00000001 /* Internal data parity error on Rx enable */
+
+#define IMASK_MASK_ALL 0x00000000
+
+/* ECNTRL - ethernet control register */
+#define ECNTRL_CFG_RO 0x80000000 /* GMIIM, RPM, R100M, SGMIIM bits are RO */
+#define ECNTRL_CLRCNT 0x00004000 /* clear all statistics */
+#define ECNTRL_AUTOZ 0x00002000 /* auto zero MIB counter */
+#define ECNTRL_STEN 0x00001000 /* enable internal counters to update */
+#define ECNTRL_GMIIM 0x00000040 /* 1- GMII or RGMII interface mode */
+#define ECNTRL_TBIM 0x00000020 /* 1- Ten-bit interface mode */
+#define ECNTRL_RPM 0x00000010 /* 1- RGMII reduced-pin mode */
+#define ECNTRL_R100M 0x00000008 /* 1- RGMII 100 Mbps, SGMII 100 Mbps
+ 0- RGMII 10 Mbps, SGMII 10 Mbps */
+#define ECNTRL_SGMIIM 0x00000002 /* 1- SGMII interface mode */
+#define ECNTRL_TBIM 0x00000020 /* 1- TBI Interface mode (for SGMII) */
+
+#define ECNTRL_DEFAULT (ECNTRL_TBIM | ECNTRL_R100M | ECNTRL_SGMIIM)
+
+/* TCTRL - Transmit control register */
+#define TCTRL_THDF 0x00000800 /* Transmit half-duplex flow control */
+#define TCTRL_TTSE 0x00000040 /* Transmit time-stamp enable */
+#define TCTRL_GTS 0x00000020 /* Graceful transmit stop */
+#define TCTRL_RFC_PAUSE 0x00000010 /* Receive flow control pause frame */
+
+/* RCTRL - Receive control register */
+#define RCTRL_PAL_MASK 0x001f0000 /* packet alignment padding length */
+#define RCTRL_PAL_SHIFT 16
+#define RCTRL_CFA 0x00008000 /* control frame accept enable */
+#define RCTRL_GHTX 0x00000800 /* group address hash table extend */
+#define RCTRL_RTSE 0x00000040 /* receive 1588 time-stamp enable */
+#define RCTRL_GRS 0x00000020 /* graceful receive stop */
+#define RCTRL_BC_REJ 0x00000010 /* broadcast frame reject */
+#define RCTRL_BC_MPROM 0x00000008 /* all multicast/broadcast frames received */
+#define RCTRL_RSF 0x00000004 /* receive short frame(17~63 bytes) enable */
+#define RCTRL_EMEN 0x00000002 /* Exact match MAC address enable */
+#define RCTRL_UPROM 0x00000001 /* all unicast frame received */
+
+/* MACCFG1 - MAC configuration 1 register */
+#define MACCFG1_SOFT_RST 0x80000000 /* place the MAC in reset */
+#define MACCFG1_RST_RXMAC 0x00080000 /* reset receive MAC control block */
+#define MACCFG1_RST_TXMAC 0x00040000 /* reet transmit MAC control block */
+#define MACCFG1_RST_RXFUN 0x00020000 /* reset receive function block */
+#define MACCFG1_RST_TXFUN 0x00010000 /* reset transmit function block */
+#define MACCFG1_LOOPBACK 0x00000100 /* MAC loopback */
+#define MACCFG1_RX_FLOW 0x00000020 /* Receive flow */
+#define MACCFG1_TX_FLOW 0x00000010 /* Transmit flow */
+#define MACCFG1_SYNC_RXEN 0x00000008 /* Frame reception enabled */
+#define MACCFG1_RX_EN 0x00000004 /* Rx enable */
+#define MACCFG1_SYNC_TXEN 0x00000002 /* Frame transmission is enabled */
+#define MACCFG1_TX_EN 0x00000001 /* Tx enable */
+#define MACCFG1_RXTX_EN (MACCFG1_RX_EN | MACCFG1_TX_EN)
+
+/* MACCFG2 - MAC configuration 2 register */
+#define MACCFG2_PRE_LEN_MASK 0x0000f000 /* preamble length */
+#define MACCFG2_PRE_LEN(x) ((x << 12) & MACCFG2_PRE_LEN_MASK)
+#define MACCFG2_IF_MODE_MASK 0x00000300
+#define MACCFG2_IF_MODE_NIBBLE 0x00000100 /* MII, 10/100 Mbps MII/RMII */
+#define MACCFG2_IF_MODE_BYTE 0x00000200 /* GMII/TBI, 1000 GMII/TBI */
+#define MACCFG2_PRE_RX_EN 0x00000080 /* receive preamble enable */
+#define MACCFG2_PRE_TX_EN 0x00000040 /* tx preable enable */
+#define MACCFG2_HUGE_FRAME 0x00000020 /* >= max frame len enable */
+#define MACCFG2_LEN_CHECK 0x00000010 /* MAC check frame's length Rx */
+#define MACCFG2_MAG_EN 0x00000008 /* magic packet enable */
+#define MACCFG2_PAD_CRC 0x00000004 /* pad and append CRC */
+#define MACCFG2_CRC_EN 0x00000002 /* MAC appends a CRC on all frames */
+#define MACCFG2_FULL_DUPLEX 0x00000001 /* Full deplex mode */
+
+struct fsl_enet_mac;
+
+void init_dtsec(struct fsl_enet_mac *mac, void *base, void *phyregs,
+ int max_rx_len);
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_enet.h b/arch/powerpc/include/asm/fsl_enet.h
new file mode 100644
index 0000000..8227b66
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_enet.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef __ASM_PPC_FSL_ENET_H
+#define __ASM_PPC_FSL_ENET_H
+
+#include <phy.h>
+
+struct tsec_mii_mng {
+ u32 miimcfg; /* MII management configuration reg */
+ u32 miimcom; /* MII management command reg */
+ u32 miimadd; /* MII management address reg */
+ u32 miimcon; /* MII management control reg */
+ u32 miimstat; /* MII management status reg */
+ u32 miimind; /* MII management indication reg */
+ u32 ifstat; /* Interface Status Register */
+} __attribute__ ((packed));
+
+int fdt_fixup_phy_connection(void *blob, int offset, phy_interface_t phyc);
+
+#endif /* __ASM_PPC_FSL_ENET_H */
diff --git a/arch/powerpc/include/asm/fsl_fman.h b/arch/powerpc/include/asm/fsl_fman.h
new file mode 100644
index 0000000..299daca
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_fman.h
@@ -0,0 +1,479 @@
+/*
+ * MPC85xx Internal Memory Map
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_FMAN_H__
+#define __FSL_FMAN_H__
+
+#include <asm/types.h>
+
+typedef struct fm_bmi_common {
+ u32 fmbm_init; /* BMI initialization */
+ u32 fmbm_cfg1; /* BMI configuration1 */
+ u32 fmbm_cfg2; /* BMI configuration2 */
+ u32 res0[0x5];
+ u32 fmbm_ievr; /* interrupt event register */
+ u32 fmbm_ier; /* interrupt enable register */
+ u32 fmbm_ifr; /* interrupt force register */
+ u32 res1[0x5];
+ u32 fmbm_arb[0x8]; /* BMI arbitration */
+ u32 res2[0x28];
+ u32 fmbm_gde; /* global debug enable */
+ u32 fmbm_pp[0x3f]; /* BMI port parameters */
+ u32 res3;
+ u32 fmbm_pfs[0x3f]; /* BMI port FIFO size */
+ u32 res4;
+ u32 fmbm_ppid[0x3f];/* port partition ID */
+} fm_bmi_common_t;
+
+typedef struct fm_qmi_common {
+ u32 fmqm_gc; /* general configuration register */
+ u32 res0;
+ u32 fmqm_eie; /* error interrupt event register */
+ u32 fmqm_eien; /* error interrupt enable register */
+ u32 fmqm_eif; /* error interrupt force register */
+ u32 fmqm_ie; /* interrupt event register */
+ u32 fmqm_ien; /* interrupt enable register */
+ u32 fmqm_if; /* interrupt force register */
+ u32 fmqm_gs; /* global status register */
+ u32 fmqm_ts; /* task status register */
+ u32 fmqm_etfc; /* enqueue total frame counter */
+ u32 fmqm_dtfc; /* dequeue total frame counter */
+ u32 fmqm_dc0; /* dequeue counter 0 */
+ u32 fmqm_dc1; /* dequeue counter 1 */
+ u32 fmqm_dc2; /* dequeue counter 2 */
+ u32 fmqm_dc3; /* dequeue counter 3 */
+ u32 fmqm_dfnoc; /* dequeue FQID not override counter */
+ u32 fmqm_dfcc; /* dequeue FQID from context counter */
+ u32 fmqm_dffc; /* dequeue FQID from FD counter */
+ u32 fmqm_dcc; /* dequeue confirm counter */
+ u32 res1[0xc];
+ u32 fmqm_dtrc; /* debug trap configuration register */
+ u32 fmqm_efddd; /* enqueue frame descriptor dynamic debug */
+ u32 res3[0x2];
+ u32 res4[0xdc]; /* missing debug regs */
+} fm_qmi_common_t;
+
+typedef struct fm_bmi {
+ u8 res[1024];
+} fm_bmi_t;
+
+typedef struct fm_qmi {
+ u8 res[1024];
+} fm_qmi_t;
+
+struct fm_bmi_rx_port {
+ u32 fmbm_rcfg; /* Rx configuration */
+ u32 fmbm_rst; /* Rx status */
+ u32 fmbm_rda; /* Rx DMA attributes */
+ u32 fmbm_rfp; /* Rx FIFO parameters */
+ u32 fmbm_rfed; /* Rx frame end data */
+ u32 fmbm_ricp; /* Rx internal context parameters */
+ u32 fmbm_rim; /* Rx internal margins */
+ u32 fmbm_rebm; /* Rx external buffer margins */
+ u32 fmbm_rfne; /* Rx frame next engine */
+ u32 fmbm_rfca; /* Rx frame command attributes */
+ u32 fmbm_rfpne; /* Rx frame parser next engine */
+ u32 fmbm_rpso; /* Rx parse start offset */
+ u32 fmbm_rpp; /* Rx policer profile */
+ u32 fmbm_rccb; /* Rx coarse classification base */
+ u32 res1[0x2];
+ u32 fmbm_rprai[0x8]; /* Rx parse results array Initialization */
+ u32 fmbm_rfqid; /* Rx frame queue ID */
+ u32 fmbm_refqid; /* Rx error frame queue ID */
+ u32 fmbm_rfsdm; /* Rx frame status discard mask */
+ u32 fmbm_rfsem; /* Rx frame status error mask */
+ u32 fmbm_rfene; /* Rx frame enqueue next engine */
+ u32 res2[0x23];
+ u32 fmbm_ebmpi[0x8]; /* buffer manager pool information */
+ u32 fmbm_acnt[0x8]; /* allocate counter */
+ u32 res3[0x8];
+ u32 fmbm_cgm[0x8]; /* congestion group map */
+ u32 fmbm_mpd; /* BMan pool depletion */
+ u32 res4[0x1F];
+ u32 fmbm_rstc; /* Rx statistics counters */
+ u32 fmbm_rfrc; /* Rx frame counters */
+ u32 fmbm_rfbc; /* Rx bad frames counter */
+ u32 fmbm_rlfc; /* Rx large frames counter */
+ u32 fmbm_rffc; /* Rx filter frames counter */
+ u32 fmbm_rfdc; /* Rx frame discard counter */
+ u32 fmbm_rfldec; /* Rx frames list DMA error counter */
+ u32 fmbm_rodc; /* Rx out of buffers discard counter */
+ u32 fmbm_rbdc; /* Rx buffers deallocate counter */
+ u32 res5[0x17];
+ u32 fmbm_rpc; /* Rx performance counters */
+ u32 fmbm_rpcp; /* Rx performance count parameters */
+ u32 fmbm_rccn; /* Rx cycle counter */
+ u32 fmbm_rtuc; /* Rx tasks utilization counter */
+ u32 fmbm_rrquc; /* Rx receive queue utilization counter */
+ u32 fmbm_rduc; /* Rx DMA utilization counter */
+ u32 fmbm_rfuc; /* Rx FIFO utilization counter */
+ u32 fmbm_rpac; /* Rx pause activation counter */
+ u32 res6[0x18];
+ u32 fmbm_rdbg; /* Rx debug configuration */
+};
+
+/* FMBM_RCFG - Rx configuration */
+#define FMBM_RCFG_EN 0x80000000 /* port is enabled to receive data */
+#define FMBM_RCFG_FDOVR 0x02000000 /* frame discard override */
+#define FMBM_RCFG_IM 0x01000000 /* independent mode */
+
+/* FMBM_RST - Rx status */
+#define FMBM_RST_BSY 0x80000000 /* Rx port is busy */
+
+/* FMBM_RFCA - Rx frame command attributes */
+#define FMBM_RFCA_ORDER 0x80000000
+#define FMBM_RFCA_MR_MASK 0x003f0000
+#define FMBM_RFCA_MR(x) ((x << 16) & FMBM_RFCA_MR_MASK)
+
+/* FMBM_RSTC - Rx statistics */
+#define FMBM_RSTC_EN 0x80000000 /* statistics counters enable */
+
+struct fm_bmi_tx_port {
+ u32 fmbm_tcfg; /* Tx configuration */
+ u32 fmbm_tst; /* Tx status */
+ u32 fmbm_tda; /* Tx DMA attributes */
+ u32 fmbm_tfp; /* Tx FIFO parameters */
+ u32 fmbm_tfed; /* Tx frame end data */
+ u32 fmbm_ticp; /* Tx internal context parameters */
+ u32 fmbm_tfne; /* Tx frame next engine */
+ u32 fmbm_tfca; /* Tx frame command attributes */
+ u32 fmbm_tcfqid;/* Tx confirmation frame queue ID */
+ u32 fmbm_tfeqid;/* Tx error frame queue ID */
+ u32 fmbm_tfene; /* Tx frame enqueue next engine */
+ u32 fmbm_trlmts;/* Tx rate limiter scale */
+ u32 fmbm_trlmt; /* Tx rate limiter */
+ u32 res0[0x73];
+ u32 fmbm_tstc; /* Tx statistics counters */
+ u32 fmbm_tfrc; /* Tx frame counter */
+ u32 fmbm_tfdc; /* Tx frames discard counter */
+ u32 fmbm_tfledc;/* Tx frame length error discard counter */
+ u32 fmbm_tfufdc;/* Tx frame unsupported format discard counter */
+ u32 fmbm_tbdc; /* Tx buffers deallocate counter */
+ u32 res1[0x1a];
+ u32 fmbm_tpc; /* Tx performance counters */
+ u32 fmbm_tpcp; /* Tx performance count parameters */
+ u32 fmbm_tccn; /* Tx cycle counter */
+ u32 fmbm_ttuc; /* Tx tasks utilization counter */
+ u32 fmbm_ttcquc;/* Tx transmit confirm queue utilization counter */
+ u32 fmbm_tduc; /* Tx DMA utilization counter */
+ u32 fmbm_tfuc; /* Tx FIFO utilization counter */
+ u32 res2[0x19];
+ u32 fmbm_tdcfg; /* Tx debug configuration */
+};
+
+/* FMBM_TCFG - Tx configuration */
+#define FMBM_TCFG_EN 0x80000000 /* port is enabled to transmit data */
+#define FMBM_TCFG_IM 0x01000000 /* independent mode enable */
+
+/* FMBM_TST - Tx status */
+#define FMBM_TST_BSY 0x80000000 /* Tx port is busy */
+
+/* FMBM_TFCA - Tx frame command attributes */
+#define FMBM_TFCA_ORDER 0x80000000
+#define FMBM_TFCA_MR_MASK 0x003f0000
+#define FMBM_TFCA_MR(x) ((x << 16) & FMBM_TFCA_MR_MASK)
+
+/* FMBM_TSTC - Tx statistics counters */
+#define FMBM_TSTC_EN 0x80000000
+
+/* FMBM_INIT - BMI initialization register */
+#define FMBM_INIT_START 0x80000000 /* init internal buffers */
+
+/* FMBM_CFG1 - BMI configuration 1 */
+#define FMBM_CFG1_FBPS_MASK 0x03ff0000 /* Free buffer pool size */
+#define FMBM_CFG1_FBPS_SHIFT 16
+#define FMBM_CFG1_FBPO_MASK 0x000003ff /* Free buffer pool offset */
+
+/* FMBM_IEVR - interrupt event */
+#define FMBM_IEVR_PEC 0x80000000 /* pipeline table ECC err detected */
+#define FMBM_IEVR_LEC 0x40000000 /* linked list RAM ECC error */
+#define FMBM_IEVR_SEC 0x20000000 /* statistics count RAM ECC error */
+#define FMBM_IEVR_CLEAR_ALL (FMBM_IEVR_PEC | FMBM_IEVR_LEC | FMBM_IEVR_SEC)
+
+/* FMBM_IER - interrupt enable */
+#define FMBM_IER_PECE 0x80000000 /* PEC interrupt enable */
+#define FMBM_IER_LECE 0x40000000 /* LEC interrupt enable */
+#define FMBM_IER_SECE 0x20000000 /* SEC interrupt enable */
+
+#define FMBM_IER_DISABLE_ALL 0x00000000
+
+/* FMBM_PP - BMI Port Parameters */
+#define FMBM_PP_MXT_MASK 0x3f000000 /* Max # tasks */
+#define FMBM_PP_MXT(x) (((x-1) << 24) & FMBM_PP_MXT_MASK)
+#define FMBM_PP_MXD_MASK 0x00000f00 /* Max DMA */
+#define FMBM_PP_MXD(x) (((x-1) << 8) & FMBM_PP_MXD_MASK)
+
+/* FMBM_PFS - BMI Port FIFO Size */
+#define FMBM_PFS_IFSZ_MASK 0x000003ff /* Internal Fifo Size */
+#define FMBM_PFS_IFSZ(x) (x & FMBM_PFS_IFSZ_MASK)
+
+/* FMQM_GC - global configuration */
+#define FMQM_GC_ENQ_EN 0x80000000 /* enqueue enable */
+#define FMQM_GC_DEQ_EN 0x40000000 /* dequeue enable */
+#define FMQM_GC_STEN 0x10000000 /* enable global stat counters */
+#define FMQM_GC_ENQ_THR_MASK 0x00003f00 /* max number of enqueue Tnum */
+#define FMQM_GC_ENQ(x) ((x << 8) & FMQM_GC_ENQ_THR_MAS)
+#define FMQM_GC_DEQ_THR_MASK 0x0000003f /* max number of dequeue Tnum */
+#define FMQM_GC_DEQ(x) (x & FMQM_GC_DEQ_THR_MASK)
+
+/* FMQM_EIE - error interrupt event register */
+#define FMQM_EIE_DEE 0x80000000 /* double-bit ECC error */
+#define FMQM_EIE_DFUPE 0x40000000 /* dequeue from unknown PortID */
+#define FMQM_EIE_CLEAR_ALL (FMQM_EIE_DEE | FMQM_EIE_DFUPE)
+
+/* FMQM_EIEN - error interrupt enable register */
+#define FMQM_EIEN_DEEN 0x80000000 /* double-bit ECC error */
+#define FMQM_EIEN_DFUPEN 0x40000000 /* dequeue from unknown PortID */
+#define FMQM_EIEN_DISABLE_ALL 0x00000000
+
+/* FMQM_IE - interrupt event register */
+#define FMQM_IE_SEE 0x80000000 /* single-bit ECC error detected */
+#define FMQM_IE_CLEAR_ALL FMQM_IE_SEE
+
+/* FMQM_IEN - interrupt enable register */
+#define FMQM_IEN_SEE 0x80000000 /* single-bit ECC err IRQ enable */
+#define FMQM_IEN_DISABLE_ALL 0x00000000
+
+/* NIA - next invoked action */
+#define NIA_ENG_RISC 0x00000000
+#define NIA_ENG_MASK 0x007c0000
+
+/* action code */
+#define NIA_RISC_AC_CC 0x00000006
+#define NIA_RISC_AC_IM_TX 0x00000008 /* independent mode Tx */
+#define NIA_RISC_AC_IM_RX 0x0000000a /* independent mode Rx */
+#define NIA_RISC_AC_HC 0x0000000c
+
+typedef struct fm_parser {
+ u8 res[1024];
+} fm_parser_t;
+
+typedef struct fm_policer {
+ u8 res[4*1024];
+} fm_policer_t;
+
+typedef struct fm_keygen {
+ u8 res[4*1024];
+} fm_keygen_t;
+
+typedef struct fm_dma {
+ u32 fmdmsr; /* status register */
+ u32 fmdmmr; /* mode register */
+ u32 fmdmtr; /* bus threshold register */
+ u32 fmdmhy; /* bus hysteresis register */
+ u32 fmdmsetr; /* SOS emergency threshold register */
+ u32 fmdmtah; /* transfer bus address high register */
+ u32 fmdmtal; /* transfer bus address low register */
+ u32 fmdmtcid; /* transfer bus communication ID register */
+ u32 fmdmra; /* DMA bus internal ram address register */
+ u32 fmdmrd; /* DMA bus internal ram data register */
+ u32 res0[0xb];
+ u32 fmdmdcr; /* debug counter */
+ u32 fmdmemsr; /* emrgency smoother register */
+ u32 res1;
+ u32 fmdmplr[32]; /* FM DMA PID-LIODN # register */
+ u32 res[0x3c8];
+} fm_dma_t;
+
+/* FMDMSR - Fman DMA status register */
+#define FMDMSR_CMDQNE 0x10000000 /* command queue not empty */
+#define FMDMSR_BER 0x08000000 /* bus err event occurred on bus */
+#define FMDMSR_RDB_ECC 0x04000000 /* read buffer ECC error */
+#define FMDMSR_WRB_SECC 0x02000000 /* write buf ECC err sys side */
+#define FMDMSR_WRB_FECC 0x01000000 /* write buf ECC err Fman side */
+#define FMDMSR_DPEXT_SECC 0x00800000 /* DP external ECC err sys side */
+#define FMDMSR_DPEXT_FECC 0x00400000 /* DP external ECC err Fman side */
+#define FMDMSR_DPDAT_SECC 0x00200000 /* DP data ECC err on sys side */
+#define FMDMSR_DPDAT_FECC 0x00100000 /* DP data ECC err on Fman side */
+#define FMDMSR_SPDAT_FECC 0x00080000 /* SP data ECC error Fman side */
+
+#define FMDMSR_CLEAR_ALL (FMDMSR_BER | FMDMSR_RDB_ECC \
+ | FMDMSR_WRB_SECC | FMDMSR_WRB_FECC \
+ | FMDMSR_DPEXT_SECC | FMDMSR_DPEXT_FECC \
+ | FMDMSR_DPDAT_SECC | FMDMSR_DPDAT_FECC \
+ | FMDMSR_SPDAT_FECC)
+
+/* FMDMMR - FMan DMA mode register */
+#define FMDMMR_SBER 0x10000000 /* stop the DMA if a bus error */
+
+typedef struct fm_fpm {
+ u32 fpmtnc; /* TNUM control */
+ u32 fpmprc; /* Port_ID control */
+ u32 res0;
+ u32 fpmflc; /* flush control */
+ u32 fpmdis1; /* dispatch thresholds1 */
+ u32 fpmdis2; /* dispatch thresholds2 */
+ u32 fmepi; /* error pending interrupts */
+ u32 fmrie; /* rams interrupt enable */
+ u32 fpmfcevent[0x4];/* FMan controller event 0-3 */
+ u32 res1[0x4];
+ u32 fpmfcmask[0x4]; /* FMan controller mask 0-3 */
+ u32 res2[0x4];
+ u32 fpmtsc1; /* timestamp control1 */
+ u32 fpmtsc2; /* timestamp control2 */
+ u32 fpmtsp; /* time stamp */
+ u32 fpmtsf; /* time stamp fraction */
+ u32 fpmrcr; /* rams control and event */
+ u32 res3[0x3];
+ u32 fpmdrd[0x4]; /* data_ram data 0-3 */
+ u32 res4[0xc];
+ u32 fpmdra; /* data ram access */
+ u32 fm_ip_rev_1; /* IP block revision 1 */
+ u32 fm_ip_rev_2; /* IP block revision 2 */
+ u32 fmrstc; /* reset command */
+ u32 fmcld; /* classifier debug control */
+ u32 fmnpi; /* normal pending interrupts */
+ u32 res5;
+ u32 fmfpee; /* event and enable */
+ u32 fpmcev[0x4]; /* CPU event 0-3 */
+ u32 res6[0x4];
+ u32 fmfp_ps[0x40]; /* port status */
+ u32 res7[0x260];
+ u32 fpmts[0x80]; /* task status */
+ u32 res8[0xa0];
+} fm_fpm_t;
+
+/* FMFP_PRC - FPM Port_ID Control Register */
+#define FMFPPRC_PORTID_MASK 0x3f000000
+#define FMFPPRC_PORTID_SHIFT 24
+#define FMFPPRC_ORA_SHIFT 16
+#define FMFPPRC_RISC1 0x00000001
+#define FMFPPRC_RISC2 0x00000002
+#define FMFPPRC_RISC_ALL (FMFPPRC_RISC1 | FMFPPRC_RSIC2)
+
+/* FPM Flush Control Register */
+#define FMFP_FLC_DISP_LIM_NONE 0x00000000 /* no dispatch limitation */
+
+/* FMFP_EE - FPM event and enable register */
+#define FMFPEE_DECC 0x80000000 /* double ECC err on FPM ram */
+#define FMFPEE_STL 0x40000000 /* stall of task ... */
+#define FMFPEE_SECC 0x20000000 /* single ECC error */
+#define FMFPEE_RFM 0x00010000 /* release FMan */
+#define FMFPEE_DECC_EN 0x00008000 /* double ECC interrupt enable */
+#define FMFPEE_STL_EN 0x00004000 /* stall of task interrupt enable */
+#define FMFPEE_SECC_EN 0x00002000 /* single ECC err interrupt enable */
+#define FMFPEE_EHM 0x00000008 /* external halt enable */
+#define FMFPEE_UEC 0x00000004 /* FMan is not halted */
+#define FMFPEE_CER 0x00000002 /* only errornous task stalled */
+#define FMFPEE_DER 0x00000001 /* DMA error is just reported */
+
+#define FMFPEE_CLEAR_EVENT (FMFPEE_DECC | FMFPEE_STL | FMFPEE_SECC | \
+ FMFPEE_EHM | FMFPEE_UEC | FMFPEE_CER | \
+ FMFPEE_DER | FMFPEE_RFM)
+
+/* FMFP_RCR - FMan Rams Control and Event */
+#define FMFP_RCR_MDEC 0x00008000 /* double ECC error in muram */
+#define FMFP_RCR_IDEC 0x00004000 /* double ECC error in iram */
+
+typedef struct fm_imem {
+ u32 iadd; /* instruction address register */
+ u32 idata; /* instruction data register */
+ u32 itcfg; /* timing config register */
+ u32 iready; /* ready register */
+ u8 res[0xff0];
+} fm_imem_t;
+#define IRAM_IADD_AIE 0x80000000 /* address auto increase enable */
+#define IRAM_READY 0x80000000 /* ready to use */
+
+typedef struct fm_soft_parser {
+ u8 res[4*1024];
+} fm_soft_parser_t;
+
+typedef struct fm_dtesc {
+ u8 res[4*1024];
+} fm_dtsec_t;
+
+typedef struct fm_mdio {
+ u8 res0[0x120];
+ u32 miimcfg; /* MII management configuration reg */
+ u32 miimcom; /* MII management command reg */
+ u32 miimadd; /* MII management address reg */
+ u32 miimcon; /* MII management control reg */
+ u32 miimstat; /* MII management status reg */
+ u32 miimind; /* MII management indication reg */
+ u8 res1[0x1000 - 0x138];
+} fm_mdio_t;
+
+typedef struct fm_10gec {
+ u8 res[4*1024];
+} fm_10gec_t;
+
+typedef struct fm_10gec_mdio {
+ u8 res[4*1024];
+} fm_10gec_mdio_t;
+
+typedef struct fm_memac {
+ u8 res[4*1024];
+} fm_memac_t;
+
+typedef struct fm_memac_mdio {
+ u8 res[4*1024];
+} fm_memac_mdio_t;
+
+typedef struct fm_1588 {
+ u8 res[4*1024];
+} fm_1588_t;
+
+typedef struct ccsr_fman {
+ u8 muram[0x80000];
+ fm_bmi_common_t fm_bmi_common;
+ fm_qmi_common_t fm_qmi_common;
+ u8 res0[2048];
+ struct {
+ fm_bmi_t fm_bmi;
+ fm_qmi_t fm_qmi;
+ fm_parser_t fm_parser;
+ u8 res[1024];
+ } port[63];
+ fm_policer_t fm_policer;
+ fm_keygen_t fm_keygen;
+ fm_dma_t fm_dma;
+ fm_fpm_t fm_fpm;
+ fm_imem_t fm_imem;
+ u8 res1[8*1024];
+ fm_soft_parser_t fm_soft_parser;
+ u8 res2[96*1024];
+#ifdef CONFIG_SYS_FMAN_V3
+ struct {
+ fm_memac_t fm_memac;
+ fm_memac_mdio_t fm_memac_mdio;
+ } memac[10];
+ u8 res4[32*1024];
+ fm_memac_mdio_t fm_dedicated_mdio[2];
+#else
+ struct {
+ fm_dtsec_t fm_dtesc;
+ fm_mdio_t fm_mdio;
+ } mac_1g[8]; /* support up to 8 1g controllers */
+ struct {
+ fm_10gec_t fm_10gec;
+ fm_10gec_mdio_t fm_10gec_mdio;
+ } mac_10g[1];
+ u8 res4[48*1024];
+#endif
+ fm_1588_t fm_1588;
+ u8 res5[4*1024];
+} ccsr_fman_t;
+
+#endif /*__FSL_FMAN_H__*/
diff --git a/arch/powerpc/include/asm/fsl_i2c.h b/arch/powerpc/include/asm/fsl_i2c.h
new file mode 100644
index 0000000..4f71341
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_i2c.h
@@ -0,0 +1,86 @@
+/*
+ * Freescale I2C Controller
+ *
+ * Copyright 2006 Freescale Semiconductor, Inc.
+ *
+ * Based on earlier versions by Gleb Natapov <gnatapov@mrv.com>,
+ * Xianghua Xiao <x.xiao@motorola.com>, Eran Liberty (liberty@freescale.com),
+ * and Jeff Brown.
+ * Some bits are taken from linux driver writen by adrian@humboldt.co.uk.
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_FSL_I2C_H_
+#define _ASM_FSL_I2C_H_
+
+#include <asm/types.h>
+
+typedef struct fsl_i2c {
+
+ u8 adr; /* I2C slave address */
+ u8 res0[3];
+#define I2C_ADR 0xFE
+#define I2C_ADR_SHIFT 1
+#define I2C_ADR_RES ~(I2C_ADR)
+
+ u8 fdr; /* I2C frequency divider register */
+ u8 res1[3];
+#define IC2_FDR 0x3F
+#define IC2_FDR_SHIFT 0
+#define IC2_FDR_RES ~(IC2_FDR)
+
+ u8 cr; /* I2C control redister */
+ u8 res2[3];
+#define I2C_CR_MEN 0x80
+#define I2C_CR_MIEN 0x40
+#define I2C_CR_MSTA 0x20
+#define I2C_CR_MTX 0x10
+#define I2C_CR_TXAK 0x08
+#define I2C_CR_RSTA 0x04
+#define I2C_CR_BCST 0x01
+
+ u8 sr; /* I2C status register */
+ u8 res3[3];
+#define I2C_SR_MCF 0x80
+#define I2C_SR_MAAS 0x40
+#define I2C_SR_MBB 0x20
+#define I2C_SR_MAL 0x10
+#define I2C_SR_BCSTM 0x08
+#define I2C_SR_SRW 0x04
+#define I2C_SR_MIF 0x02
+#define I2C_SR_RXAK 0x01
+
+ u8 dr; /* I2C data register */
+ u8 res4[3];
+#define I2C_DR 0xFF
+#define I2C_DR_SHIFT 0
+#define I2C_DR_RES ~(I2C_DR)
+
+ u8 dfsrr; /* I2C digital filter sampling rate register */
+ u8 res5[3];
+#define I2C_DFSRR 0x3F
+#define I2C_DFSRR_SHIFT 0
+#define I2C_DFSRR_RES ~(I2C_DR)
+
+ /* Fill out the reserved block */
+ u8 res6[0xE8];
+} fsl_i2c_t;
+
+#endif /* _ASM_I2C_H_ */
diff --git a/arch/powerpc/include/asm/fsl_ifc.h b/arch/powerpc/include/asm/fsl_ifc.h
new file mode 100644
index 0000000..3baf4cc
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_ifc.h
@@ -0,0 +1,999 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_PPC_FSL_IFC_H
+#define __ASM_PPC_FSL_IFC_H
+
+#ifdef CONFIG_FSL_IFC
+#include <config.h>
+#include <common.h>
+
+/*
+ * CSPR - Chip Select Property Register
+ */
+#define CSPR_BA 0xFFFF0000
+#define CSPR_BA_SHIFT 16
+#define CSPR_PORT_SIZE 0x00000180
+#define CSPR_PORT_SIZE_SHIFT 7
+/* Port Size 8 bit */
+#define CSPR_PORT_SIZE_8 0x00000080
+/* Port Size 16 bit */
+#define CSPR_PORT_SIZE_16 0x00000100
+/* Port Size 32 bit */
+#define CSPR_PORT_SIZE_32 0x00000180
+/* Write Protect */
+#define CSPR_WP 0x00000040
+#define CSPR_WP_SHIFT 6
+/* Machine Select */
+#define CSPR_MSEL 0x00000006
+#define CSPR_MSEL_SHIFT 1
+/* NOR */
+#define CSPR_MSEL_NOR 0x00000000
+/* NAND */
+#define CSPR_MSEL_NAND 0x00000002
+/* GPCM */
+#define CSPR_MSEL_GPCM 0x00000004
+/* Bank Valid */
+#define CSPR_V 0x00000001
+#define CSPR_V_SHIFT 0
+
+/* Convert an address into the right format for the CSPR Registers */
+#define CSPR_PHYS_ADDR(x) (((uint64_t)x) & 0xffff0000)
+
+/*
+ * Address Mask Register
+ */
+#define IFC_AMASK_MASK 0xFFFF0000
+#define IFC_AMASK_SHIFT 16
+#define IFC_AMASK(n) (IFC_AMASK_MASK << \
+ (__ilog2(n) - IFC_AMASK_SHIFT))
+
+/*
+ * Chip Select Option Register IFC_NAND Machine
+ */
+/* Enable ECC Encoder */
+#define CSOR_NAND_ECC_ENC_EN 0x80000000
+#define CSOR_NAND_ECC_MODE_MASK 0x30000000
+/* 4 bit correction per 520 Byte sector */
+#define CSOR_NAND_ECC_MODE_4 0x00000000
+/* 8 bit correction per 528 Byte sector */
+#define CSOR_NAND_ECC_MODE_8 0x10000000
+/* Enable ECC Decoder */
+#define CSOR_NAND_ECC_DEC_EN 0x04000000
+/* Row Address Length */
+#define CSOR_NAND_RAL_MASK 0x01800000
+#define CSOR_NAND_RAL_SHIFT 20
+#define CSOR_NAND_RAL_1 0x00000000
+#define CSOR_NAND_RAL_2 0x00800000
+#define CSOR_NAND_RAL_3 0x01000000
+#define CSOR_NAND_RAL_4 0x01800000
+/* Page Size 512b, 2k, 4k */
+#define CSOR_NAND_PGS_MASK 0x00180000
+#define CSOR_NAND_PGS_SHIFT 16
+#define CSOR_NAND_PGS_512 0x00000000
+#define CSOR_NAND_PGS_2K 0x00080000
+#define CSOR_NAND_PGS_4K 0x00100000
+/* Spare region Size */
+#define CSOR_NAND_SPRZ_MASK 0x0000E000
+#define CSOR_NAND_SPRZ_SHIFT 13
+#define CSOR_NAND_SPRZ_16 0x00000000
+#define CSOR_NAND_SPRZ_64 0x00002000
+#define CSOR_NAND_SPRZ_128 0x00004000
+#define CSOR_NAND_SPRZ_210 0x00006000
+#define CSOR_NAND_SPRZ_218 0x00008000
+#define CSOR_NAND_SPRZ_224 0x0000A000
+/* Pages Per Block */
+#define CSOR_NAND_PB_MASK 0x00000700
+#define CSOR_NAND_PB_SHIFT 8
+#define CSOR_NAND_PB(n) ((__ilog2(n) - 5) << CSOR_NAND_PB_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NAND_TRHZ_MASK 0x0000001C
+#define CSOR_NAND_TRHZ_SHIFT 2
+#define CSOR_NAND_TRHZ_20 0x00000000
+#define CSOR_NAND_TRHZ_40 0x00000004
+#define CSOR_NAND_TRHZ_60 0x00000008
+#define CSOR_NAND_TRHZ_80 0x0000000C
+#define CSOR_NAND_TRHZ_100 0x00000010
+/* Buffer control disable */
+#define CSOR_NAND_BCTLD 0x00000001
+
+/*
+ * Chip Select Option Register - NOR Flash Mode
+ */
+/* Enable Address shift Mode */
+#define CSOR_NOR_ADM_SHFT_MODE_EN 0x80000000
+/* Page Read Enable from NOR device */
+#define CSOR_NOR_PGRD_EN 0x10000000
+/* AVD Toggle Enable during Burst Program */
+#define CSOR_NOR_AVD_TGL_PGM_EN 0x01000000
+/* Address Data Multiplexing Shift */
+#define CSOR_NOR_ADM_MASK 0x0003E000
+#define CSOR_NOR_ADM_SHIFT_SHIFT 13
+#define CSOR_NOR_ADM_SHIFT(n) ((n) << CSOR_NOR_ADM_SHIFT_SHIFT)
+/* Type of the NOR device hooked */
+#define CSOR_NOR_NOR_MODE_AYSNC_NOR 0x00000000
+#define CSOR_NOR_NOR_MODE_AVD_NOR 0x00000020
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NOR_TRHZ_MASK 0x0000001C
+#define CSOR_NOR_TRHZ_SHIFT 2
+#define CSOR_NOR_TRHZ_20 0x00000000
+#define CSOR_NOR_TRHZ_40 0x00000004
+#define CSOR_NOR_TRHZ_60 0x00000008
+#define CSOR_NOR_TRHZ_80 0x0000000C
+#define CSOR_NOR_TRHZ_100 0x00000010
+/* Buffer control disable */
+#define CSOR_NOR_BCTLD 0x00000001
+
+/*
+ * Chip Select Option Register - GPCM Mode
+ */
+/* GPCM Mode - Normal */
+#define CSOR_GPCM_GPMODE_NORMAL 0x00000000
+/* GPCM Mode - GenericASIC */
+#define CSOR_GPCM_GPMODE_ASIC 0x80000000
+/* Parity Mode odd/even */
+#define CSOR_GPCM_PARITY_EVEN 0x40000000
+/* Parity Checking enable/disable */
+#define CSOR_GPCM_PAR_EN 0x20000000
+/* GPCM Timeout Count */
+#define CSOR_GPCM_GPTO_MASK 0x0F000000
+#define CSOR_GPCM_GPTO_SHIFT 24
+#define CSOR_GPCM_GPTO(n) ((__ilog2(n) - 8) << CSOR_GPCM_GPTO_SHIFT)
+/* GPCM External Access Termination mode for read access */
+#define CSOR_GPCM_RGETA_EXT 0x00080000
+/* GPCM External Access Termination mode for write access */
+#define CSOR_GPCM_WGETA_EXT 0x00040000
+/* Address Data Multiplexing Shift */
+#define CSOR_GPCM_ADM_MASK 0x0003E000
+#define CSOR_GPCM_ADM_SHIFT_SHIFT 13
+#define CSOR_GPCM_ADM_SHIFT(n) ((n) << CSOR_GPCM_ADM_SHIFT_SHIFT)
+/* Generic ASIC Parity error indication delay */
+#define CSOR_GPCM_GAPERRD_MASK 0x00000180
+#define CSOR_GPCM_GAPERRD_SHIFT 7
+#define CSOR_GPCM_GAPERRD(n) (((n) - 1) << CSOR_GPCM_GAPERRD_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_GPCM_TRHZ_MASK 0x0000001C
+#define CSOR_GPCM_TRHZ_20 0x00000000
+#define CSOR_GPCM_TRHZ_40 0x00000004
+#define CSOR_GPCM_TRHZ_60 0x00000008
+#define CSOR_GPCM_TRHZ_80 0x0000000C
+#define CSOR_GPCM_TRHZ_100 0x00000010
+/* Buffer control disable */
+#define CSOR_GPCM_BCTLD 0x00000001
+
+/*
+ * Flash Timing Registers (FTIM0 - FTIM2_CSn)
+ */
+/*
+ * FTIM0 - NAND Flash Mode
+ */
+#define FTIM0_NAND 0x7EFF3F3F
+#define FTIM0_NAND_TCCST_SHIFT 25
+#define FTIM0_NAND_TCCST(n) ((n) << FTIM0_NAND_TCCST_SHIFT)
+#define FTIM0_NAND_TWP_SHIFT 16
+#define FTIM0_NAND_TWP(n) ((n) << FTIM0_NAND_TWP_SHIFT)
+#define FTIM0_NAND_TWCHT_SHIFT 8
+#define FTIM0_NAND_TWCHT(n) ((n) << FTIM0_NAND_TWCHT_SHIFT)
+#define FTIM0_NAND_TWH_SHIFT 0
+#define FTIM0_NAND_TWH(n) ((n) << FTIM0_NAND_TWH_SHIFT)
+/*
+ * FTIM1 - NAND Flash Mode
+ */
+#define FTIM1_NAND 0xFFFF3FFF
+#define FTIM1_NAND_TADLE_SHIFT 24
+#define FTIM1_NAND_TADLE(n) ((n) << FTIM1_NAND_TADLE_SHIFT)
+#define FTIM1_NAND_TWBE_SHIFT 16
+#define FTIM1_NAND_TWBE(n) ((n) << FTIM1_NAND_TWBE_SHIFT)
+#define FTIM1_NAND_TRR_SHIFT 8
+#define FTIM1_NAND_TRR(n) ((n) << FTIM1_NAND_TRR_SHIFT)
+#define FTIM1_NAND_TRP_SHIFT 0
+#define FTIM1_NAND_TRP(n) ((n) << FTIM1_NAND_TRP_SHIFT)
+/*
+ * FTIM2 - NAND Flash Mode
+ */
+#define FTIM2_NAND 0x1FE1F8FF
+#define FTIM2_NAND_TRAD_SHIFT 21
+#define FTIM2_NAND_TRAD(n) ((n) << FTIM2_NAND_TRAD_SHIFT)
+#define FTIM2_NAND_TREH_SHIFT 11
+#define FTIM2_NAND_TREH(n) ((n) << FTIM2_NAND_TREH_SHIFT)
+#define FTIM2_NAND_TWHRE_SHIFT 0
+#define FTIM2_NAND_TWHRE(n) ((n) << FTIM2_NAND_TWHRE_SHIFT)
+/*
+ * FTIM3 - NAND Flash Mode
+ */
+#define FTIM3_NAND 0xFF000000
+#define FTIM3_NAND_TWW_SHIFT 24
+#define FTIM3_NAND_TWW(n) ((n) << FTIM3_NAND_TWW_SHIFT)
+
+/*
+ * FTIM0 - NOR Flash Mode
+ */
+#define FTIM0_NOR 0xF03F3F3F
+#define FTIM0_NOR_TACSE_SHIFT 28
+#define FTIM0_NOR_TACSE(n) ((n) << FTIM0_NOR_TACSE_SHIFT)
+#define FTIM0_NOR_TEADC_SHIFT 16
+#define FTIM0_NOR_TEADC(n) ((n) << FTIM0_NOR_TEADC_SHIFT)
+#define FTIM0_NOR_TAVDS_SHIFT 8
+#define FTIM0_NOR_TAVDS(n) ((n) << FTIM0_NOR_TAVDS_SHIFT)
+#define FTIM0_NOR_TEAHC_SHIFT 0
+#define FTIM0_NOR_TEAHC(n) ((n) << FTIM0_NOR_TEAHC_SHIFT)
+/*
+ * FTIM1 - NOR Flash Mode
+ */
+#define FTIM1_NOR 0xFF003F3F
+#define FTIM1_NOR_TACO_SHIFT 24
+#define FTIM1_NOR_TACO(n) ((n) << FTIM1_NOR_TACO_SHIFT)
+#define FTIM1_NOR_TRAD_NOR_SHIFT 8
+#define FTIM1_NOR_TRAD_NOR(n) ((n) << FTIM1_NOR_TRAD_NOR_SHIFT)
+#define FTIM1_NOR_TSEQRAD_NOR_SHIFT 0
+#define FTIM1_NOR_TSEQRAD_NOR(n) ((n) << FTIM1_NOR_TSEQRAD_NOR_SHIFT)
+/*
+ * FTIM2 - NOR Flash Mode
+ */
+#define FTIM2_NOR 0x0F3CFCFF
+#define FTIM2_NOR_TCS_SHIFT 24
+#define FTIM2_NOR_TCS(n) ((n) << FTIM2_NOR_TCS_SHIFT)
+#define FTIM2_NOR_TCH_SHIFT 18
+#define FTIM2_NOR_TCH(n) ((n) << FTIM2_NOR_TCH_SHIFT)
+#define FTIM2_NOR_TWPH_SHIFT 10
+#define FTIM2_NOR_TWPH(n) ((n) << FTIM2_NOR_TWPH_SHIFT)
+#define FTIM2_NOR_TWP_SHIFT 0
+#define FTIM2_NOR_TWP(n) ((n) << FTIM2_NOR_TWP_SHIFT)
+
+/*
+ * FTIM0 - Normal GPCM Mode
+ */
+#define FTIM0_GPCM 0xF03F3F3F
+#define FTIM0_GPCM_TACSE_SHIFT 28
+#define FTIM0_GPCM_TACSE(n) ((n) << FTIM0_GPCM_TACSE_SHIFT)
+#define FTIM0_GPCM_TEADC_SHIFT 16
+#define FTIM0_GPCM_TEADC(n) ((n) << FTIM0_GPCM_TEADC_SHIFT)
+#define FTIM0_GPCM_TAVDS_SHIFT 8
+#define FTIM0_GPCM_TAVDS(n) ((n) << FTIM0_GPCM_TAVDS_SHIFT)
+#define FTIM0_GPCM_TEAHC_SHIFT 0
+#define FTIM0_GPCM_TEAHC(n) ((n) << FTIM0_GPCM_TEAHC_SHIFT)
+/*
+ * FTIM1 - Normal GPCM Mode
+ */
+#define FTIM1_GPCM 0xFF003F00
+#define FTIM1_GPCM_TACO_SHIFT 24
+#define FTIM1_GPCM_TACO(n) ((n) << FTIM1_GPCM_TACO_SHIFT)
+#define FTIM1_GPCM_TRAD_SHIFT 8
+#define FTIM1_GPCM_TRAD(n) ((n) << FTIM1_GPCM_TRAD_SHIFT)
+/*
+ * FTIM2 - Normal GPCM Mode
+ */
+#define FTIM2_GPCM 0x0F3C00FF
+#define FTIM2_GPCM_TCS_SHIFT 24
+#define FTIM2_GPCM_TCS(n) ((n) << FTIM2_GPCM_TCS_SHIFT)
+#define FTIM2_GPCM_TCH_SHIFT 18
+#define FTIM2_GPCM_TCH(n) ((n) << FTIM2_GPCM_TCH_SHIFT)
+#define FTIM2_GPCM_TWP_SHIFT 0
+#define FTIM2_GPCM_TWP(n) ((n) << FTIM2_GPCM_TWP_SHIFT)
+
+/*
+ * Ready Busy Status Register (RB_STAT)
+ */
+/* CSn is READY */
+#define IFC_RB_STAT_READY_CS0 0x80000000
+#define IFC_RB_STAT_READY_CS1 0x40000000
+#define IFC_RB_STAT_READY_CS2 0x20000000
+#define IFC_RB_STAT_READY_CS3 0x10000000
+
+/*
+ * General Control Register (GCR)
+ */
+#define IFC_GCR_MASK 0x8000F800
+/* reset all IFC hardware */
+#define IFC_GCR_SOFT_RST_ALL 0x80000000
+/* Turnaroud Time of external buffer */
+#define IFC_GCR_TBCTL_TRN_TIME 0x0000F800
+#define IFC_GCR_TBCTL_TRN_TIME_SHIFT 11
+
+/*
+ * Common Event and Error Status Register (CM_EVTER_STAT)
+ */
+/* Chip select error */
+#define IFC_CM_EVTER_STAT_CSER 0x80000000
+
+/*
+ * Common Event and Error Enable Register (CM_EVTER_EN)
+ */
+/* Chip select error checking enable */
+#define IFC_CM_EVTER_EN_CSEREN 0x80000000
+
+/*
+ * Common Event and Error Interrupt Enable Register (CM_EVTER_INTR_EN)
+ */
+/* Chip select error interrupt enable */
+#define IFC_CM_EVTER_INTR_EN_CSERIREN 0x80000000
+
+/*
+ * Common Transfer Error Attribute Register-0 (CM_ERATTR0)
+ */
+/* transaction type of error Read/Write */
+#define IFC_CM_ERATTR0_ERTYP_READ 0x80000000
+#define IFC_CM_ERATTR0_ERAID 0x0FF00000
+#define IFC_CM_ERATTR0_ESRCID 0x0000FF00
+
+/*
+ * Clock Control Register (CCR)
+ */
+#define IFC_CCR_MASK 0x0F0F8800
+/* Clock division ratio */
+#define IFC_CCR_CLK_DIV_MASK 0x0F000000
+#define IFC_CCR_CLK_DIV_SHIFT 24
+#define IFC_CCR_CLK_DIV(n) ((n-1) << IFC_CCR_CLK_DIV_SHIFT)
+/* IFC Clock Delay */
+#define IFC_CCR_CLK_DLY_MASK 0x000F0000
+#define IFC_CCR_CLK_DLY_SHIFT 16
+#define IFC_CCR_CLK_DLY(n) ((n) << IFC_CCR_CLK_DLY_SHIFT)
+/* Invert IFC clock before sending out */
+#define IFC_CCR_INV_CLK_EN 0x00008000
+/* Fedback IFC Clock */
+#define IFC_CCR_FB_IFC_CLK_SEL 0x00000800
+
+/*
+ * Clock Status Register (CSR)
+ */
+/* Clk is stable */
+#define IFC_CSR_CLK_STAT_STABLE 0x80000000
+
+/*
+ * IFC_NAND Machine Specific Registers
+ */
+/*
+ * NAND Configuration Register (NCFGR)
+ */
+/* Auto Boot Mode */
+#define IFC_NAND_NCFGR_BOOT 0x80000000
+/* Addressing Mode-ROW0+n/COL0 */
+#define IFC_NAND_NCFGR_ADDR_MODE_RC0 0x00000000
+/* Addressing Mode-ROW0+n/COL0+n */
+#define IFC_NAND_NCFGR_ADDR_MODE_RC1 0x00400000
+/* Number of loop iterations of FIR sequences for multi page operations */
+#define IFC_NAND_NCFGR_NUM_LOOP_MASK 0x0000F000
+#define IFC_NAND_NCFGR_NUM_LOOP_SHIFT 12
+#define IFC_NAND_NCFGR_NUM_LOOP(n) ((n) << IFC_NAND_NCFGR_NUM_LOOP_SHIFT)
+/* Number of wait cycles */
+#define IFC_NAND_NCFGR_NUM_WAIT_MASK 0x000000FF
+#define IFC_NAND_NCFGR_NUM_WAIT_SHIFT 0
+
+/*
+ * NAND Flash Command Registers (NAND_FCR0/NAND_FCR1)
+ */
+/* General purpose FCM flash command bytes CMD0-CMD7 */
+#define IFC_NAND_FCR0_CMD0 0xFF000000
+#define IFC_NAND_FCR0_CMD0_SHIFT 24
+#define IFC_NAND_FCR0_CMD1 0x00FF0000
+#define IFC_NAND_FCR0_CMD1_SHIFT 16
+#define IFC_NAND_FCR0_CMD2 0x0000FF00
+#define IFC_NAND_FCR0_CMD2_SHIFT 8
+#define IFC_NAND_FCR0_CMD3 0x000000FF
+#define IFC_NAND_FCR0_CMD3_SHIFT 0
+#define IFC_NAND_FCR1_CMD4 0xFF000000
+#define IFC_NAND_FCR1_CMD4_SHIFT 24
+#define IFC_NAND_FCR1_CMD5 0x00FF0000
+#define IFC_NAND_FCR1_CMD5_SHIFT 16
+#define IFC_NAND_FCR1_CMD6 0x0000FF00
+#define IFC_NAND_FCR1_CMD6_SHIFT 8
+#define IFC_NAND_FCR1_CMD7 0x000000FF
+#define IFC_NAND_FCR1_CMD7_SHIFT 0
+
+/*
+ * Flash ROW and COL Address Register (ROWn, COLn)
+ */
+/* Main/spare region locator */
+#define IFC_NAND_COL_MS 0x80000000
+/* Column Address */
+#define IFC_NAND_COL_CA_MASK 0x00000FFF
+
+/*
+ * NAND Flash Byte Count Register (NAND_BC)
+ */
+/* Byte Count for read/Write */
+#define IFC_NAND_BC 0x000001FF
+
+/*
+ * NAND Flash Instruction Registers (NAND_FIR0/NAND_FIR1/NAND_FIR2)
+ */
+/* NAND Machine specific opcodes OP0-OP14*/
+#define IFC_NAND_FIR0_OP0 0xFC000000
+#define IFC_NAND_FIR0_OP0_SHIFT 26
+#define IFC_NAND_FIR0_OP1 0x03F00000
+#define IFC_NAND_FIR0_OP1_SHIFT 20
+#define IFC_NAND_FIR0_OP2 0x000FC000
+#define IFC_NAND_FIR0_OP2_SHIFT 14
+#define IFC_NAND_FIR0_OP3 0x00003F00
+#define IFC_NAND_FIR0_OP3_SHIFT 8
+#define IFC_NAND_FIR0_OP4 0x000000FC
+#define IFC_NAND_FIR0_OP4_SHIFT 2
+#define IFC_NAND_FIR1_OP5 0xFC000000
+#define IFC_NAND_FIR1_OP5_SHIFT 26
+#define IFC_NAND_FIR1_OP6 0x03F00000
+#define IFC_NAND_FIR1_OP6_SHIFT 20
+#define IFC_NAND_FIR1_OP7 0x000FC000
+#define IFC_NAND_FIR1_OP7_SHIFT 14
+#define IFC_NAND_FIR1_OP8 0x00003F00
+#define IFC_NAND_FIR1_OP8_SHIFT 8
+#define IFC_NAND_FIR1_OP9 0x000000FC
+#define IFC_NAND_FIR1_OP9_SHIFT 2
+#define IFC_NAND_FIR2_OP10 0xFC000000
+#define IFC_NAND_FIR2_OP10_SHIFT 26
+#define IFC_NAND_FIR2_OP11 0x03F00000
+#define IFC_NAND_FIR2_OP11_SHIFT 20
+#define IFC_NAND_FIR2_OP12 0x000FC000
+#define IFC_NAND_FIR2_OP12_SHIFT 14
+#define IFC_NAND_FIR2_OP13 0x00003F00
+#define IFC_NAND_FIR2_OP13_SHIFT 8
+#define IFC_NAND_FIR2_OP14 0x000000FC
+#define IFC_NAND_FIR2_OP14_SHIFT 2
+
+/*
+ * Instruction opcodes to be programmed
+ * in FIR registers- 6bits
+ */
+enum ifc_nand_fir_opcodes {
+ IFC_FIR_OP_NOP,
+ IFC_FIR_OP_CA0,
+ IFC_FIR_OP_CA1,
+ IFC_FIR_OP_CA2,
+ IFC_FIR_OP_CA3,
+ IFC_FIR_OP_RA0,
+ IFC_FIR_OP_RA1,
+ IFC_FIR_OP_RA2,
+ IFC_FIR_OP_RA3,
+ IFC_FIR_OP_CMD0,
+ IFC_FIR_OP_CMD1,
+ IFC_FIR_OP_CMD2,
+ IFC_FIR_OP_CMD3,
+ IFC_FIR_OP_CMD4,
+ IFC_FIR_OP_CMD5,
+ IFC_FIR_OP_CMD6,
+ IFC_FIR_OP_CMD7,
+ IFC_FIR_OP_CW0,
+ IFC_FIR_OP_CW1,
+ IFC_FIR_OP_CW2,
+ IFC_FIR_OP_CW3,
+ IFC_FIR_OP_CW4,
+ IFC_FIR_OP_CW5,
+ IFC_FIR_OP_CW6,
+ IFC_FIR_OP_CW7,
+ IFC_FIR_OP_WBCD,
+ IFC_FIR_OP_RBCD,
+ IFC_FIR_OP_BTRD,
+ IFC_FIR_OP_RDSTAT,
+ IFC_FIR_OP_NWAIT,
+ IFC_FIR_OP_WFR,
+ IFC_FIR_OP_SBRD,
+ IFC_FIR_OP_UA,
+ IFC_FIR_OP_RB,
+};
+
+/*
+ * NAND Chip Select Register (NAND_CSEL)
+ */
+#define IFC_NAND_CSEL 0x0C000000
+#define IFC_NAND_CSEL_SHIFT 26
+#define IFC_NAND_CSEL_CS0 0x00000000
+#define IFC_NAND_CSEL_CS1 0x04000000
+#define IFC_NAND_CSEL_CS2 0x08000000
+#define IFC_NAND_CSEL_CS3 0x0C000000
+
+/*
+ * NAND Operation Sequence Start (NANDSEQ_STRT)
+ */
+/* NAND Flash Operation Start */
+#define IFC_NAND_SEQ_STRT_FIR_STRT 0x80000000
+/* Automatic Erase */
+#define IFC_NAND_SEQ_STRT_AUTO_ERS 0x00800000
+/* Automatic Program */
+#define IFC_NAND_SEQ_STRT_AUTO_PGM 0x00100000
+/* Automatic Copyback */
+#define IFC_NAND_SEQ_STRT_AUTO_CPB 0x00020000
+/* Automatic Read Operation */
+#define IFC_NAND_SEQ_STRT_AUTO_RD 0x00004000
+/* Automatic Status Read */
+#define IFC_NAND_SEQ_STRT_AUTO_STAT_RD 0x00000800
+
+/*
+ * NAND Event and Error Status Register (NAND_EVTER_STAT)
+ */
+/* Operation Complete */
+#define IFC_NAND_EVTER_STAT_OPC 0x80000000
+/* Flash Timeout Error */
+#define IFC_NAND_EVTER_STAT_FTOER 0x08000000
+/* Write Protect Error */
+#define IFC_NAND_EVTER_STAT_WPER 0x04000000
+/* ECC Error */
+#define IFC_NAND_EVTER_STAT_ECCER 0x02000000
+/* RCW Load Done */
+#define IFC_NAND_EVTER_STAT_RCW_DN 0x00008000
+/* Boot Loadr Done */
+#define IFC_NAND_EVTER_STAT_BOOT_DN 0x00004000
+/* Bad Block Indicator search select */
+#define IFC_NAND_EVTER_STAT_BBI_SRCH_SE 0x00000800
+
+/*
+ * NAND Flash Page Read Completion Event Status Register
+ * (PGRDCMPL_EVT_STAT)
+ */
+#define PGRDCMPL_EVT_STAT_MASK 0xFFFF0000
+/* Small Page 0-15 Done */
+#define PGRDCMPL_EVT_STAT_SECTION_SP(n) (1 << (31 - (n)))
+/* Large Page(2K) 0-3 Done */
+#define PGRDCMPL_EVT_STAT_LP_2K(n) (0xF << (28 - (n)*4))
+/* Large Page(4K) 0-1 Done */
+#define PGRDCMPL_EVT_STAT_LP_4K(n) (0xFF << (24 - (n)*8))
+
+/*
+ * NAND Event and Error Enable Register (NAND_EVTER_EN)
+ */
+/* Operation complete event enable */
+#define IFC_NAND_EVTER_EN_OPC_EN 0x80000000
+/* Page read complete event enable */
+#define IFC_NAND_EVTER_EN_PGRDCMPL_EN 0x20000000
+/* Flash Timeout error enable */
+#define IFC_NAND_EVTER_EN_FTOER_EN 0x08000000
+/* Write Protect error enable */
+#define IFC_NAND_EVTER_EN_WPER_EN 0x04000000
+/* ECC error logging enable */
+#define IFC_NAND_EVTER_EN_ECCER_EN 0x02000000
+
+/*
+ * NAND Event and Error Interrupt Enable Register (NAND_EVTER_INTR_EN)
+ */
+/* Enable interrupt for operation complete */
+#define IFC_NAND_EVTER_INTR_OPCIR_EN 0x80000000
+/* Enable interrupt for Page read complete */
+#define IFC_NAND_EVTER_INTR_PGRDCMPLIR_EN 0x20000000
+/* Enable interrupt for Flash timeout error */
+#define IFC_NAND_EVTER_INTR_FTOERIR_EN 0x08000000
+/* Enable interrupt for Write protect error */
+#define IFC_NAND_EVTER_INTR_WPERIR_EN 0x04000000
+/* Enable interrupt for ECC error*/
+#define IFC_NAND_EVTER_INTR_ECCERIR_EN 0x02000000
+
+/*
+ * NAND Transfer Error Attribute Register-0 (NAND_ERATTR0)
+ */
+#define IFC_NAND_ERATTR0_MASK 0x0C080000
+/* Error on CS0-3 for NAND */
+#define IFC_NAND_ERATTR0_ERCS_CS0 0x00000000
+#define IFC_NAND_ERATTR0_ERCS_CS1 0x04000000
+#define IFC_NAND_ERATTR0_ERCS_CS2 0x08000000
+#define IFC_NAND_ERATTR0_ERCS_CS3 0x0C000000
+/* Transaction type of error Read/Write */
+#define IFC_NAND_ERATTR0_ERTTYPE_READ 0x00080000
+
+/*
+ * NAND Flash Status Register (NAND_FSR)
+ */
+/* First byte of data read from read status op */
+#define IFC_NAND_NFSR_RS0 0xFF000000
+/* Second byte of data read from read status op */
+#define IFC_NAND_NFSR_RS1 0x00FF0000
+
+/*
+ * ECC Error Status Registers (ECCSTAT0-ECCSTAT3)
+ */
+/* Number of ECC errors on sector n (n = 0-15) */
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR0_MASK 0x0F000000
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR0_SHIFT 24
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR1_MASK 0x000F0000
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR1_SHIFT 16
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR2_MASK 0x00000F00
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR2_SHIFT 8
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR3_MASK 0x0000000F
+#define IFC_NAND_ECCSTAT0_ERRCNT_SECTOR3_SHIFT 0
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR4_MASK 0x0F000000
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR4_SHIFT 24
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR5_MASK 0x000F0000
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR5_SHIFT 16
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR6_MASK 0x00000F00
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR6_SHIFT 8
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR7_MASK 0x0000000F
+#define IFC_NAND_ECCSTAT1_ERRCNT_SECTOR7_SHIFT 0
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR8_MASK 0x0F000000
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR8_SHIFT 24
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR9_MASK 0x000F0000
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR9_SHIFT 16
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR10_MASK 0x00000F00
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR10_SHIFT 8
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR11_MASK 0x0000000F
+#define IFC_NAND_ECCSTAT2_ERRCNT_SECTOR11_SHIFT 0
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR12_MASK 0x0F000000
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR12_SHIFT 24
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR13_MASK 0x000F0000
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR13_SHIFT 16
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR14_MASK 0x00000F00
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR14_SHIFT 8
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR15_MASK 0x0000000F
+#define IFC_NAND_ECCSTAT3_ERRCNT_SECTOR15_SHIFT 0
+
+/*
+ * NAND Control Register (NANDCR)
+ */
+#define IFC_NAND_NCR_FTOCNT_MASK 0x1E000000
+#define IFC_NAND_NCR_FTOCNT_SHIFT 25
+#define IFC_NAND_NCR_FTOCNT(n) ((_ilog2(n) - 8) << IFC_NAND_NCR_FTOCNT_SHIFT)
+
+/*
+ * NAND_AUTOBOOT_TRGR
+ */
+/* Trigger RCW load */
+#define IFC_NAND_AUTOBOOT_TRGR_RCW_LD 0x80000000
+/* Trigget Auto Boot */
+#define IFC_NAND_AUTOBOOT_TRGR_BOOT_LD 0x20000000
+
+/*
+ * NAND_MDR
+ */
+/* 1st read data byte when opcode SBRD */
+#define IFC_NAND_MDR_RDATA0 0xFF000000
+/* 2nd read data byte when opcode SBRD */
+#define IFC_NAND_MDR_RDATA1 0x00FF0000
+
+/*
+ * NOR Machine Specific Registers
+ */
+/*
+ * NOR Event and Error Status Register (NOR_EVTER_STAT)
+ */
+/* NOR Command Sequence Operation Complete */
+#define IFC_NOR_EVTER_STAT_OPC_NOR 0x80000000
+/* Write Protect Error */
+#define IFC_NOR_EVTER_STAT_WPER 0x04000000
+/* Command Sequence Timeout Error */
+#define IFC_NOR_EVTER_STAT_STOER 0x01000000
+
+/*
+ * NOR Event and Error Enable Register (NOR_EVTER_EN)
+ */
+/* NOR Command Seq complete event enable */
+#define IFC_NOR_EVTER_EN_OPCEN_NOR 0x80000000
+/* Write Protect Error Checking Enable */
+#define IFC_NOR_EVTER_EN_WPEREN 0x04000000
+/* Timeout Error Enable */
+#define IFC_NOR_EVTER_EN_STOEREN 0x01000000
+
+/*
+ * NOR Event and Error Interrupt Enable Register (NOR_EVTER_INTR_EN)
+ */
+/* Enable interrupt for OPC complete */
+#define IFC_NOR_EVTER_INTR_OPCEN_NOR 0x80000000
+/* Enable interrupt for write protect error */
+#define IFC_NOR_EVTER_INTR_WPEREN 0x04000000
+/* Enable interrupt for timeout error */
+#define IFC_NOR_EVTER_INTR_STOEREN 0x01000000
+
+/*
+ * NOR Transfer Error Attribute Register-0 (NOR_ERATTR0)
+ */
+/* Source ID for error transaction */
+#define IFC_NOR_ERATTR0_ERSRCID 0xFF000000
+/* AXI ID for error transation */
+#define IFC_NOR_ERATTR0_ERAID 0x000FF000
+/* Chip select corresponds to NOR error */
+#define IFC_NOR_ERATTR0_ERCS_CS0 0x00000000
+#define IFC_NOR_ERATTR0_ERCS_CS1 0x00000010
+#define IFC_NOR_ERATTR0_ERCS_CS2 0x00000020
+#define IFC_NOR_ERATTR0_ERCS_CS3 0x00000030
+/* Type of transaction read/write */
+#define IFC_NOR_ERATTR0_ERTYPE_READ 0x00000001
+
+/*
+ * NOR Transfer Error Attribute Register-2 (NOR_ERATTR2)
+ */
+#define IFC_NOR_ERATTR2_ER_NUM_PHASE_EXP 0x000F0000
+#define IFC_NOR_ERATTR2_ER_NUM_PHASE_PER 0x00000F00
+
+/*
+ * NOR Control Register (NORCR)
+ */
+#define IFC_NORCR_MASK 0x0F0F0000
+/* No. of Address/Data Phase */
+#define IFC_NORCR_NUM_PHASE_MASK 0x0F000000
+#define IFC_NORCR_NUM_PHASE_SHIFT 24
+#define IFC_NORCR_NUM_PHASE(n) ((n-1) << IFC_NORCR_NUM_PHASE_SHIFT)
+/* Sequence Timeout Count */
+#define IFC_NORCR_STOCNT_MASK 0x000F0000
+#define IFC_NORCR_STOCNT_SHIFT 16
+#define IFC_NORCR_STOCNT(n) ((__ilog2(n) - 8) << IFC_NORCR_STOCNT_SHIFT)
+
+/*
+ * GPCM Machine specific registers
+ */
+/*
+ * GPCM Event and Error Status Register (GPCM_EVTER_STAT)
+ */
+/* Timeout error */
+#define IFC_GPCM_EVTER_STAT_TOER 0x04000000
+/* Parity error */
+#define IFC_GPCM_EVTER_STAT_PER 0x01000000
+
+/*
+ * GPCM Event and Error Enable Register (GPCM_EVTER_EN)
+ */
+/* Timeout error enable */
+#define IFC_GPCM_EVTER_EN_TOER_EN 0x04000000
+/* Parity error enable */
+#define IFC_GPCM_EVTER_EN_PER_EN 0x01000000
+
+/*
+ * GPCM Event and Error Interrupt Enable Register (GPCM_EVTER_INTR_EN)
+ */
+/* Enable Interrupt for timeout error */
+#define IFC_GPCM_EEIER_TOERIR_EN 0x04000000
+/* Enable Interrupt for Parity error */
+#define IFC_GPCM_EEIER_PERIR_EN 0x01000000
+
+/*
+ * GPCM Transfer Error Attribute Register-0 (GPCM_ERATTR0)
+ */
+/* Source ID for error transaction */
+#define IFC_GPCM_ERATTR0_ERSRCID 0xFF000000
+/* AXI ID for error transaction */
+#define IFC_GPCM_ERATTR0_ERAID 0x000FF000
+/* Chip select corresponds to GPCM error */
+#define IFC_GPCM_ERATTR0_ERCS_CS0 0x00000000
+#define IFC_GPCM_ERATTR0_ERCS_CS1 0x00000040
+#define IFC_GPCM_ERATTR0_ERCS_CS2 0x00000080
+#define IFC_GPCM_ERATTR0_ERCS_CS3 0x000000C0
+/* Type of transaction read/Write */
+#define IFC_GPCM_ERATTR0_ERTYPE_READ 0x00000001
+
+/*
+ * GPCM Transfer Error Attribute Register-2 (GPCM_ERATTR2)
+ */
+/* On which beat of address/data parity error is observed */
+#define IFC_GPCM_ERATTR2_PERR_BEAT 0x00000C00
+/* Parity Error on byte */
+#define IFC_GPCM_ERATTR2_PERR_BYTE 0x000000F0
+/* Parity Error reported in addr or data phase */
+#define IFC_GPCM_ERATTR2_PERR_DATA_PHASE 0x00000001
+
+/*
+ * GPCM Status Register (GPCM_STAT)
+ */
+#define IFC_GPCM_STAT_BSY 0x80000000 /* GPCM is busy */
+
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+extern void print_ifc_regs(void);
+extern void init_early_memctl_regs(void);
+
+#define IFC_BASE_ADDR ((struct fsl_ifc *)CONFIG_SYS_IFC_ADDR)
+
+#define get_ifc_cspr_ext(i) (in_be32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr_ext))
+#define get_ifc_cspr(i) (in_be32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr))
+#define get_ifc_csor_ext(i) (in_be32(&(IFC_BASE_ADDR)->csor_cs[i].csor_ext))
+#define get_ifc_csor(i) (in_be32(&(IFC_BASE_ADDR)->csor_cs[i].csor))
+#define get_ifc_amask(i) (in_be32(&(IFC_BASE_ADDR)->amask_cs[i].amask))
+#define get_ifc_ftim(i, j) (in_be32(&(IFC_BASE_ADDR)->ftim_cs[i].ftim[j]))
+
+#define set_ifc_cspr_ext(i, v) (out_be32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr_ext, v))
+#define set_ifc_cspr(i, v) (out_be32(&(IFC_BASE_ADDR)->cspr_cs[i].cspr, v))
+#define set_ifc_csor_ext(i, v) (out_be32(&(IFC_BASE_ADDR)->csor_cs[i].csor_ext, v))
+#define set_ifc_csor(i, v) (out_be32(&(IFC_BASE_ADDR)->csor_cs[i].csor, v))
+#define set_ifc_amask(i, v) (out_be32(&(IFC_BASE_ADDR)->amask_cs[i].amask, v))
+#define set_ifc_ftim(i, j, v) \
+ (out_be32(&(IFC_BASE_ADDR)->ftim_cs[i].ftim[j], v))
+
+enum ifc_chip_sel {
+ IFC_CS0,
+ IFC_CS1,
+ IFC_CS2,
+ IFC_CS3,
+ IFC_CS4,
+ IFC_CS5,
+ IFC_CS6,
+ IFC_CS7,
+};
+
+enum ifc_ftims {
+ IFC_FTIM0,
+ IFC_FTIM1,
+ IFC_FTIM2,
+ IFC_FTIM3,
+};
+
+/*
+ * IFC Controller NAND Machine registers
+ */
+struct fsl_ifc_nand {
+ u32 ncfgr;
+ u32 res1[0x4];
+ u32 nand_fcr0;
+ u32 nand_fcr1;
+ u32 res2[0x8];
+ u32 row0;
+ u32 res3;
+ u32 col0;
+ u32 res4;
+ u32 row1;
+ u32 res5;
+ u32 col1;
+ u32 res6;
+ u32 row2;
+ u32 res7;
+ u32 col2;
+ u32 res8;
+ u32 row3;
+ u32 res9;
+ u32 col3;
+ u32 res10[0x24];
+ u32 nand_fbcr;
+ u32 res11;
+ u32 nand_fir0;
+ u32 nand_fir1;
+ u32 nand_fir2;
+ u32 res12[0x10];
+ u32 nand_csel;
+ u32 res13;
+ u32 nandseq_strt;
+ u32 res14;
+ u32 nand_evter_stat;
+ u32 res15;
+ u32 pgrdcmpl_evt_stat;
+ u32 res16[0x2];
+ u32 nand_evter_en;
+ u32 res17[0x2];
+ u32 nand_evter_intr_en;
+ u32 res18[0x2];
+ u32 nand_erattr0;
+ u32 nand_erattr1;
+ u32 res19[0x10];
+ u32 nand_fsr;
+ u32 res20;
+ u32 nand_eccstat[4];
+ u32 res21[0x20];
+ u32 nanndcr;
+ u32 res22[0x2];
+ u32 nand_autoboot_trgr;
+ u32 res23;
+ u32 nand_mdr;
+ u32 res24[0x5C];
+};
+
+/*
+ * IFC controller NOR Machine registers
+ */
+struct fsl_ifc_nor {
+ u32 nor_evter_stat;
+ u32 res1[0x2];
+ u32 nor_evter_en;
+ u32 res2[0x2];
+ u32 nor_evter_intr_en;
+ u32 res3[0x2];
+ u32 nor_erattr0;
+ u32 nor_erattr1;
+ u32 nor_erattr2;
+ u32 res4[0x4];
+ u32 norcr;
+ u32 res5[0xEF];
+};
+
+/*
+ * IFC controller GPCM Machine registers
+ */
+struct fsl_ifc_gpcm {
+ u32 gpcm_evter_stat;
+ u32 res1[0x2];
+ u32 gpcm_evter_en;
+ u32 res2[0x2];
+ u32 gpcm_evter_intr_en;
+ u32 res3[0x2];
+ u32 gpcm_erattr0;
+ u32 gpcm_erattr1;
+ u32 gpcm_erattr2;
+ u32 gpcm_stat;
+ u32 res4[0x1F3];
+};
+
+#ifdef CONFIG_SYS_FSL_IFC_BANK_COUNT
+#if (CONFIG_SYS_FSL_IFC_BANK_COUNT <= 8)
+#define IFC_CSPR_REG_LEN 148
+#define IFC_AMASK_REG_LEN 144
+#define IFC_CSOR_REG_LEN 144
+#define IFC_FTIM_REG_LEN 576
+
+#define IFC_CSPR_USED_LEN sizeof(struct fsl_ifc_cspr) * \
+ CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_AMASK_USED_LEN sizeof(struct fsl_ifc_amask) * \
+ CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_CSOR_USED_LEN sizeof(struct fsl_ifc_csor) * \
+ CONFIG_SYS_FSL_IFC_BANK_COUNT
+#define IFC_FTIM_USED_LEN sizeof(struct fsl_ifc_ftim) * \
+ CONFIG_SYS_FSL_IFC_BANK_COUNT
+#else
+#error IFC BANK count not vaild
+#endif
+#else
+#error IFC BANK count not defined
+#endif
+
+struct fsl_ifc_cspr {
+ u32 cspr_ext;
+ u32 cspr;
+ u32 res;
+};
+
+struct fsl_ifc_amask {
+ u32 amask;
+ u32 res[0x2];
+};
+
+struct fsl_ifc_csor {
+ u32 csor;
+ u32 csor_ext;
+ u32 res;
+};
+
+struct fsl_ifc_ftim {
+ u32 ftim[4];
+ u32 res[0x8];
+};
+
+/*
+ * IFC Controller Registers
+ */
+struct fsl_ifc {
+ u32 ifc_rev;
+ u32 res1[0x2];
+ struct fsl_ifc_cspr cspr_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+ u8 res2[IFC_CSPR_REG_LEN - IFC_CSPR_USED_LEN];
+ struct fsl_ifc_amask amask_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+ u8 res3[IFC_AMASK_REG_LEN - IFC_AMASK_USED_LEN];
+ struct fsl_ifc_csor csor_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+ u8 res4[IFC_CSOR_REG_LEN - IFC_CSOR_USED_LEN];
+ struct fsl_ifc_ftim ftim_cs[CONFIG_SYS_FSL_IFC_BANK_COUNT];
+ u8 res5[IFC_FTIM_REG_LEN - IFC_FTIM_USED_LEN];
+ u32 rb_stat;
+ u32 res6[0x2];
+ u32 ifc_gcr;
+ u32 res7[0x2];
+ u32 cm_evter_stat;
+ u32 res8[0x2];
+ u32 cm_evter_en;
+ u32 res9[0x2];
+ u32 cm_evter_intr_en;
+ u32 res10[0x2];
+ u32 cm_erattr0;
+ u32 cm_erattr1;
+ u32 res11[0x2];
+ u32 ifc_ccr;
+ u32 ifc_csr;
+ u32 res12[0x2EB];
+ struct fsl_ifc_nand ifc_nand;
+ struct fsl_ifc_nor ifc_nor;
+ struct fsl_ifc_gpcm ifc_gpcm;
+};
+
+#ifdef CONFIG_SYS_FSL_ERRATUM_IFC_A002769
+#undef CSPR_MSEL_NOR
+#define CSPR_MSEL_NOR CSPR_MSEL_GPCM
+#endif
+#endif /* CONFIG_FSL_IFC */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_PPC_FSL_IFC_H */
diff --git a/arch/powerpc/include/asm/fsl_law.h b/arch/powerpc/include/asm/fsl_law.h
new file mode 100644
index 0000000..bea1636
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_law.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef _FSL_LAW_H_
+#define _FSL_LAW_H_
+
+#include <asm/io.h>
+
+#define LAW_EN 0x80000000
+
+#define SET_LAW_ENTRY(idx, a, sz, trgt) \
+ { .index = idx, .addr = a, .size = sz, .trgt_id = trgt }
+
+#define SET_LAW(a, sz, trgt) \
+ { .index = -1, .addr = a, .size = sz, .trgt_id = trgt }
+
+enum law_size {
+ LAW_SIZE_4K = 0xb,
+ LAW_SIZE_8K,
+ LAW_SIZE_16K,
+ LAW_SIZE_32K,
+ LAW_SIZE_64K,
+ LAW_SIZE_128K,
+ LAW_SIZE_256K,
+ LAW_SIZE_512K,
+ LAW_SIZE_1M,
+ LAW_SIZE_2M,
+ LAW_SIZE_4M,
+ LAW_SIZE_8M,
+ LAW_SIZE_16M,
+ LAW_SIZE_32M,
+ LAW_SIZE_64M,
+ LAW_SIZE_128M,
+ LAW_SIZE_256M,
+ LAW_SIZE_512M,
+ LAW_SIZE_1G,
+ LAW_SIZE_2G,
+ LAW_SIZE_4G,
+ LAW_SIZE_8G,
+ LAW_SIZE_16G,
+ LAW_SIZE_32G,
+};
+
+#define law_size_bits(sz) (__ilog2_u64(sz) - 1)
+#define lawar_size(x) (1ULL << ((x & 0x3f) + 1))
+
+#ifdef CONFIG_FSL_CORENET
+enum law_trgt_if {
+ LAW_TRGT_IF_PCIE_1 = 0x00,
+ LAW_TRGT_IF_PCIE_2 = 0x01,
+ LAW_TRGT_IF_PCIE_3 = 0x02,
+ LAW_TRGT_IF_PCIE_4 = 0x03,
+ LAW_TRGT_IF_RIO_1 = 0x08,
+ LAW_TRGT_IF_RIO_2 = 0x09,
+
+ LAW_TRGT_IF_DDR_1 = 0x10,
+ LAW_TRGT_IF_DDR_2 = 0x11, /* 2nd controller */
+ LAW_TRGT_IF_DDR_3 = 0x12,
+ LAW_TRGT_IF_DDR_4 = 0x13,
+ LAW_TRGT_IF_DDR_INTRLV = 0x14,
+ LAW_TRGT_IF_DDR_INTLV_34 = 0x15,
+ LAW_TRGT_IF_DDR_INTLV_123 = 0x17,
+ LAW_TRGT_IF_DDR_INTLV_1234 = 0x16,
+ LAW_TRGT_IF_BMAN = 0x18,
+ LAW_TRGT_IF_DCSR = 0x1d,
+ LAW_TRGT_IF_LBC = 0x1f,
+ LAW_TRGT_IF_QMAN = 0x3c,
+
+ LAW_TRGT_IF_MAPLE = 0x50,
+};
+#define LAW_TRGT_IF_DDR LAW_TRGT_IF_DDR_1
+#define LAW_TRGT_IF_IFC LAW_TRGT_IF_LBC
+#else
+enum law_trgt_if {
+ LAW_TRGT_IF_PCI = 0x00,
+ LAW_TRGT_IF_PCI_2 = 0x01,
+#ifndef CONFIG_MPC8641
+ LAW_TRGT_IF_PCIE_1 = 0x02,
+#endif
+#if defined(CONFIG_BSC9131)
+ LAW_TRGT_IF_OCN_DSP = 0x03,
+#else
+#if !defined(CONFIG_MPC8572) && !defined(CONFIG_P2020)
+ LAW_TRGT_IF_PCIE_3 = 0x03,
+#endif
+#endif
+ LAW_TRGT_IF_LBC = 0x04,
+ LAW_TRGT_IF_CCSR = 0x08,
+ LAW_TRGT_IF_DSP_CCSR = 0x09,
+ LAW_TRGT_IF_DDR_INTRLV = 0x0b,
+ LAW_TRGT_IF_RIO = 0x0c,
+ LAW_TRGT_IF_RIO_2 = 0x0d,
+ LAW_TRGT_IF_DPAA_SWP_SRAM = 0x0e,
+ LAW_TRGT_IF_DDR = 0x0f,
+ LAW_TRGT_IF_DDR_2 = 0x16, /* 2nd controller */
+ /* place holder for 3-way and 4-way interleaving */
+ LAW_TRGT_IF_DDR_3,
+ LAW_TRGT_IF_DDR_4,
+ LAW_TRGT_IF_DDR_INTLV_34,
+ LAW_TRGT_IF_DDR_INTLV_123,
+ LAW_TRGT_IF_DDR_INTLV_1234,
+};
+#define LAW_TRGT_IF_DDR_1 LAW_TRGT_IF_DDR
+#define LAW_TRGT_IF_PCI_1 LAW_TRGT_IF_PCI
+#define LAW_TRGT_IF_PCIX LAW_TRGT_IF_PCI
+#define LAW_TRGT_IF_PCIE_2 LAW_TRGT_IF_PCI_2
+#define LAW_TRGT_IF_RIO_1 LAW_TRGT_IF_RIO
+#define LAW_TRGT_IF_IFC LAW_TRGT_IF_LBC
+
+#ifdef CONFIG_MPC8641
+#define LAW_TRGT_IF_PCIE_1 LAW_TRGT_IF_PCI
+#endif
+
+#if defined(CONFIG_MPC8572) || defined(CONFIG_P2020)
+#define LAW_TRGT_IF_PCIE_3 LAW_TRGT_IF_PCI
+#endif
+#endif /* CONFIG_FSL_CORENET */
+
+struct law_entry {
+ int index;
+ phys_addr_t addr;
+ enum law_size size;
+ enum law_trgt_if trgt_id;
+};
+
+extern void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
+extern int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
+extern int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id);
+extern int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id);
+extern struct law_entry find_law(phys_addr_t addr);
+extern void disable_law(u8 idx);
+extern void init_laws(void);
+extern void print_laws(void);
+
+/* define in board code */
+extern struct law_entry law_table[];
+extern int num_law_entries;
+#endif
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
new file mode 100644
index 0000000..d1def75
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -0,0 +1,539 @@
+/*
+ * Copyright (C) 2004-2008,2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef __ASM_PPC_FSL_LBC_H
+#define __ASM_PPC_FSL_LBC_H
+
+#include <config.h>
+#include <common.h>
+
+#ifdef CONFIG_MPC85xx
+void lbc_sdram_init(void);
+#endif
+
+/* BR - Base Registers
+ */
+#define BR0 0x5000 /* Register offset to immr */
+#define BR1 0x5008
+#define BR2 0x5010
+#define BR3 0x5018
+#define BR4 0x5020
+#define BR5 0x5028
+#define BR6 0x5030
+#define BR7 0x5038
+
+#define BR_BA 0xFFFF8000
+#define BR_BA_SHIFT 15
+#define BR_XBA 0x00006000
+#define BR_XBA_SHIFT 13
+#define BR_PS 0x00001800
+#define BR_PS_SHIFT 11
+#define BR_PS_8 0x00000800 /* Port Size 8 bit */
+#define BR_PS_16 0x00001000 /* Port Size 16 bit */
+#define BR_PS_32 0x00001800 /* Port Size 32 bit */
+#define BR_DECC 0x00000600
+#define BR_DECC_SHIFT 9
+#define BR_DECC_OFF 0x00000000
+#define BR_DECC_CHK 0x00000200
+#define BR_DECC_CHK_GEN 0x00000400
+#define BR_WP 0x00000100
+#define BR_WP_SHIFT 8
+#define BR_MSEL 0x000000E0
+#define BR_MSEL_SHIFT 5
+#define BR_MS_GPCM 0x00000000 /* GPCM */
+#if !defined(CONFIG_MPC834x) && !defined(CONFIG_MPC8360)
+#define BR_MS_FCM 0x00000020 /* FCM */
+#endif
+#if defined(CONFIG_MPC834x) || defined(CONFIG_MPC8360)
+#define BR_MS_SDRAM 0x00000060 /* SDRAM */
+#elif defined(CONFIG_MPC85xx)
+#define BR_MS_SDRAM 0x00000000 /* SDRAM */
+#endif
+#define BR_MS_UPMA 0x00000080 /* UPMA */
+#define BR_MS_UPMB 0x000000A0 /* UPMB */
+#define BR_MS_UPMC 0x000000C0 /* UPMC */
+#if !defined(CONFIG_MPC834x)
+#define BR_ATOM 0x0000000C
+#define BR_ATOM_SHIFT 2
+#endif
+#define BR_V 0x00000001
+#define BR_V_SHIFT 0
+
+#define BR_UPMx_TO_MSEL(x) ((x + 4) << BR_MSEL_SHIFT)
+
+#define UPMA 0
+#define UPMB 1
+#define UPMC 2
+
+#if defined(CONFIG_MPC834x)
+#define BR_RES ~(BR_BA | BR_PS | BR_DECC | BR_WP | BR_MSEL | BR_V)
+#else
+#define BR_RES ~(BR_BA | BR_PS | BR_DECC | BR_WP | BR_MSEL | BR_ATOM | BR_V)
+#endif
+
+/* Convert an address into the right format for the BR registers */
+#if defined(CONFIG_PHYS_64BIT) && !defined(CONFIG_FSL_ELBC)
+#define BR_PHYS_ADDR(x) \
+ ((u32)(((x) & 0x0ffff8000ULL) | (((x) & 0x300000000ULL) >> 19)))
+#else
+#define BR_PHYS_ADDR(x) ((u32)(x) & 0xffff8000)
+#endif
+
+/* OR - Option Registers
+ */
+#define OR0 0x5004 /* Register offset to immr */
+#define OR1 0x500C
+#define OR2 0x5014
+#define OR3 0x501C
+#define OR4 0x5024
+#define OR5 0x502C
+#define OR6 0x5034
+#define OR7 0x503C
+
+#define OR_GPCM_AM 0xFFFF8000
+#define OR_GPCM_AM_SHIFT 15
+#define OR_GPCM_XAM 0x00006000
+#define OR_GPCM_XAM_SHIFT 13
+#define OR_GPCM_BCTLD 0x00001000
+#define OR_GPCM_BCTLD_SHIFT 12
+#define OR_GPCM_CSNT 0x00000800
+#define OR_GPCM_CSNT_SHIFT 11
+#define OR_GPCM_ACS 0x00000600
+#define OR_GPCM_ACS_SHIFT 9
+#define OR_GPCM_ACS_DIV2 0x00000600
+#define OR_GPCM_ACS_DIV4 0x00000400
+#define OR_GPCM_XACS 0x00000100
+#define OR_GPCM_XACS_SHIFT 8
+#define OR_GPCM_SCY 0x000000F0
+#define OR_GPCM_SCY_SHIFT 4
+#define OR_GPCM_SCY_1 0x00000010
+#define OR_GPCM_SCY_2 0x00000020
+#define OR_GPCM_SCY_3 0x00000030
+#define OR_GPCM_SCY_4 0x00000040
+#define OR_GPCM_SCY_5 0x00000050
+#define OR_GPCM_SCY_6 0x00000060
+#define OR_GPCM_SCY_7 0x00000070
+#define OR_GPCM_SCY_8 0x00000080
+#define OR_GPCM_SCY_9 0x00000090
+#define OR_GPCM_SCY_10 0x000000a0
+#define OR_GPCM_SCY_11 0x000000b0
+#define OR_GPCM_SCY_12 0x000000c0
+#define OR_GPCM_SCY_13 0x000000d0
+#define OR_GPCM_SCY_14 0x000000e0
+#define OR_GPCM_SCY_15 0x000000f0
+#define OR_GPCM_SETA 0x00000008
+#define OR_GPCM_SETA_SHIFT 3
+#define OR_GPCM_TRLX 0x00000004
+#define OR_GPCM_TRLX_SHIFT 2
+#define OR_GPCM_TRLX_CLEAR 0x00000000
+#define OR_GPCM_TRLX_SET 0x00000004
+#define OR_GPCM_EHTR 0x00000002
+#define OR_GPCM_EHTR_SHIFT 1
+#define OR_GPCM_EHTR_CLEAR 0x00000000
+#define OR_GPCM_EHTR_SET 0x00000002
+#if !defined(CONFIG_MPC8308)
+#define OR_GPCM_EAD 0x00000001
+#define OR_GPCM_EAD_SHIFT 0
+#endif
+
+/* helpers to convert values into an OR address mask (GPCM mode) */
+#define P2SZ_TO_AM(s) ((~((s) - 1)) & 0xffff8000) /* must be pow of 2 */
+#define MEG_TO_AM(m) P2SZ_TO_AM((m) << 20)
+
+#define OR_FCM_AM 0xFFFF8000
+#define OR_FCM_AM_SHIFT 15
+#define OR_FCM_XAM 0x00006000
+#define OR_FCM_XAM_SHIFT 13
+#define OR_FCM_BCTLD 0x00001000
+#define OR_FCM_BCTLD_SHIFT 12
+#define OR_FCM_PGS 0x00000400
+#define OR_FCM_PGS_SHIFT 10
+#define OR_FCM_CSCT 0x00000200
+#define OR_FCM_CSCT_SHIFT 9
+#define OR_FCM_CST 0x00000100
+#define OR_FCM_CST_SHIFT 8
+#define OR_FCM_CHT 0x00000080
+#define OR_FCM_CHT_SHIFT 7
+#define OR_FCM_SCY 0x00000070
+#define OR_FCM_SCY_SHIFT 4
+#define OR_FCM_SCY_1 0x00000010
+#define OR_FCM_SCY_2 0x00000020
+#define OR_FCM_SCY_3 0x00000030
+#define OR_FCM_SCY_4 0x00000040
+#define OR_FCM_SCY_5 0x00000050
+#define OR_FCM_SCY_6 0x00000060
+#define OR_FCM_SCY_7 0x00000070
+#define OR_FCM_RST 0x00000008
+#define OR_FCM_RST_SHIFT 3
+#define OR_FCM_TRLX 0x00000004
+#define OR_FCM_TRLX_SHIFT 2
+#define OR_FCM_EHTR 0x00000002
+#define OR_FCM_EHTR_SHIFT 1
+
+#define OR_UPM_AM 0xFFFF8000
+#define OR_UPM_AM_SHIFT 15
+#define OR_UPM_XAM 0x00006000
+#define OR_UPM_XAM_SHIFT 13
+#define OR_UPM_BCTLD 0x00001000
+#define OR_UPM_BCTLD_SHIFT 12
+#define OR_UPM_BI 0x00000100
+#define OR_UPM_BI_SHIFT 8
+#define OR_UPM_TRLX 0x00000004
+#define OR_UPM_TRLX_SHIFT 2
+#define OR_UPM_EHTR 0x00000002
+#define OR_UPM_EHTR_SHIFT 1
+#define OR_UPM_EAD 0x00000001
+#define OR_UPM_EAD_SHIFT 0
+
+#define OR_SDRAM_AM 0xFFFF8000
+#define OR_SDRAM_AM_SHIFT 15
+#define OR_SDRAM_XAM 0x00006000
+#define OR_SDRAM_XAM_SHIFT 13
+#define OR_SDRAM_COLS 0x00001C00
+#define OR_SDRAM_COLS_SHIFT 10
+#define OR_SDRAM_MIN_COLS 7
+#define OR_SDRAM_ROWS 0x000001C0
+#define OR_SDRAM_ROWS_SHIFT 6
+#define OR_SDRAM_MIN_ROWS 9
+#define OR_SDRAM_PMSEL 0x00000020
+#define OR_SDRAM_PMSEL_SHIFT 5
+#define OR_SDRAM_EAD 0x00000001
+#define OR_SDRAM_EAD_SHIFT 0
+
+#define OR_AM_32KB 0xFFFF8000
+#define OR_AM_64KB 0xFFFF0000
+#define OR_AM_128KB 0xFFFE0000
+#define OR_AM_256KB 0xFFFC0000
+#define OR_AM_512KB 0xFFF80000
+#define OR_AM_1MB 0xFFF00000
+#define OR_AM_2MB 0xFFE00000
+#define OR_AM_4MB 0xFFC00000
+#define OR_AM_8MB 0xFF800000
+#define OR_AM_16MB 0xFF000000
+#define OR_AM_32MB 0xFE000000
+#define OR_AM_64MB 0xFC000000
+#define OR_AM_128MB 0xF8000000
+#define OR_AM_256MB 0xF0000000
+#define OR_AM_512MB 0xE0000000
+#define OR_AM_1GB 0xC0000000
+#define OR_AM_2GB 0x80000000
+#define OR_AM_4GB 0x00000000
+
+/* MxMR - UPM Machine A/B/C Mode Registers
+ */
+#define MxMR_MAD_MSK 0x0000003f /* Machine Address Mask */
+#define MxMR_TLFx_MSK 0x000003c0 /* Refresh Loop Field Mask */
+#define MxMR_WLFx_MSK 0x00003c00 /* Write Loop Field Mask */
+#define MxMR_WLFx_1X 0x00000400 /* executed 1 time */
+#define MxMR_WLFx_2X 0x00000800 /* executed 2 times */
+#define MxMR_WLFx_3X 0x00000c00 /* executed 3 times */
+#define MxMR_WLFx_4X 0x00001000 /* executed 4 times */
+#define MxMR_WLFx_5X 0x00001400 /* executed 5 times */
+#define MxMR_WLFx_6X 0x00001800 /* executed 6 times */
+#define MxMR_WLFx_7X 0x00001c00 /* executed 7 times */
+#define MxMR_WLFx_8X 0x00002000 /* executed 8 times */
+#define MxMR_WLFx_9X 0x00002400 /* executed 9 times */
+#define MxMR_WLFx_10X 0x00002800 /* executed 10 times */
+#define MxMR_WLFx_11X 0x00002c00 /* executed 11 times */
+#define MxMR_WLFx_12X 0x00003000 /* executed 12 times */
+#define MxMR_WLFx_13X 0x00003400 /* executed 13 times */
+#define MxMR_WLFx_14X 0x00003800 /* executed 14 times */
+#define MxMR_WLFx_15X 0x00003c00 /* executed 15 times */
+#define MxMR_WLFx_16X 0x00000000 /* executed 16 times */
+#define MxMR_RLFx_MSK 0x0003c000 /* Read Loop Field Mask */
+#define MxMR_GPL_x4DIS 0x00040000 /* GPL_A4 Ouput Line Disable */
+#define MxMR_G0CLx_MSK 0x00380000 /* General Line 0 Control Mask */
+#define MxMR_DSx_1_CYCL 0x00000000 /* 1 cycle Disable Period */
+#define MxMR_DSx_2_CYCL 0x00400000 /* 2 cycle Disable Period */
+#define MxMR_DSx_3_CYCL 0x00800000 /* 3 cycle Disable Period */
+#define MxMR_DSx_4_CYCL 0x00c00000 /* 4 cycle Disable Period */
+#define MxMR_DSx_MSK 0x00c00000 /* Disable Timer Period Mask */
+#define MxMR_AMx_MSK 0x07000000 /* Addess Multiplex Size Mask */
+#define MxMR_UWPL 0x08000000 /* LUPWAIT Polarity Mask */
+#define MxMR_OP_NORM 0x00000000 /* Normal Operation */
+#define MxMR_OP_WARR 0x10000000 /* Write to Array */
+#define MxMR_OP_RARR 0x20000000 /* Read from Array */
+#define MxMR_OP_RUNP 0x30000000 /* Run Pattern */
+#define MxMR_OP_MSK 0x30000000 /* Command Opcode Mask */
+#define MxMR_RFEN 0x40000000 /* Refresh Enable */
+#define MxMR_BSEL 0x80000000 /* Bus Select */
+
+#define LBLAWAR_EN 0x80000000
+#define LBLAWAR_4KB 0x0000000B
+#define LBLAWAR_8KB 0x0000000C
+#define LBLAWAR_16KB 0x0000000D
+#define LBLAWAR_32KB 0x0000000E
+#define LBLAWAR_64KB 0x0000000F
+#define LBLAWAR_128KB 0x00000010
+#define LBLAWAR_256KB 0x00000011
+#define LBLAWAR_512KB 0x00000012
+#define LBLAWAR_1MB 0x00000013
+#define LBLAWAR_2MB 0x00000014
+#define LBLAWAR_4MB 0x00000015
+#define LBLAWAR_8MB 0x00000016
+#define LBLAWAR_16MB 0x00000017
+#define LBLAWAR_32MB 0x00000018
+#define LBLAWAR_64MB 0x00000019
+#define LBLAWAR_128MB 0x0000001A
+#define LBLAWAR_256MB 0x0000001B
+#define LBLAWAR_512MB 0x0000001C
+#define LBLAWAR_1GB 0x0000001D
+#define LBLAWAR_2GB 0x0000001E
+
+/* LBCR - Local Bus Configuration Register
+ */
+#define LBCR_LDIS 0x80000000
+#define LBCR_LDIS_SHIFT 31
+#define LBCR_BCTLC 0x00C00000
+#define LBCR_BCTLC_SHIFT 22
+#define LBCR_LPBSE 0x00020000
+#define LBCR_LPBSE_SHIFT 17
+#define LBCR_EPAR 0x00010000
+#define LBCR_EPAR_SHIFT 16
+#define LBCR_BMT 0x0000FF00
+#define LBCR_BMT_SHIFT 8
+#define LBCR_BMTPS 0x0000000F
+#define LBCR_BMTPS_SHIFT 0
+
+/* LCRR - Clock Ratio Register
+ */
+#define LCRR_DBYP 0x80000000
+#define LCRR_DBYP_SHIFT 31
+#define LCRR_BUFCMDC 0x30000000
+#define LCRR_BUFCMDC_SHIFT 28
+#define LCRR_BUFCMDC_1 0x10000000
+#define LCRR_BUFCMDC_2 0x20000000
+#define LCRR_BUFCMDC_3 0x30000000
+#define LCRR_BUFCMDC_4 0x00000000
+#define LCRR_ECL 0x03000000
+#define LCRR_ECL_SHIFT 24
+#define LCRR_ECL_4 0x00000000
+#define LCRR_ECL_5 0x01000000
+#define LCRR_ECL_6 0x02000000
+#define LCRR_ECL_7 0x03000000
+#define LCRR_EADC 0x00030000
+#define LCRR_EADC_SHIFT 16
+#define LCRR_EADC_1 0x00010000
+#define LCRR_EADC_2 0x00020000
+#define LCRR_EADC_3 0x00030000
+#define LCRR_EADC_4 0x00000000
+/* CLKDIV is five bits only on 8536, 8572, and 8610, so far, but the fifth bit
+ * should always be zero on older parts that have a four bit CLKDIV.
+ */
+#define LCRR_CLKDIV 0x0000001F
+#define LCRR_CLKDIV_SHIFT 0
+#if defined(CONFIG_MPC83xx) || defined (CONFIG_MPC8540) || \
+ defined(CONFIG_MPC8541) || defined (CONFIG_MPC8555) || \
+ defined(CONFIG_MPC8560)
+#define LCRR_CLKDIV_2 0x00000002
+#define LCRR_CLKDIV_4 0x00000004
+#define LCRR_CLKDIV_8 0x00000008
+#elif defined(CONFIG_FSL_CORENET)
+#define LCRR_CLKDIV_8 0x00000002
+#define LCRR_CLKDIV_16 0x00000004
+#define LCRR_CLKDIV_32 0x00000008
+#else
+#define LCRR_CLKDIV_4 0x00000002
+#define LCRR_CLKDIV_8 0x00000004
+#define LCRR_CLKDIV_16 0x00000008
+#endif
+
+/* LTEDR - Transfer Error Check Disable Register
+ */
+#define LTEDR_BMD 0x80000000 /* Bus monitor disable */
+#define LTEDR_PARD 0x20000000 /* Parity error checking disabled */
+#define LTEDR_WPD 0x04000000 /* Write protect error checking diable */
+#define LTEDR_WARA 0x00800000 /* Write-after-read-atomic error checking diable */
+#define LTEDR_RAWA 0x00400000 /* Read-after-write-atomic error checking disable */
+#define LTEDR_CSD 0x00080000 /* Chip select error checking disable */
+
+/* FMR - Flash Mode Register
+ */
+#define FMR_CWTO 0x0000F000
+#define FMR_CWTO_SHIFT 12
+#define FMR_BOOT 0x00000800
+#define FMR_ECCM 0x00000100
+#define FMR_AL 0x00000030
+#define FMR_AL_SHIFT 4
+#define FMR_OP 0x00000003
+#define FMR_OP_SHIFT 0
+
+/* FIR - Flash Instruction Register
+ */
+#define FIR_OP0 0xF0000000
+#define FIR_OP0_SHIFT 28
+#define FIR_OP1 0x0F000000
+#define FIR_OP1_SHIFT 24
+#define FIR_OP2 0x00F00000
+#define FIR_OP2_SHIFT 20
+#define FIR_OP3 0x000F0000
+#define FIR_OP3_SHIFT 16
+#define FIR_OP4 0x0000F000
+#define FIR_OP4_SHIFT 12
+#define FIR_OP5 0x00000F00
+#define FIR_OP5_SHIFT 8
+#define FIR_OP6 0x000000F0
+#define FIR_OP6_SHIFT 4
+#define FIR_OP7 0x0000000F
+#define FIR_OP7_SHIFT 0
+#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
+#define FIR_OP_CA 0x1 /* Issue current column address */
+#define FIR_OP_PA 0x2 /* Issue current block+page address */
+#define FIR_OP_UA 0x3 /* Issue user defined address */
+#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
+#define FIR_OP_RSW 0xF /* Wait then read 1 or 2 bytes */
+
+/* FCR - Flash Command Register
+ */
+#define FCR_CMD0 0xFF000000
+#define FCR_CMD0_SHIFT 24
+#define FCR_CMD1 0x00FF0000
+#define FCR_CMD1_SHIFT 16
+#define FCR_CMD2 0x0000FF00
+#define FCR_CMD2_SHIFT 8
+#define FCR_CMD3 0x000000FF
+#define FCR_CMD3_SHIFT 0
+/* FBAR - Flash Block Address Register
+ */
+#define FBAR_BLK 0x00FFFFFF
+
+/* FPAR - Flash Page Address Register
+ */
+#define FPAR_SP_PI 0x00007C00
+#define FPAR_SP_PI_SHIFT 10
+#define FPAR_SP_MS 0x00000200
+#define FPAR_SP_CI 0x000001FF
+#define FPAR_SP_CI_SHIFT 0
+#define FPAR_LP_PI 0x0003F000
+#define FPAR_LP_PI_SHIFT 12
+#define FPAR_LP_MS 0x00000800
+#define FPAR_LP_CI 0x000007FF
+#define FPAR_LP_CI_SHIFT 0
+
+/* LSDMR - SDRAM Machine Mode Register
+ */
+#define LSDMR_RFEN (1 << (31 - 1))
+#define LSDMR_BSMA1516 (3 << (31 - 10))
+#define LSDMR_BSMA1617 (4 << (31 - 10))
+#define LSDMR_RFCR5 (3 << (31 - 16))
+#define LSDMR_RFCR16 (7 << (31 - 16))
+#define LSDMR_PRETOACT3 (3 << (31 - 19))
+#define LSDMR_PRETOACT7 (7 << (31 - 19))
+#define LSDMR_ACTTORW3 (3 << (31 - 22))
+#define LSDMR_ACTTORW7 (7 << (31 - 22))
+#define LSDMR_ACTTORW6 (6 << (31 - 22))
+#define LSDMR_BL8 (1 << (31 - 23))
+#define LSDMR_WRC2 (2 << (31 - 27))
+#define LSDMR_WRC4 (0 << (31 - 27))
+#define LSDMR_BUFCMD (1 << (31 - 29))
+#define LSDMR_CL3 (3 << (31 - 31))
+
+#define LSDMR_OP_NORMAL (0 << (31 - 4))
+#define LSDMR_OP_ARFRSH (1 << (31 - 4))
+#define LSDMR_OP_SRFRSH (2 << (31 - 4))
+#define LSDMR_OP_MRW (3 << (31 - 4))
+#define LSDMR_OP_PRECH (4 << (31 - 4))
+#define LSDMR_OP_PCHALL (5 << (31 - 4))
+#define LSDMR_OP_ACTBNK (6 << (31 - 4))
+#define LSDMR_OP_RWINV (7 << (31 - 4))
+
+/* LTESR - Transfer Error Status Register
+ */
+#define LTESR_BM 0x80000000
+#define LTESR_FCT 0x40000000
+#define LTESR_PAR 0x20000000
+#define LTESR_WP 0x04000000
+#define LTESR_ATMW 0x00800000
+#define LTESR_ATMR 0x00400000
+#define LTESR_CS 0x00080000
+#define LTESR_CC 0x00000001
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+extern void print_lbc_regs(void);
+extern void init_early_memctl_regs(void);
+extern void upmconfig(uint upm, uint *table, uint size);
+
+#define LBC_BASE_ADDR ((fsl_lbc_t *)CONFIG_SYS_LBC_ADDR)
+#define get_lbc_lcrr() (in_be32(&(LBC_BASE_ADDR)->lcrr))
+#define get_lbc_lbcr() (in_be32(&(LBC_BASE_ADDR)->lbcr))
+#define get_lbc_br(i) (in_be32(&(LBC_BASE_ADDR)->bank[i].br))
+#define get_lbc_or(i) (in_be32(&(LBC_BASE_ADDR)->bank[i].or))
+#define set_lbc_br(i, v) (out_be32(&(LBC_BASE_ADDR)->bank[i].br, v))
+#define set_lbc_or(i, v) (out_be32(&(LBC_BASE_ADDR)->bank[i].or, v))
+
+typedef struct lbc_bank {
+ u32 br;
+ u32 or;
+} lbc_bank_t;
+
+/* Local Bus Controller Registers */
+typedef struct fsl_lbc {
+ lbc_bank_t bank[8];
+ u8 res1[40];
+ u32 mar; /* LBC UPM Addr */
+ u8 res2[4];
+ u32 mamr; /* LBC UPMA Mode */
+ u32 mbmr; /* LBC UPMB Mode */
+ u32 mcmr; /* LBC UPMC Mode */
+ u8 res3[8];
+ u32 mrtpr; /* LBC Memory Refresh Timer Prescaler */
+ u32 mdr; /* LBC UPM Data */
+#ifdef CONFIG_FSL_ELBC
+ u8 res4[4];
+ u32 lsor;
+ u8 res5[12];
+ u32 lurt; /* LBC UPM Refresh Timer */
+ u8 res6[4];
+#else
+ u8 res4[8];
+ u32 lsdmr; /* LBC SDRAM Mode */
+ u8 res5[8];
+ u32 lurt; /* LBC UPM Refresh Timer */
+ u32 lsrt; /* LBC SDRAM Refresh Timer */
+#endif
+ u8 res7[8];
+ u32 ltesr; /* LBC Transfer Error Status */
+ u32 ltedr; /* LBC Transfer Error Disable */
+ u32 lteir; /* LBC Transfer Error IRQ */
+ u32 lteatr; /* LBC Transfer Error Attrs */
+ u32 ltear; /* LBC Transfer Error Addr */
+ u8 res8[12];
+ u32 lbcr; /* LBC Configuration */
+ u32 lcrr; /* LBC Clock Ratio */
+#ifdef CONFIG_NAND_FSL_ELBC
+ u8 res9[0x8];
+ u32 fmr; /* Flash Mode Register */
+ u32 fir; /* Flash Instruction Register */
+ u32 fcr; /* Flash Command Register */
+ u32 fbar; /* Flash Block Addr Register */
+ u32 fpar; /* Flash Page Addr Register */
+ u32 fbcr; /* Flash Byte Count Register */
+ u8 res10[0xF08];
+#else
+ u8 res9[0xF28];
+#endif
+} fsl_lbc_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_PPC_FSL_LBC_H */
diff --git a/arch/powerpc/include/asm/fsl_liodn.h b/arch/powerpc/include/asm/fsl_liodn.h
new file mode 100644
index 0000000..d759de9
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_liodn.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _FSL_LIODN_H_
+#define _FSL_LIODN_H_
+
+#include <asm/types.h>
+
+struct srio_liodn_id_table {
+ u32 id[2];
+ unsigned long reg_offset[2];
+ u8 num_ids;
+ u8 portid;
+};
+#define SET_SRIO_LIODN_1(port, idA) \
+ { .id = { idA }, .num_ids = 1, .portid = port, \
+ .reg_offset[0] = offsetof(ccsr_gur_t, rio##port##liodnr) \
+ + CONFIG_SYS_MPC85xx_GUTS_OFFSET + CONFIG_SYS_CCSRBAR, \
+ }
+
+#define SET_SRIO_LIODN_2(port, idA, idB) \
+ { .id = { idA, idB }, .num_ids = 2, .portid = port, \
+ .reg_offset[0] = offsetof(ccsr_gur_t, rio##port##liodnr) \
+ + CONFIG_SYS_MPC85xx_GUTS_OFFSET + CONFIG_SYS_CCSRBAR, \
+ .reg_offset[1] = offsetof(ccsr_gur_t, rio##port##maintliodnr) \
+ + CONFIG_SYS_MPC85xx_GUTS_OFFSET + CONFIG_SYS_CCSRBAR, \
+ }
+
+struct liodn_id_table {
+ const char * compat;
+ u32 id[2];
+ u8 num_ids;
+ phys_addr_t compat_offset;
+ unsigned long reg_offset;
+};
+
+extern u32 get_ppid_liodn(int ppid_tbl_idx, int ppid);
+extern void set_liodns(void);
+extern void fdt_fixup_liodn(void *blob);
+
+#define SET_LIODN_BASE_1(idA) \
+ { .id = { idA }, .num_ids = 1, }
+
+#define SET_LIODN_BASE_2(idA, idB) \
+ { .id = { idA, idB }, .num_ids = 2 }
+
+#define SET_LIODN_ENTRY_1(name, idA, off, compatoff) \
+ { .compat = name, \
+ .id = { idA }, .num_ids = 1, \
+ .reg_offset = off + CONFIG_SYS_CCSRBAR, \
+ .compat_offset = compatoff + CONFIG_SYS_CCSRBAR_PHYS, \
+ }
+
+#define SET_LIODN_ENTRY_2(name, idA, idB, off, compatoff) \
+ { .compat = name, \
+ .id = { idA, idB }, .num_ids = 2, \
+ .reg_offset = off + CONFIG_SYS_CCSRBAR, \
+ .compat_offset = compatoff + CONFIG_SYS_CCSRBAR_PHYS, \
+ }
+
+#define SET_GUTS_LIODN(compat, liodn, name, compatoff) \
+ SET_LIODN_ENTRY_1(compat, liodn, \
+ offsetof(ccsr_gur_t, name) + CONFIG_SYS_MPC85xx_GUTS_OFFSET, \
+ compatoff)
+
+#define SET_USB_LIODN(usbNum, compat, liodn) \
+ SET_GUTS_LIODN(compat, liodn, usb##usbNum##liodnr,\
+ CONFIG_SYS_MPC85xx_USB##usbNum##_OFFSET)
+
+#define SET_SATA_LIODN(sataNum, liodn) \
+ SET_GUTS_LIODN("fsl,pq-sata-v2", liodn, sata##sataNum##liodnr,\
+ CONFIG_SYS_MPC85xx_SATA##sataNum##_OFFSET)
+
+#define SET_PCI_LIODN(compat, pciNum, liodn) \
+ SET_GUTS_LIODN(compat, liodn, pex##pciNum##liodnr,\
+ CONFIG_SYS_MPC85xx_PCIE##pciNum##_OFFSET)
+
+#define SET_PCI_LIODN_BASE(compat, pciNum, liodn) \
+ SET_LIODN_ENTRY_1(compat, liodn,\
+ offsetof(ccsr_pcix_t, liodn_base) + CONFIG_SYS_MPC85xx_PCIE##pciNum##_OFFSET,\
+ CONFIG_SYS_MPC85xx_PCIE##pciNum##_OFFSET)
+
+/* reg nodes for DMA start @ 0x300 */
+#define SET_DMA_LIODN(dmaNum, liodn) \
+ SET_GUTS_LIODN("fsl,eloplus-dma", liodn, dma##dmaNum##liodnr,\
+ CONFIG_SYS_MPC85xx_DMA##dmaNum##_OFFSET + 0x300)
+
+#define SET_SDHC_LIODN(sdhcNum, liodn) \
+ SET_GUTS_LIODN("fsl,esdhc", liodn, sdmmc##sdhcNum##liodnr,\
+ CONFIG_SYS_MPC85xx_ESDHC_OFFSET)
+
+#define SET_QMAN_LIODN(liodn) \
+ SET_LIODN_ENTRY_1("fsl,qman", liodn, offsetof(ccsr_qman_t, liodnr) + \
+ CONFIG_SYS_FSL_QMAN_OFFSET, \
+ CONFIG_SYS_FSL_QMAN_OFFSET)
+
+#define SET_BMAN_LIODN(liodn) \
+ SET_LIODN_ENTRY_1("fsl,bman", liodn, offsetof(ccsr_bman_t, liodnr) + \
+ CONFIG_SYS_FSL_BMAN_OFFSET, \
+ CONFIG_SYS_FSL_BMAN_OFFSET)
+
+#define SET_PME_LIODN(liodn) \
+ SET_LIODN_ENTRY_1("fsl,pme", liodn, offsetof(ccsr_pme_t, liodnr) + \
+ CONFIG_SYS_FSL_CORENET_PME_OFFSET, \
+ CONFIG_SYS_FSL_CORENET_PME_OFFSET)
+
+#define SET_PMAN_LIODN(num, liodn) \
+ SET_LIODN_ENTRY_2("fsl,pman", liodn, 0, \
+ offsetof(struct ccsr_pman, ppa1) + \
+ CONFIG_SYS_FSL_CORENET_PMAN##num##_OFFSET, \
+ CONFIG_SYS_FSL_CORENET_PMAN##num##_OFFSET)
+
+/* -1 from portID due to how immap has the registers */
+#define FM_PPID_RX_PORT_OFFSET(fmNum, portID) \
+ CONFIG_SYS_FSL_FM##fmNum##_OFFSET + \
+ offsetof(struct ccsr_fman, fm_bmi_common.fmbm_ppid[portID - 1])
+
+/* enetNum is 0, 1, 2... so we + 8 for 1g to get to HW Port ID */
+#define SET_FMAN_RX_1G_LIODN(fmNum, enetNum, liodn) \
+ SET_LIODN_ENTRY_1("fsl,fman-port-1g-rx", liodn, \
+ FM_PPID_RX_PORT_OFFSET(fmNum, enetNum + 8), \
+ CONFIG_SYS_FSL_FM##fmNum##_RX##enetNum##_1G_OFFSET) \
+
+/* enetNum is 0, 1, 2... so we + 16 for 10g to get to HW Port ID */
+#define SET_FMAN_RX_10G_LIODN(fmNum, enetNum, liodn) \
+ SET_LIODN_ENTRY_1("fsl,fman-port-10g-rx", liodn, \
+ FM_PPID_RX_PORT_OFFSET(fmNum, enetNum + 16), \
+ CONFIG_SYS_FSL_FM##fmNum##_RX##enetNum##_10G_OFFSET) \
+
+/*
+ * handle both old and new versioned SEC properties:
+ * "fsl,secX.Y" became "fsl,sec-vX.Y" during development
+ */
+#define SET_SEC_JR_LIODN_ENTRY(jrNum, liodnA, liodnB) \
+ SET_LIODN_ENTRY_2("fsl,sec4.0-job-ring", liodnA, liodnB,\
+ offsetof(ccsr_sec_t, jrliodnr[jrNum].ls) + \
+ CONFIG_SYS_FSL_SEC_OFFSET, \
+ CONFIG_SYS_FSL_SEC_OFFSET + 0x1000 + 0x1000 * jrNum), \
+ SET_LIODN_ENTRY_2("fsl,sec-v4.0-job-ring", liodnA, liodnB,\
+ offsetof(ccsr_sec_t, jrliodnr[jrNum].ls) + \
+ CONFIG_SYS_FSL_SEC_OFFSET, \
+ CONFIG_SYS_FSL_SEC_OFFSET + 0x1000 + 0x1000 * jrNum)
+
+/* This is a bit evil since we treat rtic param as both a string & hex value */
+#define SET_SEC_RTIC_LIODN_ENTRY(rtic, liodnA) \
+ SET_LIODN_ENTRY_1("fsl,sec4.0-rtic-memory", \
+ liodnA, \
+ offsetof(ccsr_sec_t, rticliodnr[0x##rtic-0xa].ls) + \
+ CONFIG_SYS_FSL_SEC_OFFSET, \
+ CONFIG_SYS_FSL_SEC_OFFSET + 0x6100 + 0x20 * (0x##rtic-0xa)), \
+ SET_LIODN_ENTRY_1("fsl,sec-v4.0-rtic-memory", \
+ liodnA, \
+ offsetof(ccsr_sec_t, rticliodnr[0x##rtic-0xa].ls) + \
+ CONFIG_SYS_FSL_SEC_OFFSET, \
+ CONFIG_SYS_FSL_SEC_OFFSET + 0x6100 + 0x20 * (0x##rtic-0xa))
+
+#define SET_SEC_DECO_LIODN_ENTRY(num, liodnA, liodnB) \
+ SET_LIODN_ENTRY_2(NULL, liodnA, liodnB, \
+ offsetof(ccsr_sec_t, decoliodnr[num].ls) + \
+ CONFIG_SYS_FSL_SEC_OFFSET, 0)
+
+#define SET_RAID_ENGINE_JQ_LIODN_ENTRY(jqNum, rNum, liodnA) \
+ SET_LIODN_ENTRY_1("fsl,raideng-v1.0-job-ring", \
+ liodnA, \
+ offsetof(struct ccsr_raide, jq[jqNum].ring[rNum].cfg1) + \
+ CONFIG_SYS_FSL_RAID_ENGINE_OFFSET, \
+ offsetof(struct ccsr_raide, jq[jqNum].ring[rNum].cfg0) + \
+ CONFIG_SYS_FSL_RAID_ENGINE_OFFSET)
+
+#define SET_RMAN_LIODN(ibNum, liodn) \
+ SET_LIODN_ENTRY_1("fsl,rman-inbound-block", liodn, \
+ offsetof(struct ccsr_rman, mmitdr) + \
+ CONFIG_SYS_FSL_CORENET_RMAN_OFFSET, \
+ CONFIG_SYS_FSL_CORENET_RMAN_OFFSET + ibNum * 0x1000)
+
+extern struct liodn_id_table liodn_tbl[], liodn_bases[], sec_liodn_tbl[];
+extern struct liodn_id_table raide_liodn_tbl[];
+extern struct liodn_id_table fman1_liodn_tbl[], fman2_liodn_tbl[];
+#ifdef CONFIG_SYS_SRIO
+extern struct srio_liodn_id_table srio_liodn_tbl[];
+extern int srio_liodn_tbl_sz;
+#endif
+extern struct liodn_id_table rman_liodn_tbl[];
+extern int liodn_tbl_sz, sec_liodn_tbl_sz, raide_liodn_tbl_sz;
+extern int fman1_liodn_tbl_sz, fman2_liodn_tbl_sz;
+extern int rman_liodn_tbl_sz;
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_memac.h b/arch/powerpc/include/asm/fsl_memac.h
new file mode 100644
index 0000000..69f95d1
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_memac.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __MEMAC_H__
+#define __MEMAC_H__
+
+#include <phy.h>
+
+struct memac {
+ /* memac general control and status registers */
+ u32 res_0[2];
+ u32 command_config; /* Control and configuration register */
+ u32 mac_addr_0; /* Lower 32 bits of 48-bit MAC address */
+ u32 mac_addr_1; /* Upper 16 bits of 48-bit MAC address */
+ u32 maxfrm; /* Maximum frame length register */
+ u32 res_18[5];
+ u32 hashtable_ctrl; /* Hash table control register */
+ u32 res_30[4];
+ u32 ievent; /* Interrupt event register */
+ u32 tx_ipg_length; /* Transmitter inter-packet-gap register */
+ u32 res_48;
+ u32 imask; /* interrupt mask register */
+ u32 res_50;
+ u32 cl_pause_quanta[4]; /* CL01-CL67 pause quanta register */
+ u32 cl_pause_thresh[4]; /* CL01-CL67 pause thresh register */
+ u32 rx_pause_status; /* Receive pause status register */
+ u32 res_78[2];
+ u32 mac_addr[14]; /* MAC address */
+ u32 lpwake_timer; /* EEE low power wakeup timer register */
+ u32 sleep_timer; /* Transmit EEE Low Power Timer register */
+ u32 res_c0[8];
+ u32 statn_config; /* Statistics configuration register */
+ u32 res_e4[7];
+
+ /* memac statistics counter registers */
+ u32 rx_eoct_l; /* Rx ethernet octests lower */
+ u32 rx_eoct_u; /* Rx ethernet octests upper */
+ u32 rx_oct_l; /* Rx octests lower */
+ u32 rx_oct_u; /* Rx octests upper */
+ u32 rx_align_err_l; /* Rx alignment error lower */
+ u32 rx_align_err_u; /* Rx alignment error upper */
+ u32 rx_pause_frame_l; /* Rx valid pause frame upper */
+ u32 rx_pause_frame_u; /* Rx valid pause frame upper */
+ u32 rx_frame_l; /* Rx frame counter lower */
+ u32 rx_frame_u; /* Rx frame counter upper */
+ u32 rx_frame_crc_err_l; /* Rx frame check sequence error lower */
+ u32 rx_frame_crc_err_u; /* Rx frame check sequence error upper */
+ u32 rx_vlan_l; /* Rx VLAN frame lower */
+ u32 rx_vlan_u; /* Rx VLAN frame upper */
+ u32 rx_err_l; /* Rx frame error lower */
+ u32 rx_err_u; /* Rx frame error upper */
+ u32 rx_uni_l; /* Rx unicast frame lower */
+ u32 rx_uni_u; /* Rx unicast frame upper */
+ u32 rx_multi_l; /* Rx multicast frame lower */
+ u32 rx_multi_u; /* Rx multicast frame upper */
+ u32 rx_brd_l; /* Rx broadcast frame lower */
+ u32 rx_brd_u; /* Rx broadcast frame upper */
+ u32 rx_drop_l; /* Rx dropped packets lower */
+ u32 rx_drop_u; /* Rx dropped packets upper */
+ u32 rx_pkt_l; /* Rx packets lower */
+ u32 rx_pkt_u; /* Rx packets upper */
+ u32 rx_undsz_l; /* Rx undersized packet lower */
+ u32 rx_undsz_u; /* Rx undersized packet upper */
+ u32 rx_64_l; /* Rx 64 oct packet lower */
+ u32 rx_64_u; /* Rx 64 oct packet upper */
+ u32 rx_127_l; /* Rx 65 to 127 oct packet lower */
+ u32 rx_127_u; /* Rx 65 to 127 oct packet upper */
+ u32 rx_255_l; /* Rx 128 to 255 oct packet lower */
+ u32 rx_255_u; /* Rx 128 to 255 oct packet upper */
+ u32 rx_511_l; /* Rx 256 to 511 oct packet lower */
+ u32 rx_511_u; /* Rx 256 to 511 oct packet upper */
+ u32 rx_1023_l; /* Rx 512 to 1023 oct packet lower */
+ u32 rx_1023_u; /* Rx 512 to 1023 oct packet upper */
+ u32 rx_1518_l; /* Rx 1024 to 1518 oct packet lower */
+ u32 rx_1518_u; /* Rx 1024 to 1518 oct packet upper */
+ u32 rx_1519_l; /* Rx 1519 to max oct packet lower */
+ u32 rx_1519_u; /* Rx 1519 to max oct packet upper */
+ u32 rx_oversz_l; /* Rx oversized packet lower */
+ u32 rx_oversz_u; /* Rx oversized packet upper */
+ u32 rx_jabber_l; /* Rx Jabber packet lower */
+ u32 rx_jabber_u; /* Rx Jabber packet upper */
+ u32 rx_frag_l; /* Rx Fragment packet lower */
+ u32 rx_frag_u; /* Rx Fragment packet upper */
+ u32 rx_cnp_l; /* Rx control packet lower */
+ u32 rx_cnp_u; /* Rx control packet upper */
+ u32 rx_drntp_l; /* Rx dripped not truncated packet lower */
+ u32 rx_drntp_u; /* Rx dripped not truncated packet upper */
+ u32 res_1d0[0xc];
+
+ u32 tx_eoct_l; /* Tx ethernet octests lower */
+ u32 tx_eoct_u; /* Tx ethernet octests upper */
+ u32 tx_oct_l; /* Tx octests lower */
+ u32 tx_oct_u; /* Tx octests upper */
+ u32 res_210[0x2];
+ u32 tx_pause_frame_l; /* Tx valid pause frame lower */
+ u32 tx_pause_frame_u; /* Tx valid pause frame upper */
+ u32 tx_frame_l; /* Tx frame counter lower */
+ u32 tx_frame_u; /* Tx frame counter upper */
+ u32 tx_frame_crc_err_l; /* Tx frame check sequence error lower */
+ u32 tx_frame_crc_err_u; /* Tx frame check sequence error upper */
+ u32 tx_vlan_l; /* Tx VLAN frame lower */
+ u32 tx_vlan_u; /* Tx VLAN frame upper */
+ u32 tx_frame_err_l; /* Tx frame error lower */
+ u32 tx_frame_err_u; /* Tx frame error upper */
+ u32 tx_uni_l; /* Tx unicast frame lower */
+ u32 tx_uni_u; /* Tx unicast frame upper */
+ u32 tx_multi_l; /* Tx multicast frame lower */
+ u32 tx_multi_u; /* Tx multicast frame upper */
+ u32 tx_brd_l; /* Tx broadcast frame lower */
+ u32 tx_brd_u; /* Tx broadcast frame upper */
+ u32 res_258[0x2];
+ u32 tx_pkt_l; /* Tx packets lower */
+ u32 tx_pkt_u; /* Tx packets upper */
+ u32 tx_undsz_l; /* Tx undersized packet lower */
+ u32 tx_undsz_u; /* Tx undersized packet upper */
+ u32 tx_64_l; /* Tx 64 oct packet lower */
+ u32 tx_64_u; /* Tx 64 oct packet upper */
+ u32 tx_127_l; /* Tx 65 to 127 oct packet lower */
+ u32 tx_127_u; /* Tx 65 to 127 oct packet upper */
+ u32 tx_255_l; /* Tx 128 to 255 oct packet lower */
+ u32 tx_255_u; /* Tx 128 to 255 oct packet upper */
+ u32 tx_511_l; /* Tx 256 to 511 oct packet lower */
+ u32 tx_511_u; /* Tx 256 to 511 oct packet upper */
+ u32 tx_1023_l; /* Tx 512 to 1023 oct packet lower */
+ u32 tx_1023_u; /* Tx 512 to 1023 oct packet upper */
+ u32 tx_1518_l; /* Tx 1024 to 1518 oct packet lower */
+ u32 tx_1518_u; /* Tx 1024 to 1518 oct packet upper */
+ u32 tx_1519_l; /* Tx 1519 to max oct packet lower */
+ u32 tx_1519_u; /* Tx 1519 to max oct packet upper */
+ u32 res_2a8[0x6];
+ u32 tx_cnp_l; /* Tx control packet lower */
+ u32 tx_cnp_u; /* Tx control packet upper */
+ u32 res_2c8[0xe];
+
+ /* Line interface control register */
+ u32 if_mode; /* interface mode control */
+ u32 if_status; /* interface status */
+ u32 res_308[0xe];
+
+ /* HiGig/2 Register */
+ u32 hg_config; /* HiGig2 control and configuration */
+ u32 res_344[0x3];
+ u32 hg_pause_quanta; /* HiGig2 pause quanta */
+ u32 res_354[0x3];
+ u32 hg_pause_thresh; /* HiGig2 pause quanta threshold */
+ u32 res_364[0x3];
+ u32 hgrx_pause_status; /* HiGig2 rx pause quanta status */
+ u32 hg_fifos_status; /* HiGig2 fifos status */
+ u32 rhm; /* Rx HiGig2 message counter register */
+ u32 thm;/* Tx HiGig2 message counter register */
+ u32 res_380[0x320];
+};
+
+/* COMMAND_CONFIG - command and configuration register */
+#define MEMAC_CMD_CFG_RX_EN 0x00000002 /* MAC Rx path enable */
+#define MEMAC_CMD_CFG_TX_EN 0x00000001 /* MAC Tx path enable */
+#define MEMAC_CMD_CFG_RXTX_EN (MEMAC_CMD_CFG_RX_EN | MEMAC_CMD_CFG_TX_EN)
+
+/* HASHTABLE_CTRL - Hashtable control register */
+#define HASHTABLE_CTRL_MCAST_EN 0x00000200 /* enable mulitcast Rx hash */
+#define HASHTABLE_CTRL_ADDR_MASK 0x000001ff
+
+/* TX_IPG_LENGTH - Transmit inter-packet gap length register */
+#define TX_IPG_LENGTH_IPG_LEN_MASK 0x000003ff
+
+/* IMASK - interrupt mask register */
+#define IMASK_MDIO_SCAN_EVENT 0x00010000 /* MDIO scan event mask */
+#define IMASK_MDIO_CMD_CMPL 0x00008000 /* MDIO cmd completion mask */
+#define IMASK_REM_FAULT 0x00004000 /* remote fault mask */
+#define IMASK_LOC_FAULT 0x00002000 /* local fault mask */
+#define IMASK_TX_ECC_ER 0x00001000 /* Tx frame ECC error mask */
+#define IMASK_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow mask */
+#define IMASK_TX_ER 0x00000200 /* Tx frame error mask */
+#define IMASK_RX_FIFO_OVFL 0x00000100 /* Rx FIFO overflow mask */
+#define IMASK_RX_ECC_ER 0x00000080 /* Rx frame ECC error mask */
+#define IMASK_RX_JAB_FRM 0x00000040 /* Rx jabber frame mask */
+#define IMASK_RX_OVRSZ_FRM 0x00000020 /* Rx oversized frame mask */
+#define IMASK_RX_RUNT_FRM 0x00000010 /* Rx runt frame mask */
+#define IMASK_RX_FRAG_FRM 0x00000008 /* Rx fragment frame mask */
+#define IMASK_RX_LEN_ER 0x00000004 /* Rx payload length error mask */
+#define IMASK_RX_CRC_ER 0x00000002 /* Rx CRC error mask */
+#define IMASK_RX_ALIGN_ER 0x00000001 /* Rx alignment error mask */
+
+#define IMASK_MASK_ALL 0x00000000
+
+/* IEVENT - interrupt event register */
+#define IEVENT_MDIO_SCAN_EVENT 0x00010000 /* MDIO scan event */
+#define IEVENT_MDIO_CMD_CMPL 0x00008000 /* MDIO cmd completion */
+#define IEVENT_REM_FAULT 0x00004000 /* remote fault */
+#define IEVENT_LOC_FAULT 0x00002000 /* local fault */
+#define IEVENT_TX_ECC_ER 0x00001000 /* Tx frame ECC error */
+#define IEVENT_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow */
+#define IEVENT_TX_ER 0x00000200 /* Tx frame error */
+#define IEVENT_RX_FIFO_OVFL 0x00000100 /* Rx FIFO overflow */
+#define IEVENT_RX_ECC_ER 0x00000080 /* Rx frame ECC error */
+#define IEVENT_RX_JAB_FRM 0x00000040 /* Rx jabber frame */
+#define IEVENT_RX_OVRSZ_FRM 0x00000020 /* Rx oversized frame */
+#define IEVENT_RX_RUNT_FRM 0x00000010 /* Rx runt frame */
+#define IEVENT_RX_FRAG_FRM 0x00000008 /* Rx fragment frame */
+#define IEVENT_RX_LEN_ER 0x00000004 /* Rx payload length error */
+#define IEVENT_RX_CRC_ER 0x00000002 /* Rx CRC error */
+#define IEVENT_RX_ALIGN_ER 0x00000001 /* Rx alignment error */
+
+#define IEVENT_CLEAR_ALL 0xffffffff
+
+/* IF_MODE - Interface Mode Register */
+#define IF_MODE_EN_AUTO 0x00008000 /* 1 - Enable automatic speed selection */
+#define IF_MODE_SETSP_100M 0x00000000 /* 00 - 100Mbps RGMII */
+#define IF_MODE_SETSP_10M 0x00002000 /* 01 - 10Mbps RGMII */
+#define IF_MODE_SETSP_1000M 0x00004000 /* 10 - 1000Mbps RGMII */
+#define IF_MODE_SETSP_MASK 0x00006000 /* setsp mask bits */
+#define IF_MODE_XGMII 0x00000000 /* 00- XGMII(10) interface mode */
+#define IF_MODE_GMII 0x00000002 /* 10- GMII interface mode */
+#define IF_MODE_MASK 0x00000003 /* mask for mode interface mode */
+#define IF_MODE_RG 0x00000004 /* 1- RGMII */
+#define IF_MODE_RM 0x00000008 /* 1- RGMII */
+
+#define IF_DEFAULT (IF_GMII)
+
+/* Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_PHY_RESET 0x8000
+#define PHY_SGMII_CR_RESET_AN 0x0200
+#define PHY_SGMII_CR_DEF_VAL 0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001
+#define PHY_SGMII_IF_MODE_AN 0x0002
+#define PHY_SGMII_IF_MODE_SGMII 0x0001
+
+struct memac_mdio_controller {
+ u32 res0[0xc];
+ u32 mdio_stat; /* MDIO configuration and status */
+ u32 mdio_ctl; /* MDIO control */
+ u32 mdio_data; /* MDIO data */
+ u32 mdio_addr; /* MDIO address */
+};
+
+#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8)
+#define MDIO_STAT_BSY (1 << 0)
+#define MDIO_STAT_RD_ER (1 << 1)
+#define MDIO_STAT_PRE (1 << 5)
+#define MDIO_STAT_ENC (1 << 6)
+#define MDIO_STAT_HOLD_15_CLK (7 << 2)
+
+#define MDIO_CTL_DEV_ADDR(x) (x & 0x1f)
+#define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5)
+#define MDIO_CTL_PRE_DIS (1 << 10)
+#define MDIO_CTL_SCAN_EN (1 << 11)
+#define MDIO_CTL_POST_INC (1 << 14)
+#define MDIO_CTL_READ (1 << 15)
+
+#define MDIO_DATA(x) (x & 0xffff)
+#define MDIO_DATA_BSY (1 << 31)
+
+struct fsl_enet_mac;
+
+void init_memac(struct fsl_enet_mac *mac, void *base, void *phyregs,
+ int max_rx_len);
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_mpc83xx_serdes.h b/arch/powerpc/include/asm/fsl_mpc83xx_serdes.h
new file mode 100644
index 0000000..2d813f4
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_mpc83xx_serdes.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_MPC83XX_SERDES_H
+#define __FSL_MPC83XX_SERDES_H
+
+#include <config.h>
+
+#define FSL_SERDES_CLK_100 (0 << 28)
+#define FSL_SERDES_CLK_125 (1 << 28)
+#define FSL_SERDES_CLK_150 (3 << 28)
+#define FSL_SERDES_PROTO_SATA 0
+#define FSL_SERDES_PROTO_PEX 1
+#define FSL_SERDES_PROTO_PEX_X2 2
+#define FSL_SERDES_PROTO_SGMII 3
+#define FSL_SERDES_VDD_1V 1
+
+extern void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd);
+
+#endif /* __FSL_MPC83XX_SERDES_H */
diff --git a/arch/powerpc/include/asm/fsl_pci.h b/arch/powerpc/include/asm/fsl_pci.h
new file mode 100644
index 0000000..49bd2bf
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_pci.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2007,2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef __FSL_PCI_H_
+#define __FSL_PCI_H_
+
+#include <asm/fsl_law.h>
+#include <asm/fsl_serdes.h>
+#include <pci.h>
+
+#define PEX_IP_BLK_REV_2_2 0x02080202
+#define PEX_IP_BLK_REV_2_3 0x02080203
+
+int fsl_setup_hose(struct pci_controller *hose, unsigned long addr);
+int fsl_is_pci_agent(struct pci_controller *hose);
+void fsl_pci_config_unlock(struct pci_controller *hose);
+void ft_fsl_pci_setup(void *blob, const char *compat, unsigned long ctrl_addr);
+
+/*
+ * Common PCI/PCIE Register structure for mpc85xx and mpc86xx
+ */
+
+/*
+ * PCI Translation Registers
+ */
+typedef struct pci_outbound_window {
+ u32 potar; /* 0x00 - Address */
+ u32 potear; /* 0x04 - Address Extended */
+ u32 powbar; /* 0x08 - Window Base Address */
+ u32 res1;
+ u32 powar; /* 0x10 - Window Attributes */
+#define POWAR_EN 0x80000000
+#define POWAR_IO_READ 0x00080000
+#define POWAR_MEM_READ 0x00040000
+#define POWAR_IO_WRITE 0x00008000
+#define POWAR_MEM_WRITE 0x00004000
+ u32 res2[3];
+} pot_t;
+
+typedef struct pci_inbound_window {
+ u32 pitar; /* 0x00 - Address */
+ u32 res1;
+ u32 piwbar; /* 0x08 - Window Base Address */
+ u32 piwbear; /* 0x0c - Window Base Address Extended */
+ u32 piwar; /* 0x10 - Window Attributes */
+#define PIWAR_EN 0x80000000
+#define PIWAR_PF 0x20000000
+#define PIWAR_LOCAL 0x00f00000
+#define PIWAR_READ_SNOOP 0x00050000
+#define PIWAR_WRITE_SNOOP 0x00005000
+ u32 res2[3];
+} pit_t;
+
+/* PCI/PCI Express Registers */
+typedef struct ccsr_pci {
+ u32 cfg_addr; /* 0x000 - PCI Configuration Address Register */
+ u32 cfg_data; /* 0x004 - PCI Configuration Data Register */
+ u32 int_ack; /* 0x008 - PCI Interrupt Acknowledge Register */
+ u32 out_comp_to; /* 0x00C - PCI Outbound Completion Timeout Register */
+ u32 out_conf_to; /* 0x010 - PCI Configuration Timeout Register */
+ u32 config; /* 0x014 - PCIE CONFIG Register */
+ u32 int_status; /* 0x018 - PCIE interrupt status register */
+ char res2[4];
+ u32 pme_msg_det; /* 0x020 - PCIE PME & message detect register */
+ u32 pme_msg_dis; /* 0x024 - PCIE PME & message disable register */
+ u32 pme_msg_int_en; /* 0x028 - PCIE PME & message interrupt enable register */
+ u32 pm_command; /* 0x02c - PCIE PM Command register */
+ char res4[3016]; /* (- #xbf8 #x30)3016 */
+ u32 block_rev1; /* 0xbf8 - PCIE Block Revision register 1 */
+ u32 block_rev2; /* 0xbfc - PCIE Block Revision register 2 */
+
+ pot_t pot[5]; /* 0xc00 - 0xc9f Outbound ATMU's 0, 1, 2, 3, and 4 */
+ u32 res5[24];
+ pit_t pmit; /* 0xd00 - 0xd9c Inbound ATMU's MSI */
+ u32 res6[24];
+ pit_t pit[4]; /* 0xd80 - 0xdff Inbound ATMU's 3, 2, 1 and 0 */
+
+#define PIT3 0
+#define PIT2 1
+#define PIT1 2
+
+#if 0
+ u32 potar0; /* 0xc00 - PCI Outbound Transaction Address Register 0 */
+ u32 potear0; /* 0xc04 - PCI Outbound Translation Extended Address Register 0 */
+ char res5[8];
+ u32 powar0; /* 0xc10 - PCI Outbound Window Attributes Register 0 */
+ char res6[12];
+ u32 potar1; /* 0xc20 - PCI Outbound Transaction Address Register 1 */
+ u32 potear1; /* 0xc24 - PCI Outbound Translation Extended Address Register 1 */
+ u32 powbar1; /* 0xc28 - PCI Outbound Window Base Address Register 1 */
+ char res7[4];
+ u32 powar1; /* 0xc30 - PCI Outbound Window Attributes Register 1 */
+ char res8[12];
+ u32 potar2; /* 0xc40 - PCI Outbound Transaction Address Register 2 */
+ u32 potear2; /* 0xc44 - PCI Outbound Translation Extended Address Register 2 */
+ u32 powbar2; /* 0xc48 - PCI Outbound Window Base Address Register 2 */
+ char res9[4];
+ u32 powar2; /* 0xc50 - PCI Outbound Window Attributes Register 2 */
+ char res10[12];
+ u32 potar3; /* 0xc60 - PCI Outbound Transaction Address Register 3 */
+ u32 potear3; /* 0xc64 - PCI Outbound Translation Extended Address Register 3 */
+ u32 powbar3; /* 0xc68 - PCI Outbound Window Base Address Register 3 */
+ char res11[4];
+ u32 powar3; /* 0xc70 - PCI Outbound Window Attributes Register 3 */
+ char res12[12];
+ u32 potar4; /* 0xc80 - PCI Outbound Transaction Address Register 4 */
+ u32 potear4; /* 0xc84 - PCI Outbound Translation Extended Address Register 4 */
+ u32 powbar4; /* 0xc88 - PCI Outbound Window Base Address Register 4 */
+ char res13[4];
+ u32 powar4; /* 0xc90 - PCI Outbound Window Attributes Register 4 */
+ char res14[268];
+ u32 pitar3; /* 0xda0 - PCI Inbound Translation Address Register 3 */
+ char res15[4];
+ u32 piwbar3; /* 0xda8 - PCI Inbound Window Base Address Register 3 */
+ u32 piwbear3; /* 0xdac - PCI Inbound Window Base Extended Address Register 3 */
+ u32 piwar3; /* 0xdb0 - PCI Inbound Window Attributes Register 3 */
+ char res16[12];
+ u32 pitar2; /* 0xdc0 - PCI Inbound Translation Address Register 2 */
+ char res17[4];
+ u32 piwbar2; /* 0xdc8 - PCI Inbound Window Base Address Register 2 */
+ u32 piwbear2; /* 0xdcc - PCI Inbound Window Base Extended Address Register 2 */
+ u32 piwar2; /* 0xdd0 - PCI Inbound Window Attributes Register 2 */
+ char res18[12];
+ u32 pitar1; /* 0xde0 - PCI Inbound Translation Address Register 1 */
+ char res19[4];
+ u32 piwbar1; /* 0xde8 - PCI Inbound Window Base Address Register 1 */
+ char res20[4];
+ u32 piwar1; /* 0xdf0 - PCI Inbound Window Attributes Register 1 */
+ char res21[12];
+#endif
+ u32 pedr; /* 0xe00 - PCI Error Detect Register */
+ u32 pecdr; /* 0xe04 - PCI Error Capture Disable Register */
+ u32 peer; /* 0xe08 - PCI Error Interrupt Enable Register */
+ u32 peattrcr; /* 0xe0c - PCI Error Attributes Capture Register */
+ u32 peaddrcr; /* 0xe10 - PCI Error Address Capture Register */
+/* u32 perr_disr * 0xe10 - PCIE Erorr Disable Register */
+ u32 peextaddrcr; /* 0xe14 - PCI Error Extended Address Capture Register */
+ u32 pedlcr; /* 0xe18 - PCI Error Data Low Capture Register */
+ u32 pedhcr; /* 0xe1c - PCI Error Error Data High Capture Register */
+ u32 gas_timr; /* 0xe20 - PCI Gasket Timer Register */
+/* u32 perr_cap_stat; * 0xe20 - PCIE Error Capture Status Register */
+ char res22[4];
+ u32 perr_cap0; /* 0xe28 - PCIE Error Capture Register 0 */
+ u32 perr_cap1; /* 0xe2c - PCIE Error Capture Register 1 */
+ u32 perr_cap2; /* 0xe30 - PCIE Error Capture Register 2 */
+ u32 perr_cap3; /* 0xe34 - PCIE Error Capture Register 3 */
+ char res23[200];
+ u32 pdb_stat; /* 0xf00 - PCIE Debug Status */
+ char res24[252];
+} ccsr_fsl_pci_t;
+#define PCIE_CONFIG_PC 0x00020000
+#define PCIE_CONFIG_OB_CK 0x00002000
+#define PCIE_CONFIG_SAC 0x00000010
+#define PCIE_CONFIG_SP 0x80000002
+#define PCIE_CONFIG_SCC 0x80000001
+
+struct fsl_pci_info {
+ unsigned long regs;
+ pci_addr_t mem_bus;
+ phys_size_t mem_phys;
+ pci_size_t mem_size;
+ pci_addr_t io_bus;
+ phys_size_t io_phys;
+ pci_size_t io_size;
+ enum law_trgt_if law;
+ int pci_num;
+};
+
+void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info);
+int fsl_pci_init_port(struct fsl_pci_info *pci_info,
+ struct pci_controller *hose, int busno);
+int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev,
+ struct fsl_pci_info *pci_info);
+int fsl_pcie_init_board(int busno);
+
+#define SET_STD_PCI_INFO(x, num) \
+{ \
+ x.regs = CONFIG_SYS_PCI##num##_ADDR; \
+ x.mem_bus = CONFIG_SYS_PCI##num##_MEM_BUS; \
+ x.mem_phys = CONFIG_SYS_PCI##num##_MEM_PHYS; \
+ x.mem_size = CONFIG_SYS_PCI##num##_MEM_SIZE; \
+ x.io_bus = CONFIG_SYS_PCI##num##_IO_BUS; \
+ x.io_phys = CONFIG_SYS_PCI##num##_IO_PHYS; \
+ x.io_size = CONFIG_SYS_PCI##num##_IO_SIZE; \
+ x.law = LAW_TRGT_IF_PCI_##num; \
+ x.pci_num = num; \
+}
+
+#define SET_STD_PCIE_INFO(x, num) \
+{ \
+ x.regs = CONFIG_SYS_PCIE##num##_ADDR; \
+ x.mem_bus = CONFIG_SYS_PCIE##num##_MEM_BUS; \
+ x.mem_phys = CONFIG_SYS_PCIE##num##_MEM_PHYS; \
+ x.mem_size = CONFIG_SYS_PCIE##num##_MEM_SIZE; \
+ x.io_bus = CONFIG_SYS_PCIE##num##_IO_BUS; \
+ x.io_phys = CONFIG_SYS_PCIE##num##_IO_PHYS; \
+ x.io_size = CONFIG_SYS_PCIE##num##_IO_SIZE; \
+ x.law = LAW_TRGT_IF_PCIE_##num; \
+ x.pci_num = num; \
+}
+
+#define __FT_FSL_PCI_SETUP(blob, compat, num) \
+ ft_fsl_pci_setup(blob, compat, CONFIG_SYS_PCI##num##_ADDR)
+
+#define __FT_FSL_PCIE_SETUP(blob, compat, num) \
+ ft_fsl_pci_setup(blob, compat, CONFIG_SYS_PCIE##num##_ADDR)
+
+#define FT_FSL_PCI1_SETUP __FT_FSL_PCI_SETUP(blob, FSL_PCI_COMPAT, 1)
+#define FT_FSL_PCI2_SETUP __FT_FSL_PCI_SETUP(blob, FSL_PCI_COMPAT, 2)
+
+#define FT_FSL_PCIE1_SETUP __FT_FSL_PCIE_SETUP(blob, FSL_PCIE_COMPAT, 1)
+#define FT_FSL_PCIE2_SETUP __FT_FSL_PCIE_SETUP(blob, FSL_PCIE_COMPAT, 2)
+#define FT_FSL_PCIE3_SETUP __FT_FSL_PCIE_SETUP(blob, FSL_PCIE_COMPAT, 3)
+#define FT_FSL_PCIE4_SETUP __FT_FSL_PCIE_SETUP(blob, FSL_PCIE_COMPAT, 4)
+
+#if !defined(CONFIG_PCI)
+#define FT_FSL_PCI_SETUP
+#elif defined(CONFIG_FSL_CORENET)
+#define FSL_PCIE_COMPAT CONFIG_SYS_FSL_PCIE_COMPAT
+#define FT_FSL_PCI_SETUP \
+ FT_FSL_PCIE1_SETUP; \
+ FT_FSL_PCIE2_SETUP; \
+ FT_FSL_PCIE3_SETUP; \
+ FT_FSL_PCIE4_SETUP;
+#define FT_FSL_PCIE_SETUP FT_FSL_PCI_SETUP
+#elif defined(CONFIG_MPC85xx)
+#define FSL_PCI_COMPAT "fsl,mpc8540-pci"
+#ifdef CONFIG_SYS_FSL_PCIE_COMPAT
+#define FSL_PCIE_COMPAT CONFIG_SYS_FSL_PCIE_COMPAT
+#else
+#define FSL_PCIE_COMPAT "fsl,mpc8548-pcie"
+#endif
+#define FT_FSL_PCI_SETUP \
+ FT_FSL_PCI1_SETUP; \
+ FT_FSL_PCI2_SETUP; \
+ FT_FSL_PCIE1_SETUP; \
+ FT_FSL_PCIE2_SETUP; \
+ FT_FSL_PCIE3_SETUP;
+#define FT_FSL_PCIE_SETUP \
+ FT_FSL_PCIE1_SETUP; \
+ FT_FSL_PCIE2_SETUP; \
+ FT_FSL_PCIE3_SETUP;
+#elif defined(CONFIG_MPC86xx)
+#define FSL_PCI_COMPAT "fsl,mpc8610-pci"
+#define FSL_PCIE_COMPAT "fsl,mpc8641-pcie"
+#define FT_FSL_PCI_SETUP \
+ FT_FSL_PCI1_SETUP; \
+ FT_FSL_PCIE1_SETUP; \
+ FT_FSL_PCIE2_SETUP;
+#else
+#error FT_FSL_PCI_SETUP not defined
+#endif
+
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_portals.h b/arch/powerpc/include/asm/fsl_portals.h
new file mode 100644
index 0000000..b75f5b9
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_portals.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _FSL_PORTALS_H_
+#define _FSL_PORTALS_H_
+
+/* entries must be in order and contiguous */
+enum fsl_dpaa_dev {
+ FSL_HW_PORTAL_SEC,
+#ifdef CONFIG_SYS_DPAA_FMAN
+ FSL_HW_PORTAL_FMAN1,
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ FSL_HW_PORTAL_FMAN2,
+#endif
+#endif
+ FSL_HW_PORTAL_PME,
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+ FSL_HW_PORTAL_RAID_ENGINE,
+#endif
+#ifdef CONFIG_SYS_DPAA_RMAN
+ FSL_HW_PORTAL_RMAN,
+#endif
+#ifdef CONFIG_SYS_DPAA_DCE
+ FSL_HW_PORTAL_DCE,
+#endif
+
+};
+
+struct qportal_info {
+ u16 dliodn; /* DQRR LIODN */
+ u16 fliodn; /* frame data LIODN */
+ u16 liodn_offset;
+ u8 sdest;
+};
+
+#define SET_QP_INFO(dqrr, fdata, off, dest) \
+ { .dliodn = dqrr, .fliodn = fdata, .liodn_offset = off, .sdest = dest }
+
+extern int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev,
+ u32 *liodns, int liodn_offset);
+extern void setup_portals(void);
+extern void fdt_fixup_qportals(void *blob);
+extern void fdt_fixup_bportals(void *blob);
+
+extern struct qportal_info qp_info[];
+extern void fdt_portal(void *blob, const char *compat, const char *container,
+ u64 addr, u32 size);
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_secure_boot.h b/arch/powerpc/include/asm/fsl_secure_boot.h
new file mode 100644
index 0000000..2bc6ed1
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_secure_boot.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_SECURE_BOOT_H
+#define __FSL_SECURE_BOOT_H
+
+#if defined(CONFIG_FSL_CORENET)
+#define CONFIG_SYS_PBI_FLASH_BASE 0xc0000000
+#else
+#define CONFIG_SYS_PBI_FLASH_BASE 0xce000000
+#endif
+#define CONFIG_SYS_PBI_FLASH_WINDOW 0xcff80000
+
+#endif
diff --git a/arch/powerpc/include/asm/fsl_serdes.h b/arch/powerpc/include/asm/fsl_serdes.h
new file mode 100644
index 0000000..ccb91fb
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_serdes.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __FSL_SERDES_H
+#define __FSL_SERDES_H
+
+#include <config.h>
+
+enum srds_prtcl {
+ NONE = 0,
+ PCIE1,
+ PCIE2,
+ PCIE3,
+ PCIE4,
+ SATA1,
+ SATA2,
+ SRIO1,
+ SRIO2,
+ SGMII_FM1_DTSEC1,
+ SGMII_FM1_DTSEC2,
+ SGMII_FM1_DTSEC3,
+ SGMII_FM1_DTSEC4,
+ SGMII_FM1_DTSEC5,
+ SGMII_FM1_DTSEC6,
+ SGMII_FM1_DTSEC9,
+ SGMII_FM1_DTSEC10,
+ SGMII_FM2_DTSEC1,
+ SGMII_FM2_DTSEC2,
+ SGMII_FM2_DTSEC3,
+ SGMII_FM2_DTSEC4,
+ SGMII_FM2_DTSEC5,
+ SGMII_FM2_DTSEC6,
+ SGMII_FM2_DTSEC9,
+ SGMII_FM2_DTSEC10,
+ SGMII_TSEC1,
+ SGMII_TSEC2,
+ SGMII_TSEC3,
+ SGMII_TSEC4,
+ XAUI_FM1,
+ XAUI_FM2,
+ AURORA,
+ CPRI1,
+ CPRI2,
+ CPRI3,
+ CPRI4,
+ CPRI5,
+ CPRI6,
+ CPRI7,
+ CPRI8,
+ XAUI_FM1_MAC9,
+ XAUI_FM1_MAC10,
+ XAUI_FM2_MAC9,
+ XAUI_FM2_MAC10,
+ HIGIG_FM1_MAC9,
+ HIGIG_FM1_MAC10,
+ HIGIG_FM2_MAC9,
+ HIGIG_FM2_MAC10,
+ QSGMII_FM1_A, /* A indicates MACs 1-4 */
+ QSGMII_FM1_B, /* B indicates MACs 5,6,9,10 */
+ QSGMII_FM2_A,
+ QSGMII_FM2_B,
+ XFI_FM1_MAC9,
+ XFI_FM1_MAC10,
+ XFI_FM2_MAC9,
+ XFI_FM2_MAC10,
+ INTERLAKEN,
+ SGMII_SW1_DTSEC1, /* SW indicates on L2 switch */
+ SGMII_SW1_DTSEC2,
+ SGMII_SW1_DTSEC3,
+ SGMII_SW1_DTSEC4,
+ SGMII_SW1_DTSEC5,
+ SGMII_SW1_DTSEC6,
+ QSGMII_SW1_A, /* SW indicates on L2 swtich */
+ QSGMII_SW1_B,
+};
+
+enum srds {
+ FSL_SRDS_1 = 0,
+ FSL_SRDS_2 = 1,
+ FSL_SRDS_3 = 2,
+ FSL_SRDS_4 = 3,
+};
+
+int is_serdes_configured(enum srds_prtcl device);
+void fsl_serdes_init(void);
+
+#ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+int serdes_get_first_lane(u32 sd, enum srds_prtcl device);
+#else
+int serdes_get_first_lane(enum srds_prtcl device);
+#endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
+void serdes_reset_rx(enum srds_prtcl device);
+#endif
+#endif
+
+#endif /* __FSL_SERDES_H */
diff --git a/arch/powerpc/include/asm/fsl_srio.h b/arch/powerpc/include/asm/fsl_srio.h
new file mode 100644
index 0000000..dfd8e08
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_srio.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _FSL_SRIO_H_
+#define _FSL_SRIO_H_
+
+enum atmu_size {
+ ATMU_SIZE_4K = 0xb,
+ ATMU_SIZE_8K,
+ ATMU_SIZE_16K,
+ ATMU_SIZE_32K,
+ ATMU_SIZE_64K,
+ ATMU_SIZE_128K,
+ ATMU_SIZE_256K,
+ ATMU_SIZE_512K,
+ ATMU_SIZE_1M,
+ ATMU_SIZE_2M,
+ ATMU_SIZE_4M,
+ ATMU_SIZE_8M,
+ ATMU_SIZE_16M,
+ ATMU_SIZE_32M,
+ ATMU_SIZE_64M,
+ ATMU_SIZE_128M,
+ ATMU_SIZE_256M,
+ ATMU_SIZE_512M,
+ ATMU_SIZE_1G,
+ ATMU_SIZE_2G,
+ ATMU_SIZE_4G,
+ ATMU_SIZE_8G,
+ ATMU_SIZE_16G,
+ ATMU_SIZE_32G,
+ ATMU_SIZE_64G,
+};
+
+#define atmu_size_mask(sz) (__ilog2_u64(sz) - 1)
+#define atmu_size_bytes(x) (1ULL << ((x & 0x3f) + 1))
+
+extern void srio_init(void);
+#ifdef CONFIG_FSL_CORENET
+extern void srio_boot_master(int port);
+extern void srio_boot_master_release_slave(int port);
+#endif
+#endif
diff --git a/arch/powerpc/include/asm/fsl_tgec.h b/arch/powerpc/include/asm/fsl_tgec.h
new file mode 100644
index 0000000..8de37c9
--- /dev/null
+++ b/arch/powerpc/include/asm/fsl_tgec.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ * Dave Liu <daveliu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __TGEC_H__
+#define __TGEC_H__
+
+#include <phy.h>
+
+struct tgec {
+ /* 10GEC general control and status registers */
+ u32 tgec_id; /* Controller ID register */
+ u32 res0;
+ u32 command_config; /* Control and configuration register */
+ u32 mac_addr_0; /* Lower 32 bits of 48-bit MAC address */
+ u32 mac_addr_1; /* Upper 16 bits of 48-bit MAC address */
+ u32 maxfrm; /* Maximum frame length register */
+ u32 pause_quant; /* Pause quanta register */
+ u32 res1[4];
+ u32 hashtable_ctrl; /* Hash table control register */
+ u32 res2[4];
+ u32 status; /* MAC status register */
+ u32 tx_ipg_length; /* Transmitter inter-packet-gap register */
+ u32 mac_addr_2; /* Lower 32 bits of the 2nd 48-bit MAC addr */
+ u32 mac_addr_3; /* Upper 16 bits of the 2nd 48-bit MAC addr */
+ u32 res3[4];
+ u32 imask; /* Interrupt mask register */
+ u32 ievent; /* Interrupt event register */
+ u32 res4[6];
+ /* 10GEC statistics counter registers */
+ u32 tx_frame_u; /* Tx frame counter upper */
+ u32 tx_frame_l; /* Tx frame counter lower */
+ u32 rx_frame_u; /* Rx frame counter upper */
+ u32 rx_frame_l; /* Rx frame counter lower */
+ u32 rx_frame_crc_err_u; /* Rx frame check sequence error upper */
+ u32 rx_frame_crc_err_l; /* Rx frame check sequence error lower */
+ u32 rx_align_err_u; /* Rx alignment error upper */
+ u32 rx_align_err_l; /* Rx alignment error lower */
+ u32 tx_pause_frame_u; /* Tx valid pause frame upper */
+ u32 tx_pause_frame_l; /* Tx valid pause frame lower */
+ u32 rx_pause_frame_u; /* Rx valid pause frame upper */
+ u32 rx_pause_frame_l; /* Rx valid pause frame upper */
+ u32 rx_long_err_u; /* Rx too long frame error upper */
+ u32 rx_long_err_l; /* Rx too long frame error lower */
+ u32 rx_frame_err_u; /* Rx frame length error upper */
+ u32 rx_frame_err_l; /* Rx frame length error lower */
+ u32 tx_vlan_u; /* Tx VLAN frame upper */
+ u32 tx_vlan_l; /* Tx VLAN frame lower */
+ u32 rx_vlan_u; /* Rx VLAN frame upper */
+ u32 rx_vlan_l; /* Rx VLAN frame lower */
+ u32 tx_oct_u; /* Tx octets upper */
+ u32 tx_oct_l; /* Tx octets lower */
+ u32 rx_oct_u; /* Rx octets upper */
+ u32 rx_oct_l; /* Rx octets lower */
+ u32 rx_uni_u; /* Rx unicast frame upper */
+ u32 rx_uni_l; /* Rx unicast frame lower */
+ u32 rx_multi_u; /* Rx multicast frame upper */
+ u32 rx_multi_l; /* Rx multicast frame lower */
+ u32 rx_brd_u; /* Rx broadcast frame upper */
+ u32 rx_brd_l; /* Rx broadcast frame lower */
+ u32 tx_frame_err_u; /* Tx frame error upper */
+ u32 tx_frame_err_l; /* Tx frame error lower */
+ u32 tx_uni_u; /* Tx unicast frame upper */
+ u32 tx_uni_l; /* Tx unicast frame lower */
+ u32 tx_multi_u; /* Tx multicast frame upper */
+ u32 tx_multi_l; /* Tx multicast frame lower */
+ u32 tx_brd_u; /* Tx broadcast frame upper */
+ u32 tx_brd_l; /* Tx broadcast frame lower */
+ u32 rx_drop_u; /* Rx dropped packets upper */
+ u32 rx_drop_l; /* Rx dropped packets lower */
+ u32 rx_eoct_u; /* Rx ethernet octets upper */
+ u32 rx_eoct_l; /* Rx ethernet octets lower */
+ u32 rx_pkt_u; /* Rx packets upper */
+ u32 rx_pkt_l; /* Rx packets lower */
+ u32 tx_undsz_u; /* Undersized packet upper */
+ u32 tx_undsz_l; /* Undersized packet lower */
+ u32 rx_64_u; /* Rx 64 oct packet upper */
+ u32 rx_64_l; /* Rx 64 oct packet lower */
+ u32 rx_127_u; /* Rx 65 to 127 oct packet upper */
+ u32 rx_127_l; /* Rx 65 to 127 oct packet lower */
+ u32 rx_255_u; /* Rx 128 to 255 oct packet upper */
+ u32 rx_255_l; /* Rx 128 to 255 oct packet lower */
+ u32 rx_511_u; /* Rx 256 to 511 oct packet upper */
+ u32 rx_511_l; /* Rx 256 to 511 oct packet lower */
+ u32 rx_1023_u; /* Rx 512 to 1023 oct packet upper */
+ u32 rx_1023_l; /* Rx 512 to 1023 oct packet lower */
+ u32 rx_1518_u; /* Rx 1024 to 1518 oct packet upper */
+ u32 rx_1518_l; /* Rx 1024 to 1518 oct packet lower */
+ u32 rx_1519_u; /* Rx 1519 to max oct packet upper */
+ u32 rx_1519_l; /* Rx 1519 to max oct packet lower */
+ u32 tx_oversz_u; /* oversized packet upper */
+ u32 tx_oversz_l; /* oversized packet lower */
+ u32 tx_jabber_u; /* Jabber packet upper */
+ u32 tx_jabber_l; /* Jabber packet lower */
+ u32 tx_frag_u; /* Fragment packet upper */
+ u32 tx_frag_l; /* Fragment packet lower */
+ u32 rx_err_u; /* Rx frame error upper */
+ u32 rx_err_l; /* Rx frame error lower */
+ u32 res5[0x39a];
+};
+
+/* EC10G_ID - 10-gigabit ethernet MAC controller ID */
+#define EC10G_ID_VER_MASK 0x0000ff00
+#define EC10G_ID_VER_SHIFT 8
+#define EC10G_ID_REV_MASK 0x000000ff
+
+/* COMMAND_CONFIG - command and configuration register */
+#define TGEC_CMD_CFG_EN_TIMESTAMP 0x00100000 /* enable IEEE1588 */
+#define TGEC_CMD_CFG_TX_ADDR_INS_SEL 0x00080000 /* Tx mac addr w/ second */
+#define TGEC_CMD_CFG_NO_LEN_CHK 0x00020000 /* payload len chk disable */
+#define TGEC_CMD_CFG_SEND_IDLE 0x00010000 /* send XGMII idle seqs */
+#define TGEC_CMD_CFG_RX_ER_DISC 0x00004000 /* Rx err frm discard enb */
+#define TGEC_CMD_CFG_CMD_FRM_EN 0x00002000 /* CMD frame RX enable */
+#define TGEC_CMD_CFG_STAT_CLR 0x00001000 /* clear stats */
+#define TGEC_CMD_CFG_TX_ADDR_INS 0x00000200 /* overwrite src MAC addr */
+#define TGEC_CMD_CFG_PAUSE_IGNORE 0x00000100 /* ignore pause frames */
+#define TGEC_CMD_CFG_PAUSE_FWD 0x00000080 /* fwd pause frames */
+#define TGEC_CMD_CFG_CRC_FWD 0x00000040 /* fwd Rx CRC frames */
+#define TGEC_CMD_CFG_PAD_EN 0x00000020 /* MAC remove Rx padding */
+#define TGEC_CMD_CFG_PROM_EN 0x00000010 /* promiscuous mode enable */
+#define TGEC_CMD_CFG_WAN_MODE 0x00000008 /* WAN mode enable */
+#define TGEC_CMD_CFG_RX_EN 0x00000002 /* MAC Rx path enable */
+#define TGEC_CMD_CFG_TX_EN 0x00000001 /* MAC Tx path enable */
+#define TGEC_CMD_CFG_RXTX_EN (TGEC_CMD_CFG_RX_EN | TGEC_CMD_CFG_TX_EN)
+
+/* HASHTABLE_CTRL - Hashtable control register */
+#define HASHTABLE_CTRL_MCAST_EN 0x00000200 /* enable mulitcast Rx hash */
+#define HASHTABLE_CTRL_ADDR_MASK 0x000001ff
+
+/* TX_IPG_LENGTH - Transmit inter-packet gap length register */
+#define TX_IPG_LENGTH_IPG_LEN_MASK 0x000003ff
+
+/* IMASK - interrupt mask register */
+#define IMASK_MDIO_SCAN_EVENT 0x00010000 /* MDIO scan event mask */
+#define IMASK_MDIO_CMD_CMPL 0x00008000 /* MDIO cmd completion mask */
+#define IMASK_REM_FAULT 0x00004000 /* remote fault mask */
+#define IMASK_LOC_FAULT 0x00002000 /* local fault mask */
+#define IMASK_TX_ECC_ER 0x00001000 /* Tx frame ECC error mask */
+#define IMASK_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow mask */
+#define IMASK_TX_ER 0x00000200 /* Tx frame error mask */
+#define IMASK_RX_FIFO_OVFL 0x00000100 /* Rx FIFO overflow mask */
+#define IMASK_RX_ECC_ER 0x00000080 /* Rx frame ECC error mask */
+#define IMASK_RX_JAB_FRM 0x00000040 /* Rx jabber frame mask */
+#define IMASK_RX_OVRSZ_FRM 0x00000020 /* Rx oversized frame mask */
+#define IMASK_RX_RUNT_FRM 0x00000010 /* Rx runt frame mask */
+#define IMASK_RX_FRAG_FRM 0x00000008 /* Rx fragment frame mask */
+#define IMASK_RX_LEN_ER 0x00000004 /* Rx payload length error mask */
+#define IMASK_RX_CRC_ER 0x00000002 /* Rx CRC error mask */
+#define IMASK_RX_ALIGN_ER 0x00000001 /* Rx alignment error mask */
+
+#define IMASK_MASK_ALL 0x00000000
+
+/* IEVENT - interrupt event register */
+#define IEVENT_MDIO_SCAN_EVENT 0x00010000 /* MDIO scan event */
+#define IEVENT_MDIO_CMD_CMPL 0x00008000 /* MDIO cmd completion */
+#define IEVENT_REM_FAULT 0x00004000 /* remote fault */
+#define IEVENT_LOC_FAULT 0x00002000 /* local fault */
+#define IEVENT_TX_ECC_ER 0x00001000 /* Tx frame ECC error */
+#define IEVENT_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow */
+#define IEVENT_TX_ER 0x00000200 /* Tx frame error */
+#define IEVENT_RX_FIFO_OVFL 0x00000100 /* Rx FIFO overflow */
+#define IEVENT_RX_ECC_ER 0x00000080 /* Rx frame ECC error */
+#define IEVENT_RX_JAB_FRM 0x00000040 /* Rx jabber frame */
+#define IEVENT_RX_OVRSZ_FRM 0x00000020 /* Rx oversized frame */
+#define IEVENT_RX_RUNT_FRM 0x00000010 /* Rx runt frame */
+#define IEVENT_RX_FRAG_FRM 0x00000008 /* Rx fragment frame */
+#define IEVENT_RX_LEN_ER 0x00000004 /* Rx payload length error */
+#define IEVENT_RX_CRC_ER 0x00000002 /* Rx CRC error */
+#define IEVENT_RX_ALIGN_ER 0x00000001 /* Rx alignment error */
+
+#define IEVENT_CLEAR_ALL 0xffffffff
+
+struct tgec_mdio_controller {
+ u32 res0[0xc];
+ u32 mdio_stat; /* MDIO configuration and status */
+ u32 mdio_ctl; /* MDIO control */
+ u32 mdio_data; /* MDIO data */
+ u32 mdio_addr; /* MDIO address */
+};
+
+#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8)
+#define MDIO_STAT_BSY (1 << 0)
+#define MDIO_STAT_RD_ER (1 << 1)
+#define MDIO_CTL_DEV_ADDR(x) (x & 0x1f)
+#define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5)
+#define MDIO_CTL_PRE_DIS (1 << 10)
+#define MDIO_CTL_SCAN_EN (1 << 11)
+#define MDIO_CTL_POST_INC (1 << 14)
+#define MDIO_CTL_READ (1 << 15)
+
+#define MDIO_DATA(x) (x & 0xffff)
+#define MDIO_DATA_BSY (1 << 31)
+
+struct fsl_enet_mac;
+
+void init_tgec(struct fsl_enet_mac *mac, void *base, void *phyregs,
+ int max_rx_len);
+
+#endif
diff --git a/arch/powerpc/include/asm/global_data.h b/arch/powerpc/include/asm/global_data.h
new file mode 100644
index 0000000..c02447f
--- /dev/null
+++ b/arch/powerpc/include/asm/global_data.h
@@ -0,0 +1,143 @@
+/*
+ * (C) Copyright 2002-2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_GBL_DATA_H
+#define __ASM_GBL_DATA_H
+
+#include "config.h"
+#include "asm/types.h"
+
+/* Architecture-specific global data */
+struct arch_global_data {
+#if defined(CONFIG_FSL_ESDHC)
+ u32 sdhc_clk;
+#endif
+#if defined(CONFIG_8xx)
+ unsigned long brg_clk;
+#endif
+#if defined(CONFIG_CPM2)
+ /* There are many clocks on the MPC8260 - see page 9-5 */
+ unsigned long vco_out;
+ unsigned long cpm_clk;
+ unsigned long scc_clk;
+ unsigned long brg_clk;
+#endif
+ /* TODO: sjg@chromium.org: Should these be unslgned long? */
+#if defined(CONFIG_MPC83xx)
+ /* There are other clocks in the MPC83XX */
+ u32 csb_clk;
+# if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC834x) || defined(CONFIG_MPC837x)
+ u32 tsec1_clk;
+ u32 tsec2_clk;
+ u32 usbdr_clk;
+# elif defined(CONFIG_MPC8309)
+ u32 usbdr_clk;
+# endif
+# if defined(CONFIG_MPC834x)
+ u32 usbmph_clk;
+# endif /* CONFIG_MPC834x */
+# if defined(CONFIG_MPC8315)
+ u32 tdm_clk;
+# endif
+ u32 core_clk;
+ u32 enc_clk;
+ u32 lbiu_clk;
+ u32 lclk_clk;
+# if defined(CONFIG_MPC8308) || defined(CONFIG_MPC831x) || \
+ defined(CONFIG_MPC837x)
+ u32 pciexp1_clk;
+ u32 pciexp2_clk;
+# endif
+# if defined(CONFIG_MPC837x) || defined(CONFIG_MPC8315)
+ u32 sata_clk;
+# endif
+# if defined(CONFIG_MPC8360)
+ u32 mem_sec_clk;
+# endif /* CONFIG_MPC8360 */
+#endif
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+ u32 lbc_clk;
+ void *cpu;
+#endif /* CONFIG_MPC85xx || CONFIG_MPC86xx */
+#if defined(CONFIG_MPC83xx) || defined(CONFIG_MPC85xx) || \
+ defined(CONFIG_MPC86xx)
+ u32 i2c1_clk;
+ u32 i2c2_clk;
+#endif
+#if defined(CONFIG_QE)
+ u32 qe_clk;
+ u32 brg_clk;
+ uint mp_alloc_base;
+ uint mp_alloc_top;
+#endif /* CONFIG_QE */
+#if defined(CONFIG_FSL_LAW)
+ u32 used_laws;
+#endif
+#if defined(CONFIG_E500)
+ u32 used_tlb_cams[(CONFIG_SYS_NUM_TLBCAMS+31)/32];
+#endif
+#if defined(CONFIG_MPC5xxx)
+ unsigned long ipb_clk;
+#endif
+#if defined(CONFIG_MPC512X)
+ u32 ips_clk;
+ u32 csb_clk;
+#endif /* CONFIG_MPC512X */
+ unsigned long reset_status; /* reset status register at boot */
+#if defined(CONFIG_MPC83xx)
+ unsigned long arbiter_event_attributes;
+ unsigned long arbiter_event_address;
+#endif
+#if defined(CONFIG_SYS_ALLOC_DPRAM) || defined(CONFIG_CPM2)
+ unsigned int dp_alloc_base;
+ unsigned int dp_alloc_top;
+#endif
+#if defined(CONFIG_4xx)
+ u32 uart_clk;
+#endif /* CONFIG_4xx */
+#if defined(CONFIG_SYS_GT_6426x)
+ unsigned int mirror_hack[16];
+#endif
+#ifdef CONFIG_SYS_FPGA_COUNT
+ unsigned fpga_state[CONFIG_SYS_FPGA_COUNT];
+#endif
+#if defined(CONFIG_WD_MAX_RATE)
+ unsigned long long wdt_last; /* trace watch-dog triggering rate */
+#endif
+#if defined(CONFIG_LWMON) || defined(CONFIG_LWMON5)
+ unsigned long kbd_status;
+#endif
+};
+
+#include <asm-generic/global_data.h>
+
+#if 1
+#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r2")
+#else /* We could use plain global data, but the resulting code is bigger */
+#define XTRN_DECLARE_GLOBAL_DATA_PTR extern
+#define DECLARE_GLOBAL_DATA_PTR XTRN_DECLARE_GLOBAL_DATA_PTR \
+ gd_t *gd
+#endif
+
+#endif /* __ASM_GBL_DATA_H */
diff --git a/arch/powerpc/include/asm/gpio.h b/arch/powerpc/include/asm/gpio.h
new file mode 100644
index 0000000..d49ad08
--- /dev/null
+++ b/arch/powerpc/include/asm/gpio.h
@@ -0,0 +1,2 @@
+#include <asm/arch/gpio.h>
+#include <asm-generic/gpio.h>
diff --git a/arch/powerpc/include/asm/immap_512x.h b/arch/powerpc/include/asm/immap_512x.h
new file mode 100644
index 0000000..8248219
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_512x.h
@@ -0,0 +1,1277 @@
+/*
+ * (C) Copyright 2007-2009 DENX Software Engineering
+ *
+ * MPC512x Internal Memory Map
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Based on the MPC83xx header.
+ */
+
+#ifndef __IMMAP_512x__
+#define __IMMAP_512x__
+
+#include <asm/types.h>
+#if defined(CONFIG_E300)
+#include <asm/e300.h>
+#endif
+
+/*
+ * System reset offset (PowerPC standard)
+ */
+#define EXC_OFF_SYS_RESET 0x0100
+#define _START_OFFSET EXC_OFF_SYS_RESET
+
+#define SPR_5121E 0x80180000
+
+/*
+ * IMMRBAR - Internal Memory Register Base Address
+ */
+#define CONFIG_DEFAULT_IMMR 0xFF400000 /* Default IMMR base address */
+#define IMMRBAR 0x0000 /* Register offset to immr */
+#define IMMRBAR_BASE_ADDR 0xFFF00000 /* Base address mask */
+#define IMMRBAR_RES ~(IMMRBAR_BASE_ADDR)
+
+
+#ifndef __ASSEMBLY__
+typedef struct law512x {
+ u32 bar; /* Base Addr Register */
+ u32 ar; /* Attributes Register */
+} law512x_t;
+
+/*
+ * System configuration registers
+ */
+typedef struct sysconf512x {
+ u32 immrbar; /* Internal memory map base address register */
+ u8 res0[0x1c];
+ u32 lpbaw; /* LP Boot Access Window */
+ u32 lpcs0aw; /* LP CS0 Access Window */
+ u32 lpcs1aw; /* LP CS1 Access Window */
+ u32 lpcs2aw; /* LP CS2 Access Window */
+ u32 lpcs3aw; /* LP CS3 Access Window */
+ u32 lpcs4aw; /* LP CS4 Access Window */
+ u32 lpcs5aw; /* LP CS5 Access Window */
+ u32 lpcs6aw; /* LP CS6 Access Window */
+ u32 lpcs7aw; /* LP CS7 Access Window */
+ u8 res1[0x1c];
+ law512x_t pcilaw[3]; /* PCI Local Access Window 0-2 Registers */
+ u8 res2[0x28];
+ law512x_t ddrlaw; /* DDR Local Access Window */
+ u8 res3[0x18];
+ u32 mbxbar; /* MBX Base Address */
+ u32 srambar; /* SRAM Base Address */
+ u32 nfcbar; /* NFC Base Address */
+ u8 res4[0x34];
+ u32 spridr; /* System Part and Revision ID Register */
+ u32 spcr; /* System Priority Configuration Register */
+ u8 res5[0xf8];
+} sysconf512x_t;
+
+#define LAWBAR_BAR 0xFFFFF000 /* Base address mask */
+
+/*
+ * Watch Dog Timer (WDT) Registers
+ */
+typedef struct wdt512x {
+ u8 res0[4];
+ u32 swcrr; /* System watchdog control register */
+ u32 swcnr; /* System watchdog count register */
+ u8 res1[2];
+ u16 swsrr; /* System watchdog service register */
+ u8 res2[0xF0];
+} wdt512x_t;
+
+/*
+ * RTC Module Registers
+ */
+typedef struct rtclk512x {
+ u8 fixme[0x100];
+} rtclk512x_t;
+
+/*
+ * General Purpose Timer
+ */
+typedef struct gpt512x {
+ u8 fixme[0x100];
+} gpt512x_t;
+
+/*
+ * Integrated Programmable Interrupt Controller
+ */
+typedef struct ipic512x {
+ u8 fixme[0x100];
+} ipic512x_t;
+
+/*
+ * System Arbiter Registers
+ */
+typedef struct arbiter512x {
+ u32 acr; /* Arbiter Configuration Register */
+ u32 atr; /* Arbiter Timers Register */
+ u32 ater; /* Arbiter Transfer Error Register */
+ u32 aer; /* Arbiter Event Register */
+ u32 aidr; /* Arbiter Interrupt Definition Register */
+ u32 amr; /* Arbiter Mask Register */
+ u32 aeatr; /* Arbiter Event Attributes Register */
+ u32 aeadr; /* Arbiter Event Address Register */
+ u32 aerr; /* Arbiter Event Response Register */
+ u8 res1[0xDC];
+} arbiter512x_t;
+
+/*
+ * Reset Module
+ */
+typedef struct reset512x {
+ u32 rcwl; /* Reset Configuration Word Low Register */
+ u32 rcwh; /* Reset Configuration Word High Register */
+ u8 res0[8];
+ u32 rsr; /* Reset Status Register */
+ u32 rmr; /* Reset Mode Register */
+ u32 rpr; /* Reset protection Register */
+ u32 rcr; /* Reset Control Register */
+ u32 rcer; /* Reset Control Enable Register */
+ u8 res1[0xDC];
+} reset512x_t;
+
+/* RSR - Reset Status Register */
+#define RSR_SWSR 0x00002000 /* software soft reset */
+#define RSR_SWHR 0x00001000 /* software hard reset */
+#define RSR_JHRS 0x00000200 /* jtag hreset */
+#define RSR_JSRS 0x00000100 /* jtag sreset status */
+#define RSR_CSHR 0x00000010 /* checkstop reset status */
+#define RSR_SWRS 0x00000008 /* software watchdog reset status */
+#define RSR_BMRS 0x00000004 /* bus monitop reset status */
+#define RSR_SRS 0x00000002 /* soft reset status */
+#define RSR_HRS 0x00000001 /* hard reset status */
+#define RSR_RES ~(RSR_SWSR | RSR_SWHR |\
+ RSR_JHRS | RSR_JSRS | RSR_CSHR | RSR_SWRS |\
+ RSR_BMRS | RSR_SRS | RSR_HRS)
+
+/* RMR - Reset Mode Register */
+#define RMR_CSRE 0x00000001 /* checkstop reset enable */
+#define RMR_CSRE_SHIFT 0
+#define RMR_RES (~(RMR_CSRE))
+
+/* RCR - Reset Control Register */
+#define RCR_SWHR 0x00000002 /* software hard reset */
+#define RCR_SWSR 0x00000001 /* software soft reset */
+#define RCR_RES (~(RCR_SWHR | RCR_SWSR))
+
+/* RCER - Reset Control Enable Register */
+#define RCER_CRE 0x00000001 /* software hard reset */
+#define RCER_RES (~(RCER_CRE))
+
+/*
+ * Clock Module
+ */
+typedef struct clk512x {
+ u32 spmr; /* System PLL Mode Register */
+ u32 sccr[2]; /* System Clock Control Registers */
+ u32 scfr[2]; /* System Clock Frequency Registers */
+ u8 res0[4];
+ u32 bcr; /* Bread Crumb Register */
+ u32 pscccr[12]; /* PSC0-11 Clock Control Registers */
+ u32 spccr; /* SPDIF Clock Control Register */
+ u32 cccr; /* CFM Clock Control Register */
+ u32 dccr; /* DIU Clock Control Register */
+ u32 msccr[4]; /* MSCAN1-4 Clock Control Registers */
+ u8 res1[0x98];
+} clk512x_t;
+
+/* SPMR - System PLL Mode Register */
+#define SPMR_SPMF 0x0F000000
+#define SPMR_SPMF_SHIFT 24
+#define SPMR_CPMF 0x000F0000
+#define SPMR_CPMF_SHIFT 16
+
+/* System Clock Control Register 1 commands */
+#define CLOCK_SCCR1_CFG_EN 0x80000000
+#define CLOCK_SCCR1_LPC_EN 0x40000000
+#define CLOCK_SCCR1_NFC_EN 0x20000000
+#define CLOCK_SCCR1_PATA_EN 0x10000000
+#define CLOCK_SCCR1_PSC_EN(cn) (0x08000000 >> (cn))
+#define CLOCK_SCCR1_PSCFIFO_EN 0x00008000
+#define CLOCK_SCCR1_SATA_EN 0x00004000
+#define CLOCK_SCCR1_FEC_EN 0x00002000
+#define CLOCK_SCCR1_TPR_EN 0x00001000
+#define CLOCK_SCCR1_PCI_EN 0x00000800
+#define CLOCK_SCCR1_DDR_EN 0x00000400
+
+/* System Clock Control Register 2 commands */
+#define CLOCK_SCCR2_DIU_EN 0x80000000
+#define CLOCK_SCCR2_AXE_EN 0x40000000
+#define CLOCK_SCCR2_MEM_EN 0x20000000
+#define CLOCK_SCCR2_USB1_EN 0x10000000
+#define CLOCK_SCCR2_USB2_EN 0x08000000
+#define CLOCK_SCCR2_I2C_EN 0x04000000
+#define CLOCK_SCCR2_BDLC_EN 0x02000000
+#define CLOCK_SCCR2_SDHC_EN 0x01000000
+#define CLOCK_SCCR2_SPDIF_EN 0x00800000
+#define CLOCK_SCCR2_MBX_BUS_EN 0x00400000
+#define CLOCK_SCCR2_MBX_EN 0x00200000
+#define CLOCK_SCCR2_MBX_3D_EN 0x00100000
+#define CLOCK_SCCR2_IIM_EN 0x00080000
+
+/* SCFR1 System Clock Frequency Register 1 */
+#ifndef SCFR1_IPS_DIV
+#define SCFR1_IPS_DIV 0x3
+#endif
+#define SCFR1_IPS_DIV_MASK 0x03800000
+#define SCFR1_IPS_DIV_SHIFT 23
+
+#define SCFR1_PCI_DIV 0x6
+#define SCFR1_PCI_DIV_MASK 0x00700000
+#define SCFR1_PCI_DIV_SHIFT 20
+
+#define SCFR1_LPC_DIV_MASK 0x00003800
+#define SCFR1_LPC_DIV_SHIFT 11
+
+#define SCFR1_NFC_DIV_MASK 0x00000700
+#define SCFR1_NFC_DIV_SHIFT 8
+
+#define SCFR1_DIU_DIV_MASK 0x000000FF
+#define SCFR1_DIU_DIV_SHIFT 0
+
+/* SCFR2 System Clock Frequency Register 2 */
+#define SCFR2_SYS_DIV 0xFC000000
+#define SCFR2_SYS_DIV_SHIFT 26
+
+/* SPCR - System Priority Configuration Register */
+#define SPCR_TBEN 0x00400000 /* E300 core time base unit enable */
+
+/*
+ * Power Management Control Module
+ */
+typedef struct pmc512x {
+ u8 fixme[0x100];
+} pmc512x_t;
+
+/*
+ * General purpose I/O module
+ */
+typedef struct gpio512x {
+ u32 gpdir;
+ u32 gpodr;
+ u32 gpdat;
+ u32 gpier;
+ u32 gpimr;
+ u32 gpicr1;
+ u32 gpicr2;
+ u8 res0[0xE4];
+} gpio512x_t;
+
+/*
+ * DDR Memory Controller Memory Map
+ */
+typedef struct ddr512x {
+ u32 ddr_sys_config; /* System Configuration Register */
+ u32 ddr_time_config0; /* Timing Configuration Register */
+ u32 ddr_time_config1; /* Timing Configuration Register */
+ u32 ddr_time_config2; /* Timing Configuration Register */
+ u32 ddr_command; /* Command Register */
+ u32 ddr_compact_command; /* Compact Command Register */
+ u32 self_refresh_cmd_0; /* Enter/Exit Self Refresh Registers */
+ u32 self_refresh_cmd_1; /* Enter/Exit Self Refresh Registers */
+ u32 self_refresh_cmd_2; /* Enter/Exit Self Refresh Registers */
+ u32 self_refresh_cmd_3; /* Enter/Exit Self Refresh Registers */
+ u32 self_refresh_cmd_4; /* Enter/Exit Self Refresh Registers */
+ u32 self_refresh_cmd_5; /* Enter/Exit Self Refresh Registers */
+ u32 self_refresh_cmd_6; /* Enter/Exit Self Refresh Registers */
+ u32 self_refresh_cmd_7; /* Enter/Exit Self Refresh Registers */
+ u32 DQS_config_offset_count; /* DQS Config Offset Count */
+ u32 DQS_config_offset_time; /* DQS Config Offset Time */
+ u32 DQS_delay_status; /* DQS Delay Status */
+ u32 res0[0xF];
+ u32 prioman_config1; /* Priority Manager Configuration */
+ u32 prioman_config2; /* Priority Manager Configuration */
+ u32 hiprio_config; /* High Priority Configuration */
+ u32 lut_table0_main_upper; /* LUT0 Main Upper */
+ u32 lut_table1_main_upper; /* LUT1 Main Upper */
+ u32 lut_table2_main_upper; /* LUT2 Main Upper */
+ u32 lut_table3_main_upper; /* LUT3 Main Upper */
+ u32 lut_table4_main_upper; /* LUT4 Main Upper */
+ u32 lut_table0_main_lower; /* LUT0 Main Lower */
+ u32 lut_table1_main_lower; /* LUT1 Main Lower */
+ u32 lut_table2_main_lower; /* LUT2 Main Lower */
+ u32 lut_table3_main_lower; /* LUT3 Main Lower */
+ u32 lut_table4_main_lower; /* LUT4 Main Lower */
+ u32 lut_table0_alternate_upper; /* LUT0 Alternate Upper */
+ u32 lut_table1_alternate_upper; /* LUT1 Alternate Upper */
+ u32 lut_table2_alternate_upper; /* LUT2 Alternate Upper */
+ u32 lut_table3_alternate_upper; /* LUT3 Alternate Upper */
+ u32 lut_table4_alternate_upper; /* LUT4 Alternate Upper */
+ u32 lut_table0_alternate_lower; /* LUT0 Alternate Lower */
+ u32 lut_table1_alternate_lower; /* LUT1 Alternate Lower */
+ u32 lut_table2_alternate_lower; /* LUT2 Alternate Lower */
+ u32 lut_table3_alternate_lower; /* LUT3 Alternate Lower */
+ u32 lut_table4_alternate_lower; /* LUT4 Alternate Lower */
+ u32 performance_monitor_config;
+ u32 event_time_counter;
+ u32 event_time_preset;
+ u32 performance_monitor1_address_low;
+ u32 performance_monitor2_address_low;
+ u32 performance_monitor1_address_hi;
+ u32 performance_monitor2_address_hi;
+ u32 res1[2];
+ u32 performance_monitor1_read_counter;
+ u32 performance_monitor2_read_counter;
+ u32 performance_monitor1_write_counter;
+ u32 performance_monitor2_write_counter;
+ u32 granted_ack_counter0;
+ u32 granted_ack_counter1;
+ u32 granted_ack_counter2;
+ u32 granted_ack_counter3;
+ u32 granted_ack_counter4;
+ u32 cumulative_wait_counter0;
+ u32 cumulative_wait_counter1;
+ u32 cumulative_wait_counter2;
+ u32 cumulative_wait_counter3;
+ u32 cumulative_wait_counter4;
+ u32 summed_priority_counter0;
+ u32 summed_priority_counter1;
+ u32 summed_priority_counter2;
+ u32 summed_priority_counter3;
+ u32 summed_priority_counter4;
+ u32 res2[0x3AD];
+} ddr512x_t;
+
+/* MDDRC SYS CFG and Timing CFG0 Registers */
+#define MDDRC_SYS_CFG_EN 0xF0000000
+#define MDDRC_SYS_CFG_CKE_MASK 0x40000000
+#define MDDRC_SYS_CFG_CMD_MASK 0x10000000
+#define MDDRC_REFRESH_ZERO_MASK 0x0000FFFF
+
+/*
+ * DDR Memory Controller Configuration settings
+ */
+typedef struct ddr512x_config {
+ u32 ddr_sys_config; /* System Configuration Register */
+ u32 ddr_time_config0; /* Timing Configuration Register */
+ u32 ddr_time_config1; /* Timing Configuration Register */
+ u32 ddr_time_config2; /* Timing Configuration Register */
+} ddr512x_config_t;
+
+typedef struct sdram_conf_s {
+ unsigned long size;
+ ddr512x_config_t cfg;
+} sdram_conf_t;
+
+/*
+ * DMA/Messaging Unit
+ */
+typedef struct dma512x {
+ u8 fixme[0x1800];
+} dma512x_t;
+
+/*
+ * PCI Software Configuration Registers
+ */
+typedef struct pciconf512x {
+ u32 config_address;
+ u32 config_data;
+ u32 int_ack;
+ u8 res[116];
+} pciconf512x_t;
+
+/*
+ * PCI Outbound Translation Register
+ */
+typedef struct pci_outbound_window {
+ u32 potar;
+ u8 res0[4];
+ u32 pobar;
+ u8 res1[4];
+ u32 pocmr;
+ u8 res2[4];
+} pot512x_t;
+
+/* POTAR - PCI Outbound Translation Address Register */
+#define POTAR_TA_MASK 0x000fffff
+
+/* POBAR - PCI Outbound Base Address Register */
+#define POBAR_BA_MASK 0x000fffff
+
+/* POCMR - PCI Outbound Comparision Mask Register */
+#define POCMR_EN 0x80000000
+#define POCMR_IO 0x40000000 /* 0-memory space 1-I/O space */
+#define POCMR_PRE 0x20000000 /* prefetch enable */
+#define POCMR_SBS 0x00100000 /* special byte swap enable */
+#define POCMR_CM_MASK 0x000fffff
+#define POCMR_CM_4G 0x00000000
+#define POCMR_CM_2G 0x00080000
+#define POCMR_CM_1G 0x000C0000
+#define POCMR_CM_512M 0x000E0000
+#define POCMR_CM_256M 0x000F0000
+#define POCMR_CM_128M 0x000F8000
+#define POCMR_CM_64M 0x000FC000
+#define POCMR_CM_32M 0x000FE000
+#define POCMR_CM_16M 0x000FF000
+#define POCMR_CM_8M 0x000FF800
+#define POCMR_CM_4M 0x000FFC00
+#define POCMR_CM_2M 0x000FFE00
+#define POCMR_CM_1M 0x000FFF00
+#define POCMR_CM_512K 0x000FFF80
+#define POCMR_CM_256K 0x000FFFC0
+#define POCMR_CM_128K 0x000FFFE0
+#define POCMR_CM_64K 0x000FFFF0
+#define POCMR_CM_32K 0x000FFFF8
+#define POCMR_CM_16K 0x000FFFFC
+#define POCMR_CM_8K 0x000FFFFE
+#define POCMR_CM_4K 0x000FFFFF
+
+/*
+ * Sequencer
+ */
+typedef struct ios512x {
+ pot512x_t pot[6];
+ u8 res0[0x60];
+ u32 pmcr;
+ u8 res1[4];
+ u32 dtcr;
+ u8 res2[4];
+} ios512x_t;
+
+/*
+ * PCI Controller
+ */
+typedef struct pcictrl512x {
+ u32 esr;
+ u32 ecdr;
+ u32 eer;
+ u32 eatcr;
+ u32 eacr;
+ u32 eeacr;
+ u32 edlcr;
+ u32 edhcr;
+ u32 gcr;
+ u32 ecr;
+ u32 gsr;
+ u8 res0[12];
+ u32 pitar2;
+ u8 res1[4];
+ u32 pibar2;
+ u32 piebar2;
+ u32 piwar2;
+ u8 res2[4];
+ u32 pitar1;
+ u8 res3[4];
+ u32 pibar1;
+ u32 piebar1;
+ u32 piwar1;
+ u8 res4[4];
+ u32 pitar0;
+ u8 res5[4];
+ u32 pibar0;
+ u8 res6[4];
+ u32 piwar0;
+ u8 res7[132];
+} pcictrl512x_t;
+
+
+/* PITAR - PCI Inbound Translation Address Register
+ */
+#define PITAR_TA_MASK 0x000fffff
+
+/* PIBAR - PCI Inbound Base/Extended Address Register
+ */
+#define PIBAR_MASK 0xffffffff
+#define PIEBAR_EBA_MASK 0x000fffff
+
+/* PIWAR - PCI Inbound Windows Attributes Register
+ */
+#define PIWAR_EN 0x80000000
+#define PIWAR_SBS 0x40000000
+#define PIWAR_PF 0x20000000
+#define PIWAR_RTT_MASK 0x000f0000
+#define PIWAR_RTT_NO_SNOOP 0x00040000
+#define PIWAR_RTT_SNOOP 0x00050000
+#define PIWAR_WTT_MASK 0x0000f000
+#define PIWAR_WTT_NO_SNOOP 0x00004000
+#define PIWAR_WTT_SNOOP 0x00005000
+
+/*
+ * MSCAN
+ */
+typedef struct mscan512x {
+ u8 fixme[0x100];
+} mscan512x_t;
+
+/*
+ * BDLC
+ */
+typedef struct bdlc512x {
+ u8 fixme[0x100];
+} bdlc512x_t;
+
+/*
+ * SDHC
+ */
+typedef struct sdhc512x {
+ u8 fixme[0x100];
+} sdhc512x_t;
+
+/*
+ * SPDIF
+ */
+typedef struct spdif512x {
+ u8 fixme[0x100];
+} spdif512x_t;
+
+/*
+ * I2C
+ */
+typedef struct i2c512x_dev {
+ volatile u32 madr; /* I2Cn + 0x00 */
+ volatile u32 mfdr; /* I2Cn + 0x04 */
+ volatile u32 mcr; /* I2Cn + 0x08 */
+ volatile u32 msr; /* I2Cn + 0x0C */
+ volatile u32 mdr; /* I2Cn + 0x10 */
+ u8 res0[0x0C];
+} i2c512x_dev_t;
+
+/* Number of I2C buses */
+#define I2C_BUS_CNT 3
+
+typedef struct i2c512x {
+ i2c512x_dev_t dev[I2C_BUS_CNT];
+ volatile u32 icr;
+ volatile u32 mifr;
+ u8 res0[0x98];
+} i2c512x_t;
+
+/* I2Cn control register bits */
+#define I2C_EN 0x80
+#define I2C_IEN 0x40
+#define I2C_STA 0x20
+#define I2C_TX 0x10
+#define I2C_TXAK 0x08
+#define I2C_RSTA 0x04
+#define I2C_INIT_MASK (I2C_EN | I2C_STA | I2C_TX | I2C_RSTA)
+
+/* I2Cn status register bits */
+#define I2C_CF 0x80
+#define I2C_AAS 0x40
+#define I2C_BB 0x20
+#define I2C_AL 0x10
+#define I2C_SRW 0x04
+#define I2C_IF 0x02
+#define I2C_RXAK 0x01
+
+/*
+ * AXE
+ */
+typedef struct axe512x {
+ u8 fixme[0x100];
+} axe512x_t;
+
+/*
+ * DIU
+ */
+typedef struct diu512x {
+ u8 fixme[0x100];
+} diu512x_t;
+
+/*
+ * CFM
+ */
+typedef struct cfm512x {
+ u8 fixme[0x100];
+} cfm512x_t;
+
+/*
+ * FEC
+ */
+typedef struct fec512x {
+ u32 fec_id; /* FEC_ID register */
+ u32 ievent; /* Interrupt event register */
+ u32 imask; /* Interrupt mask register */
+ u32 reserved_01;
+ u32 r_des_active; /* Receive ring updated flag */
+ u32 x_des_active; /* Transmit ring updated flag */
+ u32 reserved_02[3];
+ u32 ecntrl; /* Ethernet control register */
+ u32 reserved_03[6];
+ u32 mii_data; /* MII data register */
+ u32 mii_speed; /* MII speed register */
+ u32 reserved_04[7];
+ u32 mib_control; /* MIB control/status register */
+ u32 reserved_05[7];
+ u32 r_cntrl; /* Receive control register */
+ u32 r_hash; /* Receive hash */
+ u32 reserved_06[14];
+ u32 x_cntrl; /* Transmit control register */
+ u32 reserved_07[7];
+ u32 paddr1; /* Physical address low */
+ u32 paddr2; /* Physical address high + type field */
+ u32 op_pause; /* Opcode + pause duration */
+ u32 reserved_08[10];
+ u32 iaddr1; /* Upper 32 bits of individual hash table */
+ u32 iaddr2; /* Lower 32 bits of individual hash table */
+ u32 gaddr1; /* Upper 32 bits of group hash table */
+ u32 gaddr2; /* Lower 32 bits of group hash table */
+ u32 reserved_09[7];
+ u32 x_wmrk; /* Transmit FIFO watermark */
+ u32 reserved_10;
+ u32 r_bound; /* End of RAM */
+ u32 r_fstart; /* Receive FIFO start address */
+ u32 reserved_11[11];
+ u32 r_des_start; /* Beginning of receive descriptor ring */
+ u32 x_des_start; /* Pointer to beginning of transmit descriptor ring */
+ u32 r_buff_size; /* Receive buffer size */
+ u32 reserved_12[26];
+ u32 dma_control; /* DMA control for IP bus, AMBA IF + DMA revision */
+ u32 reserved_13[2];
+
+ u32 mib[128]; /* MIB Block Counters */
+
+ u32 fifo[256]; /* used by FEC, can only be accessed by DMA */
+} fec512x_t;
+
+/*
+ * ULPI
+ */
+typedef struct ulpi512x {
+ u8 fixme[0x600];
+} ulpi512x_t;
+
+/*
+ * UTMI
+ */
+typedef struct utmi512x {
+ u8 fixme[0x3000];
+} utmi512x_t;
+
+/*
+ * PCI DMA
+ */
+typedef struct pcidma512x {
+ u8 fixme[0x300];
+} pcidma512x_t;
+
+/*
+ * IO Control
+ */
+typedef struct ioctrl512x {
+ u32 io_control_mem; /* MEM pad ctrl reg */
+ u32 io_control_gp; /* GP pad ctrl reg */
+ u32 io_control_lpc_clk; /* LPC_CLK pad ctrl reg */
+ u32 io_control_lpc_oe; /* LPC_OE pad ctrl reg */
+ u32 io_control_lpc_rw; /* LPC_R/W pad ctrl reg */
+ u32 io_control_lpc_ack; /* LPC_ACK pad ctrl reg */
+ u32 io_control_lpc_cs0; /* LPC_CS0 pad ctrl reg */
+ u32 io_control_nfc_ce0; /* NFC_CE0 pad ctrl reg */
+ u32 io_control_lpc_cs1; /* LPC_CS1 pad ctrl reg */
+ u32 io_control_lpc_cs2; /* LPC_CS2 pad ctrl reg */
+ u32 io_control_lpc_ax03; /* LPC_AX03 pad ctrl reg */
+ u32 io_control_emb_ax02; /* EMB_AX02 pad ctrl reg */
+ u32 io_control_emb_ax01; /* EMB_AX01 pad ctrl reg */
+ u32 io_control_emb_ax00; /* EMB_AX00 pad ctrl reg */
+ u32 io_control_emb_ad31; /* EMB_AD31 pad ctrl reg */
+ u32 io_control_emb_ad30; /* EMB_AD30 pad ctrl reg */
+ u32 io_control_emb_ad29; /* EMB_AD29 pad ctrl reg */
+ u32 io_control_emb_ad28; /* EMB_AD28 pad ctrl reg */
+ u32 io_control_emb_ad27; /* EMB_AD27 pad ctrl reg */
+ u32 io_control_emb_ad26; /* EMB_AD26 pad ctrl reg */
+ u32 io_control_emb_ad25; /* EMB_AD25 pad ctrl reg */
+ u32 io_control_emb_ad24; /* EMB_AD24 pad ctrl reg */
+ u32 io_control_emb_ad23; /* EMB_AD23 pad ctrl reg */
+ u32 io_control_emb_ad22; /* EMB_AD22 pad ctrl reg */
+ u32 io_control_emb_ad21; /* EMB_AD21 pad ctrl reg */
+ u32 io_control_emb_ad20; /* EMB_AD20 pad ctrl reg */
+ u32 io_control_emb_ad19; /* EMB_AD19 pad ctrl reg */
+ u32 io_control_emb_ad18; /* EMB_AD18 pad ctrl reg */
+ u32 io_control_emb_ad17; /* EMB_AD17 pad ctrl reg */
+ u32 io_control_emb_ad16; /* EMB_AD16 pad ctrl reg */
+ u32 io_control_emb_ad15; /* EMB_AD15 pad ctrl reg */
+ u32 io_control_emb_ad14; /* EMB_AD14 pad ctrl reg */
+ u32 io_control_emb_ad13; /* EMB_AD13 pad ctrl reg */
+ u32 io_control_emb_ad12; /* EMB_AD12 pad ctrl reg */
+ u32 io_control_emb_ad11; /* EMB_AD11 pad ctrl reg */
+ u32 io_control_emb_ad10; /* EMB_AD10 pad ctrl reg */
+ u32 io_control_emb_ad09; /* EMB_AD09 pad ctrl reg */
+ u32 io_control_emb_ad08; /* EMB_AD08 pad ctrl reg */
+ u32 io_control_emb_ad07; /* EMB_AD07 pad ctrl reg */
+ u32 io_control_emb_ad06; /* EMB_AD06 pad ctrl reg */
+ u32 io_control_emb_ad05; /* EMB_AD05 pad ctrl reg */
+ u32 io_control_emb_ad04; /* EMB_AD04 pad ctrl reg */
+ u32 io_control_emb_ad03; /* EMB_AD03 pad ctrl reg */
+ u32 io_control_emb_ad02; /* EMB_AD02 pad ctrl reg */
+ u32 io_control_emb_ad01; /* EMB_AD01 pad ctrl reg */
+ u32 io_control_emb_ad00; /* EMB_AD00 pad ctrl reg */
+ u32 io_control_pata_ce1; /* PATA_CE1 pad ctrl reg */
+ u32 io_control_pata_ce2; /* PATA_CE2 pad ctrl reg */
+ u32 io_control_pata_isolate; /* PATA_ISOLATE pad ctrl reg */
+ u32 io_control_pata_ior; /* PATA_IOR pad ctrl reg */
+ u32 io_control_pata_iow; /* PATA_IOW pad ctrl reg */
+ u32 io_control_pata_iochrdy; /* PATA_IOCHRDY pad ctrl reg */
+ u32 io_control_pata_intrq; /* PATA_INTRQ pad ctrl reg */
+ u32 io_control_pata_drq; /* PATA_DRQ pad ctrl reg */
+ u32 io_control_pata_dack; /* PATA_DACK pad ctrl reg */
+ u32 io_control_nfc_wp; /* NFC_WP pad ctrl reg */
+ u32 io_control_nfc_rb; /* NFC_RB pad ctrl reg */
+ u32 io_control_nfc_ale; /* NFC_ALE pad ctrl reg */
+ u32 io_control_nfc_cle; /* NFC_CLE pad ctrl reg */
+ u32 io_control_nfc_we; /* NFC_WE pad ctrl reg */
+ u32 io_control_nfc_re; /* NFC_RE pad ctrl reg */
+ u32 io_control_pci_ad31; /* PCI_AD31 pad ctrl reg */
+ u32 io_control_pci_ad30; /* PCI_AD30 pad ctrl reg */
+ u32 io_control_pci_ad29; /* PCI_AD29 pad ctrl reg */
+ u32 io_control_pci_ad28; /* PCI_AD28 pad ctrl reg */
+ u32 io_control_pci_ad27; /* PCI_AD27 pad ctrl reg */
+ u32 io_control_pci_ad26; /* PCI_AD26 pad ctrl reg */
+ u32 io_control_pci_ad25; /* PCI_AD25 pad ctrl reg */
+ u32 io_control_pci_ad24; /* PCI_AD24 pad ctrl reg */
+ u32 io_control_pci_ad23; /* PCI_AD23 pad ctrl reg */
+ u32 io_control_pci_ad22; /* PCI_AD22 pad ctrl reg */
+ u32 io_control_pci_ad21; /* PCI_AD21 pad ctrl reg */
+ u32 io_control_pci_ad20; /* PCI_AD20 pad ctrl reg */
+ u32 io_control_pci_ad19; /* PCI_AD19 pad ctrl reg */
+ u32 io_control_pci_ad18; /* PCI_AD18 pad ctrl reg */
+ u32 io_control_pci_ad17; /* PCI_AD17 pad ctrl reg */
+ u32 io_control_pci_ad16; /* PCI_AD16 pad ctrl reg */
+ u32 io_control_pci_ad15; /* PCI_AD15 pad ctrl reg */
+ u32 io_control_pci_ad14; /* PCI_AD14 pad ctrl reg */
+ u32 io_control_pci_ad13; /* PCI_AD13 pad ctrl reg */
+ u32 io_control_pci_ad12; /* PCI_AD12 pad ctrl reg */
+ u32 io_control_pci_ad11; /* PCI_AD11 pad ctrl reg */
+ u32 io_control_pci_ad10; /* PCI_AD10 pad ctrl reg */
+ u32 io_control_pci_ad09; /* PCI_AD09 pad ctrl reg */
+ u32 io_control_pci_ad08; /* PCI_AD08 pad ctrl reg */
+ u32 io_control_pci_ad07; /* PCI_AD07 pad ctrl reg */
+ u32 io_control_pci_ad06; /* PCI_AD06 pad ctrl reg */
+ u32 io_control_pci_ad05; /* PCI_AD05 pad ctrl reg */
+ u32 io_control_pci_ad04; /* PCI_AD04 pad ctrl reg */
+ u32 io_control_pci_ad03; /* PCI_AD03 pad ctrl reg */
+ u32 io_control_pci_ad02; /* PCI_AD02 pad ctrl reg */
+ u32 io_control_pci_ad01; /* PCI_AD01 pad ctrl reg */
+ u32 io_control_pci_ad00; /* PCI_AD00 pad ctrl reg */
+ u32 io_control_pci_cbe0; /* PCI_CBE0 pad ctrl reg */
+ u32 io_control_pci_cbe1; /* PCI_CBE1 pad ctrl reg */
+ u32 io_control_pci_cbe2; /* PCI_CBE2 pad ctrl reg */
+ u32 io_control_pci_cbe3; /* PCI_CBE3 pad ctrl reg */
+ u32 io_control_pci_grant2; /* PCI_GRANT2 pad ctrl reg */
+ u32 io_control_pci_req2; /* PCI_REQ2 pad ctrl reg */
+ u32 io_control_pci_grant1; /* PCI_GRANT1 pad ctrl reg */
+ u32 io_control_pci_req1; /* PCI_REQ1 pad ctrl reg */
+ u32 io_control_pci_grant0; /* PCI_GRANT0 pad ctrl reg */
+ u32 io_control_pci_req0; /* PCI_REQ0 pad ctrl reg */
+ u32 io_control_pci_inta; /* PCI_INTA pad ctrl reg */
+ u32 io_control_pci_clk; /* PCI_CLK pad ctrl reg */
+ u32 io_control_pci_rst; /* PCI_RST- pad ctrl reg */
+ u32 io_control_pci_frame; /* PCI_FRAME pad ctrl reg */
+ u32 io_control_pci_idsel; /* PCI_IDSEL pad ctrl reg */
+ u32 io_control_pci_devsel; /* PCI_DEVSEL pad ctrl reg */
+ u32 io_control_pci_irdy; /* PCI_IRDY pad ctrl reg */
+ u32 io_control_pci_trdy; /* PCI_TRDY pad ctrl reg */
+ u32 io_control_pci_stop; /* PCI_STOP pad ctrl reg */
+ u32 io_control_pci_par; /* PCI_PAR pad ctrl reg */
+ u32 io_control_pci_perr; /* PCI_PERR pad ctrl reg */
+ u32 io_control_pci_serr; /* PCI_SERR pad ctrl reg */
+ u32 io_control_spdif_txclk; /* SPDIF_TXCLK pad ctrl reg */
+ u32 io_control_spdif_tx; /* SPDIF_TX pad ctrl reg */
+ u32 io_control_spdif_rx; /* SPDIF_RX pad ctrl reg */
+ u32 io_control_i2c0_scl; /* I2C0_SCL pad ctrl reg */
+ u32 io_control_i2c0_sda; /* I2C0_SDA pad ctrl reg */
+ u32 io_control_i2c1_scl; /* I2C1_SCL pad ctrl reg */
+ u32 io_control_i2c1_sda; /* I2C1_SDA pad ctrl reg */
+ u32 io_control_i2c2_scl; /* I2C2_SCL pad ctrl reg */
+ u32 io_control_i2c2_sda; /* I2C2_SDA pad ctrl reg */
+ u32 io_control_irq0; /* IRQ0 pad ctrl reg */
+ u32 io_control_irq1; /* IRQ1 pad ctrl reg */
+ u32 io_control_can1_tx; /* CAN1_TX pad ctrl reg */
+ u32 io_control_can2_tx; /* CAN2_TX pad ctrl reg */
+ u32 io_control_j1850_tx; /* J1850_TX pad ctrl reg */
+ u32 io_control_j1850_rx; /* J1850_RX pad ctrl reg */
+ u32 io_control_psc_mclk_in; /* PSC_MCLK_IN pad ctrl reg */
+ u32 io_control_psc0_0; /* PSC0_0 pad ctrl reg */
+ u32 io_control_psc0_1; /* PSC0_1 pad ctrl reg */
+ u32 io_control_psc0_2; /* PSC0_2 pad ctrl reg */
+ u32 io_control_psc0_3; /* PSC0_3 pad ctrl reg */
+ u32 io_control_psc0_4; /* PSC0_4 pad ctrl reg */
+ u32 io_control_psc1_0; /* PSC1_0 pad ctrl reg */
+ u32 io_control_psc1_1; /* PSC1_1 pad ctrl reg */
+ u32 io_control_psc1_2; /* PSC1_2 pad ctrl reg */
+ u32 io_control_psc1_3; /* PSC1_3 pad ctrl reg */
+ u32 io_control_psc1_4; /* PSC1_4 pad ctrl reg */
+ u32 io_control_psc2_0; /* PSC2_0 pad ctrl reg */
+ u32 io_control_psc2_1; /* PSC2_1 pad ctrl reg */
+ u32 io_control_psc2_2; /* PSC2_2 pad ctrl reg */
+ u32 io_control_psc2_3; /* PSC2_3 pad ctrl reg */
+ u32 io_control_psc2_4; /* PSC2_4 pad ctrl reg */
+ u32 io_control_psc3_0; /* PSC3_0 pad ctrl reg */
+ u32 io_control_psc3_1; /* PSC3_1 pad ctrl reg */
+ u32 io_control_psc3_2; /* PSC3_2 pad ctrl reg */
+ u32 io_control_psc3_3; /* PSC3_3 pad ctrl reg */
+ u32 io_control_psc3_4; /* PSC3_4 pad ctrl reg */
+ u32 io_control_psc4_0; /* PSC4_0 pad ctrl reg */
+ u32 io_control_psc4_1; /* PSC4_1 pad ctrl reg */
+ u32 io_control_psc4_2; /* PSC4_2 pad ctrl reg */
+ u32 io_control_psc4_3; /* PSC4_3 pad ctrl reg */
+ u32 io_control_psc4_4; /* PSC4_4 pad ctrl reg */
+ u32 io_control_psc5_0; /* PSC5_0 pad ctrl reg */
+ u32 io_control_psc5_1; /* PSC5_1 pad ctrl reg */
+ u32 io_control_psc5_2; /* PSC5_2 pad ctrl reg */
+ u32 io_control_psc5_3; /* PSC5_3 pad ctrl reg */
+ u32 io_control_psc5_4; /* PSC5_4 pad ctrl reg */
+ u32 io_control_psc6_0; /* PSC6_0 pad ctrl reg */
+ u32 io_control_psc6_1; /* PSC6_1 pad ctrl reg */
+ u32 io_control_psc6_2; /* PSC6_2 pad ctrl reg */
+ u32 io_control_psc6_3; /* PSC6_3 pad ctrl reg */
+ u32 io_control_psc6_4; /* PSC6_4 pad ctrl reg */
+ u32 io_control_psc7_0; /* PSC7_0 pad ctrl reg */
+ u32 io_control_psc7_1; /* PSC7_1 pad ctrl reg */
+ u32 io_control_psc7_2; /* PSC7_2 pad ctrl reg */
+ u32 io_control_psc7_3; /* PSC7_3 pad ctrl reg */
+ u32 io_control_psc7_4; /* PSC7_4 pad ctrl reg */
+ u32 io_control_psc8_0; /* PSC8_0 pad ctrl reg */
+ u32 io_control_psc8_1; /* PSC8_1 pad ctrl reg */
+ u32 io_control_psc8_2; /* PSC8_2 pad ctrl reg */
+ u32 io_control_psc8_3; /* PSC8_3 pad ctrl reg */
+ u32 io_control_psc8_4; /* PSC8_4 pad ctrl reg */
+ u32 io_control_psc9_0; /* PSC9_0 pad ctrl reg */
+ u32 io_control_psc9_1; /* PSC9_1 pad ctrl reg */
+ u32 io_control_psc9_2; /* PSC9_2 pad ctrl reg */
+ u32 io_control_psc9_3; /* PSC9_3 pad ctrl reg */
+ u32 io_control_psc9_4; /* PSC9_4 pad ctrl reg */
+ u32 io_control_psc10_0; /* PSC10_0 pad ctrl reg */
+ u32 io_control_psc10_1; /* PSC10_1 pad ctrl reg */
+ u32 io_control_psc10_2; /* PSC10_2 pad ctrl reg */
+ u32 io_control_psc10_3; /* PSC10_3 pad ctrl reg */
+ u32 io_control_psc10_4; /* PSC10_4 pad ctrl reg */
+ u32 io_control_psc11_0; /* PSC11_0 pad ctrl reg */
+ u32 io_control_psc11_1; /* PSC11_1 pad ctrl reg */
+ u32 io_control_psc11_2; /* PSC11_2 pad ctrl reg */
+ u32 io_control_psc11_3; /* PSC11_3 pad ctrl reg */
+ u32 io_control_psc11_4; /* PSC11_4 pad ctrl reg */
+ u32 io_control_ckstp_out; /* CKSTP_OUT pad ctrl reg */
+ u32 io_control_usb_phy_drvvbus; /* USB2_DRVVBUS pad ctrl reg */
+ u8 reserved[0x0cfc]; /* fill to 4096 bytes size */
+} ioctrl512x_t;
+
+/* IO pin fields */
+#define IO_PIN_FMUX(v) ((v) << 7) /* pin function */
+#define IO_PIN_HOLD(v) ((v) << 5) /* hold time, pci only */
+#define IO_PIN_PUD(v) ((v) << 4) /* if PUE, 0=pull-down, 1=pull-up */
+#define IO_PIN_PUE(v) ((v) << 3) /* pull up/down enable */
+#define IO_PIN_ST(v) ((v) << 2) /* schmitt trigger */
+#define IO_PIN_DS(v) ((v)) /* slew rate */
+
+typedef struct iopin_t {
+ int p_offset; /* offset from IOCTL_MEM_OFFSET */
+ int nr_pins; /* number of pins to set this way */
+ int bit_or; /* or in the value instead of overwrite */
+ u_long val; /* value to write or or */
+}iopin_t;
+
+void iopin_initialize(iopin_t *,int);
+
+/*
+ * support to adjust individual parts of the IO pin setup
+ */
+
+#define IO_PIN_OVER_EACH (1 << 0) /* for compatibility */
+#define IO_PIN_OVER_FMUX (1 << 1)
+#define IO_PIN_OVER_HOLD (1 << 2)
+#define IO_PIN_OVER_PULL (1 << 3)
+#define IO_PIN_OVER_STRIG (1 << 4)
+#define IO_PIN_OVER_DRVSTR (1 << 5)
+
+void iopin_initialize_bits(iopin_t *, int);
+
+/*
+ * IIM
+ */
+typedef struct iim512x {
+ u32 stat; /* IIM status register */
+ u32 statm; /* IIM status IRQ mask */
+ u32 err; /* IIM errors register */
+ u32 emask; /* IIM error IRQ mask */
+ u32 fctl; /* IIM fuse control register */
+ u32 ua; /* IIM upper address register */
+ u32 la; /* IIM lower address register */
+ u32 sdat; /* IIM explicit sense data */
+ u8 res0[0x08];
+ u32 prg_p; /* IIM program protection register */
+ u8 res1[0x10];
+ u32 divide; /* IIM divide factor register */
+ u8 res2[0x7c0];
+ u32 fbac0; /* IIM fuse bank 0 prot (for Freescale use) */
+ u32 fb0w0[0x1f]; /* IIM fuse bank 0 data (for Freescale use) */
+ u8 res3[0x380];
+ u32 fbac1; /* IIM fuse bank 1 protection */
+ u32 fb1w1[0x01f]; /* IIM fuse bank 1 data */
+ u8 res4[0x380];
+} iim512x_t;
+
+/*
+ * LPC
+ */
+typedef struct lpc512x {
+ u32 cs_cfg[8]; /* Chip Select N Configuration Registers
+ No dedicated entry for CS Boot as == CS0 */
+ u32 cs_cr; /* Chip Select Control Register */
+ u32 cs_sr; /* Chip Select Status Register */
+ u32 cs_bcr; /* Chip Select Burst Control Register */
+ u32 cs_dccr; /* Chip Select Deadcycle Control Register */
+ u32 cs_hccr; /* Chip Select Holdcycle Control Register */
+ u32 altr; /* Address Latch Timing Register */
+ u8 res0[0xc8];
+ u32 sclpc_psr; /* SCLPC Packet Size Register */
+ u32 sclpc_sar; /* SCLPC Start Address Register */
+ u32 sclpc_cr; /* SCLPC Control Register */
+ u32 sclpc_er; /* SCLPC Enable Register */
+ u32 sclpc_nar; /* SCLPC NextAddress Register */
+ u32 sclpc_sr; /* SCLPC Status Register */
+ u32 sclpc_bdr; /* SCLPC Bytes Done Register */
+ u32 emb_scr; /* EMB Share Counter Register */
+ u32 emb_pcr; /* EMB Pause Control Register */
+ u8 res1[0x1c];
+ u32 lpc_fdwr; /* LPC RX/TX FIFO Data Word Register */
+ u32 lpc_fsr; /* LPC RX/TX FIFO Status Register */
+ u32 lpc_cr; /* LPC RX/TX FIFO Control Register */
+ u32 lpc_ar; /* LPC RX/TX FIFO Alarm Register */
+ u8 res2[0xb0];
+} lpc512x_t;
+
+/*
+ * PATA
+ */
+typedef struct pata512x {
+ /* LOCAL Registers */
+ u32 pata_time1; /* Time register 1: PIO and tx timing parameter */
+ u32 pata_time2; /* Time register 2: PIO timing parameter */
+ u32 pata_time3; /* Time register 3: PIO and MDMA timing parameter */
+ u32 pata_time4; /* Time register 4: MDMA and UDMA timing parameter */
+ u32 pata_time5; /* Time register 5: UDMA timing parameter */
+ u32 pata_time6; /* Time register 6: UDMA timing parameter */
+ u32 pata_fifo_data32; /* 32bit wide dataport to/from FIFO */
+ u32 pata_fifo_data16; /* 16bit wide dataport to/from FIFO */
+ u32 pata_fifo_fill; /* FIFO filling in halfwords (READONLY)*/
+ u32 pata_ata_control; /* ATA Interface control register */
+ u32 pata_irq_pending; /* Interrupt pending register (READONLY) */
+ u32 pata_irq_enable; /* Interrupt enable register */
+ u32 pata_irq_clear; /* Interrupt clear register (WRITEONLY)*/
+ u32 pata_fifo_alarm; /* fifo alarm threshold */
+ u32 res1[0x1A];
+ /* DRIVE Registers */
+ u32 pata_drive_data; /* drive data register*/
+ u32 pata_drive_features;/* drive features register */
+ u32 pata_drive_sectcnt; /* drive sector count register */
+ u32 pata_drive_sectnum; /* drive sector number register */
+ u32 pata_drive_cyllow; /* drive cylinder low register */
+ u32 pata_drive_cylhigh; /* drive cylinder high register */
+ u32 pata_drive_dev_head;/* drive device head register */
+ u32 pata_drive_command; /* write = drive command, read = drive status reg */
+ u32 res2[0x06];
+ u32 pata_drive_alt_stat;/* write = drive control, read = drive alt status reg */
+ u32 res3[0x09];
+} pata512x_t;
+
+/*
+ * PSC
+ */
+typedef struct psc512x {
+ volatile u8 mode; /* PSC + 0x00 */
+ volatile u8 res0[3];
+ union { /* PSC + 0x04 */
+ volatile u16 status;
+ volatile u16 clock_select;
+ } sr_csr;
+#define psc_status sr_csr.status
+#define psc_clock_select sr_csr.clock_select
+ volatile u16 res1;
+ volatile u8 command; /* PSC + 0x08 */
+ volatile u8 res2[3];
+ union { /* PSC + 0x0c */
+ volatile u8 buffer_8;
+ volatile u16 buffer_16;
+ volatile u32 buffer_32;
+ } buffer;
+#define psc_buffer_8 buffer.buffer_8
+#define psc_buffer_16 buffer.buffer_16
+#define psc_buffer_32 buffer.buffer_32
+ union { /* PSC + 0x10 */
+ volatile u8 ipcr;
+ volatile u8 acr;
+ } ipcr_acr;
+#define psc_ipcr ipcr_acr.ipcr
+#define psc_acr ipcr_acr.acr
+ volatile u8 res3[3];
+ union { /* PSC + 0x14 */
+ volatile u16 isr;
+ volatile u16 imr;
+ } isr_imr;
+#define psc_isr isr_imr.isr
+#define psc_imr isr_imr.imr
+ volatile u16 res4;
+ volatile u8 ctur; /* PSC + 0x18 */
+ volatile u8 res5[3];
+ volatile u8 ctlr; /* PSC + 0x1c */
+ volatile u8 res6[3];
+ volatile u32 ccr; /* PSC + 0x20 */
+ volatile u8 res7[12];
+ volatile u8 ivr; /* PSC + 0x30 */
+ volatile u8 res8[3];
+ volatile u8 ip; /* PSC + 0x34 */
+ volatile u8 res9[3];
+ volatile u8 op1; /* PSC + 0x38 */
+ volatile u8 res10[3];
+ volatile u8 op0; /* PSC + 0x3c */
+ volatile u8 res11[3];
+ volatile u32 sicr; /* PSC + 0x40 */
+ volatile u8 res12[60];
+ volatile u32 tfcmd; /* PSC + 0x80 */
+ volatile u32 tfalarm; /* PSC + 0x84 */
+ volatile u32 tfstat; /* PSC + 0x88 */
+ volatile u32 tfintstat; /* PSC + 0x8C */
+ volatile u32 tfintmask; /* PSC + 0x90 */
+ volatile u32 tfcount; /* PSC + 0x94 */
+ volatile u16 tfwptr; /* PSC + 0x98 */
+ volatile u16 tfrptr; /* PSC + 0x9A */
+ volatile u32 tfsize; /* PSC + 0x9C */
+ volatile u8 res13[28];
+ union { /* PSC + 0xBC */
+ volatile u8 buffer_8;
+ volatile u16 buffer_16;
+ volatile u32 buffer_32;
+ } tfdata_buffer;
+#define tfdata_8 tfdata_buffer.buffer_8
+#define tfdata_16 tfdata_buffer.buffer_16
+#define tfdata_32 tfdata_buffer.buffer_32
+
+ volatile u32 rfcmd; /* PSC + 0xC0 */
+ volatile u32 rfalarm; /* PSC + 0xC4 */
+ volatile u32 rfstat; /* PSC + 0xC8 */
+ volatile u32 rfintstat; /* PSC + 0xCC */
+ volatile u32 rfintmask; /* PSC + 0xD0 */
+ volatile u32 rfcount; /* PSC + 0xD4 */
+ volatile u16 rfwptr; /* PSC + 0xD8 */
+ volatile u16 rfrptr; /* PSC + 0xDA */
+ volatile u32 rfsize; /* PSC + 0xDC */
+ volatile u8 res18[28];
+ union { /* PSC + 0xFC */
+ volatile u8 buffer_8;
+ volatile u16 buffer_16;
+ volatile u32 buffer_32;
+ } rfdata_buffer;
+#define rfdata_8 rfdata_buffer.buffer_8
+#define rfdata_16 rfdata_buffer.buffer_16
+#define rfdata_32 rfdata_buffer.buffer_32
+} psc512x_t;
+
+/* PSC FIFO Command values */
+#define PSC_FIFO_RESET_SLICE 0x80
+#define PSC_FIFO_ENABLE_SLICE 0x01
+
+/* PSC FIFO Controller Command values */
+#define FIFOC_ENABLE_CLOCK_GATE 0x01
+#define FIFOC_DISABLE_CLOCK_GATE 0x00
+
+/* PSC FIFO status */
+#define PSC_FIFO_EMPTY 0x01
+
+/* PSC Command values */
+#define PSC_RX_ENABLE 0x01
+#define PSC_RX_DISABLE 0x02
+#define PSC_TX_ENABLE 0x04
+#define PSC_TX_DISABLE 0x08
+#define PSC_SEL_MODE_REG_1 0x10
+#define PSC_RST_RX 0x20
+#define PSC_RST_TX 0x30
+#define PSC_RST_ERR_STAT 0x40
+#define PSC_RST_BRK_CHG_INT 0x50
+#define PSC_START_BRK 0x60
+#define PSC_STOP_BRK 0x70
+
+/* PSC status register bits */
+#define PSC_SR_CDE 0x0080
+#define PSC_SR_TXEMP 0x0800
+#define PSC_SR_OE 0x1000
+#define PSC_SR_PE 0x2000
+#define PSC_SR_FE 0x4000
+#define PSC_SR_RB 0x8000
+
+/* PSC mode fields */
+#define PSC_MODE_5_BITS 0x00
+#define PSC_MODE_6_BITS 0x01
+#define PSC_MODE_7_BITS 0x02
+#define PSC_MODE_8_BITS 0x03
+#define PSC_MODE_PAREVEN 0x00
+#define PSC_MODE_PARODD 0x04
+#define PSC_MODE_PARFORCE 0x08
+#define PSC_MODE_PARNONE 0x10
+#define PSC_MODE_ENTIMEOUT 0x20
+#define PSC_MODE_RXRTS 0x80
+#define PSC_MODE_1_STOPBIT 0x07
+
+/*
+ * FIFOC
+ */
+typedef struct fifoc512x {
+ u32 fifoc_cmd;
+ u32 fifoc_int;
+ u32 fifoc_dma;
+ u32 fifoc_axe;
+ u32 fifoc_debug;
+ u8 fixme[0xEC];
+} fifoc512x_t;
+
+/*
+ * Centralized FIFO Controller has internal memory for all 12 PSCs FIFOs
+ *
+ * NOTE: individual PSC units are free to use whatever area (and size) of the
+ * FIFOC internal memory, so make sure memory areas for FIFO slices used by
+ * different PSCs do not overlap!
+ *
+ * Overall size of FIFOC memory is not documented in the MPC5121e RM, but
+ * tests indicate that it is 1024 words total.
+ *
+ * *_TX_SIZE and *_RX_SIZE is the number of 4-byte words for FIFO slice.
+ */
+#define FIFOC_PSC0_TX_SIZE 0x04
+#define FIFOC_PSC0_TX_ADDR 0x0
+#define FIFOC_PSC0_RX_SIZE 0x04
+#define FIFOC_PSC0_RX_ADDR 0x10
+
+#define FIFOC_PSC1_TX_SIZE 0x04
+#define FIFOC_PSC1_TX_ADDR 0x20
+#define FIFOC_PSC1_RX_SIZE 0x04
+#define FIFOC_PSC1_RX_ADDR 0x30
+
+#define FIFOC_PSC2_TX_SIZE 0x04
+#define FIFOC_PSC2_TX_ADDR 0x40
+#define FIFOC_PSC2_RX_SIZE 0x04
+#define FIFOC_PSC2_RX_ADDR 0x50
+
+#define FIFOC_PSC3_TX_SIZE 0x04
+#define FIFOC_PSC3_TX_ADDR 0x60
+#define FIFOC_PSC3_RX_SIZE 0x04
+#define FIFOC_PSC3_RX_ADDR 0x70
+
+#define FIFOC_PSC4_TX_SIZE 0x04
+#define FIFOC_PSC4_TX_ADDR 0x80
+#define FIFOC_PSC4_RX_SIZE 0x04
+#define FIFOC_PSC4_RX_ADDR 0x90
+
+#define FIFOC_PSC5_TX_SIZE 0x04
+#define FIFOC_PSC5_TX_ADDR 0xa0
+#define FIFOC_PSC5_RX_SIZE 0x04
+#define FIFOC_PSC5_RX_ADDR 0xb0
+
+#define FIFOC_PSC6_TX_SIZE 0x04
+#define FIFOC_PSC6_TX_ADDR 0xc0
+#define FIFOC_PSC6_RX_SIZE 0x04
+#define FIFOC_PSC6_RX_ADDR 0xd0
+
+#define FIFOC_PSC7_TX_SIZE 0x04
+#define FIFOC_PSC7_TX_ADDR 0xe0
+#define FIFOC_PSC7_RX_SIZE 0x04
+#define FIFOC_PSC7_RX_ADDR 0xf0
+
+#define FIFOC_PSC8_TX_SIZE 0x04
+#define FIFOC_PSC8_TX_ADDR 0x100
+#define FIFOC_PSC8_RX_SIZE 0x04
+#define FIFOC_PSC8_RX_ADDR 0x110
+
+#define FIFOC_PSC9_TX_SIZE 0x04
+#define FIFOC_PSC9_TX_ADDR 0x120
+#define FIFOC_PSC9_RX_SIZE 0x04
+#define FIFOC_PSC9_RX_ADDR 0x130
+
+#define FIFOC_PSC10_TX_SIZE 0x04
+#define FIFOC_PSC10_TX_ADDR 0x140
+#define FIFOC_PSC10_RX_SIZE 0x04
+#define FIFOC_PSC10_RX_ADDR 0x150
+
+#define FIFOC_PSC11_TX_SIZE 0x04
+#define FIFOC_PSC11_TX_ADDR 0x160
+#define FIFOC_PSC11_RX_SIZE 0x04
+#define FIFOC_PSC11_RX_ADDR 0x170
+
+/*
+ * SATA
+ */
+typedef struct sata512x {
+ u8 fixme[0x2000];
+} sata512x_t;
+
+typedef struct immap {
+ sysconf512x_t sysconf; /* System configuration */
+ u8 res0[0x700];
+ wdt512x_t wdt; /* Watch Dog Timer (WDT) */
+ rtclk512x_t rtc; /* Real Time Clock Module */
+ gpt512x_t gpt; /* General Purpose Timer */
+ ipic512x_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter512x_t arbiter; /* CSB Arbiter */
+ reset512x_t reset; /* Reset Module */
+ clk512x_t clk; /* Clock Module */
+ pmc512x_t pmc; /* Power Management Control Module */
+ gpio512x_t gpio; /* General purpose I/O module */
+ u8 res1[0x100];
+ mscan512x_t mscan; /* MSCAN */
+ bdlc512x_t bdlc; /* BDLC */
+ sdhc512x_t sdhc; /* SDHC */
+ spdif512x_t spdif; /* SPDIF */
+ i2c512x_t i2c; /* I2C Controllers */
+ u8 res2[0x800];
+ axe512x_t axe; /* AXE */
+ diu512x_t diu; /* Display Interface Unit */
+ cfm512x_t cfm; /* Clock Frequency Measurement */
+ u8 res3[0x500];
+ fec512x_t fec; /* Fast Ethernet Controller */
+ ulpi512x_t ulpi; /* USB ULPI */
+ u8 res4[0xa00];
+ utmi512x_t utmi; /* USB UTMI */
+ u8 res5[0x1000];
+ pcidma512x_t pci_dma; /* PCI DMA */
+ pciconf512x_t pci_conf; /* PCI Configuration */
+ u8 res6[0x80];
+ ios512x_t ios; /* PCI Sequencer */
+ pcictrl512x_t pci_ctrl; /* PCI Controller Control and Status */
+ u8 res7[0xa00];
+ ddr512x_t mddrc; /* Multi-port DDR Memory Controller */
+ ioctrl512x_t io_ctrl; /* IO Control */
+ iim512x_t iim; /* IC Identification module */
+ u8 res8[0x4000];
+ lpc512x_t lpc; /* LocalPlus Controller */
+ pata512x_t pata; /* Parallel ATA */
+ u8 res9[0xd00];
+ psc512x_t psc[12]; /* PSCs */
+ u8 res10[0x300];
+ fifoc512x_t fifoc; /* FIFO Controller */
+ u8 res11[0x2000];
+ dma512x_t dma; /* DMA */
+ u8 res12[0xa800];
+ sata512x_t sata; /* Serial ATA */
+ u8 res13[0xde000];
+} immap_t;
+
+/* provide interface to get PATA base address */
+static inline u32 get_pata_base (void)
+{
+ volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
+ return (u32)(&im->pata);
+}
+#endif /* __ASSEMBLY__ */
+
+#define CONFIG_SYS_MPC512x_USB_OFFSET 0x4000
+#define CONFIG_SYS_MPC512x_USB_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC512x_USB_OFFSET)
+
+#define IIM_BASE_ADDR (CONFIG_SYS_IMMR + offsetof(immap_t, iim))
+
+#endif /* __IMMAP_512x__ */
diff --git a/arch/powerpc/include/asm/immap_8260.h b/arch/powerpc/include/asm/immap_8260.h
new file mode 100644
index 0000000..c7021a7
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_8260.h
@@ -0,0 +1,604 @@
+/*
+ * MPC8260 Internal Memory Map
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
+ *
+ * The Internal Memory Map of the 8260. I don't know how generic
+ * this will be, as I don't have any knowledge of the subsequent
+ * parts at this time. I copied this from the 8xx_immap.h.
+ */
+#ifndef __IMMAP_82XX__
+#define __IMMAP_82XX__
+
+/* System configuration registers.
+*/
+typedef struct sys_conf {
+ uint sc_siumcr;
+ uint sc_sypcr;
+ char res1[6];
+ ushort sc_swsr;
+ char res2[20];
+ uint sc_bcr;
+ u_char sc_ppc_acr;
+ char res3[3];
+ uint sc_ppc_alrh;
+ uint sc_ppc_alrl;
+ u_char sc_lcl_acr;
+ char res4[3];
+ uint sc_lcl_alrh;
+ uint sc_lcl_alrl;
+ uint sc_tescr1;
+ uint sc_tescr2;
+ uint sc_ltescr1;
+ uint sc_ltescr2;
+ uint sc_pdtea;
+ u_char sc_pdtem;
+ char res5[3];
+ uint sc_ldtea;
+ u_char sc_ldtem;
+ char res6[163];
+} sysconf8260_t;
+
+
+/* Memory controller registers.
+*/
+typedef struct mem_ctlr {
+ uint memc_br0;
+ uint memc_or0;
+ uint memc_br1;
+ uint memc_or1;
+ uint memc_br2;
+ uint memc_or2;
+ uint memc_br3;
+ uint memc_or3;
+ uint memc_br4;
+ uint memc_or4;
+ uint memc_br5;
+ uint memc_or5;
+ uint memc_br6;
+ uint memc_or6;
+ uint memc_br7;
+ uint memc_or7;
+ uint memc_br8;
+ uint memc_or8;
+ uint memc_br9;
+ uint memc_or9;
+ uint memc_br10;
+ uint memc_or10;
+ uint memc_br11;
+ uint memc_or11;
+ char res1[8];
+ uint memc_mar;
+ char res2[4];
+ uint memc_mamr;
+ uint memc_mbmr;
+ uint memc_mcmr;
+ char res3[8];
+ ushort memc_mptpr;
+ char res4[2];
+ uint memc_mdr;
+ char res5[4];
+ uint memc_psdmr;
+ uint memc_lsdmr;
+ u_char memc_purt;
+ char res6[3];
+ u_char memc_psrt;
+ char res7[3];
+ u_char memc_lurt;
+ char res8[3];
+ u_char memc_lsrt;
+ char res9[3];
+ uint memc_immr;
+ uint memc_pcibr0;
+ uint memc_pcibr1;
+ char res10[16];
+ uint memc_pcimsk0;
+ uint memc_pcimsk1;
+ char res11[52];
+} memctl8260_t;
+
+/* System Integration Timers.
+*/
+typedef struct sys_int_timers {
+ char res1[32];
+ ushort sit_tmcntsc;
+ char res2[2];
+ uint sit_tmcnt;
+ char res3[4];
+ uint sit_tmcntal;
+ char res4[16];
+ ushort sit_piscr;
+ char res5[2];
+ uint sit_pitc;
+ uint sit_pitr;
+ char res6[94];
+ char res7[390];
+} sit8260_t;
+
+/* PCI
+ */
+typedef struct pci_config {
+ uint pci_omisr;
+ uint pci_ominr;
+ char res1[8];
+ uint pci_ifqpr;
+ uint pci_ofqpr;
+ char res2[8];
+ uint pci_imr0;
+ uint pci_imr1;
+ uint pci_omr0;
+ uint pci_omr1;
+ uint pci_odr;
+ char res3[4];
+ uint pci_idr;
+ char res4[20];
+ uint pci_imisr;
+ uint pci_imimr;
+ char res5[24];
+ uint pci_ifhpr;
+ char res5_2[4];
+ uint pci_iftpr;
+ char res6[4];
+ uint pci_iphpr;
+ char res6_2[4];
+ uint pci_iptpr;
+ char res7[4];
+ uint pci_ofhpr;
+ char res7_2[4];
+ uint pci_oftpr;
+ char res8[4];
+ uint pci_ophpr;
+ char res8_2[4];
+ uint pci_optpr;
+ char res9[8];
+ uint pci_mucr;
+ char res10[8];
+ uint pci_qbar;
+ char res11[12];
+ uint pci_dmamr0;
+ uint pci_dmasr0;
+ uint pci_dmacdar0;
+ char res12[4];
+ uint pci_dmasar0;
+ char res13[4];
+ uint pci_dmadar0;
+ char res14[4];
+ uint pci_dmabcr0;
+ uint pci_dmandar0;
+ char res15[88];
+ uint pci_dmamr1;
+ uint pci_dmasr1;
+ uint pci_dmacdar1;
+ char res16[4];
+ uint pci_dmasar1;
+ char res17[4];
+ uint pci_dmadar1;
+ char res18[4];
+ uint pci_dmabcr1;
+ uint pci_dmandar1;
+ char res19[88];
+ uint pci_dmamr2;
+ uint pci_dmasr2;
+ uint pci_dmacdar2;
+ char res20[4];
+ uint pci_dmasar2;
+ char res21[4];
+ uint pci_dmadar2;
+ char res22[4];
+ uint pci_dmabcr2;
+ uint pci_dmandar2;
+ char res23[88];
+ uint pci_dmamr3;
+ uint pci_dmasr3;
+ uint pci_dmacdar3;
+ char res24[4];
+ uint pci_dmasar3;
+ char res25[4];
+ uint pci_dmadar3;
+ char res26[4];
+ uint pci_dmabcr3;
+ uint pci_dmandar3;
+ char res27[344];
+ uint pci_potar0;
+ char res28[4];
+ uint pci_pobar0;
+ char res29[4];
+ uint pci_pocmr0;
+ char res30[4];
+ uint pci_potar1;
+ char res31[4];
+ uint pci_pobar1;
+ char res32[4];
+ uint pci_pocmr1;
+ char res33[4];
+ uint pci_potar2;
+ char res34[4];
+ uint pci_pobar2;
+ char res35[4];
+ uint pci_pocmr2;
+ char res36[52];
+ uint pci_ptcr;
+ uint pci_gpcr;
+ uint pci_gcr;
+ uint pci_esr;
+ uint pci_emr;
+ uint pci_ecr;
+ uint pci_eacr;
+ char res37[4];
+ uint pci_edcr;
+ char res38[4];
+ uint pci_eccr;
+ char res39[44];
+ uint pci_pitar1;
+ char res40[4];
+ uint pci_pibar1;
+ char res41[4];
+ uint pci_picmr1;
+ char res42[4];
+ uint pci_pitar0;
+ char res43[4];
+ uint pci_pibar0;
+ char res44[4];
+ uint pci_picmr0;
+ char res45[4];
+ uint pci_cfg_addr;
+ uint pci_cfg_data;
+ uint pci_int_ack;
+ char res46[756];
+}pci8260_t;
+#define PISCR_PIRQ_MASK ((ushort)0xff00)
+#define PISCR_PS ((ushort)0x0080)
+#define PISCR_PIE ((ushort)0x0004)
+#define PISCR_PTF ((ushort)0x0002)
+#define PISCR_PTE ((ushort)0x0001)
+
+/* Interrupt Controller.
+*/
+typedef struct interrupt_controller {
+ ushort ic_sicr;
+ char res1[2];
+ uint ic_sivec;
+ uint ic_sipnrh;
+ uint ic_sipnrl;
+ uint ic_siprr;
+ uint ic_scprrh;
+ uint ic_scprrl;
+ uint ic_simrh;
+ uint ic_simrl;
+ uint ic_siexr;
+ char res2[88];
+} intctl8260_t;
+
+/* Clocks and Reset.
+*/
+typedef struct clk_and_reset {
+ uint car_sccr;
+ char res1[4];
+ uint car_scmr;
+ char res2[4];
+ uint car_rsr;
+ uint car_rmr;
+ char res[104];
+} car8260_t;
+
+/* Input/Output Port control/status registers.
+ * Names consistent with processor manual, although they are different
+ * from the original 8xx names.......
+ */
+typedef struct io_port {
+ uint iop_pdira;
+ uint iop_ppara;
+ uint iop_psora;
+ uint iop_podra;
+ uint iop_pdata;
+ char res1[12];
+ uint iop_pdirb;
+ uint iop_pparb;
+ uint iop_psorb;
+ uint iop_podrb;
+ uint iop_pdatb;
+ char res2[12];
+ uint iop_pdirc;
+ uint iop_pparc;
+ uint iop_psorc;
+ uint iop_podrc;
+ uint iop_pdatc;
+ char res3[12];
+ uint iop_pdird;
+ uint iop_ppard;
+ uint iop_psord;
+ uint iop_podrd;
+ uint iop_pdatd;
+ char res4[12];
+} iop8260_t;
+
+/* Communication Processor Module Timers
+*/
+typedef struct cpm_timers {
+ u_char cpmt_tgcr1;
+ char res1[3];
+ u_char cpmt_tgcr2;
+ char res2[11];
+ ushort cpmt_tmr1;
+ ushort cpmt_tmr2;
+ ushort cpmt_trr1;
+ ushort cpmt_trr2;
+ ushort cpmt_tcr1;
+ ushort cpmt_tcr2;
+ ushort cpmt_tcn1;
+ ushort cpmt_tcn2;
+ ushort cpmt_tmr3;
+ ushort cpmt_tmr4;
+ ushort cpmt_trr3;
+ ushort cpmt_trr4;
+ ushort cpmt_tcr3;
+ ushort cpmt_tcr4;
+ ushort cpmt_tcn3;
+ ushort cpmt_tcn4;
+ ushort cpmt_ter1;
+ ushort cpmt_ter2;
+ ushort cpmt_ter3;
+ ushort cpmt_ter4;
+ char res3[584];
+} cpmtimer8260_t;
+
+/* DMA control/status registers.
+*/
+typedef struct sdma_csr {
+ char res0[24];
+ u_char sdma_sdsr;
+ char res1[3];
+ u_char sdma_sdmr;
+ char res2[3];
+ u_char sdma_idsr1;
+ char res3[3];
+ u_char sdma_idmr1;
+ char res4[3];
+ u_char sdma_idsr2;
+ char res5[3];
+ u_char sdma_idmr2;
+ char res6[3];
+ u_char sdma_idsr3;
+ char res7[3];
+ u_char sdma_idmr3;
+ char res8[3];
+ u_char sdma_idsr4;
+ char res9[3];
+ u_char sdma_idmr4;
+ char res10[707];
+} sdma8260_t;
+
+/* Fast controllers
+*/
+typedef struct fcc {
+ uint fcc_gfmr;
+ uint fcc_fpsmr;
+ ushort fcc_ftodr;
+ char res1[2];
+ ushort fcc_fdsr;
+ char res2[2];
+ ushort fcc_fcce;
+ char res3[2];
+ ushort fcc_fccm;
+ char res4[2];
+ u_char fcc_fccs;
+ char res5[3];
+ u_char fcc_ftirr_phy[4];
+} fcc_t;
+
+/* Fast controllers continued
+ */
+typedef struct fcc_c {
+ uint fcc_firper;
+ uint fcc_firer;
+ uint fcc_firsr_hi;
+ uint fcc_firsr_lo;
+ u_char fcc_gfemr;
+ char res1[15];
+} fcc_c_t;
+
+/* TC Layer
+ */
+typedef struct tclayer {
+ ushort tc_tcmode;
+ ushort tc_cdsmr;
+ ushort tc_tcer;
+ ushort tc_rcc;
+ ushort tc_tcmr;
+ ushort tc_fcc;
+ ushort tc_ccc;
+ ushort tc_icc;
+ ushort tc_tcc;
+ ushort tc_ecc;
+ char res1[12];
+} tclayer_t;
+
+/* I2C
+*/
+typedef struct i2c {
+ u_char i2c_i2mod;
+ char res1[3];
+ u_char i2c_i2add;
+ char res2[3];
+ u_char i2c_i2brg;
+ char res3[3];
+ u_char i2c_i2com;
+ char res4[3];
+ u_char i2c_i2cer;
+ char res5[3];
+ u_char i2c_i2cmr;
+ char res6[331];
+} i2c8260_t;
+
+typedef struct scc { /* Serial communication channels */
+ uint scc_gsmrl;
+ uint scc_gsmrh;
+ ushort scc_psmr;
+ char res1[2];
+ ushort scc_todr;
+ ushort scc_dsr;
+ ushort scc_scce;
+ char res2[2];
+ ushort scc_sccm;
+ char res3;
+ u_char scc_sccs;
+ char res4[8];
+} scc_t;
+
+typedef struct smc { /* Serial management channels */
+ char res1[2];
+ ushort smc_smcmr;
+ char res2[2];
+ u_char smc_smce;
+ char res3[3];
+ u_char smc_smcm;
+ char res4[5];
+} smc_t;
+
+/* Serial Peripheral Interface.
+*/
+typedef struct im_spi {
+ ushort spi_spmode;
+ char res1[4];
+ u_char spi_spie;
+ char res2[3];
+ u_char spi_spim;
+ char res3[2];
+ u_char spi_spcom;
+ char res4[82];
+} im_spi_t;
+
+/* CPM Mux.
+*/
+typedef struct cpmux {
+ u_char cmx_si1cr;
+ char res1;
+ u_char cmx_si2cr;
+ char res2;
+ uint cmx_fcr;
+ uint cmx_scr;
+ u_char cmx_smr;
+ char res3;
+ ushort cmx_uar;
+ char res4[16];
+} cpmux_t;
+
+/* SIRAM control
+*/
+typedef struct siram {
+ ushort si_amr;
+ ushort si_bmr;
+ ushort si_cmr;
+ ushort si_dmr;
+ u_char si_gmr;
+ char res1;
+ u_char si_cmdr;
+ char res2;
+ u_char si_str;
+ char res3;
+ ushort si_rsr;
+} siramctl_t;
+
+typedef struct mcc {
+ ushort mcc_mcce;
+ char res1[2];
+ ushort mcc_mccm;
+ char res2[2];
+ u_char mcc_mccf;
+ char res3[7];
+} mcc_t;
+
+typedef struct comm_proc {
+ uint cp_cpcr;
+ uint cp_rccr;
+ char res1[14];
+ ushort cp_rter;
+ char res2[2];
+ ushort cp_rtmr;
+ ushort cp_rtscr;
+ char res3[2];
+ uint cp_rtsr;
+ char res4[12];
+} cpm8260_t;
+
+/* ...and the whole thing wrapped up....
+*/
+typedef struct immap {
+ /* Some references are into the unique and known dpram spaces,
+ * others are from the generic base.
+ */
+ union {
+ struct {
+ u_char im_dpram1[16 * 1024];
+ char res1[16 * 1024];
+ u_char im_dpram2[4 * 1024];
+ char res2[8 * 1024];
+ u_char im_dpram3[4 * 1024];
+ char res3[16 * 1024];
+ };
+ u8 im_dprambase[64 * 1024];
+ u16 im_dprambase16[32 * 1024];
+ };
+
+ sysconf8260_t im_siu_conf; /* SIU Configuration */
+ memctl8260_t im_memctl; /* Memory Controller */
+ sit8260_t im_sit; /* System Integration Timers */
+ pci8260_t im_pci; /* PCI Configuration */
+ intctl8260_t im_intctl; /* Interrupt Controller */
+ car8260_t im_clkrst; /* Clocks and reset */
+ iop8260_t im_ioport; /* IO Port control/status */
+ cpmtimer8260_t im_cpmtimer; /* CPM timers */
+ sdma8260_t im_sdma; /* SDMA control/status */
+
+ fcc_t im_fcc[3]; /* Three FCCs */
+
+ char res4[32];
+ fcc_c_t im_fcc_c[3]; /* Continued FCCs */
+ char res4a[32];
+
+ tclayer_t im_tclayer[8]; /* Eight TCLayers */
+ ushort tc_tcgsr;
+ ushort tc_tcger;
+
+ /* First set of baud rate generators.
+ */
+ char res4b[236];
+ uint im_brgc5;
+ uint im_brgc6;
+ uint im_brgc7;
+ uint im_brgc8;
+
+ char res5[608];
+
+ i2c8260_t im_i2c; /* I2C control/status */
+ cpm8260_t im_cpm; /* Communication processor */
+
+ /* Second set of baud rate generators.
+ */
+ uint im_brgc1;
+ uint im_brgc2;
+ uint im_brgc3;
+ uint im_brgc4;
+
+ scc_t im_scc[4]; /* Four SCCs */
+ smc_t im_smc[2]; /* Couple of SMCs */
+ im_spi_t im_spi; /* A SPI */
+ cpmux_t im_cpmux; /* CPM clock route mux */
+ siramctl_t im_siramctl1; /* First SI RAM Control */
+ mcc_t im_mcc1; /* First MCC */
+ siramctl_t im_siramctl2; /* Second SI RAM Control */
+ mcc_t im_mcc2; /* Second MCC */
+
+ char res6[1184];
+
+ ushort im_si1txram[256];
+ char res7[512];
+ ushort im_si1rxram[256];
+ char res8[512];
+ ushort im_si2txram[256];
+ char res9[512];
+ ushort im_si2rxram[256];
+ char res10[512];
+ char res11[4096];
+} immap_t;
+
+#endif /* __IMMAP_82XX__ */
diff --git a/arch/powerpc/include/asm/immap_83xx.h b/arch/powerpc/include/asm/immap_83xx.h
new file mode 100644
index 0000000..8ac13fc
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_83xx.h
@@ -0,0 +1,1060 @@
+/*
+ * Copyright 2004-2011 Freescale Semiconductor, Inc.
+ *
+ * MPC83xx Internal Memory Map
+ *
+ * Contributors:
+ * Dave Liu <daveliu@freescale.com>
+ * Tanya Jiang <tanya.jiang@freescale.com>
+ * Mandy Lavi <mandy.lavi@freescale.com>
+ * Eran Liberty <liberty@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#ifndef __IMMAP_83xx__
+#define __IMMAP_83xx__
+
+#include <asm/types.h>
+#include <asm/fsl_i2c.h>
+#include <asm/mpc8xxx_spi.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_dma.h>
+
+/*
+ * Local Access Window
+ */
+typedef struct law83xx {
+ u32 bar; /* LBIU local access window base address register */
+ u32 ar; /* LBIU local access window attribute register */
+} law83xx_t;
+
+/*
+ * System configuration registers
+ */
+typedef struct sysconf83xx {
+ u32 immrbar; /* Internal memory map base address register */
+ u8 res0[0x04];
+ u32 altcbar; /* Alternate configuration base address register */
+ u8 res1[0x14];
+ law83xx_t lblaw[4]; /* LBIU local access window */
+ u8 res2[0x20];
+ law83xx_t pcilaw[2]; /* PCI local access window */
+ u8 res3[0x10];
+ law83xx_t pcielaw[2]; /* PCI Express local access window */
+ u8 res4[0x10];
+ law83xx_t ddrlaw[2]; /* DDR local access window */
+ u8 res5[0x50];
+ u32 sgprl; /* System General Purpose Register Low */
+ u32 sgprh; /* System General Purpose Register High */
+ u32 spridr; /* System Part and Revision ID Register */
+ u8 res6[0x04];
+ u32 spcr; /* System Priority Configuration Register */
+ u32 sicrl; /* System I/O Configuration Register Low */
+ u32 sicrh; /* System I/O Configuration Register High */
+ u8 res7[0x04];
+ u32 sidcr0; /* System I/O Delay Configuration Register 0 */
+ u32 sidcr1; /* System I/O Delay Configuration Register 1 */
+ u32 ddrcdr; /* DDR Control Driver Register */
+ u32 ddrdsr; /* DDR Debug Status Register */
+ u32 obir; /* Output Buffer Impedance Register */
+ u8 res8[0xC];
+ u32 pecr1; /* PCI Express control register 1 */
+#if defined(CONFIG_MPC830x)
+ u32 sdhccr; /* eSDHC Control Registers for MPC830x */
+#else
+ u32 pecr2; /* PCI Express control register 2 */
+#endif
+#if defined(CONFIG_MPC8309)
+ u32 can_dbg_ctrl;
+ u32 res9a;
+ u32 gpr1;
+ u8 res9b[0xAC];
+#else
+ u8 res9[0xB8];
+#endif
+} sysconf83xx_t;
+
+/*
+ * Watch Dog Timer (WDT) Registers
+ */
+typedef struct wdt83xx {
+ u8 res0[4];
+ u32 swcrr; /* System watchdog control register */
+ u32 swcnr; /* System watchdog count register */
+ u8 res1[2];
+ u16 swsrr; /* System watchdog service register */
+ u8 res2[0xF0];
+} wdt83xx_t;
+
+/*
+ * RTC/PIT Module Registers
+ */
+typedef struct rtclk83xx {
+ u32 cnr; /* control register */
+ u32 ldr; /* load register */
+ u32 psr; /* prescale register */
+ u32 ctr; /* counter value field register */
+ u32 evr; /* event register */
+ u32 alr; /* alarm register */
+ u8 res0[0xE8];
+} rtclk83xx_t;
+
+/*
+ * Global timer module
+ */
+typedef struct gtm83xx {
+ u8 cfr1; /* Timer1/2 Configuration */
+ u8 res0[3];
+ u8 cfr2; /* Timer3/4 Configuration */
+ u8 res1[11];
+ u16 mdr1; /* Timer1 Mode Register */
+ u16 mdr2; /* Timer2 Mode Register */
+ u16 rfr1; /* Timer1 Reference Register */
+ u16 rfr2; /* Timer2 Reference Register */
+ u16 cpr1; /* Timer1 Capture Register */
+ u16 cpr2; /* Timer2 Capture Register */
+ u16 cnr1; /* Timer1 Counter Register */
+ u16 cnr2; /* Timer2 Counter Register */
+ u16 mdr3; /* Timer3 Mode Register */
+ u16 mdr4; /* Timer4 Mode Register */
+ u16 rfr3; /* Timer3 Reference Register */
+ u16 rfr4; /* Timer4 Reference Register */
+ u16 cpr3; /* Timer3 Capture Register */
+ u16 cpr4; /* Timer4 Capture Register */
+ u16 cnr3; /* Timer3 Counter Register */
+ u16 cnr4; /* Timer4 Counter Register */
+ u16 evr1; /* Timer1 Event Register */
+ u16 evr2; /* Timer2 Event Register */
+ u16 evr3; /* Timer3 Event Register */
+ u16 evr4; /* Timer4 Event Register */
+ u16 psr1; /* Timer1 Prescaler Register */
+ u16 psr2; /* Timer2 Prescaler Register */
+ u16 psr3; /* Timer3 Prescaler Register */
+ u16 psr4; /* Timer4 Prescaler Register */
+ u8 res[0xC0];
+} gtm83xx_t;
+
+/*
+ * Integrated Programmable Interrupt Controller
+ */
+typedef struct ipic83xx {
+ u32 sicfr; /* System Global Interrupt Configuration Register */
+ u32 sivcr; /* System Global Interrupt Vector Register */
+ u32 sipnr_h; /* System Internal Interrupt Pending Register - High */
+ u32 sipnr_l; /* System Internal Interrupt Pending Register - Low */
+ u32 siprr_a; /* System Internal Interrupt Group A Priority Register */
+ u32 siprr_b; /* System Internal Interrupt Group B Priority Register */
+ u32 siprr_c; /* System Internal Interrupt Group C Priority Register */
+ u32 siprr_d; /* System Internal Interrupt Group D Priority Register */
+ u32 simsr_h; /* System Internal Interrupt Mask Register - High */
+ u32 simsr_l; /* System Internal Interrupt Mask Register - Low */
+ u32 sicnr; /* System Internal Interrupt Control Register */
+ u32 sepnr; /* System External Interrupt Pending Register */
+ u32 smprr_a; /* System Mixed Interrupt Group A Priority Register */
+ u32 smprr_b; /* System Mixed Interrupt Group B Priority Register */
+ u32 semsr; /* System External Interrupt Mask Register */
+ u32 secnr; /* System External Interrupt Control Register */
+ u32 sersr; /* System Error Status Register */
+ u32 sermr; /* System Error Mask Register */
+ u32 sercr; /* System Error Control Register */
+ u32 sepcr; /* System External Interrupt Polarity Control Register */
+ u32 sifcr_h; /* System Internal Interrupt Force Register - High */
+ u32 sifcr_l; /* System Internal Interrupt Force Register - Low */
+ u32 sefcr; /* System External Interrupt Force Register */
+ u32 serfr; /* System Error Force Register */
+ u32 scvcr; /* System Critical Interrupt Vector Register */
+ u32 smvcr; /* System Management Interrupt Vector Register */
+ u8 res[0x98];
+} ipic83xx_t;
+
+/*
+ * System Arbiter Registers
+ */
+typedef struct arbiter83xx {
+ u32 acr; /* Arbiter Configuration Register */
+ u32 atr; /* Arbiter Timers Register */
+ u8 res[4];
+ u32 aer; /* Arbiter Event Register */
+ u32 aidr; /* Arbiter Interrupt Definition Register */
+ u32 amr; /* Arbiter Mask Register */
+ u32 aeatr; /* Arbiter Event Attributes Register */
+ u32 aeadr; /* Arbiter Event Address Register */
+ u32 aerr; /* Arbiter Event Response Register */
+ u8 res1[0xDC];
+} arbiter83xx_t;
+
+/*
+ * Reset Module
+ */
+typedef struct reset83xx {
+ u32 rcwl; /* Reset Configuration Word Low Register */
+ u32 rcwh; /* Reset Configuration Word High Register */
+ u8 res0[8];
+ u32 rsr; /* Reset Status Register */
+ u32 rmr; /* Reset Mode Register */
+ u32 rpr; /* Reset protection Register */
+ u32 rcr; /* Reset Control Register */
+ u32 rcer; /* Reset Control Enable Register */
+ u8 res1[0xDC];
+} reset83xx_t;
+
+/*
+ * Clock Module
+ */
+typedef struct clk83xx {
+ u32 spmr; /* system PLL mode Register */
+ u32 occr; /* output clock control Register */
+ u32 sccr; /* system clock control Register */
+ u8 res0[0xF4];
+} clk83xx_t;
+
+/*
+ * Power Management Control Module
+ */
+typedef struct pmc83xx {
+ u32 pmccr; /* PMC Configuration Register */
+ u32 pmcer; /* PMC Event Register */
+ u32 pmcmr; /* PMC Mask Register */
+ u32 pmccr1; /* PMC Configuration Register 1 */
+ u32 pmccr2; /* PMC Configuration Register 2 */
+ u8 res0[0xEC];
+} pmc83xx_t;
+
+/*
+ * General purpose I/O module
+ */
+typedef struct gpio83xx {
+ u32 dir; /* direction register */
+ u32 odr; /* open drain register */
+ u32 dat; /* data register */
+ u32 ier; /* interrupt event register */
+ u32 imr; /* interrupt mask register */
+ u32 icr; /* external interrupt control register */
+ u8 res0[0xE8];
+} gpio83xx_t;
+
+/*
+ * QE Ports Interrupts Registers
+ */
+typedef struct qepi83xx {
+ u8 res0[0xC];
+ u32 qepier; /* QE Ports Interrupt Event Register */
+ u32 qepimr; /* QE Ports Interrupt Mask Register */
+ u32 qepicr; /* QE Ports Interrupt Control Register */
+ u8 res1[0xE8];
+} qepi83xx_t;
+
+/*
+ * QE Parallel I/O Ports
+ */
+typedef struct gpio_n {
+ u32 podr; /* Open Drain Register */
+ u32 pdat; /* Data Register */
+ u32 dir1; /* direction register 1 */
+ u32 dir2; /* direction register 2 */
+ u32 ppar1; /* Pin Assignment Register 1 */
+ u32 ppar2; /* Pin Assignment Register 2 */
+} gpio_n_t;
+
+typedef struct qegpio83xx {
+ gpio_n_t ioport[0x7];
+ u8 res0[0x358];
+} qepio83xx_t;
+
+/*
+ * QE Secondary Bus Access Windows
+ */
+typedef struct qesba83xx {
+ u32 lbmcsar; /* Local bus memory controller start address */
+ u32 sdmcsar; /* Secondary DDR memory controller start address */
+ u8 res0[0x38];
+ u32 lbmcear; /* Local bus memory controller end address */
+ u32 sdmcear; /* Secondary DDR memory controller end address */
+ u8 res1[0x38];
+ u32 lbmcar; /* Local bus memory controller attributes */
+ u32 sdmcar; /* Secondary DDR memory controller attributes */
+ u8 res2[0x378];
+} qesba83xx_t;
+
+/*
+ * DDR Memory Controller Memory Map
+ */
+#if defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3)
+typedef struct ccsr_ddr {
+ u32 cs0_bnds; /* Chip Select 0 Memory Bounds */
+ u8 res1[4];
+ u32 cs1_bnds; /* Chip Select 1 Memory Bounds */
+ u8 res2[4];
+ u32 cs2_bnds; /* Chip Select 2 Memory Bounds */
+ u8 res3[4];
+ u32 cs3_bnds; /* Chip Select 3 Memory Bounds */
+ u8 res4[100];
+ u32 cs0_config; /* Chip Select Configuration */
+ u32 cs1_config; /* Chip Select Configuration */
+ u32 cs2_config; /* Chip Select Configuration */
+ u32 cs3_config; /* Chip Select Configuration */
+ u8 res4a[48];
+ u32 cs0_config_2; /* Chip Select Configuration 2 */
+ u32 cs1_config_2; /* Chip Select Configuration 2 */
+ u32 cs2_config_2; /* Chip Select Configuration 2 */
+ u32 cs3_config_2; /* Chip Select Configuration 2 */
+ u8 res5[48];
+ u32 timing_cfg_3; /* SDRAM Timing Configuration 3 */
+ u32 timing_cfg_0; /* SDRAM Timing Configuration 0 */
+ u32 timing_cfg_1; /* SDRAM Timing Configuration 1 */
+ u32 timing_cfg_2; /* SDRAM Timing Configuration 2 */
+ u32 sdram_cfg; /* SDRAM Control Configuration */
+ u32 sdram_cfg_2; /* SDRAM Control Configuration 2 */
+ u32 sdram_mode; /* SDRAM Mode Configuration */
+ u32 sdram_mode_2; /* SDRAM Mode Configuration 2 */
+ u32 sdram_md_cntl; /* SDRAM Mode Control */
+ u32 sdram_interval; /* SDRAM Interval Configuration */
+ u32 sdram_data_init; /* SDRAM Data initialization */
+ u8 res6[4];
+ u32 sdram_clk_cntl; /* SDRAM Clock Control */
+ u8 res7[20];
+ u32 init_addr; /* training init addr */
+ u32 init_ext_addr; /* training init extended addr */
+ u8 res8_1[16];
+ u32 timing_cfg_4; /* SDRAM Timing Configuration 4 */
+ u32 timing_cfg_5; /* SDRAM Timing Configuration 5 */
+ u8 reg8_1a[8];
+ u32 ddr_zq_cntl; /* ZQ calibration control*/
+ u32 ddr_wrlvl_cntl; /* write leveling control*/
+ u8 reg8_1aa[4];
+ u32 ddr_sr_cntr; /* self refresh counter */
+ u32 ddr_sdram_rcw_1; /* Control Words 1 */
+ u32 ddr_sdram_rcw_2; /* Control Words 2 */
+ u8 reg_1ab[8];
+ u32 ddr_wrlvl_cntl_2; /* write leveling control 2 */
+ u32 ddr_wrlvl_cntl_3; /* write leveling control 3 */
+ u8 res8_1b[104];
+ u32 sdram_mode_3; /* SDRAM Mode Configuration 3 */
+ u32 sdram_mode_4; /* SDRAM Mode Configuration 4 */
+ u32 sdram_mode_5; /* SDRAM Mode Configuration 5 */
+ u32 sdram_mode_6; /* SDRAM Mode Configuration 6 */
+ u32 sdram_mode_7; /* SDRAM Mode Configuration 7 */
+ u32 sdram_mode_8; /* SDRAM Mode Configuration 8 */
+ u8 res8_1ba[0x908];
+ u32 ddr_dsr1; /* Debug Status 1 */
+ u32 ddr_dsr2; /* Debug Status 2 */
+ u32 ddr_cdr1; /* Control Driver 1 */
+ u32 ddr_cdr2; /* Control Driver 2 */
+ u8 res8_1c[200];
+ u32 ip_rev1; /* IP Block Revision 1 */
+ u32 ip_rev2; /* IP Block Revision 2 */
+ u32 eor; /* Enhanced Optimization Register */
+ u8 res8_2[252];
+ u32 mtcr; /* Memory Test Control Register */
+ u8 res8_3[28];
+ u32 mtp1; /* Memory Test Pattern 1 */
+ u32 mtp2; /* Memory Test Pattern 2 */
+ u32 mtp3; /* Memory Test Pattern 3 */
+ u32 mtp4; /* Memory Test Pattern 4 */
+ u32 mtp5; /* Memory Test Pattern 5 */
+ u32 mtp6; /* Memory Test Pattern 6 */
+ u32 mtp7; /* Memory Test Pattern 7 */
+ u32 mtp8; /* Memory Test Pattern 8 */
+ u32 mtp9; /* Memory Test Pattern 9 */
+ u32 mtp10; /* Memory Test Pattern 10 */
+ u8 res8_4[184];
+ u32 data_err_inject_hi; /* Data Path Err Injection Mask High */
+ u32 data_err_inject_lo; /* Data Path Err Injection Mask Low */
+ u32 ecc_err_inject; /* Data Path Err Injection Mask ECC */
+ u8 res9[20];
+ u32 capture_data_hi; /* Data Path Read Capture High */
+ u32 capture_data_lo; /* Data Path Read Capture Low */
+ u32 capture_ecc; /* Data Path Read Capture ECC */
+ u8 res10[20];
+ u32 err_detect; /* Error Detect */
+ u32 err_disable; /* Error Disable */
+ u32 err_int_en;
+ u32 capture_attributes; /* Error Attrs Capture */
+ u32 capture_address; /* Error Addr Capture */
+ u32 capture_ext_address; /* Error Extended Addr Capture */
+ u32 err_sbe; /* Single-Bit ECC Error Management */
+ u8 res11[164];
+ u32 debug[32]; /* debug_1 to debug_32 */
+ u8 res12[128];
+} ccsr_ddr_t;
+#else
+typedef struct ddr_cs_bnds {
+ u32 csbnds;
+ u8 res0[4];
+} ddr_cs_bnds_t;
+
+typedef struct ddr83xx {
+ ddr_cs_bnds_t csbnds[4];/* Chip Select x Memory Bounds */
+ u8 res0[0x60];
+ u32 cs_config[4]; /* Chip Select x Configuration */
+ u8 res1[0x70];
+ u32 timing_cfg_3; /* SDRAM Timing Configuration 3 */
+ u32 timing_cfg_0; /* SDRAM Timing Configuration 0 */
+ u32 timing_cfg_1; /* SDRAM Timing Configuration 1 */
+ u32 timing_cfg_2; /* SDRAM Timing Configuration 2 */
+ u32 sdram_cfg; /* SDRAM Control Configuration */
+ u32 sdram_cfg2; /* SDRAM Control Configuration 2 */
+ u32 sdram_mode; /* SDRAM Mode Configuration */
+ u32 sdram_mode2; /* SDRAM Mode Configuration 2 */
+ u32 sdram_md_cntl; /* SDRAM Mode Control */
+ u32 sdram_interval; /* SDRAM Interval Configuration */
+ u32 ddr_data_init; /* SDRAM Data Initialization */
+ u8 res2[4];
+ u32 sdram_clk_cntl; /* SDRAM Clock Control */
+ u8 res3[0x14];
+ u32 ddr_init_addr; /* DDR training initialization address */
+ u32 ddr_init_ext_addr; /* DDR training initialization extended address */
+ u8 res4[0xAA8];
+ u32 ddr_ip_rev1; /* DDR IP block revision 1 */
+ u32 ddr_ip_rev2; /* DDR IP block revision 2 */
+ u8 res5[0x200];
+ u32 data_err_inject_hi; /* Memory Data Path Error Injection Mask High */
+ u32 data_err_inject_lo; /* Memory Data Path Error Injection Mask Low */
+ u32 ecc_err_inject; /* Memory Data Path Error Injection Mask ECC */
+ u8 res6[0x14];
+ u32 capture_data_hi; /* Memory Data Path Read Capture High */
+ u32 capture_data_lo; /* Memory Data Path Read Capture Low */
+ u32 capture_ecc; /* Memory Data Path Read Capture ECC */
+ u8 res7[0x14];
+ u32 err_detect; /* Memory Error Detect */
+ u32 err_disable; /* Memory Error Disable */
+ u32 err_int_en; /* Memory Error Interrupt Enable */
+ u32 capture_attributes; /* Memory Error Attributes Capture */
+ u32 capture_address; /* Memory Error Address Capture */
+ u32 capture_ext_address;/* Memory Error Extended Address Capture */
+ u32 err_sbe; /* Memory Single-Bit ECC Error Management */
+ u8 res8[0xA4];
+ u32 debug_reg;
+ u8 res9[0xFC];
+} ddr83xx_t;
+#endif
+
+/*
+ * DUART
+ */
+typedef struct duart83xx {
+ u8 urbr_ulcr_udlb; /* combined register for URBR, UTHR and UDLB */
+ u8 uier_udmb; /* combined register for UIER and UDMB */
+ u8 uiir_ufcr_uafr; /* combined register for UIIR, UFCR and UAFR */
+ u8 ulcr; /* line control register */
+ u8 umcr; /* MODEM control register */
+ u8 ulsr; /* line status register */
+ u8 umsr; /* MODEM status register */
+ u8 uscr; /* scratch register */
+ u8 res0[8];
+ u8 udsr; /* DMA status register */
+ u8 res1[3];
+ u8 res2[0xEC];
+} duart83xx_t;
+
+/*
+ * DMA/Messaging Unit
+ */
+typedef struct dma83xx {
+ u32 res0[0xC]; /* 0x0-0x29 reseverd */
+ u32 omisr; /* 0x30 Outbound message interrupt status register */
+ u32 omimr; /* 0x34 Outbound message interrupt mask register */
+ u32 res1[0x6]; /* 0x38-0x49 reserved */
+ u32 imr0; /* 0x50 Inbound message register 0 */
+ u32 imr1; /* 0x54 Inbound message register 1 */
+ u32 omr0; /* 0x58 Outbound message register 0 */
+ u32 omr1; /* 0x5C Outbound message register 1 */
+ u32 odr; /* 0x60 Outbound doorbell register */
+ u32 res2; /* 0x64-0x67 reserved */
+ u32 idr; /* 0x68 Inbound doorbell register */
+ u32 res3[0x5]; /* 0x6C-0x79 reserved */
+ u32 imisr; /* 0x80 Inbound message interrupt status register */
+ u32 imimr; /* 0x84 Inbound message interrupt mask register */
+ u32 res4[0x1E]; /* 0x88-0x99 reserved */
+ struct fsl_dma dma[4];
+} dma83xx_t;
+
+/*
+ * PCI Software Configuration Registers
+ */
+typedef struct pciconf83xx {
+ u32 config_address;
+ u32 config_data;
+ u32 int_ack;
+ u8 res[116];
+} pciconf83xx_t;
+
+/*
+ * PCI Outbound Translation Register
+ */
+typedef struct pci_outbound_window {
+ u32 potar;
+ u8 res0[4];
+ u32 pobar;
+ u8 res1[4];
+ u32 pocmr;
+ u8 res2[4];
+} pot83xx_t;
+
+/*
+ * Sequencer
+ */
+typedef struct ios83xx {
+ pot83xx_t pot[6];
+ u8 res0[0x60];
+ u32 pmcr;
+ u8 res1[4];
+ u32 dtcr;
+ u8 res2[4];
+} ios83xx_t;
+
+/*
+ * PCI Controller Control and Status Registers
+ */
+typedef struct pcictrl83xx {
+ u32 esr;
+ u32 ecdr;
+ u32 eer;
+ u32 eatcr;
+ u32 eacr;
+ u32 eeacr;
+ u32 edlcr;
+ u32 edhcr;
+ u32 gcr;
+ u32 ecr;
+ u32 gsr;
+ u8 res0[12];
+ u32 pitar2;
+ u8 res1[4];
+ u32 pibar2;
+ u32 piebar2;
+ u32 piwar2;
+ u8 res2[4];
+ u32 pitar1;
+ u8 res3[4];
+ u32 pibar1;
+ u32 piebar1;
+ u32 piwar1;
+ u8 res4[4];
+ u32 pitar0;
+ u8 res5[4];
+ u32 pibar0;
+ u8 res6[4];
+ u32 piwar0;
+ u8 res7[132];
+} pcictrl83xx_t;
+
+/*
+ * USB
+ */
+typedef struct usb83xx {
+ u8 fixme[0x1000];
+} usb83xx_t;
+
+/*
+ * TSEC
+ */
+typedef struct tsec83xx {
+ u8 fixme[0x1000];
+} tsec83xx_t;
+
+/*
+ * Security
+ */
+typedef struct security83xx {
+ u8 fixme[0x10000];
+} security83xx_t;
+
+/*
+ * PCI Express
+ */
+struct pex_inbound_window {
+ u32 ar;
+ u32 tar;
+ u32 barl;
+ u32 barh;
+};
+
+struct pex_outbound_window {
+ u32 ar;
+ u32 bar;
+ u32 tarl;
+ u32 tarh;
+};
+
+struct pex_csb_bridge {
+ u32 pex_csb_ver;
+ u32 pex_csb_cab;
+ u32 pex_csb_ctrl;
+ u8 res0[8];
+ u32 pex_dms_dstmr;
+ u8 res1[4];
+ u32 pex_cbs_stat;
+ u8 res2[0x20];
+ u32 pex_csb_obctrl;
+ u32 pex_csb_obstat;
+ u8 res3[0x98];
+ u32 pex_csb_ibctrl;
+ u32 pex_csb_ibstat;
+ u8 res4[0xb8];
+ u32 pex_wdma_ctrl;
+ u32 pex_wdma_addr;
+ u32 pex_wdma_stat;
+ u8 res5[0x94];
+ u32 pex_rdma_ctrl;
+ u32 pex_rdma_addr;
+ u32 pex_rdma_stat;
+ u8 res6[0xd4];
+ u32 pex_ombcr;
+ u32 pex_ombdr;
+ u8 res7[0x38];
+ u32 pex_imbcr;
+ u32 pex_imbdr;
+ u8 res8[0x38];
+ u32 pex_int_enb;
+ u32 pex_int_stat;
+ u32 pex_int_apio_vec1;
+ u32 pex_int_apio_vec2;
+ u8 res9[0x10];
+ u32 pex_int_ppio_vec1;
+ u32 pex_int_ppio_vec2;
+ u32 pex_int_wdma_vec1;
+ u32 pex_int_wdma_vec2;
+ u32 pex_int_rdma_vec1;
+ u32 pex_int_rdma_vec2;
+ u32 pex_int_misc_vec;
+ u8 res10[4];
+ u32 pex_int_axi_pio_enb;
+ u32 pex_int_axi_wdma_enb;
+ u32 pex_int_axi_rdma_enb;
+ u32 pex_int_axi_misc_enb;
+ u32 pex_int_axi_pio_stat;
+ u32 pex_int_axi_wdma_stat;
+ u32 pex_int_axi_rdma_stat;
+ u32 pex_int_axi_misc_stat;
+ u8 res11[0xa0];
+ struct pex_outbound_window pex_outbound_win[4];
+ u8 res12[0x100];
+ u32 pex_epiwtar0;
+ u32 pex_epiwtar1;
+ u32 pex_epiwtar2;
+ u32 pex_epiwtar3;
+ u8 res13[0x70];
+ struct pex_inbound_window pex_inbound_win[4];
+};
+
+typedef struct pex83xx {
+ u8 pex_cfg_header[0x404];
+ u32 pex_ltssm_stat;
+ u8 res0[0x30];
+ u32 pex_ack_replay_timeout;
+ u8 res1[4];
+ u32 pex_gclk_ratio;
+ u8 res2[0xc];
+ u32 pex_pm_timer;
+ u32 pex_pme_timeout;
+ u8 res3[4];
+ u32 pex_aspm_req_timer;
+ u8 res4[0x18];
+ u32 pex_ssvid_update;
+ u8 res5[0x34];
+ u32 pex_cfg_ready;
+ u8 res6[0x24];
+ u32 pex_bar_sizel;
+ u8 res7[4];
+ u32 pex_bar_sel;
+ u8 res8[0x20];
+ u32 pex_bar_pf;
+ u8 res9[0x88];
+ u32 pex_pme_to_ack_tor;
+ u8 res10[0xc];
+ u32 pex_ss_intr_mask;
+ u8 res11[0x25c];
+ struct pex_csb_bridge bridge;
+ u8 res12[0x160];
+} pex83xx_t;
+
+/*
+ * SATA
+ */
+typedef struct sata83xx {
+ u8 fixme[0x1000];
+} sata83xx_t;
+
+/*
+ * eSDHC
+ */
+typedef struct sdhc83xx {
+ u8 fixme[0x1000];
+} sdhc83xx_t;
+
+/*
+ * SerDes
+ */
+typedef struct serdes83xx {
+ u32 srdscr0;
+ u32 srdscr1;
+ u32 srdscr2;
+ u32 srdscr3;
+ u32 srdscr4;
+ u8 res0[0xc];
+ u32 srdsrstctl;
+ u8 res1[0xdc];
+} serdes83xx_t;
+
+/*
+ * On Chip ROM
+ */
+typedef struct rom83xx {
+#if defined(CONFIG_MPC8309)
+ u8 mem[0x8000];
+#else
+ u8 mem[0x10000];
+#endif
+} rom83xx_t;
+
+/*
+ * TDM
+ */
+typedef struct tdm83xx {
+ u8 fixme[0x200];
+} tdm83xx_t;
+
+/*
+ * TDM DMAC
+ */
+typedef struct tdmdmac83xx {
+ u8 fixme[0x2000];
+} tdmdmac83xx_t;
+
+#if defined(CONFIG_MPC834x)
+typedef struct immap {
+ sysconf83xx_t sysconf; /* System configuration */
+ wdt83xx_t wdt; /* Watch Dog Timer (WDT) Registers */
+ rtclk83xx_t rtc; /* Real Time Clock Module Registers */
+ rtclk83xx_t pit; /* Periodic Interval Timer */
+ gtm83xx_t gtm[2]; /* Global Timers Module */
+ ipic83xx_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter83xx_t arbiter; /* System Arbiter Registers */
+ reset83xx_t reset; /* Reset Module */
+ clk83xx_t clk; /* System Clock Module */
+ pmc83xx_t pmc; /* Power Management Control Module */
+ gpio83xx_t gpio[2]; /* General purpose I/O module */
+ u8 res0[0x200];
+ u8 dll_ddr[0x100];
+ u8 dll_lbc[0x100];
+ u8 res1[0xE00];
+#if defined(CONFIG_FSL_DDR2) || defined(CONFIG_FSL_DDR3)
+ ccsr_ddr_t ddr; /* DDR Memory Controller Memory */
+#else
+ ddr83xx_t ddr; /* DDR Memory Controller Memory */
+#endif
+ fsl_i2c_t i2c[2]; /* I2C Controllers */
+ u8 res2[0x1300];
+ duart83xx_t duart[2]; /* DUART */
+ u8 res3[0x900];
+ fsl_lbc_t im_lbc; /* Local Bus Controller Regs */
+ u8 res4[0x1000];
+ spi8xxx_t spi; /* Serial Peripheral Interface */
+ dma83xx_t dma; /* DMA */
+ pciconf83xx_t pci_conf[2]; /* PCI Software Configuration Registers */
+ ios83xx_t ios; /* Sequencer */
+ pcictrl83xx_t pci_ctrl[2]; /* PCI Controller Control and Status Registers */
+ u8 res5[0x19900];
+ usb83xx_t usb[2];
+ tsec83xx_t tsec[2];
+ u8 res6[0xA000];
+ security83xx_t security;
+ u8 res7[0xC0000];
+} immap_t;
+
+#ifdef CONFIG_HAS_FSL_MPH_USB
+#define CONFIG_SYS_MPC83xx_USB_OFFSET 0x22000 /* use the MPH controller */
+#else
+#define CONFIG_SYS_MPC83xx_USB_OFFSET 0x23000 /* use the DR controller */
+#endif
+
+#elif defined(CONFIG_MPC8313)
+typedef struct immap {
+ sysconf83xx_t sysconf; /* System configuration */
+ wdt83xx_t wdt; /* Watch Dog Timer (WDT) Registers */
+ rtclk83xx_t rtc; /* Real Time Clock Module Registers */
+ rtclk83xx_t pit; /* Periodic Interval Timer */
+ gtm83xx_t gtm[2]; /* Global Timers Module */
+ ipic83xx_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter83xx_t arbiter; /* System Arbiter Registers */
+ reset83xx_t reset; /* Reset Module */
+ clk83xx_t clk; /* System Clock Module */
+ pmc83xx_t pmc; /* Power Management Control Module */
+ gpio83xx_t gpio[1]; /* General purpose I/O module */
+ u8 res0[0x1300];
+ ddr83xx_t ddr; /* DDR Memory Controller Memory */
+ fsl_i2c_t i2c[2]; /* I2C Controllers */
+ u8 res1[0x1300];
+ duart83xx_t duart[2]; /* DUART */
+ u8 res2[0x900];
+ fsl_lbc_t im_lbc; /* Local Bus Controller Regs */
+ u8 res3[0x1000];
+ spi8xxx_t spi; /* Serial Peripheral Interface */
+ dma83xx_t dma; /* DMA */
+ pciconf83xx_t pci_conf[1]; /* PCI Software Configuration Registers */
+ u8 res4[0x80];
+ ios83xx_t ios; /* Sequencer */
+ pcictrl83xx_t pci_ctrl[1]; /* PCI Controller Control and Status Registers */
+ u8 res5[0x1aa00];
+ usb83xx_t usb[1];
+ tsec83xx_t tsec[2];
+ u8 res6[0xA000];
+ security83xx_t security;
+ u8 res7[0xC0000];
+} immap_t;
+
+#elif defined(CONFIG_MPC8308) || defined(CONFIG_MPC8315)
+typedef struct immap {
+ sysconf83xx_t sysconf; /* System configuration */
+ wdt83xx_t wdt; /* Watch Dog Timer (WDT) Registers */
+ rtclk83xx_t rtc; /* Real Time Clock Module Registers */
+ rtclk83xx_t pit; /* Periodic Interval Timer */
+ gtm83xx_t gtm[2]; /* Global Timers Module */
+ ipic83xx_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter83xx_t arbiter; /* System Arbiter Registers */
+ reset83xx_t reset; /* Reset Module */
+ clk83xx_t clk; /* System Clock Module */
+ pmc83xx_t pmc; /* Power Management Control Module */
+ gpio83xx_t gpio[1]; /* General purpose I/O module */
+ u8 res0[0x1300];
+ ddr83xx_t ddr; /* DDR Memory Controller Memory */
+ fsl_i2c_t i2c[2]; /* I2C Controllers */
+ u8 res1[0x1300];
+ duart83xx_t duart[2]; /* DUART */
+ u8 res2[0x900];
+ fsl_lbc_t im_lbc; /* Local Bus Controller Regs */
+ u8 res3[0x1000];
+ spi8xxx_t spi; /* Serial Peripheral Interface */
+ dma83xx_t dma; /* DMA */
+ pciconf83xx_t pci_conf[1]; /* PCI Software Configuration Registers */
+ u8 res4[0x80];
+ ios83xx_t ios; /* Sequencer */
+ pcictrl83xx_t pci_ctrl[1]; /* PCI Controller Control and Status Registers */
+ u8 res5[0xa00];
+ pex83xx_t pciexp[2]; /* PCI Express Controller */
+ u8 res6[0xb000];
+ tdm83xx_t tdm; /* TDM Controller */
+ u8 res7[0x1e00];
+ sata83xx_t sata[2]; /* SATA Controller */
+ u8 res8[0x9000];
+ usb83xx_t usb[1]; /* USB DR Controller */
+ tsec83xx_t tsec[2];
+ u8 res9[0x6000];
+ tdmdmac83xx_t tdmdmac; /* TDM DMAC */
+ u8 res10[0x2000];
+ security83xx_t security;
+ u8 res11[0xA3000];
+ serdes83xx_t serdes[1]; /* SerDes Registers */
+ u8 res12[0x1CF00];
+} immap_t;
+
+#elif defined(CONFIG_MPC837x)
+typedef struct immap {
+ sysconf83xx_t sysconf; /* System configuration */
+ wdt83xx_t wdt; /* Watch Dog Timer (WDT) Registers */
+ rtclk83xx_t rtc; /* Real Time Clock Module Registers */
+ rtclk83xx_t pit; /* Periodic Interval Timer */
+ gtm83xx_t gtm[2]; /* Global Timers Module */
+ ipic83xx_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter83xx_t arbiter; /* System Arbiter Registers */
+ reset83xx_t reset; /* Reset Module */
+ clk83xx_t clk; /* System Clock Module */
+ pmc83xx_t pmc; /* Power Management Control Module */
+ gpio83xx_t gpio[2]; /* General purpose I/O module */
+ u8 res0[0x1200];
+ ddr83xx_t ddr; /* DDR Memory Controller Memory */
+ fsl_i2c_t i2c[2]; /* I2C Controllers */
+ u8 res1[0x1300];
+ duart83xx_t duart[2]; /* DUART */
+ u8 res2[0x900];
+ fsl_lbc_t im_lbc; /* Local Bus Controller Regs */
+ u8 res3[0x1000];
+ spi8xxx_t spi; /* Serial Peripheral Interface */
+ dma83xx_t dma; /* DMA */
+ pciconf83xx_t pci_conf[1]; /* PCI Software Configuration Registers */
+ u8 res4[0x80];
+ ios83xx_t ios; /* Sequencer */
+ pcictrl83xx_t pci_ctrl[1]; /* PCI Controller Control and Status Registers */
+ u8 res5[0xa00];
+ pex83xx_t pciexp[2]; /* PCI Express Controller */
+ u8 res6[0xd000];
+ sata83xx_t sata[4]; /* SATA Controller */
+ u8 res7[0x7000];
+ usb83xx_t usb[1]; /* USB DR Controller */
+ tsec83xx_t tsec[2];
+ u8 res8[0x8000];
+ sdhc83xx_t sdhc; /* SDHC Controller */
+ u8 res9[0x1000];
+ security83xx_t security;
+ u8 res10[0xA3000];
+ serdes83xx_t serdes[2]; /* SerDes Registers */
+ u8 res11[0xCE00];
+ rom83xx_t rom; /* On Chip ROM */
+} immap_t;
+
+#elif defined(CONFIG_MPC8360)
+typedef struct immap {
+ sysconf83xx_t sysconf; /* System configuration */
+ wdt83xx_t wdt; /* Watch Dog Timer (WDT) Registers */
+ rtclk83xx_t rtc; /* Real Time Clock Module Registers */
+ rtclk83xx_t pit; /* Periodic Interval Timer */
+ u8 res0[0x200];
+ ipic83xx_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter83xx_t arbiter; /* System Arbiter Registers */
+ reset83xx_t reset; /* Reset Module */
+ clk83xx_t clk; /* System Clock Module */
+ pmc83xx_t pmc; /* Power Management Control Module */
+ qepi83xx_t qepi; /* QE Ports Interrupts Registers */
+ u8 res1[0x300];
+ u8 dll_ddr[0x100];
+ u8 dll_lbc[0x100];
+ u8 res2[0x200];
+ qepio83xx_t qepio; /* QE Parallel I/O ports */
+ qesba83xx_t qesba; /* QE Secondary Bus Access Windows */
+ u8 res3[0x400];
+ ddr83xx_t ddr; /* DDR Memory Controller Memory */
+ fsl_i2c_t i2c[2]; /* I2C Controllers */
+ u8 res4[0x1300];
+ duart83xx_t duart[2]; /* DUART */
+ u8 res5[0x900];
+ fsl_lbc_t im_lbc; /* Local Bus Controller Regs */
+ u8 res6[0x2000];
+ dma83xx_t dma; /* DMA */
+ pciconf83xx_t pci_conf[1]; /* PCI Software Configuration Registers */
+ u8 res7[128];
+ ios83xx_t ios; /* Sequencer (IOS) */
+ pcictrl83xx_t pci_ctrl[1]; /* PCI Controller Control and Status Registers */
+ u8 res8[0x4A00];
+ ddr83xx_t ddr_secondary; /* Secondary DDR Memory Controller Memory Map */
+ u8 res9[0x22000];
+ security83xx_t security;
+ u8 res10[0xC0000];
+ u8 qe[0x100000]; /* QE block */
+} immap_t;
+
+#elif defined(CONFIG_MPC832x)
+typedef struct immap {
+ sysconf83xx_t sysconf; /* System configuration */
+ wdt83xx_t wdt; /* Watch Dog Timer (WDT) Registers */
+ rtclk83xx_t rtc; /* Real Time Clock Module Registers */
+ rtclk83xx_t pit; /* Periodic Interval Timer */
+ gtm83xx_t gtm[2]; /* Global Timers Module */
+ ipic83xx_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter83xx_t arbiter; /* System Arbiter Registers */
+ reset83xx_t reset; /* Reset Module */
+ clk83xx_t clk; /* System Clock Module */
+ pmc83xx_t pmc; /* Power Management Control Module */
+ qepi83xx_t qepi; /* QE Ports Interrupts Registers */
+ u8 res0[0x300];
+ u8 dll_ddr[0x100];
+ u8 dll_lbc[0x100];
+ u8 res1[0x200];
+ qepio83xx_t qepio; /* QE Parallel I/O ports */
+ u8 res2[0x800];
+ ddr83xx_t ddr; /* DDR Memory Controller Memory */
+ fsl_i2c_t i2c[2]; /* I2C Controllers */
+ u8 res3[0x1300];
+ duart83xx_t duart[2]; /* DUART */
+ u8 res4[0x900];
+ fsl_lbc_t im_lbc; /* Local Bus Controller Regs */
+ u8 res5[0x2000];
+ dma83xx_t dma; /* DMA */
+ pciconf83xx_t pci_conf[1]; /* PCI Software Configuration Registers */
+ u8 res6[128];
+ ios83xx_t ios; /* Sequencer (IOS) */
+ pcictrl83xx_t pci_ctrl[1]; /* PCI Controller Control and Status Registers */
+ u8 res7[0x27A00];
+ security83xx_t security;
+ u8 res8[0xC0000];
+ u8 qe[0x100000]; /* QE block */
+} immap_t;
+#elif defined(CONFIG_MPC8309)
+typedef struct immap {
+ sysconf83xx_t sysconf; /* System configuration */
+ wdt83xx_t wdt; /* Watch Dog Timer (WDT) Registers */
+ rtclk83xx_t rtc; /* Real Time Clock Module Registers */
+ rtclk83xx_t pit; /* Periodic Interval Timer */
+ gtm83xx_t gtm[2]; /* Global Timers Module */
+ ipic83xx_t ipic; /* Integrated Programmable Interrupt Controller */
+ arbiter83xx_t arbiter; /* System Arbiter Registers */
+ reset83xx_t reset; /* Reset Module */
+ clk83xx_t clk; /* System Clock Module */
+ pmc83xx_t pmc; /* Power Management Control Module */
+ gpio83xx_t gpio[2]; /* General purpose I/O module */
+ u8 res0[0x500]; /* res0 1.25 KBytes added for 8309 */
+ qepi83xx_t qepi; /* QE Ports Interrupts Registers */
+ qepio83xx_t qepio; /* QE Parallel I/O ports */
+ u8 res1[0x800];
+ ddr83xx_t ddr; /* DDR Memory Controller Memory */
+ fsl_i2c_t i2c[2]; /* I2C Controllers */
+ u8 res2[0x1300];
+ duart83xx_t duart[2]; /* DUART */
+ u8 res3[0x200];
+ duart83xx_t duart1[2]; /* DUART */
+ u8 res4[0x500];
+ fsl_lbc_t im_lbc; /* Local Bus Controller Regs */
+ u8 res5[0x1000];
+ u8 spi[0x100];
+ u8 res6[0xf00];
+ dma83xx_t dma; /* DMA */
+ pciconf83xx_t pci_conf[1]; /* PCI Configuration Registers */
+ u8 res7[0x80];
+ ios83xx_t ios; /* Sequencer (IOS) */
+ pcictrl83xx_t pci_ctrl[1]; /* PCI Control & Status Registers */
+ u8 res8[0x13A00];
+ u8 can1[0x1000]; /* Flexcan 1 */
+ u8 can2[0x1000]; /* Flexcan 2 */
+ u8 res9[0x5000];
+ usb83xx_t usb;
+ u8 res10[0x5000];
+ u8 can3[0x1000]; /* Flexcan 3 */
+ u8 can4[0x1000]; /* Flexcan 4 */
+ u8 res11[0x1000];
+ u8 dma1[0x2000]; /* DMA */
+ sdhc83xx_t sdhc; /* SDHC Controller */
+ u8 res12[0xC1000];
+ rom83xx_t rom; /* On Chip ROM */
+ u8 res13[0x8000];
+ u8 qe[0x100000]; /* QE block */
+ u8 res14[0xE00000];/* Added for 8309 */
+} immap_t;
+#endif
+
+#define CONFIG_SYS_MPC8xxx_DDR_OFFSET (0x2000)
+#define CONFIG_SYS_MPC8xxx_DDR_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR_OFFSET)
+#define CONFIG_SYS_MPC83xx_DMA_OFFSET (0x8000)
+#define CONFIG_SYS_MPC83xx_DMA_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC83xx_DMA_OFFSET)
+#define CONFIG_SYS_MPC83xx_ESDHC_OFFSET (0x2e000)
+#define CONFIG_SYS_MPC83xx_ESDHC_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC83xx_ESDHC_OFFSET)
+
+#ifndef CONFIG_SYS_MPC83xx_USB_OFFSET
+#define CONFIG_SYS_MPC83xx_USB_OFFSET 0x23000
+#endif
+#define CONFIG_SYS_MPC83xx_USB_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC83xx_USB_OFFSET)
+#define CONFIG_SYS_LBC_ADDR (&((immap_t *)CONFIG_SYS_IMMR)->im_lbc)
+
+#define CONFIG_SYS_TSEC1_OFFSET 0x24000
+#define CONFIG_SYS_MDIO1_OFFSET 0x24000
+
+#define TSEC_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_TSEC1_OFFSET)
+#define MDIO_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MDIO1_OFFSET)
+#endif /* __IMMAP_83xx__ */
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
new file mode 100644
index 0000000..db70d04
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -0,0 +1,3212 @@
+/*
+ * MPC85xx Internal Memory Map
+ *
+ * Copyright 2007-2012 Freescale Semiconductor, Inc.
+ *
+ * Copyright(c) 2002,2003 Motorola Inc.
+ * Xianghua Xiao (x.xiao@motorola.com)
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __IMMAP_85xx__
+#define __IMMAP_85xx__
+
+#include <asm/types.h>
+#include <asm/fsl_dma.h>
+#include <asm/fsl_i2c.h>
+#include <asm/fsl_ifc.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_fman.h>
+
+typedef struct ccsr_local {
+ u32 ccsrbarh; /* CCSR Base Addr High */
+ u32 ccsrbarl; /* CCSR Base Addr Low */
+ u32 ccsrar; /* CCSR Attr */
+#define CCSRAR_C 0x80000000 /* Commit */
+ u8 res1[4];
+ u32 altcbarh; /* Alternate Configuration Base Addr High */
+ u32 altcbarl; /* Alternate Configuration Base Addr Low */
+ u32 altcar; /* Alternate Configuration Attr */
+ u8 res2[4];
+ u32 bstrh; /* Boot space translation high */
+ u32 bstrl; /* Boot space translation Low */
+ u32 bstrar; /* Boot space translation attributes */
+ u8 res3[0xbd4];
+ struct {
+ u32 lawbarh; /* LAWn base addr high */
+ u32 lawbarl; /* LAWn base addr low */
+ u32 lawar; /* LAWn attributes */
+ u8 res4[4];
+ } law[32];
+ u8 res35[0x204];
+} ccsr_local_t;
+
+/* Local-Access Registers & ECM Registers */
+typedef struct ccsr_local_ecm {
+ u32 ccsrbar; /* CCSR Base Addr */
+ u8 res1[4];
+ u32 altcbar; /* Alternate Configuration Base Addr */
+ u8 res2[4];
+ u32 altcar; /* Alternate Configuration Attr */
+ u8 res3[12];
+ u32 bptr; /* Boot Page Translation */
+ u8 res4[3044];
+ u32 lawbar0; /* Local Access Window 0 Base Addr */
+ u8 res5[4];
+ u32 lawar0; /* Local Access Window 0 Attrs */
+ u8 res6[20];
+ u32 lawbar1; /* Local Access Window 1 Base Addr */
+ u8 res7[4];
+ u32 lawar1; /* Local Access Window 1 Attrs */
+ u8 res8[20];
+ u32 lawbar2; /* Local Access Window 2 Base Addr */
+ u8 res9[4];
+ u32 lawar2; /* Local Access Window 2 Attrs */
+ u8 res10[20];
+ u32 lawbar3; /* Local Access Window 3 Base Addr */
+ u8 res11[4];
+ u32 lawar3; /* Local Access Window 3 Attrs */
+ u8 res12[20];
+ u32 lawbar4; /* Local Access Window 4 Base Addr */
+ u8 res13[4];
+ u32 lawar4; /* Local Access Window 4 Attrs */
+ u8 res14[20];
+ u32 lawbar5; /* Local Access Window 5 Base Addr */
+ u8 res15[4];
+ u32 lawar5; /* Local Access Window 5 Attrs */
+ u8 res16[20];
+ u32 lawbar6; /* Local Access Window 6 Base Addr */
+ u8 res17[4];
+ u32 lawar6; /* Local Access Window 6 Attrs */
+ u8 res18[20];
+ u32 lawbar7; /* Local Access Window 7 Base Addr */
+ u8 res19[4];
+ u32 lawar7; /* Local Access Window 7 Attrs */
+ u8 res19_8a[20];
+ u32 lawbar8; /* Local Access Window 8 Base Addr */
+ u8 res19_8b[4];
+ u32 lawar8; /* Local Access Window 8 Attrs */
+ u8 res19_9a[20];
+ u32 lawbar9; /* Local Access Window 9 Base Addr */
+ u8 res19_9b[4];
+ u32 lawar9; /* Local Access Window 9 Attrs */
+ u8 res19_10a[20];
+ u32 lawbar10; /* Local Access Window 10 Base Addr */
+ u8 res19_10b[4];
+ u32 lawar10; /* Local Access Window 10 Attrs */
+ u8 res19_11a[20];
+ u32 lawbar11; /* Local Access Window 11 Base Addr */
+ u8 res19_11b[4];
+ u32 lawar11; /* Local Access Window 11 Attrs */
+ u8 res20[652];
+ u32 eebacr; /* ECM CCB Addr Configuration */
+ u8 res21[12];
+ u32 eebpcr; /* ECM CCB Port Configuration */
+ u8 res22[3564];
+ u32 eedr; /* ECM Error Detect */
+ u8 res23[4];
+ u32 eeer; /* ECM Error Enable */
+ u32 eeatr; /* ECM Error Attrs Capture */
+ u32 eeadr; /* ECM Error Addr Capture */
+ u8 res24[492];
+} ccsr_local_ecm_t;
+
+/* DDR memory controller registers */
+typedef struct ccsr_ddr {
+ u32 cs0_bnds; /* Chip Select 0 Memory Bounds */
+ u8 res1[4];
+ u32 cs1_bnds; /* Chip Select 1 Memory Bounds */
+ u8 res2[4];
+ u32 cs2_bnds; /* Chip Select 2 Memory Bounds */
+ u8 res3[4];
+ u32 cs3_bnds; /* Chip Select 3 Memory Bounds */
+ u8 res4[100];
+ u32 cs0_config; /* Chip Select Configuration */
+ u32 cs1_config; /* Chip Select Configuration */
+ u32 cs2_config; /* Chip Select Configuration */
+ u32 cs3_config; /* Chip Select Configuration */
+ u8 res4a[48];
+ u32 cs0_config_2; /* Chip Select Configuration 2 */
+ u32 cs1_config_2; /* Chip Select Configuration 2 */
+ u32 cs2_config_2; /* Chip Select Configuration 2 */
+ u32 cs3_config_2; /* Chip Select Configuration 2 */
+ u8 res5[48];
+ u32 timing_cfg_3; /* SDRAM Timing Configuration 3 */
+ u32 timing_cfg_0; /* SDRAM Timing Configuration 0 */
+ u32 timing_cfg_1; /* SDRAM Timing Configuration 1 */
+ u32 timing_cfg_2; /* SDRAM Timing Configuration 2 */
+ u32 sdram_cfg; /* SDRAM Control Configuration */
+ u32 sdram_cfg_2; /* SDRAM Control Configuration 2 */
+ u32 sdram_mode; /* SDRAM Mode Configuration */
+ u32 sdram_mode_2; /* SDRAM Mode Configuration 2 */
+ u32 sdram_md_cntl; /* SDRAM Mode Control */
+ u32 sdram_interval; /* SDRAM Interval Configuration */
+ u32 sdram_data_init; /* SDRAM Data initialization */
+ u8 res6[4];
+ u32 sdram_clk_cntl; /* SDRAM Clock Control */
+ u8 res7[20];
+ u32 init_addr; /* training init addr */
+ u32 init_ext_addr; /* training init extended addr */
+ u8 res8_1[16];
+ u32 timing_cfg_4; /* SDRAM Timing Configuration 4 */
+ u32 timing_cfg_5; /* SDRAM Timing Configuration 5 */
+ u8 reg8_1a[8];
+ u32 ddr_zq_cntl; /* ZQ calibration control*/
+ u32 ddr_wrlvl_cntl; /* write leveling control*/
+ u8 reg8_1aa[4];
+ u32 ddr_sr_cntr; /* self refresh counter */
+ u32 ddr_sdram_rcw_1; /* Control Words 1 */
+ u32 ddr_sdram_rcw_2; /* Control Words 2 */
+ u8 reg_1ab[8];
+ u32 ddr_wrlvl_cntl_2; /* write leveling control 2 */
+ u32 ddr_wrlvl_cntl_3; /* write leveling control 3 */
+ u8 res8_1b[104];
+ u32 sdram_mode_3; /* SDRAM Mode Configuration 3 */
+ u32 sdram_mode_4; /* SDRAM Mode Configuration 4 */
+ u32 sdram_mode_5; /* SDRAM Mode Configuration 5 */
+ u32 sdram_mode_6; /* SDRAM Mode Configuration 6 */
+ u32 sdram_mode_7; /* SDRAM Mode Configuration 7 */
+ u32 sdram_mode_8; /* SDRAM Mode Configuration 8 */
+ u8 res8_1ba[0x908];
+ u32 ddr_dsr1; /* Debug Status 1 */
+ u32 ddr_dsr2; /* Debug Status 2 */
+ u32 ddr_cdr1; /* Control Driver 1 */
+ u32 ddr_cdr2; /* Control Driver 2 */
+ u8 res8_1c[200];
+ u32 ip_rev1; /* IP Block Revision 1 */
+ u32 ip_rev2; /* IP Block Revision 2 */
+ u32 eor; /* Enhanced Optimization Register */
+ u8 res8_2[252];
+ u32 mtcr; /* Memory Test Control Register */
+ u8 res8_3[28];
+ u32 mtp1; /* Memory Test Pattern 1 */
+ u32 mtp2; /* Memory Test Pattern 2 */
+ u32 mtp3; /* Memory Test Pattern 3 */
+ u32 mtp4; /* Memory Test Pattern 4 */
+ u32 mtp5; /* Memory Test Pattern 5 */
+ u32 mtp6; /* Memory Test Pattern 6 */
+ u32 mtp7; /* Memory Test Pattern 7 */
+ u32 mtp8; /* Memory Test Pattern 8 */
+ u32 mtp9; /* Memory Test Pattern 9 */
+ u32 mtp10; /* Memory Test Pattern 10 */
+ u8 res8_4[184];
+ u32 data_err_inject_hi; /* Data Path Err Injection Mask High */
+ u32 data_err_inject_lo; /* Data Path Err Injection Mask Low */
+ u32 ecc_err_inject; /* Data Path Err Injection Mask ECC */
+ u8 res9[20];
+ u32 capture_data_hi; /* Data Path Read Capture High */
+ u32 capture_data_lo; /* Data Path Read Capture Low */
+ u32 capture_ecc; /* Data Path Read Capture ECC */
+ u8 res10[20];
+ u32 err_detect; /* Error Detect */
+ u32 err_disable; /* Error Disable */
+ u32 err_int_en;
+ u32 capture_attributes; /* Error Attrs Capture */
+ u32 capture_address; /* Error Addr Capture */
+ u32 capture_ext_address; /* Error Extended Addr Capture */
+ u32 err_sbe; /* Single-Bit ECC Error Management */
+ u8 res11[164];
+ u32 debug[32]; /* debug_1 to debug_32 */
+ u8 res12[128];
+} ccsr_ddr_t;
+
+#define DDR_EOR_RD_BDW_OPT_DIS 0x80000000 /* Read BDW Opt. disable */
+#define DDR_EOR_ADDR_HASH_EN 0x40000000 /* Address hash enabled */
+
+/* I2C Registers */
+typedef struct ccsr_i2c {
+ struct fsl_i2c i2c[1];
+ u8 res[4096 - 1 * sizeof(struct fsl_i2c)];
+} ccsr_i2c_t;
+
+#if defined(CONFIG_MPC8540) \
+ || defined(CONFIG_MPC8541) \
+ || defined(CONFIG_MPC8548) \
+ || defined(CONFIG_MPC8555)
+/* DUART Registers */
+typedef struct ccsr_duart {
+ u8 res1[1280];
+/* URBR1, UTHR1, UDLB1 with the same addr */
+ u8 urbr1_uthr1_udlb1;
+/* UIER1, UDMB1 with the same addr01 */
+ u8 uier1_udmb1;
+/* UIIR1, UFCR1, UAFR1 with the same addr */
+ u8 uiir1_ufcr1_uafr1;
+ u8 ulcr1; /* UART1 Line Control */
+ u8 umcr1; /* UART1 Modem Control */
+ u8 ulsr1; /* UART1 Line Status */
+ u8 umsr1; /* UART1 Modem Status */
+ u8 uscr1; /* UART1 Scratch */
+ u8 res2[8];
+ u8 udsr1; /* UART1 DMA Status */
+ u8 res3[239];
+/* URBR2, UTHR2, UDLB2 with the same addr */
+ u8 urbr2_uthr2_udlb2;
+/* UIER2, UDMB2 with the same addr */
+ u8 uier2_udmb2;
+/* UIIR2, UFCR2, UAFR2 with the same addr */
+ u8 uiir2_ufcr2_uafr2;
+ u8 ulcr2; /* UART2 Line Control */
+ u8 umcr2; /* UART2 Modem Control */
+ u8 ulsr2; /* UART2 Line Status */
+ u8 umsr2; /* UART2 Modem Status */
+ u8 uscr2; /* UART2 Scratch */
+ u8 res4[8];
+ u8 udsr2; /* UART2 DMA Status */
+ u8 res5[2543];
+} ccsr_duart_t;
+#else /* MPC8560 uses UART on its CPM */
+typedef struct ccsr_duart {
+ u8 res[4096];
+} ccsr_duart_t;
+#endif
+
+/* eSPI Registers */
+typedef struct ccsr_espi {
+ u32 mode; /* eSPI mode */
+ u32 event; /* eSPI event */
+ u32 mask; /* eSPI mask */
+ u32 com; /* eSPI command */
+ u32 tx; /* eSPI transmit FIFO access */
+ u32 rx; /* eSPI receive FIFO access */
+ u8 res1[8]; /* reserved */
+ u32 csmode[4]; /* 0x2c: sSPI CS0/1/2/3 mode */
+ u8 res2[4048]; /* fill up to 0x1000 */
+} ccsr_espi_t;
+
+/* PCI Registers */
+typedef struct ccsr_pcix {
+ u32 cfg_addr; /* PCIX Configuration Addr */
+ u32 cfg_data; /* PCIX Configuration Data */
+ u32 int_ack; /* PCIX IRQ Acknowledge */
+ u8 res000c[52];
+ u32 liodn_base; /* PCIX LIODN base register */
+ u8 res0044[3004];
+ u32 potar0; /* PCIX Outbound Transaction Addr 0 */
+ u32 potear0; /* PCIX Outbound Translation Extended Addr 0 */
+ u32 powbar0; /* PCIX Outbound Window Base Addr 0 */
+ u32 powbear0; /* PCIX Outbound Window Base Extended Addr 0 */
+ u32 powar0; /* PCIX Outbound Window Attrs 0 */
+ u8 res2[12];
+ u32 potar1; /* PCIX Outbound Transaction Addr 1 */
+ u32 potear1; /* PCIX Outbound Translation Extended Addr 1 */
+ u32 powbar1; /* PCIX Outbound Window Base Addr 1 */
+ u32 powbear1; /* PCIX Outbound Window Base Extended Addr 1 */
+ u32 powar1; /* PCIX Outbound Window Attrs 1 */
+ u8 res3[12];
+ u32 potar2; /* PCIX Outbound Transaction Addr 2 */
+ u32 potear2; /* PCIX Outbound Translation Extended Addr 2 */
+ u32 powbar2; /* PCIX Outbound Window Base Addr 2 */
+ u32 powbear2; /* PCIX Outbound Window Base Extended Addr 2 */
+ u32 powar2; /* PCIX Outbound Window Attrs 2 */
+ u8 res4[12];
+ u32 potar3; /* PCIX Outbound Transaction Addr 3 */
+ u32 potear3; /* PCIX Outbound Translation Extended Addr 3 */
+ u32 powbar3; /* PCIX Outbound Window Base Addr 3 */
+ u32 powbear3; /* PCIX Outbound Window Base Extended Addr 3 */
+ u32 powar3; /* PCIX Outbound Window Attrs 3 */
+ u8 res5[12];
+ u32 potar4; /* PCIX Outbound Transaction Addr 4 */
+ u32 potear4; /* PCIX Outbound Translation Extended Addr 4 */
+ u32 powbar4; /* PCIX Outbound Window Base Addr 4 */
+ u32 powbear4; /* PCIX Outbound Window Base Extended Addr 4 */
+ u32 powar4; /* PCIX Outbound Window Attrs 4 */
+ u8 res6[268];
+ u32 pitar3; /* PCIX Inbound Translation Addr 3 */
+ u32 pitear3; /* PCIX Inbound Translation Extended Addr 3 */
+ u32 piwbar3; /* PCIX Inbound Window Base Addr 3 */
+ u32 piwbear3; /* PCIX Inbound Window Base Extended Addr 3 */
+ u32 piwar3; /* PCIX Inbound Window Attrs 3 */
+ u8 res7[12];
+ u32 pitar2; /* PCIX Inbound Translation Addr 2 */
+ u32 pitear2; /* PCIX Inbound Translation Extended Addr 2 */
+ u32 piwbar2; /* PCIX Inbound Window Base Addr 2 */
+ u32 piwbear2; /* PCIX Inbound Window Base Extended Addr 2 */
+ u32 piwar2; /* PCIX Inbound Window Attrs 2 */
+ u8 res8[12];
+ u32 pitar1; /* PCIX Inbound Translation Addr 1 */
+ u32 pitear1; /* PCIX Inbound Translation Extended Addr 1 */
+ u32 piwbar1; /* PCIX Inbound Window Base Addr 1 */
+ u8 res9[4];
+ u32 piwar1; /* PCIX Inbound Window Attrs 1 */
+ u8 res10[12];
+ u32 pedr; /* PCIX Error Detect */
+ u32 pecdr; /* PCIX Error Capture Disable */
+ u32 peer; /* PCIX Error Enable */
+ u32 peattrcr; /* PCIX Error Attrs Capture */
+ u32 peaddrcr; /* PCIX Error Addr Capture */
+ u32 peextaddrcr; /* PCIX Error Extended Addr Capture */
+ u32 pedlcr; /* PCIX Error Data Low Capture */
+ u32 pedhcr; /* PCIX Error Error Data High Capture */
+ u32 gas_timr; /* PCIX Gasket Timer */
+ u8 res11[476];
+} ccsr_pcix_t;
+
+#define PCIX_COMMAND 0x62
+#define POWAR_EN 0x80000000
+#define POWAR_IO_READ 0x00080000
+#define POWAR_MEM_READ 0x00040000
+#define POWAR_IO_WRITE 0x00008000
+#define POWAR_MEM_WRITE 0x00004000
+#define POWAR_MEM_512M 0x0000001c
+#define POWAR_IO_1M 0x00000013
+
+#define PIWAR_EN 0x80000000
+#define PIWAR_PF 0x20000000
+#define PIWAR_LOCAL 0x00f00000
+#define PIWAR_READ_SNOOP 0x00050000
+#define PIWAR_WRITE_SNOOP 0x00005000
+#define PIWAR_MEM_2G 0x0000001e
+
+typedef struct ccsr_gpio {
+ u32 gpdir;
+ u32 gpodr;
+ u32 gpdat;
+ u32 gpier;
+ u32 gpimr;
+ u32 gpicr;
+} ccsr_gpio_t;
+
+/* L2 Cache Registers */
+typedef struct ccsr_l2cache {
+ u32 l2ctl; /* L2 configuration 0 */
+ u8 res1[12];
+ u32 l2cewar0; /* L2 cache external write addr 0 */
+ u8 res2[4];
+ u32 l2cewcr0; /* L2 cache external write control 0 */
+ u8 res3[4];
+ u32 l2cewar1; /* L2 cache external write addr 1 */
+ u8 res4[4];
+ u32 l2cewcr1; /* L2 cache external write control 1 */
+ u8 res5[4];
+ u32 l2cewar2; /* L2 cache external write addr 2 */
+ u8 res6[4];
+ u32 l2cewcr2; /* L2 cache external write control 2 */
+ u8 res7[4];
+ u32 l2cewar3; /* L2 cache external write addr 3 */
+ u8 res8[4];
+ u32 l2cewcr3; /* L2 cache external write control 3 */
+ u8 res9[180];
+ u32 l2srbar0; /* L2 memory-mapped SRAM base addr 0 */
+ u8 res10[4];
+ u32 l2srbar1; /* L2 memory-mapped SRAM base addr 1 */
+ u8 res11[3316];
+ u32 l2errinjhi; /* L2 error injection mask high */
+ u32 l2errinjlo; /* L2 error injection mask low */
+ u32 l2errinjctl; /* L2 error injection tag/ECC control */
+ u8 res12[20];
+ u32 l2captdatahi; /* L2 error data high capture */
+ u32 l2captdatalo; /* L2 error data low capture */
+ u32 l2captecc; /* L2 error ECC capture */
+ u8 res13[20];
+ u32 l2errdet; /* L2 error detect */
+ u32 l2errdis; /* L2 error disable */
+ u32 l2errinten; /* L2 error interrupt enable */
+ u32 l2errattr; /* L2 error attributes capture */
+ u32 l2erraddr; /* L2 error addr capture */
+ u8 res14[4];
+ u32 l2errctl; /* L2 error control */
+ u8 res15[420];
+} ccsr_l2cache_t;
+
+#define MPC85xx_L2CTL_L2E 0x80000000
+#define MPC85xx_L2CTL_L2SRAM_ENTIRE 0x00010000
+#define MPC85xx_L2ERRDIS_MBECC 0x00000008
+#define MPC85xx_L2ERRDIS_SBECC 0x00000004
+
+/* DMA Registers */
+typedef struct ccsr_dma {
+ u8 res1[256];
+ struct fsl_dma dma[4];
+ u32 dgsr; /* DMA General Status */
+ u8 res2[11516];
+} ccsr_dma_t;
+
+/* tsec */
+typedef struct ccsr_tsec {
+ u8 res1[16];
+ u32 ievent; /* IRQ Event */
+ u32 imask; /* IRQ Mask */
+ u32 edis; /* Error Disabled */
+ u8 res2[4];
+ u32 ecntrl; /* Ethernet Control */
+ u32 minflr; /* Minimum Frame Len */
+ u32 ptv; /* Pause Time Value */
+ u32 dmactrl; /* DMA Control */
+ u32 tbipa; /* TBI PHY Addr */
+ u8 res3[88];
+ u32 fifo_tx_thr; /* FIFO transmit threshold */
+ u8 res4[8];
+ u32 fifo_tx_starve; /* FIFO transmit starve */
+ u32 fifo_tx_starve_shutoff; /* FIFO transmit starve shutoff */
+ u8 res5[96];
+ u32 tctrl; /* TX Control */
+ u32 tstat; /* TX Status */
+ u8 res6[4];
+ u32 tbdlen; /* TX Buffer Desc Data Len */
+ u8 res7[16];
+ u32 ctbptrh; /* Current TX Buffer Desc Ptr High */
+ u32 ctbptr; /* Current TX Buffer Desc Ptr */
+ u8 res8[88];
+ u32 tbptrh; /* TX Buffer Desc Ptr High */
+ u32 tbptr; /* TX Buffer Desc Ptr Low */
+ u8 res9[120];
+ u32 tbaseh; /* TX Desc Base Addr High */
+ u32 tbase; /* TX Desc Base Addr */
+ u8 res10[168];
+ u32 ostbd; /* Out-of-Sequence(OOS) TX Buffer Desc */
+ u32 ostbdp; /* OOS TX Data Buffer Ptr */
+ u32 os32tbdp; /* OOS 32 Bytes TX Data Buffer Ptr Low */
+ u32 os32iptrh; /* OOS 32 Bytes TX Insert Ptr High */
+ u32 os32iptrl; /* OOS 32 Bytes TX Insert Ptr Low */
+ u32 os32tbdr; /* OOS 32 Bytes TX Reserved */
+ u32 os32iil; /* OOS 32 Bytes TX Insert Idx/Len */
+ u8 res11[52];
+ u32 rctrl; /* RX Control */
+ u32 rstat; /* RX Status */
+ u8 res12[4];
+ u32 rbdlen; /* RxBD Data Len */
+ u8 res13[16];
+ u32 crbptrh; /* Current RX Buffer Desc Ptr High */
+ u32 crbptr; /* Current RX Buffer Desc Ptr */
+ u8 res14[24];
+ u32 mrblr; /* Maximum RX Buffer Len */
+ u32 mrblr2r3; /* Maximum RX Buffer Len R2R3 */
+ u8 res15[56];
+ u32 rbptrh; /* RX Buffer Desc Ptr High 0 */
+ u32 rbptr; /* RX Buffer Desc Ptr */
+ u32 rbptrh1; /* RX Buffer Desc Ptr High 1 */
+ u32 rbptrl1; /* RX Buffer Desc Ptr Low 1 */
+ u32 rbptrh2; /* RX Buffer Desc Ptr High 2 */
+ u32 rbptrl2; /* RX Buffer Desc Ptr Low 2 */
+ u32 rbptrh3; /* RX Buffer Desc Ptr High 3 */
+ u32 rbptrl3; /* RX Buffer Desc Ptr Low 3 */
+ u8 res16[96];
+ u32 rbaseh; /* RX Desc Base Addr High 0 */
+ u32 rbase; /* RX Desc Base Addr */
+ u32 rbaseh1; /* RX Desc Base Addr High 1 */
+ u32 rbasel1; /* RX Desc Base Addr Low 1 */
+ u32 rbaseh2; /* RX Desc Base Addr High 2 */
+ u32 rbasel2; /* RX Desc Base Addr Low 2 */
+ u32 rbaseh3; /* RX Desc Base Addr High 3 */
+ u32 rbasel3; /* RX Desc Base Addr Low 3 */
+ u8 res17[224];
+ u32 maccfg1; /* MAC Configuration 1 */
+ u32 maccfg2; /* MAC Configuration 2 */
+ u32 ipgifg; /* Inter Packet Gap/Inter Frame Gap */
+ u32 hafdup; /* Half Duplex */
+ u32 maxfrm; /* Maximum Frame Len */
+ u8 res18[12];
+ u32 miimcfg; /* MII Management Configuration */
+ u32 miimcom; /* MII Management Cmd */
+ u32 miimadd; /* MII Management Addr */
+ u32 miimcon; /* MII Management Control */
+ u32 miimstat; /* MII Management Status */
+ u32 miimind; /* MII Management Indicator */
+ u8 res19[4];
+ u32 ifstat; /* Interface Status */
+ u32 macstnaddr1; /* Station Addr Part 1 */
+ u32 macstnaddr2; /* Station Addr Part 2 */
+ u8 res20[312];
+ u32 tr64; /* TX & RX 64-byte Frame Counter */
+ u32 tr127; /* TX & RX 65-127 byte Frame Counter */
+ u32 tr255; /* TX & RX 128-255 byte Frame Counter */
+ u32 tr511; /* TX & RX 256-511 byte Frame Counter */
+ u32 tr1k; /* TX & RX 512-1023 byte Frame Counter */
+ u32 trmax; /* TX & RX 1024-1518 byte Frame Counter */
+ u32 trmgv; /* TX & RX 1519-1522 byte Good VLAN Frame */
+ u32 rbyt; /* RX Byte Counter */
+ u32 rpkt; /* RX Packet Counter */
+ u32 rfcs; /* RX FCS Error Counter */
+ u32 rmca; /* RX Multicast Packet Counter */
+ u32 rbca; /* RX Broadcast Packet Counter */
+ u32 rxcf; /* RX Control Frame Packet Counter */
+ u32 rxpf; /* RX Pause Frame Packet Counter */
+ u32 rxuo; /* RX Unknown OP Code Counter */
+ u32 raln; /* RX Alignment Error Counter */
+ u32 rflr; /* RX Frame Len Error Counter */
+ u32 rcde; /* RX Code Error Counter */
+ u32 rcse; /* RX Carrier Sense Error Counter */
+ u32 rund; /* RX Undersize Packet Counter */
+ u32 rovr; /* RX Oversize Packet Counter */
+ u32 rfrg; /* RX Fragments Counter */
+ u32 rjbr; /* RX Jabber Counter */
+ u32 rdrp; /* RX Drop Counter */
+ u32 tbyt; /* TX Byte Counter Counter */
+ u32 tpkt; /* TX Packet Counter */
+ u32 tmca; /* TX Multicast Packet Counter */
+ u32 tbca; /* TX Broadcast Packet Counter */
+ u32 txpf; /* TX Pause Control Frame Counter */
+ u32 tdfr; /* TX Deferral Packet Counter */
+ u32 tedf; /* TX Excessive Deferral Packet Counter */
+ u32 tscl; /* TX Single Collision Packet Counter */
+ u32 tmcl; /* TX Multiple Collision Packet Counter */
+ u32 tlcl; /* TX Late Collision Packet Counter */
+ u32 txcl; /* TX Excessive Collision Packet Counter */
+ u32 tncl; /* TX Total Collision Counter */
+ u8 res21[4];
+ u32 tdrp; /* TX Drop Frame Counter */
+ u32 tjbr; /* TX Jabber Frame Counter */
+ u32 tfcs; /* TX FCS Error Counter */
+ u32 txcf; /* TX Control Frame Counter */
+ u32 tovr; /* TX Oversize Frame Counter */
+ u32 tund; /* TX Undersize Frame Counter */
+ u32 tfrg; /* TX Fragments Frame Counter */
+ u32 car1; /* Carry One */
+ u32 car2; /* Carry Two */
+ u32 cam1; /* Carry Mask One */
+ u32 cam2; /* Carry Mask Two */
+ u8 res22[192];
+ u32 iaddr0; /* Indivdual addr 0 */
+ u32 iaddr1; /* Indivdual addr 1 */
+ u32 iaddr2; /* Indivdual addr 2 */
+ u32 iaddr3; /* Indivdual addr 3 */
+ u32 iaddr4; /* Indivdual addr 4 */
+ u32 iaddr5; /* Indivdual addr 5 */
+ u32 iaddr6; /* Indivdual addr 6 */
+ u32 iaddr7; /* Indivdual addr 7 */
+ u8 res23[96];
+ u32 gaddr0; /* Global addr 0 */
+ u32 gaddr1; /* Global addr 1 */
+ u32 gaddr2; /* Global addr 2 */
+ u32 gaddr3; /* Global addr 3 */
+ u32 gaddr4; /* Global addr 4 */
+ u32 gaddr5; /* Global addr 5 */
+ u32 gaddr6; /* Global addr 6 */
+ u32 gaddr7; /* Global addr 7 */
+ u8 res24[96];
+ u32 pmd0; /* Pattern Match Data */
+ u8 res25[4];
+ u32 pmask0; /* Pattern Mask */
+ u8 res26[4];
+ u32 pcntrl0; /* Pattern Match Control */
+ u8 res27[4];
+ u32 pattrb0; /* Pattern Match Attrs */
+ u32 pattrbeli0; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd1; /* Pattern Match Data */
+ u8 res28[4];
+ u32 pmask1; /* Pattern Mask */
+ u8 res29[4];
+ u32 pcntrl1; /* Pattern Match Control */
+ u8 res30[4];
+ u32 pattrb1; /* Pattern Match Attrs */
+ u32 pattrbeli1; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd2; /* Pattern Match Data */
+ u8 res31[4];
+ u32 pmask2; /* Pattern Mask */
+ u8 res32[4];
+ u32 pcntrl2; /* Pattern Match Control */
+ u8 res33[4];
+ u32 pattrb2; /* Pattern Match Attrs */
+ u32 pattrbeli2; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd3; /* Pattern Match Data */
+ u8 res34[4];
+ u32 pmask3; /* Pattern Mask */
+ u8 res35[4];
+ u32 pcntrl3; /* Pattern Match Control */
+ u8 res36[4];
+ u32 pattrb3; /* Pattern Match Attrs */
+ u32 pattrbeli3; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd4; /* Pattern Match Data */
+ u8 res37[4];
+ u32 pmask4; /* Pattern Mask */
+ u8 res38[4];
+ u32 pcntrl4; /* Pattern Match Control */
+ u8 res39[4];
+ u32 pattrb4; /* Pattern Match Attrs */
+ u32 pattrbeli4; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd5; /* Pattern Match Data */
+ u8 res40[4];
+ u32 pmask5; /* Pattern Mask */
+ u8 res41[4];
+ u32 pcntrl5; /* Pattern Match Control */
+ u8 res42[4];
+ u32 pattrb5; /* Pattern Match Attrs */
+ u32 pattrbeli5; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd6; /* Pattern Match Data */
+ u8 res43[4];
+ u32 pmask6; /* Pattern Mask */
+ u8 res44[4];
+ u32 pcntrl6; /* Pattern Match Control */
+ u8 res45[4];
+ u32 pattrb6; /* Pattern Match Attrs */
+ u32 pattrbeli6; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd7; /* Pattern Match Data */
+ u8 res46[4];
+ u32 pmask7; /* Pattern Mask */
+ u8 res47[4];
+ u32 pcntrl7; /* Pattern Match Control */
+ u8 res48[4];
+ u32 pattrb7; /* Pattern Match Attrs */
+ u32 pattrbeli7; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd8; /* Pattern Match Data */
+ u8 res49[4];
+ u32 pmask8; /* Pattern Mask */
+ u8 res50[4];
+ u32 pcntrl8; /* Pattern Match Control */
+ u8 res51[4];
+ u32 pattrb8; /* Pattern Match Attrs */
+ u32 pattrbeli8; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd9; /* Pattern Match Data */
+ u8 res52[4];
+ u32 pmask9; /* Pattern Mask */
+ u8 res53[4];
+ u32 pcntrl9; /* Pattern Match Control */
+ u8 res54[4];
+ u32 pattrb9; /* Pattern Match Attrs */
+ u32 pattrbeli9; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd10; /* Pattern Match Data */
+ u8 res55[4];
+ u32 pmask10; /* Pattern Mask */
+ u8 res56[4];
+ u32 pcntrl10; /* Pattern Match Control */
+ u8 res57[4];
+ u32 pattrb10; /* Pattern Match Attrs */
+ u32 pattrbeli10; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd11; /* Pattern Match Data */
+ u8 res58[4];
+ u32 pmask11; /* Pattern Mask */
+ u8 res59[4];
+ u32 pcntrl11; /* Pattern Match Control */
+ u8 res60[4];
+ u32 pattrb11; /* Pattern Match Attrs */
+ u32 pattrbeli11; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd12; /* Pattern Match Data */
+ u8 res61[4];
+ u32 pmask12; /* Pattern Mask */
+ u8 res62[4];
+ u32 pcntrl12; /* Pattern Match Control */
+ u8 res63[4];
+ u32 pattrb12; /* Pattern Match Attrs */
+ u32 pattrbeli12; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd13; /* Pattern Match Data */
+ u8 res64[4];
+ u32 pmask13; /* Pattern Mask */
+ u8 res65[4];
+ u32 pcntrl13; /* Pattern Match Control */
+ u8 res66[4];
+ u32 pattrb13; /* Pattern Match Attrs */
+ u32 pattrbeli13; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd14; /* Pattern Match Data */
+ u8 res67[4];
+ u32 pmask14; /* Pattern Mask */
+ u8 res68[4];
+ u32 pcntrl14; /* Pattern Match Control */
+ u8 res69[4];
+ u32 pattrb14; /* Pattern Match Attrs */
+ u32 pattrbeli14; /* Pattern Match Attrs Extract Len & Idx */
+ u32 pmd15; /* Pattern Match Data */
+ u8 res70[4];
+ u32 pmask15; /* Pattern Mask */
+ u8 res71[4];
+ u32 pcntrl15; /* Pattern Match Control */
+ u8 res72[4];
+ u32 pattrb15; /* Pattern Match Attrs */
+ u32 pattrbeli15; /* Pattern Match Attrs Extract Len & Idx */
+ u8 res73[248];
+ u32 attr; /* Attrs */
+ u32 attreli; /* Attrs Extract Len & Idx */
+ u8 res74[1024];
+} ccsr_tsec_t;
+
+/* PIC Registers */
+typedef struct ccsr_pic {
+ u8 res1[64];
+ u32 ipidr0; /* Interprocessor IRQ Dispatch 0 */
+ u8 res2[12];
+ u32 ipidr1; /* Interprocessor IRQ Dispatch 1 */
+ u8 res3[12];
+ u32 ipidr2; /* Interprocessor IRQ Dispatch 2 */
+ u8 res4[12];
+ u32 ipidr3; /* Interprocessor IRQ Dispatch 3 */
+ u8 res5[12];
+ u32 ctpr; /* Current Task Priority */
+ u8 res6[12];
+ u32 whoami; /* Who Am I */
+ u8 res7[12];
+ u32 iack; /* IRQ Acknowledge */
+ u8 res8[12];
+ u32 eoi; /* End Of IRQ */
+ u8 res9[3916];
+ u32 frr; /* Feature Reporting */
+ u8 res10[28];
+ u32 gcr; /* Global Configuration */
+#define MPC85xx_PICGCR_RST 0x80000000
+#define MPC85xx_PICGCR_M 0x20000000
+ u8 res11[92];
+ u32 vir; /* Vendor Identification */
+ u8 res12[12];
+ u32 pir; /* Processor Initialization */
+ u8 res13[12];
+ u32 ipivpr0; /* IPI Vector/Priority 0 */
+ u8 res14[12];
+ u32 ipivpr1; /* IPI Vector/Priority 1 */
+ u8 res15[12];
+ u32 ipivpr2; /* IPI Vector/Priority 2 */
+ u8 res16[12];
+ u32 ipivpr3; /* IPI Vector/Priority 3 */
+ u8 res17[12];
+ u32 svr; /* Spurious Vector */
+ u8 res18[12];
+ u32 tfrr; /* Timer Frequency Reporting */
+ u8 res19[12];
+ u32 gtccr0; /* Global Timer Current Count 0 */
+ u8 res20[12];
+ u32 gtbcr0; /* Global Timer Base Count 0 */
+ u8 res21[12];
+ u32 gtvpr0; /* Global Timer Vector/Priority 0 */
+ u8 res22[12];
+ u32 gtdr0; /* Global Timer Destination 0 */
+ u8 res23[12];
+ u32 gtccr1; /* Global Timer Current Count 1 */
+ u8 res24[12];
+ u32 gtbcr1; /* Global Timer Base Count 1 */
+ u8 res25[12];
+ u32 gtvpr1; /* Global Timer Vector/Priority 1 */
+ u8 res26[12];
+ u32 gtdr1; /* Global Timer Destination 1 */
+ u8 res27[12];
+ u32 gtccr2; /* Global Timer Current Count 2 */
+ u8 res28[12];
+ u32 gtbcr2; /* Global Timer Base Count 2 */
+ u8 res29[12];
+ u32 gtvpr2; /* Global Timer Vector/Priority 2 */
+ u8 res30[12];
+ u32 gtdr2; /* Global Timer Destination 2 */
+ u8 res31[12];
+ u32 gtccr3; /* Global Timer Current Count 3 */
+ u8 res32[12];
+ u32 gtbcr3; /* Global Timer Base Count 3 */
+ u8 res33[12];
+ u32 gtvpr3; /* Global Timer Vector/Priority 3 */
+ u8 res34[12];
+ u32 gtdr3; /* Global Timer Destination 3 */
+ u8 res35[268];
+ u32 tcr; /* Timer Control */
+ u8 res36[12];
+ u32 irqsr0; /* IRQ_OUT Summary 0 */
+ u8 res37[12];
+ u32 irqsr1; /* IRQ_OUT Summary 1 */
+ u8 res38[12];
+ u32 cisr0; /* Critical IRQ Summary 0 */
+ u8 res39[12];
+ u32 cisr1; /* Critical IRQ Summary 1 */
+ u8 res40[188];
+ u32 msgr0; /* Message 0 */
+ u8 res41[12];
+ u32 msgr1; /* Message 1 */
+ u8 res42[12];
+ u32 msgr2; /* Message 2 */
+ u8 res43[12];
+ u32 msgr3; /* Message 3 */
+ u8 res44[204];
+ u32 mer; /* Message Enable */
+ u8 res45[12];
+ u32 msr; /* Message Status */
+ u8 res46[60140];
+ u32 eivpr0; /* External IRQ Vector/Priority 0 */
+ u8 res47[12];
+ u32 eidr0; /* External IRQ Destination 0 */
+ u8 res48[12];
+ u32 eivpr1; /* External IRQ Vector/Priority 1 */
+ u8 res49[12];
+ u32 eidr1; /* External IRQ Destination 1 */
+ u8 res50[12];
+ u32 eivpr2; /* External IRQ Vector/Priority 2 */
+ u8 res51[12];
+ u32 eidr2; /* External IRQ Destination 2 */
+ u8 res52[12];
+ u32 eivpr3; /* External IRQ Vector/Priority 3 */
+ u8 res53[12];
+ u32 eidr3; /* External IRQ Destination 3 */
+ u8 res54[12];
+ u32 eivpr4; /* External IRQ Vector/Priority 4 */
+ u8 res55[12];
+ u32 eidr4; /* External IRQ Destination 4 */
+ u8 res56[12];
+ u32 eivpr5; /* External IRQ Vector/Priority 5 */
+ u8 res57[12];
+ u32 eidr5; /* External IRQ Destination 5 */
+ u8 res58[12];
+ u32 eivpr6; /* External IRQ Vector/Priority 6 */
+ u8 res59[12];
+ u32 eidr6; /* External IRQ Destination 6 */
+ u8 res60[12];
+ u32 eivpr7; /* External IRQ Vector/Priority 7 */
+ u8 res61[12];
+ u32 eidr7; /* External IRQ Destination 7 */
+ u8 res62[12];
+ u32 eivpr8; /* External IRQ Vector/Priority 8 */
+ u8 res63[12];
+ u32 eidr8; /* External IRQ Destination 8 */
+ u8 res64[12];
+ u32 eivpr9; /* External IRQ Vector/Priority 9 */
+ u8 res65[12];
+ u32 eidr9; /* External IRQ Destination 9 */
+ u8 res66[12];
+ u32 eivpr10; /* External IRQ Vector/Priority 10 */
+ u8 res67[12];
+ u32 eidr10; /* External IRQ Destination 10 */
+ u8 res68[12];
+ u32 eivpr11; /* External IRQ Vector/Priority 11 */
+ u8 res69[12];
+ u32 eidr11; /* External IRQ Destination 11 */
+ u8 res70[140];
+ u32 iivpr0; /* Internal IRQ Vector/Priority 0 */
+ u8 res71[12];
+ u32 iidr0; /* Internal IRQ Destination 0 */
+ u8 res72[12];
+ u32 iivpr1; /* Internal IRQ Vector/Priority 1 */
+ u8 res73[12];
+ u32 iidr1; /* Internal IRQ Destination 1 */
+ u8 res74[12];
+ u32 iivpr2; /* Internal IRQ Vector/Priority 2 */
+ u8 res75[12];
+ u32 iidr2; /* Internal IRQ Destination 2 */
+ u8 res76[12];
+ u32 iivpr3; /* Internal IRQ Vector/Priority 3 */
+ u8 res77[12];
+ u32 iidr3; /* Internal IRQ Destination 3 */
+ u8 res78[12];
+ u32 iivpr4; /* Internal IRQ Vector/Priority 4 */
+ u8 res79[12];
+ u32 iidr4; /* Internal IRQ Destination 4 */
+ u8 res80[12];
+ u32 iivpr5; /* Internal IRQ Vector/Priority 5 */
+ u8 res81[12];
+ u32 iidr5; /* Internal IRQ Destination 5 */
+ u8 res82[12];
+ u32 iivpr6; /* Internal IRQ Vector/Priority 6 */
+ u8 res83[12];
+ u32 iidr6; /* Internal IRQ Destination 6 */
+ u8 res84[12];
+ u32 iivpr7; /* Internal IRQ Vector/Priority 7 */
+ u8 res85[12];
+ u32 iidr7; /* Internal IRQ Destination 7 */
+ u8 res86[12];
+ u32 iivpr8; /* Internal IRQ Vector/Priority 8 */
+ u8 res87[12];
+ u32 iidr8; /* Internal IRQ Destination 8 */
+ u8 res88[12];
+ u32 iivpr9; /* Internal IRQ Vector/Priority 9 */
+ u8 res89[12];
+ u32 iidr9; /* Internal IRQ Destination 9 */
+ u8 res90[12];
+ u32 iivpr10; /* Internal IRQ Vector/Priority 10 */
+ u8 res91[12];
+ u32 iidr10; /* Internal IRQ Destination 10 */
+ u8 res92[12];
+ u32 iivpr11; /* Internal IRQ Vector/Priority 11 */
+ u8 res93[12];
+ u32 iidr11; /* Internal IRQ Destination 11 */
+ u8 res94[12];
+ u32 iivpr12; /* Internal IRQ Vector/Priority 12 */
+ u8 res95[12];
+ u32 iidr12; /* Internal IRQ Destination 12 */
+ u8 res96[12];
+ u32 iivpr13; /* Internal IRQ Vector/Priority 13 */
+ u8 res97[12];
+ u32 iidr13; /* Internal IRQ Destination 13 */
+ u8 res98[12];
+ u32 iivpr14; /* Internal IRQ Vector/Priority 14 */
+ u8 res99[12];
+ u32 iidr14; /* Internal IRQ Destination 14 */
+ u8 res100[12];
+ u32 iivpr15; /* Internal IRQ Vector/Priority 15 */
+ u8 res101[12];
+ u32 iidr15; /* Internal IRQ Destination 15 */
+ u8 res102[12];
+ u32 iivpr16; /* Internal IRQ Vector/Priority 16 */
+ u8 res103[12];
+ u32 iidr16; /* Internal IRQ Destination 16 */
+ u8 res104[12];
+ u32 iivpr17; /* Internal IRQ Vector/Priority 17 */
+ u8 res105[12];
+ u32 iidr17; /* Internal IRQ Destination 17 */
+ u8 res106[12];
+ u32 iivpr18; /* Internal IRQ Vector/Priority 18 */
+ u8 res107[12];
+ u32 iidr18; /* Internal IRQ Destination 18 */
+ u8 res108[12];
+ u32 iivpr19; /* Internal IRQ Vector/Priority 19 */
+ u8 res109[12];
+ u32 iidr19; /* Internal IRQ Destination 19 */
+ u8 res110[12];
+ u32 iivpr20; /* Internal IRQ Vector/Priority 20 */
+ u8 res111[12];
+ u32 iidr20; /* Internal IRQ Destination 20 */
+ u8 res112[12];
+ u32 iivpr21; /* Internal IRQ Vector/Priority 21 */
+ u8 res113[12];
+ u32 iidr21; /* Internal IRQ Destination 21 */
+ u8 res114[12];
+ u32 iivpr22; /* Internal IRQ Vector/Priority 22 */
+ u8 res115[12];
+ u32 iidr22; /* Internal IRQ Destination 22 */
+ u8 res116[12];
+ u32 iivpr23; /* Internal IRQ Vector/Priority 23 */
+ u8 res117[12];
+ u32 iidr23; /* Internal IRQ Destination 23 */
+ u8 res118[12];
+ u32 iivpr24; /* Internal IRQ Vector/Priority 24 */
+ u8 res119[12];
+ u32 iidr24; /* Internal IRQ Destination 24 */
+ u8 res120[12];
+ u32 iivpr25; /* Internal IRQ Vector/Priority 25 */
+ u8 res121[12];
+ u32 iidr25; /* Internal IRQ Destination 25 */
+ u8 res122[12];
+ u32 iivpr26; /* Internal IRQ Vector/Priority 26 */
+ u8 res123[12];
+ u32 iidr26; /* Internal IRQ Destination 26 */
+ u8 res124[12];
+ u32 iivpr27; /* Internal IRQ Vector/Priority 27 */
+ u8 res125[12];
+ u32 iidr27; /* Internal IRQ Destination 27 */
+ u8 res126[12];
+ u32 iivpr28; /* Internal IRQ Vector/Priority 28 */
+ u8 res127[12];
+ u32 iidr28; /* Internal IRQ Destination 28 */
+ u8 res128[12];
+ u32 iivpr29; /* Internal IRQ Vector/Priority 29 */
+ u8 res129[12];
+ u32 iidr29; /* Internal IRQ Destination 29 */
+ u8 res130[12];
+ u32 iivpr30; /* Internal IRQ Vector/Priority 30 */
+ u8 res131[12];
+ u32 iidr30; /* Internal IRQ Destination 30 */
+ u8 res132[12];
+ u32 iivpr31; /* Internal IRQ Vector/Priority 31 */
+ u8 res133[12];
+ u32 iidr31; /* Internal IRQ Destination 31 */
+ u8 res134[4108];
+ u32 mivpr0; /* Messaging IRQ Vector/Priority 0 */
+ u8 res135[12];
+ u32 midr0; /* Messaging IRQ Destination 0 */
+ u8 res136[12];
+ u32 mivpr1; /* Messaging IRQ Vector/Priority 1 */
+ u8 res137[12];
+ u32 midr1; /* Messaging IRQ Destination 1 */
+ u8 res138[12];
+ u32 mivpr2; /* Messaging IRQ Vector/Priority 2 */
+ u8 res139[12];
+ u32 midr2; /* Messaging IRQ Destination 2 */
+ u8 res140[12];
+ u32 mivpr3; /* Messaging IRQ Vector/Priority 3 */
+ u8 res141[12];
+ u32 midr3; /* Messaging IRQ Destination 3 */
+ u8 res142[59852];
+ u32 ipi0dr0; /* Processor 0 Interprocessor IRQ Dispatch 0 */
+ u8 res143[12];
+ u32 ipi0dr1; /* Processor 0 Interprocessor IRQ Dispatch 1 */
+ u8 res144[12];
+ u32 ipi0dr2; /* Processor 0 Interprocessor IRQ Dispatch 2 */
+ u8 res145[12];
+ u32 ipi0dr3; /* Processor 0 Interprocessor IRQ Dispatch 3 */
+ u8 res146[12];
+ u32 ctpr0; /* Current Task Priority for Processor 0 */
+ u8 res147[12];
+ u32 whoami0; /* Who Am I for Processor 0 */
+ u8 res148[12];
+ u32 iack0; /* IRQ Acknowledge for Processor 0 */
+ u8 res149[12];
+ u32 eoi0; /* End Of IRQ for Processor 0 */
+ u8 res150[130892];
+} ccsr_pic_t;
+
+/* CPM Block */
+#ifndef CONFIG_CPM2
+typedef struct ccsr_cpm {
+ u8 res[262144];
+} ccsr_cpm_t;
+#else
+/*
+ * DPARM
+ * General SIU
+ */
+typedef struct ccsr_cpm_siu {
+ u8 res1[80];
+ u32 smaer;
+ u32 smser;
+ u32 smevr;
+ u8 res2[4];
+ u32 lmaer;
+ u32 lmser;
+ u32 lmevr;
+ u8 res3[2964];
+} ccsr_cpm_siu_t;
+
+/* IRQ Controller */
+typedef struct ccsr_cpm_intctl {
+ u16 sicr;
+ u8 res1[2];
+ u32 sivec;
+ u32 sipnrh;
+ u32 sipnrl;
+ u32 siprr;
+ u32 scprrh;
+ u32 scprrl;
+ u32 simrh;
+ u32 simrl;
+ u32 siexr;
+ u8 res2[88];
+ u32 sccr;
+ u8 res3[124];
+} ccsr_cpm_intctl_t;
+
+/* input/output port */
+typedef struct ccsr_cpm_iop {
+ u32 pdira;
+ u32 ppara;
+ u32 psora;
+ u32 podra;
+ u32 pdata;
+ u8 res1[12];
+ u32 pdirb;
+ u32 pparb;
+ u32 psorb;
+ u32 podrb;
+ u32 pdatb;
+ u8 res2[12];
+ u32 pdirc;
+ u32 pparc;
+ u32 psorc;
+ u32 podrc;
+ u32 pdatc;
+ u8 res3[12];
+ u32 pdird;
+ u32 ppard;
+ u32 psord;
+ u32 podrd;
+ u32 pdatd;
+ u8 res4[12];
+} ccsr_cpm_iop_t;
+
+/* CPM timers */
+typedef struct ccsr_cpm_timer {
+ u8 tgcr1;
+ u8 res1[3];
+ u8 tgcr2;
+ u8 res2[11];
+ u16 tmr1;
+ u16 tmr2;
+ u16 trr1;
+ u16 trr2;
+ u16 tcr1;
+ u16 tcr2;
+ u16 tcn1;
+ u16 tcn2;
+ u16 tmr3;
+ u16 tmr4;
+ u16 trr3;
+ u16 trr4;
+ u16 tcr3;
+ u16 tcr4;
+ u16 tcn3;
+ u16 tcn4;
+ u16 ter1;
+ u16 ter2;
+ u16 ter3;
+ u16 ter4;
+ u8 res3[608];
+} ccsr_cpm_timer_t;
+
+/* SDMA */
+typedef struct ccsr_cpm_sdma {
+ u8 sdsr;
+ u8 res1[3];
+ u8 sdmr;
+ u8 res2[739];
+} ccsr_cpm_sdma_t;
+
+/* FCC1 */
+typedef struct ccsr_cpm_fcc1 {
+ u32 gfmr;
+ u32 fpsmr;
+ u16 ftodr;
+ u8 res1[2];
+ u16 fdsr;
+ u8 res2[2];
+ u16 fcce;
+ u8 res3[2];
+ u16 fccm;
+ u8 res4[2];
+ u8 fccs;
+ u8 res5[3];
+ u8 ftirr_phy[4];
+} ccsr_cpm_fcc1_t;
+
+/* FCC2 */
+typedef struct ccsr_cpm_fcc2 {
+ u32 gfmr;
+ u32 fpsmr;
+ u16 ftodr;
+ u8 res1[2];
+ u16 fdsr;
+ u8 res2[2];
+ u16 fcce;
+ u8 res3[2];
+ u16 fccm;
+ u8 res4[2];
+ u8 fccs;
+ u8 res5[3];
+ u8 ftirr_phy[4];
+} ccsr_cpm_fcc2_t;
+
+/* FCC3 */
+typedef struct ccsr_cpm_fcc3 {
+ u32 gfmr;
+ u32 fpsmr;
+ u16 ftodr;
+ u8 res1[2];
+ u16 fdsr;
+ u8 res2[2];
+ u16 fcce;
+ u8 res3[2];
+ u16 fccm;
+ u8 res4[2];
+ u8 fccs;
+ u8 res5[3];
+ u8 res[36];
+} ccsr_cpm_fcc3_t;
+
+/* FCC1 extended */
+typedef struct ccsr_cpm_fcc1_ext {
+ u32 firper;
+ u32 firer;
+ u32 firsr_h;
+ u32 firsr_l;
+ u8 gfemr;
+ u8 res[15];
+
+} ccsr_cpm_fcc1_ext_t;
+
+/* FCC2 extended */
+typedef struct ccsr_cpm_fcc2_ext {
+ u32 firper;
+ u32 firer;
+ u32 firsr_h;
+ u32 firsr_l;
+ u8 gfemr;
+ u8 res[31];
+} ccsr_cpm_fcc2_ext_t;
+
+/* FCC3 extended */
+typedef struct ccsr_cpm_fcc3_ext {
+ u8 gfemr;
+ u8 res[47];
+} ccsr_cpm_fcc3_ext_t;
+
+/* TC layers */
+typedef struct ccsr_cpm_tmp1 {
+ u8 res[496];
+} ccsr_cpm_tmp1_t;
+
+/* BRGs:5,6,7,8 */
+typedef struct ccsr_cpm_brg2 {
+ u32 brgc5;
+ u32 brgc6;
+ u32 brgc7;
+ u32 brgc8;
+ u8 res[608];
+} ccsr_cpm_brg2_t;
+
+/* I2C */
+typedef struct ccsr_cpm_i2c {
+ u8 i2mod;
+ u8 res1[3];
+ u8 i2add;
+ u8 res2[3];
+ u8 i2brg;
+ u8 res3[3];
+ u8 i2com;
+ u8 res4[3];
+ u8 i2cer;
+ u8 res5[3];
+ u8 i2cmr;
+ u8 res6[331];
+} ccsr_cpm_i2c_t;
+
+/* CPM core */
+typedef struct ccsr_cpm_cp {
+ u32 cpcr;
+ u32 rccr;
+ u8 res1[14];
+ u16 rter;
+ u8 res2[2];
+ u16 rtmr;
+ u16 rtscr;
+ u8 res3[2];
+ u32 rtsr;
+ u8 res4[12];
+} ccsr_cpm_cp_t;
+
+/* BRGs:1,2,3,4 */
+typedef struct ccsr_cpm_brg1 {
+ u32 brgc1;
+ u32 brgc2;
+ u32 brgc3;
+ u32 brgc4;
+} ccsr_cpm_brg1_t;
+
+/* SCC1-SCC4 */
+typedef struct ccsr_cpm_scc {
+ u32 gsmrl;
+ u32 gsmrh;
+ u16 psmr;
+ u8 res1[2];
+ u16 todr;
+ u16 dsr;
+ u16 scce;
+ u8 res2[2];
+ u16 sccm;
+ u8 res3;
+ u8 sccs;
+ u8 res4[8];
+} ccsr_cpm_scc_t;
+
+typedef struct ccsr_cpm_tmp2 {
+ u8 res[32];
+} ccsr_cpm_tmp2_t;
+
+/* SPI */
+typedef struct ccsr_cpm_spi {
+ u16 spmode;
+ u8 res1[4];
+ u8 spie;
+ u8 res2[3];
+ u8 spim;
+ u8 res3[2];
+ u8 spcom;
+ u8 res4[82];
+} ccsr_cpm_spi_t;
+
+/* CPM MUX */
+typedef struct ccsr_cpm_mux {
+ u8 cmxsi1cr;
+ u8 res1;
+ u8 cmxsi2cr;
+ u8 res2;
+ u32 cmxfcr;
+ u32 cmxscr;
+ u8 res3[2];
+ u16 cmxuar;
+ u8 res4[16];
+} ccsr_cpm_mux_t;
+
+/* SI,MCC,etc */
+typedef struct ccsr_cpm_tmp3 {
+ u8 res[58592];
+} ccsr_cpm_tmp3_t;
+
+typedef struct ccsr_cpm_iram {
+ u32 iram[8192];
+ u8 res[98304];
+} ccsr_cpm_iram_t;
+
+typedef struct ccsr_cpm {
+ /* Some references are into the unique & known dpram spaces,
+ * others are from the generic base.
+ */
+#define im_dprambase im_dpram1
+ u8 im_dpram1[16*1024];
+ u8 res1[16*1024];
+ u8 im_dpram2[16*1024];
+ u8 res2[16*1024];
+ ccsr_cpm_siu_t im_cpm_siu; /* SIU Configuration */
+ ccsr_cpm_intctl_t im_cpm_intctl; /* IRQ Controller */
+ ccsr_cpm_iop_t im_cpm_iop; /* IO Port control/status */
+ ccsr_cpm_timer_t im_cpm_timer; /* CPM timers */
+ ccsr_cpm_sdma_t im_cpm_sdma; /* SDMA control/status */
+ ccsr_cpm_fcc1_t im_cpm_fcc1;
+ ccsr_cpm_fcc2_t im_cpm_fcc2;
+ ccsr_cpm_fcc3_t im_cpm_fcc3;
+ ccsr_cpm_fcc1_ext_t im_cpm_fcc1_ext;
+ ccsr_cpm_fcc2_ext_t im_cpm_fcc2_ext;
+ ccsr_cpm_fcc3_ext_t im_cpm_fcc3_ext;
+ ccsr_cpm_tmp1_t im_cpm_tmp1;
+ ccsr_cpm_brg2_t im_cpm_brg2;
+ ccsr_cpm_i2c_t im_cpm_i2c;
+ ccsr_cpm_cp_t im_cpm_cp;
+ ccsr_cpm_brg1_t im_cpm_brg1;
+ ccsr_cpm_scc_t im_cpm_scc[4];
+ ccsr_cpm_tmp2_t im_cpm_tmp2;
+ ccsr_cpm_spi_t im_cpm_spi;
+ ccsr_cpm_mux_t im_cpm_mux;
+ ccsr_cpm_tmp3_t im_cpm_tmp3;
+ ccsr_cpm_iram_t im_cpm_iram;
+} ccsr_cpm_t;
+#endif
+
+#ifdef CONFIG_SYS_SRIO
+/* Architectural regsiters */
+struct rio_arch {
+ u32 didcar; /* Device Identity CAR */
+ u32 dicar; /* Device Information CAR */
+ u32 aidcar; /* Assembly Identity CAR */
+ u32 aicar; /* Assembly Information CAR */
+ u32 pefcar; /* Processing Element Features CAR */
+ u8 res0[4];
+ u32 socar; /* Source Operations CAR */
+ u32 docar; /* Destination Operations CAR */
+ u8 res1[32];
+ u32 mcsr; /* Mailbox CSR */
+ u32 pwdcsr; /* Port-Write and Doorbell CSR */
+ u8 res2[4];
+ u32 pellccsr; /* Processing Element Logic Layer CCSR */
+ u8 res3[12];
+ u32 lcsbacsr; /* Local Configuration Space BACSR */
+ u32 bdidcsr; /* Base Device ID CSR */
+ u8 res4[4];
+ u32 hbdidlcsr; /* Host Base Device ID Lock CSR */
+ u32 ctcsr; /* Component Tag CSR */
+};
+
+/* Extended Features Space: 1x/4x LP-Serial Port registers */
+struct rio_lp_serial_port {
+ u32 plmreqcsr; /* Port Link Maintenance Request CSR */
+ u32 plmrespcsr; /* Port Link Maintenance Response CS */
+ u32 plascsr; /* Port Local Ackid Status CSR */
+ u8 res0[12];
+ u32 pescsr; /* Port Error and Status CSR */
+ u32 pccsr; /* Port Control CSR */
+};
+
+/* Extended Features Space: 1x/4x LP-Serial registers */
+struct rio_lp_serial {
+ u32 pmbh0csr; /* Port Maintenance Block Header 0 CSR */
+ u8 res0[28];
+ u32 pltoccsr; /* Port Link Time-out CCSR */
+ u32 prtoccsr; /* Port Response Time-out CCSR */
+ u8 res1[20];
+ u32 pgccsr; /* Port General CSR */
+ struct rio_lp_serial_port port[CONFIG_SYS_FSL_SRIO_MAX_PORTS];
+};
+
+/* Logical error reporting registers */
+struct rio_logical_err {
+ u32 erbh; /* Error Reporting Block Header Register */
+ u8 res0[4];
+ u32 ltledcsr; /* Logical/Transport layer error DCSR */
+ u32 ltleecsr; /* Logical/Transport layer error ECSR */
+ u8 res1[4];
+ u32 ltlaccsr; /* Logical/Transport layer ACCSR */
+ u32 ltldidccsr; /* Logical/Transport layer DID CCSR */
+ u32 ltlcccsr; /* Logical/Transport layer control CCSR */
+};
+
+/* Physical error reporting port registers */
+struct rio_phys_err_port {
+ u32 edcsr; /* Port error detect CSR */
+ u32 erecsr; /* Port error rate enable CSR */
+ u32 ecacsr; /* Port error capture attributes CSR */
+ u32 pcseccsr0; /* Port packet/control symbol ECCSR 0 */
+ u32 peccsr[3]; /* Port error capture CSR */
+ u8 res0[12];
+ u32 ercsr; /* Port error rate CSR */
+ u32 ertcsr; /* Port error rate threshold CSR */
+ u8 res1[16];
+};
+
+/* Physical error reporting registers */
+struct rio_phys_err {
+ struct rio_phys_err_port port[CONFIG_SYS_FSL_SRIO_MAX_PORTS];
+};
+
+/* Implementation Space: General Port-Common */
+struct rio_impl_common {
+ u8 res0[4];
+ u32 llcr; /* Logical Layer Configuration Register */
+ u8 res1[8];
+ u32 epwisr; /* Error / Port-Write Interrupt SR */
+ u8 res2[12];
+ u32 lretcr; /* Logical Retry Error Threshold CR */
+ u8 res3[92];
+ u32 pretcr; /* Physical Retry Erorr Threshold CR */
+ u8 res4[124];
+};
+
+/* Implementation Space: Port Specific */
+struct rio_impl_port_spec {
+ u32 adidcsr; /* Port Alt. Device ID CSR */
+ u8 res0[28];
+ u32 ptaacr; /* Port Pass-Through/Accept-All CR */
+ u32 lopttlcr;
+ u8 res1[8];
+ u32 iecsr; /* Port Implementation Error CSR */
+ u8 res2[12];
+ u32 pcr; /* Port Phsyical Configuration Register */
+ u8 res3[20];
+ u32 slcsr; /* Port Serial Link CSR */
+ u8 res4[4];
+ u32 sleicr; /* Port Serial Link Error Injection */
+ u32 a0txcr; /* Port Arbitration 0 Tx CR */
+ u32 a1txcr; /* Port Arbitration 1 Tx CR */
+ u32 a2txcr; /* Port Arbitration 2 Tx CR */
+ u32 mreqtxbacr[3]; /* Port Request Tx Buffer ACR */
+ u32 mrspfctxbacr; /* Port Response/Flow Control Tx Buffer ACR */
+};
+
+/* Implementation Space: register */
+struct rio_implement {
+ struct rio_impl_common com;
+ struct rio_impl_port_spec port[CONFIG_SYS_FSL_SRIO_MAX_PORTS];
+};
+
+/* Revision Control Register */
+struct rio_rev_ctrl {
+ u32 ipbrr[2]; /* IP Block Revision Register */
+};
+
+struct rio_atmu_row {
+ u32 rowtar; /* RapidIO Outbound Window TAR */
+ u32 rowtear; /* RapidIO Outbound Window TEAR */
+ u32 rowbar;
+ u8 res0[4];
+ u32 rowar; /* RapidIO Outbound Attributes Register */
+ u32 rowsr[3]; /* Port RapidIO outbound window segment register */
+};
+
+struct rio_atmu_riw {
+ u32 riwtar; /* RapidIO Inbound Window Translation AR */
+ u8 res0[4];
+ u32 riwbar; /* RapidIO Inbound Window Base AR */
+ u8 res1[4];
+ u32 riwar; /* RapidIO Inbound Attributes Register */
+ u8 res2[12];
+};
+
+/* ATMU window registers */
+struct rio_atmu_win {
+ struct rio_atmu_row outbw[CONFIG_SYS_FSL_SRIO_OB_WIN_NUM];
+ u8 res0[64];
+ struct rio_atmu_riw inbw[CONFIG_SYS_FSL_SRIO_IB_WIN_NUM];
+};
+
+struct rio_atmu {
+ struct rio_atmu_win port[CONFIG_SYS_FSL_SRIO_MAX_PORTS];
+};
+
+#ifdef CONFIG_SYS_FSL_RMU
+struct rio_msg {
+ u32 omr; /* Outbound Mode Register */
+ u32 osr; /* Outbound Status Register */
+ u32 eodqdpar; /* Extended Outbound DQ DPAR */
+ u32 odqdpar; /* Outbound Descriptor Queue DPAR */
+ u32 eosar; /* Extended Outbound Unit Source AR */
+ u32 osar; /* Outbound Unit Source AR */
+ u32 odpr; /* Outbound Destination Port Register */
+ u32 odatr; /* Outbound Destination Attributes Register */
+ u32 odcr; /* Outbound Doubleword Count Register */
+ u32 eodqepar; /* Extended Outbound DQ EPAR */
+ u32 odqepar; /* Outbound Descriptor Queue EPAR */
+ u32 oretr; /* Outbound Retry Error Threshold Register */
+ u32 omgr; /* Outbound Multicast Group Register */
+ u32 omlr; /* Outbound Multicast List Register */
+ u8 res0[40];
+ u32 imr; /* Outbound Mode Register */
+ u32 isr; /* Inbound Status Register */
+ u32 eidqdpar; /* Extended Inbound Descriptor Queue DPAR */
+ u32 idqdpar; /* Inbound Descriptor Queue DPAR */
+ u32 eifqepar; /* Extended Inbound Frame Queue EPAR */
+ u32 ifqepar; /* Inbound Frame Queue EPAR */
+ u32 imirir; /* Inbound Maximum Interrutp RIR */
+ u8 res1[4];
+ u32 eihqepar; /* Extended inbound message header queue EPAR */
+ u32 ihqepar; /* Inbound message header queue EPAR */
+ u8 res2[120];
+};
+
+struct rio_dbell {
+ u32 odmr; /* Outbound Doorbell Mode Register */
+ u32 odsr; /* Outbound Doorbell Status Register */
+ u8 res0[16];
+ u32 oddpr; /* Outbound Doorbell Destination Port */
+ u32 oddatr; /* Outbound Doorbell Destination AR */
+ u8 res1[12];
+ u32 oddretr; /* Outbound Doorbell Retry Threshold CR */
+ u8 res2[48];
+ u32 idmr; /* Inbound Doorbell Mode Register */
+ u32 idsr; /* Inbound Doorbell Status Register */
+ u32 iedqdpar; /* Extended Inbound Doorbell Queue DPAR */
+ u32 iqdpar; /* Inbound Doorbell Queue DPAR */
+ u32 iedqepar; /* Extended Inbound Doorbell Queue EPAR */
+ u32 idqepar; /* Inbound Doorbell Queue EPAR */
+ u32 idmirir; /* Inbound Doorbell Max Interrupt RIR */
+};
+
+struct rio_pw {
+ u32 pwmr; /* Port-Write Mode Register */
+ u32 pwsr; /* Port-Write Status Register */
+ u32 epwqbar; /* Extended Port-Write Queue BAR */
+ u32 pwqbar; /* Port-Write Queue Base Address Register */
+};
+#endif
+
+/* RapidIO Registers */
+struct ccsr_rio {
+ struct rio_arch arch;
+ u8 res0[144];
+ struct rio_lp_serial lp_serial;
+ u8 res1[1152];
+ struct rio_logical_err logical_err;
+ u8 res2[32];
+ struct rio_phys_err phys_err;
+ u8 res3[63808];
+ struct rio_implement impl;
+ u8 res4[2552];
+ struct rio_rev_ctrl rev;
+ struct rio_atmu atmu;
+#ifdef CONFIG_SYS_FSL_RMU
+ u8 res5[8192];
+ struct rio_msg msg[CONFIG_SYS_FSL_SRIO_MSG_UNIT_NUM];
+ u8 res6[512];
+ struct rio_dbell dbell;
+ u8 res7[100];
+ struct rio_pw pw;
+#endif
+};
+#endif
+
+/* Quick Engine Block Pin Muxing Registers */
+typedef struct par_io {
+ u32 cpodr;
+ u32 cpdat;
+ u32 cpdir1;
+ u32 cpdir2;
+ u32 cppar1;
+ u32 cppar2;
+ u8 res[8];
+} par_io_t;
+
+#ifdef CONFIG_SYS_FSL_CPC
+/*
+ * Define a single offset that is the start of all the CPC register
+ * blocks - if there is more than one CPC, we expect these to be
+ * contiguous 4k regions
+ */
+
+typedef struct cpc_corenet {
+ u32 cpccsr0; /* Config/status reg */
+ u32 res1;
+ u32 cpccfg0; /* Configuration register */
+ u32 res2;
+ u32 cpcewcr0; /* External Write reg 0 */
+ u32 cpcewabr0; /* External write base reg 0 */
+ u32 res3[2];
+ u32 cpcewcr1; /* External Write reg 1 */
+ u32 cpcewabr1; /* External write base reg 1 */
+ u32 res4[54];
+ u32 cpcsrcr1; /* SRAM control reg 1 */
+ u32 cpcsrcr0; /* SRAM control reg 0 */
+ u32 res5[62];
+ struct {
+ u32 id; /* partition ID */
+ u32 res;
+ u32 alloc; /* partition allocation */
+ u32 way; /* partition way */
+ } partition_regs[16];
+ u32 res6[704];
+ u32 cpcerrinjhi; /* Error injection high */
+ u32 cpcerrinjlo; /* Error injection lo */
+ u32 cpcerrinjctl; /* Error injection control */
+ u32 res7[5];
+ u32 cpccaptdatahi; /* capture data high */
+ u32 cpccaptdatalo; /* capture data low */
+ u32 cpcaptecc; /* capture ECC */
+ u32 res8[5];
+ u32 cpcerrdet; /* error detect */
+ u32 cpcerrdis; /* error disable */
+ u32 cpcerrinten; /* errir interrupt enable */
+ u32 cpcerrattr; /* error attribute */
+ u32 cpcerreaddr; /* error extended address */
+ u32 cpcerraddr; /* error address */
+ u32 cpcerrctl; /* error control */
+ u32 res9[41]; /* pad out to 4k */
+ u32 cpchdbcr0; /* hardware debug control register 0 */
+ u32 res10[63]; /* pad out to 4k */
+} cpc_corenet_t;
+
+#define CPC_CSR0_CE 0x80000000 /* Cache Enable */
+#define CPC_CSR0_PE 0x40000000 /* Enable ECC */
+#define CPC_CSR0_FI 0x00200000 /* Cache Flash Invalidate */
+#define CPC_CSR0_WT 0x00080000 /* Write-through mode */
+#define CPC_CSR0_FL 0x00000800 /* Hardware cache flush */
+#define CPC_CSR0_LFC 0x00000400 /* Cache Lock Flash Clear */
+#define CPC_CFG0_SZ_MASK 0x00003fff
+#define CPC_CFG0_SZ_K(x) ((x & CPC_CFG0_SZ_MASK) << 6)
+#define CPC_CFG0_NUM_WAYS(x) (((x >> 14) & 0x1f) + 1)
+#define CPC_CFG0_LINE_SZ(x) ((((x >> 23) & 0x3) + 1) * 32)
+#define CPC_SRCR1_SRBARU_MASK 0x0000ffff
+#define CPC_SRCR1_SRBARU(x) (((unsigned long long)x >> 32) \
+ & CPC_SRCR1_SRBARU_MASK)
+#define CPC_SRCR0_SRBARL_MASK 0xffff8000
+#define CPC_SRCR0_SRBARL(x) (x & CPC_SRCR0_SRBARL_MASK)
+#define CPC_SRCR0_INTLVEN 0x00000100
+#define CPC_SRCR0_SRAMSZ_1_WAY 0x00000000
+#define CPC_SRCR0_SRAMSZ_2_WAY 0x00000002
+#define CPC_SRCR0_SRAMSZ_4_WAY 0x00000004
+#define CPC_SRCR0_SRAMSZ_8_WAY 0x00000006
+#define CPC_SRCR0_SRAMSZ_16_WAY 0x00000008
+#define CPC_SRCR0_SRAMSZ_32_WAY 0x0000000a
+#define CPC_SRCR0_SRAMEN 0x00000001
+#define CPC_ERRDIS_TMHITDIS 0x00000080 /* multi-way hit disable */
+#define CPC_HDBCR0_CDQ_SPEC_DIS 0x08000000
+#define CPC_HDBCR0_TAG_ECC_SCRUB_DIS 0x01000000
+#define CPC_HDBCR0_DATA_ECC_SCRUB_DIS 0x00400000
+#endif /* CONFIG_SYS_FSL_CPC */
+
+/* Global Utilities Block */
+#ifdef CONFIG_FSL_CORENET
+typedef struct ccsr_gur {
+ u32 porsr1; /* POR status 1 */
+ u32 porsr2; /* POR status 2 */
+ u8 res_008[0x20-0x8];
+ u32 gpporcr1; /* General-purpose POR configuration */
+ u32 gpporcr2; /* General-purpose POR configuration 2 */
+ u32 dcfg_fusesr; /* Fuse status register */
+#define FSL_CORENET_DCFG_FUSESR_VID_SHIFT 25
+#define FSL_CORENET_DCFG_FUSESR_VID_MASK 0x1F
+#define FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT 20
+#define FSL_CORENET_DCFG_FUSESR_ALTVID_MASK 0x1F
+ u8 res_02c[0x70-0x2c];
+ u32 devdisr; /* Device disable control */
+ u32 devdisr2; /* Device disable control 2 */
+ u32 devdisr3; /* Device disable control 3 */
+ u32 devdisr4; /* Device disable control 4 */
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ u32 devdisr5; /* Device disable control 5 */
+#define FSL_CORENET_DEVDISR_PBL 0x80000000
+#define FSL_CORENET_DEVDISR_PMAN 0x40000000
+#define FSL_CORENET_DEVDISR_ESDHC 0x20000000
+#define FSL_CORENET_DEVDISR_DMA1 0x00800000
+#define FSL_CORENET_DEVDISR_DMA2 0x00400000
+#define FSL_CORENET_DEVDISR_USB1 0x00080000
+#define FSL_CORENET_DEVDISR_USB2 0x00040000
+#define FSL_CORENET_DEVDISR_SATA1 0x00008000
+#define FSL_CORENET_DEVDISR_SATA2 0x00004000
+#define FSL_CORENET_DEVDISR_PME 0x00000800
+#define FSL_CORENET_DEVDISR_SEC 0x00000200
+#define FSL_CORENET_DEVDISR_RMU 0x00000080
+#define FSL_CORENET_DEVDISR_DCE 0x00000040
+#define FSL_CORENET_DEVDISR2_DTSEC1_1 0x80000000
+#define FSL_CORENET_DEVDISR2_DTSEC1_2 0x40000000
+#define FSL_CORENET_DEVDISR2_DTSEC1_3 0x20000000
+#define FSL_CORENET_DEVDISR2_DTSEC1_4 0x10000000
+#define FSL_CORENET_DEVDISR2_DTSEC1_5 0x08000000
+#define FSL_CORENET_DEVDISR2_DTSEC1_6 0x04000000
+#define FSL_CORENET_DEVDISR2_DTSEC1_9 0x00800000
+#define FSL_CORENET_DEVDISR2_DTSEC1_10 0x00400000
+#define FSL_CORENET_DEVDISR2_10GEC1_1 0x00800000
+#define FSL_CORENET_DEVDISR2_10GEC1_2 0x00400000
+#define FSL_CORENET_DEVDISR2_DTSEC2_1 0x00080000
+#define FSL_CORENET_DEVDISR2_DTSEC2_2 0x00040000
+#define FSL_CORENET_DEVDISR2_DTSEC2_3 0x00020000
+#define FSL_CORENET_DEVDISR2_DTSEC2_4 0x00010000
+#define FSL_CORENET_DEVDISR2_DTSEC2_5 0x00008000
+#define FSL_CORENET_DEVDISR2_DTSEC2_6 0x00004000
+#define FSL_CORENET_DEVDISR2_DTSEC2_9 0x00000800
+#define FSL_CORENET_DEVDISR2_DTSEC2_10 0x00000400
+#define FSL_CORENET_DEVDISR2_10GEC2_1 0x00000800
+#define FSL_CORENET_DEVDISR2_10GEC2_2 0x00000400
+#define FSL_CORENET_DEVDISR2_FM1 0x00000080
+#define FSL_CORENET_DEVDISR2_FM2 0x00000040
+#define FSL_CORENET_DEVDISR2_CPRI 0x00000008
+#define FSL_CORENET_DEVDISR3_PCIE1 0x80000000
+#define FSL_CORENET_DEVDISR3_PCIE2 0x40000000
+#define FSL_CORENET_DEVDISR3_PCIE3 0x20000000
+#define FSL_CORENET_DEVDISR3_PCIE4 0x10000000
+#define FSL_CORENET_DEVDISR3_SRIO1 0x08000000
+#define FSL_CORENET_DEVDISR3_SRIO2 0x04000000
+#define FSL_CORENET_DEVDISR3_QMAN 0x00080000
+#define FSL_CORENET_DEVDISR3_BMAN 0x00040000
+#define FSL_CORENET_DEVDISR3_LA1 0x00008000
+#define FSL_CORENET_DEVDISR3_MAPLE1 0x00000800
+#define FSL_CORENET_DEVDISR3_MAPLE2 0x00000400
+#define FSL_CORENET_DEVDISR3_MAPLE3 0x00000200
+#define FSL_CORENET_DEVDISR4_I2C1 0x80000000
+#define FSL_CORENET_DEVDISR4_I2C2 0x40000000
+#define FSL_CORENET_DEVDISR4_DUART1 0x20000000
+#define FSL_CORENET_DEVDISR4_DUART2 0x10000000
+#define FSL_CORENET_DEVDISR4_ESPI 0x08000000
+#define FSL_CORENET_DEVDISR5_DDR1 0x80000000
+#define FSL_CORENET_DEVDISR5_DDR2 0x40000000
+#define FSL_CORENET_DEVDISR5_DDR3 0x20000000
+#define FSL_CORENET_DEVDISR5_CPC1 0x08000000
+#define FSL_CORENET_DEVDISR5_CPC2 0x04000000
+#define FSL_CORENET_DEVDISR5_CPC3 0x02000000
+#define FSL_CORENET_DEVDISR5_IFC 0x00800000
+#define FSL_CORENET_DEVDISR5_GPIO 0x00400000
+#define FSL_CORENET_DEVDISR5_DBG 0x00200000
+#define FSL_CORENET_DEVDISR5_NAL 0x00100000
+#define FSL_CORENET_DEVDISR5_TIMERS 0x00020000
+#define FSL_CORENET_NUM_DEVDISR 5
+#else
+#define FSL_CORENET_DEVDISR_PCIE1 0x80000000
+#define FSL_CORENET_DEVDISR_PCIE2 0x40000000
+#define FSL_CORENET_DEVDISR_PCIE3 0x20000000
+#define FSL_CORENET_DEVDISR_PCIE4 0x10000000
+#define FSL_CORENET_DEVDISR_RMU 0x08000000
+#define FSL_CORENET_DEVDISR_SRIO1 0x04000000
+#define FSL_CORENET_DEVDISR_SRIO2 0x02000000
+#define FSL_CORENET_DEVDISR_DMA1 0x00400000
+#define FSL_CORENET_DEVDISR_DMA2 0x00200000
+#define FSL_CORENET_DEVDISR_DDR1 0x00100000
+#define FSL_CORENET_DEVDISR_DDR2 0x00080000
+#define FSL_CORENET_DEVDISR_DBG 0x00010000
+#define FSL_CORENET_DEVDISR_NAL 0x00008000
+#define FSL_CORENET_DEVDISR_SATA1 0x00004000
+#define FSL_CORENET_DEVDISR_SATA2 0x00002000
+#define FSL_CORENET_DEVDISR_ELBC 0x00001000
+#define FSL_CORENET_DEVDISR_USB1 0x00000800
+#define FSL_CORENET_DEVDISR_USB2 0x00000400
+#define FSL_CORENET_DEVDISR_ESDHC 0x00000100
+#define FSL_CORENET_DEVDISR_GPIO 0x00000080
+#define FSL_CORENET_DEVDISR_ESPI 0x00000040
+#define FSL_CORENET_DEVDISR_I2C1 0x00000020
+#define FSL_CORENET_DEVDISR_I2C2 0x00000010
+#define FSL_CORENET_DEVDISR_DUART1 0x00000002
+#define FSL_CORENET_DEVDISR_DUART2 0x00000001
+#define FSL_CORENET_DEVDISR2_PME 0x80000000
+#define FSL_CORENET_DEVDISR2_SEC 0x40000000
+#define FSL_CORENET_DEVDISR2_QMBM 0x08000000
+#define FSL_CORENET_DEVDISR2_FM1 0x02000000
+#define FSL_CORENET_DEVDISR2_10GEC1 0x01000000
+#define FSL_CORENET_DEVDISR2_DTSEC1_1 0x00800000
+#define FSL_CORENET_DEVDISR2_DTSEC1_2 0x00400000
+#define FSL_CORENET_DEVDISR2_DTSEC1_3 0x00200000
+#define FSL_CORENET_DEVDISR2_DTSEC1_4 0x00100000
+#define FSL_CORENET_DEVDISR2_DTSEC1_5 0x00080000
+#define FSL_CORENET_DEVDISR2_FM2 0x00020000
+#define FSL_CORENET_DEVDISR2_10GEC2 0x00010000
+#define FSL_CORENET_DEVDISR2_DTSEC2_1 0x00008000
+#define FSL_CORENET_DEVDISR2_DTSEC2_2 0x00004000
+#define FSL_CORENET_DEVDISR2_DTSEC2_3 0x00002000
+#define FSL_CORENET_DEVDISR2_DTSEC2_4 0x00001000
+#define FSL_CORENET_DEVDISR2_DTSEC2_5 0x00000800
+#define FSL_CORENET_NUM_DEVDISR 2
+ u32 powmgtcsr; /* Power management status & control */
+#endif
+ u8 res8[12];
+ u32 coredisru; /* uppper portion for support of 64 cores */
+ u32 coredisrl; /* lower portion for support of 64 cores */
+ u8 res9[8];
+ u32 pvr; /* Processor version */
+ u32 svr; /* System version */
+ u8 res10[8];
+ u32 rstcr; /* Reset control */
+ u32 rstrqpblsr; /* Reset request preboot loader status */
+ u8 res11[8];
+ u32 rstrqmr1; /* Reset request mask */
+ u8 res12[4];
+ u32 rstrqsr1; /* Reset request status */
+ u8 res13[4];
+ u8 res14[4];
+ u32 rstrqwdtmrl; /* Reset request WDT mask */
+ u8 res15[4];
+ u32 rstrqwdtsrl; /* Reset request WDT status */
+ u8 res16[4];
+ u32 brrl; /* Boot release */
+ u8 res17[24];
+ u32 rcwsr[16]; /* Reset control word status */
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+#define FSL_CORENET_RCWSR0_MEM_PLL_RAT_SHIFT 16
+#define FSL_CORENET_RCWSR0_MEM_PLL_RAT_MASK 0x3f
+#if defined(CONFIG_PPC_T4240) || defined(CONFIG_PPC_T4160)
+#define FSL_CORENET2_RCWSR4_SRDS1_PRTCL 0xfc000000
+#define FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT 26
+#define FSL_CORENET2_RCWSR4_SRDS2_PRTCL 0x00fe0000
+#define FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT 17
+#define FSL_CORENET2_RCWSR4_SRDS3_PRTCL 0x0000f800
+#define FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT 11
+#define FSL_CORENET2_RCWSR4_SRDS4_PRTCL 0x000000f8
+#define FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT 3
+#define FSL_CORENET_RCWSR6_BOOT_LOC 0x0f800000
+#elif defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_B4420)
+#define FSL_CORENET2_RCWSR4_SRDS1_PRTCL 0xfe000000
+#define FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT 25
+#define FSL_CORENET2_RCWSR4_SRDS2_PRTCL 0x00ff0000
+#define FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT 16
+#define FSL_CORENET_RCWSR6_BOOT_LOC 0x0f800000
+#elif defined(CONFIG_PPC_T1040)
+#define FSL_CORENET2_RCWSR4_SRDS1_PRTCL 0xff000000
+#define FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT 24
+#define FSL_CORENET2_RCWSR4_SRDS2_PRTCL 0x00fe0000
+#define FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT 17
+#endif
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S1_PLL1 0x00800000
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S1_PLL2 0x00400000
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S2_PLL1 0x00200000
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S2_PLL2 0x00100000
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S3_PLL1 0x00080000
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S3_PLL2 0x00040000
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S4_PLL1 0x00020000
+#define FSL_CORENET2_RCWSR5_SRDS_PLL_PD_S4_PLL2 0x00010000
+
+#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+#define FSL_CORENET_RCWSR0_MEM_PLL_RAT_SHIFT 17
+#define FSL_CORENET_RCWSR0_MEM_PLL_RAT_MASK 0x1f
+#define FSL_CORENET_RCWSR4_SRDS_PRTCL 0xfc000000
+#define FSL_CORENET_RCWSR5_DDR_SYNC 0x00000080
+#define FSL_CORENET_RCWSR5_DDR_SYNC_SHIFT 7
+#define FSL_CORENET_RCWSR5_SRDS_EN 0x00002000
+#define FSL_CORENET_RCWSR5_SRDS2_EN 0x00001000
+#define FSL_CORENET_RCWSR6_BOOT_LOC 0x0f800000
+#define FSL_CORENET_RCWSRn_SRDS_LPD_B2 0x3c000000 /* bits 162..165 */
+#define FSL_CORENET_RCWSRn_SRDS_LPD_B3 0x003c0000 /* bits 170..173 */
+#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+#define FSL_CORENET_RCWSR7_MCK_TO_PLAT_RAT 0x00400000
+#define FSL_CORENET_RCWSR8_HOST_AGT_B1 0x00e00000
+#define FSL_CORENET_RCWSR8_HOST_AGT_B2 0x00100000
+#define FSL_CORENET_RCWSR11_EC1 0x00c00000 /* bits 360..361 */
+#ifdef CONFIG_PPC_P4080
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC1 0x00000000
+#define FSL_CORENET_RCWSR11_EC1_FM1_USB1 0x00800000
+#define FSL_CORENET_RCWSR11_EC2 0x001c0000 /* bits 363..365 */
+#define FSL_CORENET_RCWSR11_EC2_FM2_DTSEC1 0x00000000
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC2 0x00080000
+#define FSL_CORENET_RCWSR11_EC2_USB2 0x00100000
+#endif
+#if defined(CONFIG_PPC_P2041) \
+ || defined(CONFIG_PPC_P3041) || defined(CONFIG_PPC_P5020)
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_RGMII 0x00000000
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_MII 0x00800000
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC4_NONE 0x00c00000
+#define FSL_CORENET_RCWSR11_EC2 0x00180000 /* bits 363..364 */
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_RGMII 0x00000000
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_MII 0x00100000
+#define FSL_CORENET_RCWSR11_EC2_FM1_DTSEC5_NONE 0x00180000
+#endif
+#if defined(CONFIG_PPC_P5040)
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC5_RGMII 0x00000000
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC5_MII 0x00800000
+#define FSL_CORENET_RCWSR11_EC1_FM1_DTSEC5_NONE 0x00c00000
+#define FSL_CORENET_RCWSR11_EC2 0x00180000 /* bits 363..364 */
+#define FSL_CORENET_RCWSR11_EC2_FM2_DTSEC5_RGMII 0x00000000
+#define FSL_CORENET_RCWSR11_EC2_FM2_DTSEC5_MII 0x00100000
+#define FSL_CORENET_RCWSR11_EC2_FM2_DTSEC5_NONE 0x00180000
+#endif
+#if defined(CONFIG_PPC_T4240) || defined(CONFIG_PPC_T4160)
+#define FSL_CORENET_RCWSR13_EC1 0x60000000 /* bits 417..418 */
+#define FSL_CORENET_RCWSR13_EC1_FM2_DTSEC5_RGMII 0x00000000
+#define FSL_CORENET_RCWSR13_EC1_FM2_GPIO 0x40000000
+#define FSL_CORENET_RCWSR13_EC2 0x18000000 /* bits 419..420 */
+#define FSL_CORENET_RCWSR13_EC2_FM1_DTSEC5_RGMII 0x00000000
+#define FSL_CORENET_RCWSR13_EC2_FM1_DTSEC6_RGMII 0x08000000
+#define FSL_CORENET_RCWSR13_EC2_FM1_GPIO 0x10000000
+#endif
+ u8 res18[192];
+ u32 scratchrw[4]; /* Scratch Read/Write */
+ u8 res19[240];
+ u32 scratchw1r[4]; /* Scratch Read (Write once) */
+ u8 res20[240];
+ u32 scrtsr[8]; /* Core reset status */
+ u8 res21[224];
+ u32 pex1liodnr; /* PCI Express 1 LIODN */
+ u32 pex2liodnr; /* PCI Express 2 LIODN */
+ u32 pex3liodnr; /* PCI Express 3 LIODN */
+ u32 pex4liodnr; /* PCI Express 4 LIODN */
+ u32 rio1liodnr; /* RIO 1 LIODN */
+ u32 rio2liodnr; /* RIO 2 LIODN */
+ u32 rio3liodnr; /* RIO 3 LIODN */
+ u32 rio4liodnr; /* RIO 4 LIODN */
+ u32 usb1liodnr; /* USB 1 LIODN */
+ u32 usb2liodnr; /* USB 2 LIODN */
+ u32 usb3liodnr; /* USB 3 LIODN */
+ u32 usb4liodnr; /* USB 4 LIODN */
+ u32 sdmmc1liodnr; /* SD/MMC 1 LIODN */
+ u32 sdmmc2liodnr; /* SD/MMC 2 LIODN */
+ u32 sdmmc3liodnr; /* SD/MMC 3 LIODN */
+ u32 sdmmc4liodnr; /* SD/MMC 4 LIODN */
+ u32 rio1maintliodnr;/* RIO 1 Maintenance LIODN */
+ u32 rio2maintliodnr;/* RIO 2 Maintenance LIODN */
+ u32 rio3maintliodnr;/* RIO 3 Maintenance LIODN */
+ u32 rio4maintliodnr;/* RIO 4 Maintenance LIODN */
+ u32 sata1liodnr; /* SATA 1 LIODN */
+ u32 sata2liodnr; /* SATA 2 LIODN */
+ u32 sata3liodnr; /* SATA 3 LIODN */
+ u32 sata4liodnr; /* SATA 4 LIODN */
+ u8 res22[32];
+ u32 dma1liodnr; /* DMA 1 LIODN */
+ u32 dma2liodnr; /* DMA 2 LIODN */
+ u32 dma3liodnr; /* DMA 3 LIODN */
+ u32 dma4liodnr; /* DMA 4 LIODN */
+ u8 res23[48];
+ u8 res24[64];
+ u32 pblsr; /* Preboot loader status */
+ u32 pamubypenr; /* PAMU bypass enable */
+ u32 dmacr1; /* DMA control */
+ u8 res25[4];
+ u32 gensr1; /* General status */
+ u8 res26[12];
+ u32 gencr1; /* General control */
+ u8 res27[12];
+ u8 res28[4];
+ u32 cgensrl; /* Core general status */
+ u8 res29[8];
+ u8 res30[4];
+ u32 cgencrl; /* Core general control */
+ u8 res31[184];
+ u32 sriopstecr; /* SRIO prescaler timer enable control */
+ u32 dcsrcr; /* DCSR Control register */
+ u8 res31a[56];
+ u32 tp_ityp[64]; /* Topology Initiator Type Register */
+ struct {
+ u32 upper;
+ u32 lower;
+ } tp_cluster[16]; /* Core Cluster n Topology Register */
+ u8 res32[1344];
+ u32 pmuxcr; /* Pin multiplexing control */
+ u8 res33[60];
+ u32 iovselsr; /* I/O voltage selection status */
+ u8 res34[28];
+ u32 ddrclkdr; /* DDR clock disable */
+ u8 res35;
+ u32 elbcclkdr; /* eLBC clock disable */
+ u8 res36[20];
+ u32 sdhcpcr; /* eSDHC polarity configuration */
+ u8 res37[380];
+} ccsr_gur_t;
+
+#define TP_ITYP_AV 0x00000001 /* Initiator available */
+#define TP_ITYP_TYPE(x) (((x) & 0x6) >> 1) /* Initiator Type */
+#define TP_ITYP_TYPE_OTHER 0x0
+#define TP_ITYP_TYPE_PPC 0x1 /* PowerPC */
+#define TP_ITYP_TYPE_SC 0x2 /* StarCore DSP */
+#define TP_ITYP_TYPE_HA 0x3 /* HW Accelerator */
+#define TP_ITYP_THDS(x) (((x) & 0x18) >> 3) /* # threads */
+#define TP_ITYP_VER(x) (((x) & 0xe0) >> 5) /* Initiator Version */
+
+#define TP_CLUSTER_EOC 0x80000000 /* end of clusters */
+#define TP_CLUSTER_INIT_MASK 0x0000003f /* initiator mask */
+#define TP_INIT_PER_CLUSTER 4
+
+#define FSL_CORENET_DCSR_SZ_MASK 0x00000003
+#define FSL_CORENET_DCSR_SZ_4M 0x0
+#define FSL_CORENET_DCSR_SZ_1G 0x3
+
+/*
+ * On p4080 we have an LIODN for msg unit (rmu) but not maintenance
+ * everything after has RMan thus msg unit LIODN is used for maintenance
+ */
+#define rmuliodnr rio1maintliodnr
+
+typedef struct ccsr_clk {
+ struct {
+ u32 clkcncsr; /* core cluster n clock control status */
+ u8 res_004[0x0c];
+ u32 clkcgnhwacsr;/* clock generator n hardware accelerator */
+ u8 res_014[0x0c];
+ } clkcsr[8];
+ u8 res_100[0x700]; /* 0x100 */
+ u32 pllc1gsr; /* 0x800 Cluster PLL 1 General Status */
+ u8 res10[0x1c];
+ u32 pllc2gsr; /* 0x820 Cluster PLL 2 General Status */
+ u8 res11[0x1c];
+ u32 pllc3gsr; /* 0x840 Cluster PLL 3 General Status */
+ u8 res12[0x1c];
+ u32 pllc4gsr; /* 0x860 Cluster PLL 4 General Status */
+ u8 res13[0x1c];
+ u32 pllc5gsr; /* 0x880 Cluster PLL 5 General Status */
+ u8 res14[0x1c];
+ u32 pllc6gsr; /* 0x8a0 Cluster PLL 6 General Status */
+ u8 res15[0x35c];
+ u32 pllpgsr; /* 0xc00 Platform PLL General Status */
+ u8 res16[0x1c];
+ u32 plldgsr; /* 0xc20 DDR PLL General Status */
+ u8 res17[0x3dc];
+} ccsr_clk_t;
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+typedef struct ccsr_rcpm {
+ u8 res_00[12];
+ u32 tph10sr0; /* Thread PH10 Status Register */
+ u8 res_10[12];
+ u32 tph10setr0; /* Thread PH10 Set Control Register */
+ u8 res_20[12];
+ u32 tph10clrr0; /* Thread PH10 Clear Control Register */
+ u8 res_30[12];
+ u32 tph10psr0; /* Thread PH10 Previous Status Register */
+ u8 res_40[12];
+ u32 twaitsr0; /* Thread Wait Status Register */
+ u8 res_50[96];
+ u32 pcph15sr; /* Physical Core PH15 Status Register */
+ u32 pcph15setr; /* Physical Core PH15 Set Control Register */
+ u32 pcph15clrr; /* Physical Core PH15 Clear Control Register */
+ u32 pcph15psr; /* Physical Core PH15 Prev Status Register */
+ u8 res_c0[16];
+ u32 pcph20sr; /* Physical Core PH20 Status Register */
+ u32 pcph20setr; /* Physical Core PH20 Set Control Register */
+ u32 pcph20clrr; /* Physical Core PH20 Clear Control Register */
+ u32 pcph20psr; /* Physical Core PH20 Prev Status Register */
+ u32 pcpw20sr; /* Physical Core PW20 Status Register */
+ u8 res_e0[12];
+ u32 pcph30sr; /* Physical Core PH30 Status Register */
+ u32 pcph30setr; /* Physical Core PH30 Set Control Register */
+ u32 pcph30clrr; /* Physical Core PH30 Clear Control Register */
+ u32 pcph30psr; /* Physical Core PH30 Prev Status Register */
+ u8 res_100[32];
+ u32 ippwrgatecr; /* IP Power Gating Control Register */
+ u8 res_124[12];
+ u32 powmgtcsr; /* Power Management Control & Status Reg */
+ u8 res_134[12];
+ u32 ippdexpcr[4]; /* IP Powerdown Exception Control Reg */
+ u8 res_150[12];
+ u32 tpmimr0; /* Thread PM Interrupt Mask Reg */
+ u8 res_160[12];
+ u32 tpmcimr0; /* Thread PM Crit Interrupt Mask Reg */
+ u8 res_170[12];
+ u32 tpmmcmr0; /* Thread PM Machine Check Interrupt Mask Reg */
+ u8 res_180[12];
+ u32 tpmnmimr0; /* Thread PM NMI Mask Reg */
+ u8 res_190[12];
+ u32 tmcpmaskcr0; /* Thread Machine Check Mask Control Reg */
+ u32 pctbenr; /* Physical Core Time Base Enable Reg */
+ u32 pctbclkselr; /* Physical Core Time Base Clock Select */
+ u32 tbclkdivr; /* Time Base Clock Divider Register */
+ u8 res_1ac[4];
+ u32 ttbhltcr[4]; /* Thread Time Base Halt Control Register */
+ u32 clpcl10sr; /* Cluster PCL10 Status Register */
+ u32 clpcl10setr; /* Cluster PCL30 Set Control Register */
+ u32 clpcl10clrr; /* Cluster PCL30 Clear Control Register */
+ u32 clpcl10psr; /* Cluster PCL30 Prev Status Register */
+ u32 cddslpsetr; /* Core Domain Deep Sleep Set Register */
+ u32 cddslpclrr; /* Core Domain Deep Sleep Clear Register */
+ u32 cdpwroksetr; /* Core Domain Power OK Set Register */
+ u32 cdpwrokclrr; /* Core Domain Power OK Clear Register */
+ u32 cdpwrensr; /* Core Domain Power Enable Status Register */
+ u32 cddslsr; /* Core Domain Deep Sleep Status Register */
+ u8 res_1e8[8];
+ u32 dslpcntcr[8]; /* Deep Sleep Counter Cfg Register */
+ u8 res_300[3568];
+} ccsr_rcpm_t;
+
+#define ctbenrl pctbenr
+
+#else
+typedef struct ccsr_rcpm {
+ u8 res1[4];
+ u32 cdozsrl; /* Core Doze Status */
+ u8 res2[4];
+ u32 cdozcrl; /* Core Doze Control */
+ u8 res3[4];
+ u32 cnapsrl; /* Core Nap Status */
+ u8 res4[4];
+ u32 cnapcrl; /* Core Nap Control */
+ u8 res5[4];
+ u32 cdozpsrl; /* Core Doze Previous Status */
+ u8 res6[4];
+ u32 cdozpcrl; /* Core Doze Previous Control */
+ u8 res7[4];
+ u32 cwaitsrl; /* Core Wait Status */
+ u8 res8[8];
+ u32 powmgtcsr; /* Power Mangement Control & Status */
+ u8 res9[12];
+ u32 ippdexpcr0; /* IP Powerdown Exception Control 0 */
+ u8 res10[12];
+ u8 res11[4];
+ u32 cpmimrl; /* Core PM IRQ Masking */
+ u8 res12[4];
+ u32 cpmcimrl; /* Core PM Critical IRQ Masking */
+ u8 res13[4];
+ u32 cpmmcimrl; /* Core PM Machine Check IRQ Masking */
+ u8 res14[4];
+ u32 cpmnmimrl; /* Core PM NMI Masking */
+ u8 res15[4];
+ u32 ctbenrl; /* Core Time Base Enable */
+ u8 res16[4];
+ u32 ctbclkselrl; /* Core Time Base Clock Select */
+ u8 res17[4];
+ u32 ctbhltcrl; /* Core Time Base Halt Control */
+ u8 res18[0xf68];
+} ccsr_rcpm_t;
+#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+#else
+typedef struct ccsr_gur {
+ u32 porpllsr; /* POR PLL ratio status */
+#ifdef CONFIG_MPC8536
+#define MPC85xx_PORPLLSR_DDR_RATIO 0x3e000000
+#define MPC85xx_PORPLLSR_DDR_RATIO_SHIFT 25
+#else
+#if defined(CONFIG_BSC9131) || defined(CONFIG_BSC9132)
+#define MPC85xx_PORPLLSR_DDR_RATIO 0x00003f00
+#else
+#define MPC85xx_PORPLLSR_DDR_RATIO 0x00003e00
+#endif
+#define MPC85xx_PORPLLSR_DDR_RATIO_SHIFT 9
+#endif
+#define MPC85xx_PORPLLSR_QE_RATIO 0x3e000000
+#define MPC85xx_PORPLLSR_QE_RATIO_SHIFT 25
+#define MPC85xx_PORPLLSR_PLAT_RATIO 0x0000003e
+#define MPC85xx_PORPLLSR_PLAT_RATIO_SHIFT 1
+ u32 porbmsr; /* POR boot mode status */
+#define MPC85xx_PORBMSR_HA 0x00070000
+#define MPC85xx_PORBMSR_HA_SHIFT 16
+#define MPC85xx_PORBMSR_ROMLOC_SHIFT 24
+#define PORBMSR_ROMLOC_SPI 0x6
+#define PORBMSR_ROMLOC_SDHC 0x7
+#define PORBMSR_ROMLOC_NAND_2K 0x9
+#define PORBMSR_ROMLOC_NOR 0xf
+ u32 porimpscr; /* POR I/O impedance status & control */
+ u32 pordevsr; /* POR I/O device status regsiter */
+#if defined(CONFIG_P1017) || defined(CONFIG_P1023)
+#define MPC85xx_PORDEVSR_SGMII1_DIS 0x10000000
+#define MPC85xx_PORDEVSR_SGMII2_DIS 0x08000000
+#define MPC85xx_PORDEVSR_TSEC1_PRTC 0x02000000
+#else
+#define MPC85xx_PORDEVSR_SGMII1_DIS 0x20000000
+#define MPC85xx_PORDEVSR_SGMII2_DIS 0x10000000
+#endif
+#define MPC85xx_PORDEVSR_SGMII3_DIS 0x08000000
+#define MPC85xx_PORDEVSR_SGMII4_DIS 0x04000000
+#define MPC85xx_PORDEVSR_SRDS2_IO_SEL 0x38000000
+#define MPC85xx_PORDEVSR_PCI1 0x00800000
+#if defined(CONFIG_P1013) || defined(CONFIG_P1022)
+#define MPC85xx_PORDEVSR_IO_SEL 0x007c0000
+#define MPC85xx_PORDEVSR_IO_SEL_SHIFT 18
+#elif defined(CONFIG_P1017) || defined(CONFIG_P1023)
+#define MPC85xx_PORDEVSR_IO_SEL 0x00600000
+#define MPC85xx_PORDEVSR_IO_SEL_SHIFT 21
+#else
+#if defined(CONFIG_P1010)
+#define MPC85xx_PORDEVSR_IO_SEL 0x00600000
+#define MPC85xx_PORDEVSR_IO_SEL_SHIFT 21
+#elif defined(CONFIG_BSC9132)
+#define MPC85xx_PORDEVSR_IO_SEL 0x00FE0000
+#define MPC85xx_PORDEVSR_IO_SEL_SHIFT 17
+#else
+#define MPC85xx_PORDEVSR_IO_SEL 0x00780000
+#define MPC85xx_PORDEVSR_IO_SEL_SHIFT 19
+#endif /* if defined(CONFIG_P1010) */
+#endif
+#define MPC85xx_PORDEVSR_PCI2_ARB 0x00040000
+#define MPC85xx_PORDEVSR_PCI1_ARB 0x00020000
+#define MPC85xx_PORDEVSR_PCI1_PCI32 0x00010000
+#define MPC85xx_PORDEVSR_PCI1_SPD 0x00008000
+#define MPC85xx_PORDEVSR_PCI2_SPD 0x00004000
+#define MPC85xx_PORDEVSR_DRAM_RTYPE 0x00000060
+#define MPC85xx_PORDEVSR_RIO_CTLS 0x00000008
+#define MPC85xx_PORDEVSR_RIO_DEV_ID 0x00000007
+ u32 pordbgmsr; /* POR debug mode status */
+ u32 pordevsr2; /* POR I/O device status 2 */
+/* The 8544 RM says this is bit 26, but it's really bit 24 */
+#define MPC85xx_PORDEVSR2_SEC_CFG 0x00000080
+ u8 res1[8];
+ u32 gpporcr; /* General-purpose POR configuration */
+ u8 res2[12];
+#if defined(CONFIG_MPC8536)
+ u32 gencfgr; /* General Configuration Register */
+#define MPC85xx_GENCFGR_SDHC_WP_INV 0x20000000
+#else
+ u32 gpiocr; /* GPIO control */
+#endif
+ u8 res3[12];
+#if defined(CONFIG_MPC8569)
+ u32 plppar1; /* Platform port pin assignment 1 */
+ u32 plppar2; /* Platform port pin assignment 2 */
+ u32 plpdir1; /* Platform port pin direction 1 */
+ u32 plpdir2; /* Platform port pin direction 2 */
+#else
+ u32 gpoutdr; /* General-purpose output data */
+ u8 res4[12];
+#endif
+ u32 gpindr; /* General-purpose input data */
+ u8 res5[12];
+ u32 pmuxcr; /* Alt. function signal multiplex control */
+#if defined(CONFIG_P1010) || defined(CONFIG_P1014)
+#define MPC85xx_PMUXCR_TSEC1_0_1588 0x40000000
+#define MPC85xx_PMUXCR_TSEC1_0_RES 0xC0000000
+#define MPC85xx_PMUXCR_TSEC1_1_1588_TRIG 0x10000000
+#define MPC85xx_PMUXCR_TSEC1_1_GPIO_12 0x20000000
+#define MPC85xx_PMUXCR_TSEC1_1_RES 0x30000000
+#define MPC85xx_PMUXCR_TSEC1_2_DMA 0x04000000
+#define MPC85xx_PMUXCR_TSEC1_2_GPIO 0x08000000
+#define MPC85xx_PMUXCR_TSEC1_2_RES 0x0C000000
+#define MPC85xx_PMUXCR_TSEC1_3_RES 0x01000000
+#define MPC85xx_PMUXCR_TSEC1_3_GPIO_15 0x02000000
+#define MPC85xx_PMUXCR_IFC_ADDR16_SDHC 0x00400000
+#define MPC85xx_PMUXCR_IFC_ADDR16_USB 0x00800000
+#define MPC85xx_PMUXCR_IFC_ADDR16_IFC_CS2 0x00C00000
+#define MPC85xx_PMUXCR_IFC_ADDR17_18_SDHC 0x00100000
+#define MPC85xx_PMUXCR_IFC_ADDR17_18_USB 0x00200000
+#define MPC85xx_PMUXCR_IFC_ADDR17_18_DMA 0x00300000
+#define MPC85xx_PMUXCR_IFC_ADDR19_SDHC_DATA 0x00040000
+#define MPC85xx_PMUXCR_IFC_ADDR19_USB 0x00080000
+#define MPC85xx_PMUXCR_IFC_ADDR19_DMA 0x000C0000
+#define MPC85xx_PMUXCR_IFC_ADDR20_21_SDHC_DATA 0x00010000
+#define MPC85xx_PMUXCR_IFC_ADDR20_21_USB 0x00020000
+#define MPC85xx_PMUXCR_IFC_ADDR20_21_RES 0x00030000
+#define MPC85xx_PMUXCR_IFC_ADDR22_SDHC 0x00004000
+#define MPC85xx_PMUXCR_IFC_ADDR22_USB 0x00008000
+#define MPC85xx_PMUXCR_IFC_ADDR22_RES 0x0000C000
+#define MPC85xx_PMUXCR_IFC_ADDR23_SDHC 0x00001000
+#define MPC85xx_PMUXCR_IFC_ADDR23_USB 0x00002000
+#define MPC85xx_PMUXCR_IFC_ADDR23_RES 0x00003000
+#define MPC85xx_PMUXCR_IFC_ADDR24_SDHC 0x00000400
+#define MPC85xx_PMUXCR_IFC_ADDR24_USB 0x00000800
+#define MPC85xx_PMUXCR_IFC_ADDR24_RES 0x00000C00
+#define MPC85xx_PMUXCR_IFC_PAR_PERR_RES 0x00000300
+#define MPC85xx_PMUXCR_IFC_PAR_PERR_USB 0x00000200
+#define MPC85xx_PMUXCR_LCLK_RES 0x00000040
+#define MPC85xx_PMUXCR_LCLK_USB 0x00000080
+#define MPC85xx_PMUXCR_LCLK_IFC_CS3 0x000000C0
+#define MPC85xx_PMUXCR_SPI_RES 0x00000030
+#define MPC85xx_PMUXCR_SPI_GPIO 0x00000020
+#define MPC85xx_PMUXCR_CAN1_UART 0x00000004
+#define MPC85xx_PMUXCR_CAN1_TDM 0x00000008
+#define MPC85xx_PMUXCR_CAN1_RES 0x0000000C
+#define MPC85xx_PMUXCR_CAN2_UART 0x00000001
+#define MPC85xx_PMUXCR_CAN2_TDM 0x00000002
+#define MPC85xx_PMUXCR_CAN2_RES 0x00000003
+#endif
+#if defined(CONFIG_P1017) || defined(CONFIG_P1023)
+#define MPC85xx_PMUXCR_TSEC1_1 0x10000000
+#else
+#define MPC85xx_PMUXCR_SD_DATA 0x80000000
+#define MPC85xx_PMUXCR_SDHC_CD 0x40000000
+#define MPC85xx_PMUXCR_SDHC_WP 0x20000000
+#define MPC85xx_PMUXCR_ELBC_OFF_USB2_ON 0x01000000
+#define MPC85xx_PMUXCR_TDM_ENA 0x00800000
+#define MPC85xx_PMUXCR_QE0 0x00008000
+#define MPC85xx_PMUXCR_QE1 0x00004000
+#define MPC85xx_PMUXCR_QE2 0x00002000
+#define MPC85xx_PMUXCR_QE3 0x00001000
+#define MPC85xx_PMUXCR_QE4 0x00000800
+#define MPC85xx_PMUXCR_QE5 0x00000400
+#define MPC85xx_PMUXCR_QE6 0x00000200
+#define MPC85xx_PMUXCR_QE7 0x00000100
+#define MPC85xx_PMUXCR_QE8 0x00000080
+#define MPC85xx_PMUXCR_QE9 0x00000040
+#define MPC85xx_PMUXCR_QE10 0x00000020
+#define MPC85xx_PMUXCR_QE11 0x00000010
+#define MPC85xx_PMUXCR_QE12 0x00000008
+#endif
+#if defined(CONFIG_P1013) || defined(CONFIG_P1022)
+#define MPC85xx_PMUXCR_TDM_MASK 0x0001cc00
+#define MPC85xx_PMUXCR_TDM 0x00014800
+#define MPC85xx_PMUXCR_SPI_MASK 0x00600000
+#define MPC85xx_PMUXCR_SPI 0x00000000
+#endif
+#if defined(CONFIG_BSC9131)
+#define MPC85xx_PMUXCR_TSEC2_DMA_GPIO_IRQ 0x40000000
+#define MPC85xx_PMUXCR_TSEC2_USB 0xC0000000
+#define MPC85xx_PMUXCR_TSEC2_1588_PPS 0x10000000
+#define MPC85xx_PMUXCR_TSEC2_1588_RSVD 0x30000000
+#define MPC85xx_PMUXCR_IFC_AD_GPIO 0x04000000
+#define MPC85xx_PMUXCR_IFC_AD_GPIO_MASK 0x0C000000
+#define MPC85xx_PMUXCR_IFC_AD15_GPIO 0x01000000
+#define MPC85xx_PMUXCR_IFC_AD15_TIMER2 0x02000000
+#define MPC85xx_PMUXCR_IFC_AD16_GPO8 0x00400000
+#define MPC85xx_PMUXCR_IFC_AD16_MSRCID0 0x00800000
+#define MPC85xx_PMUXCR_IFC_AD17_GPO 0x00100000
+#define MPC85xx_PMUXCR_IFC_AD17_GPO_MASK 0x00300000
+#define MPC85xx_PMUXCR_IFC_AD17_MSRCID_DSP 0x00200000
+#define MPC85xx_PMUXCR_IFC_CS2_GPO65 0x00040000
+#define MPC85xx_PMUXCR_IFC_CS2_DSP_TDI 0x00080000
+#define MPC85xx_PMUXCR_SDHC_USIM 0x00010000
+#define MPC85xx_PMUXCR_SDHC_TDM_RFS_RCK 0x00020000
+#define MPC85xx_PMUXCR_SDHC_GPIO77 0x00030000
+#define MPC85xx_PMUXCR_SDHC_RESV 0x00004000
+#define MPC85xx_PMUXCR_SDHC_TDM_TXD_RXD 0x00008000
+#define MPC85xx_PMUXCR_SDHC_GPIO_TIMER4 0x0000C000
+#define MPC85xx_PMUXCR_USB_CLK_UART_SIN 0x00001000
+#define MPC85xx_PMUXCR_USB_CLK_GPIO69 0x00002000
+#define MPC85xx_PMUXCR_USB_CLK_TIMER3 0x00003000
+#define MPC85xx_PMUXCR_USB_UART_GPIO0 0x00000400
+#define MPC85xx_PMUXCR_USB_RSVD 0x00000C00
+#define MPC85xx_PMUXCR_USB_GPIO62_TRIG_IN 0x00000800
+#define MPC85xx_PMUXCR_USB_D1_2_IIC2_SDA_SCL 0x00000100
+#define MPC85xx_PMUXCR_USB_D1_2_GPIO71_72 0x00000200
+#define MPC85xx_PMUXCR_USB_D1_2_RSVD 0x00000300
+#define MPC85xx_PMUXCR_USB_DIR_GPIO2 0x00000040
+#define MPC85xx_PMUXCR_USB_DIR_TIMER1 0x00000080
+#define MPC85xx_PMUXCR_USB_DIR_MCP_B 0x000000C0
+#define MPC85xx_PMUXCR_SPI1_UART3 0x00000010
+#define MPC85xx_PMUXCR_SPI1_SIM 0x00000020
+#define MPC85xx_PMUXCR_SPI1_CKSTP_IN_GPO74 0x00000030
+#define MPC85xx_PMUXCR_SPI1_CS2_CKSTP_OUT_B 0x00000004
+#define MPC85xx_PMUXCR_SPI1_CS2_dbg_adi1_rxen 0x00000008
+#define MPC85xx_PMUXCR_SPI1_CS2_GPO75 0x0000000C
+#define MPC85xx_PMUXCR_SPI1_CS3_ANT_TCXO_PWM 0x00000001
+#define MPC85xx_PMUXCR_SPI1_CS3_dbg_adi2_rxen 0x00000002
+#define MPC85xx_PMUXCR_SPI1_CS3_GPO76 0x00000003
+#endif
+#ifdef CONFIG_BSC9132
+#define MPC85xx_PMUXCR0_SIM_SEL_MASK 0x0003b000
+#define MPC85xx_PMUXCR0_SIM_SEL 0x00014000
+#endif
+ u32 pmuxcr2; /* Alt. function signal multiplex control 2 */
+#if defined(CONFIG_P1010) || defined(CONFIG_P1014)
+#define MPC85xx_PMUXCR2_UART_GPIO 0x40000000
+#define MPC85xx_PMUXCR2_UART_TDM 0x80000000
+#define MPC85xx_PMUXCR2_UART_RES 0xC0000000
+#define MPC85xx_PMUXCR2_IRQ2_TRIG_IN 0x10000000
+#define MPC85xx_PMUXCR2_IRQ2_RES 0x30000000
+#define MPC85xx_PMUXCR2_IRQ3_SRESET 0x04000000
+#define MPC85xx_PMUXCR2_IRQ3_RES 0x0C000000
+#define MPC85xx_PMUXCR2_GPIO01_DRVVBUS 0x01000000
+#define MPC85xx_PMUXCR2_GPIO01_RES 0x03000000
+#define MPC85xx_PMUXCR2_GPIO23_CKSTP 0x00400000
+#define MPC85xx_PMUXCR2_GPIO23_RES 0x00800000
+#define MPC85xx_PMUXCR2_GPIO23_USB 0x00C00000
+#define MPC85xx_PMUXCR2_GPIO4_MCP 0x00100000
+#define MPC85xx_PMUXCR2_GPIO4_RES 0x00200000
+#define MPC85xx_PMUXCR2_GPIO4_CLK_OUT 0x00300000
+#define MPC85xx_PMUXCR2_GPIO5_UDE 0x00040000
+#define MPC85xx_PMUXCR2_GPIO5_RES 0x00080000
+#define MPC85xx_PMUXCR2_READY_ASLEEP 0x00020000
+#define MPC85xx_PMUXCR2_DDR_ECC_MUX 0x00010000
+#define MPC85xx_PMUXCR2_DEBUG_PORT_EXPOSE 0x00008000
+#define MPC85xx_PMUXCR2_POST_EXPOSE 0x00004000
+#define MPC85xx_PMUXCR2_DEBUG_MUX_SEL_USBPHY 0x00002000
+#define MPC85xx_PMUXCR2_PLL_LKDT_EXPOSE 0x00001000
+#endif
+#if defined(CONFIG_P1013) || defined(CONFIG_P1022)
+#define MPC85xx_PMUXCR2_ETSECUSB_MASK 0x001f8000
+#define MPC85xx_PMUXCR2_USB 0x00150000
+#endif
+#if defined(CONFIG_BSC9131) || defined(CONFIG_BSC9132)
+#if defined(CONFIG_BSC9131)
+#define MPC85xx_PMUXCR2_UART_CTS_B0_SIM_PD 0X40000000
+#define MPC85xx_PMUXCR2_UART_CTS_B0_DSP_TMS 0X80000000
+#define MPC85xx_PMUXCR2_UART_CTS_B0_GPIO42 0xC0000000
+#define MPC85xx_PMUXCR2_UART_RTS_B0_PWM2 0x10000000
+#define MPC85xx_PMUXCR2_UART_RTS_B0_DSP_TCK 0x20000000
+#define MPC85xx_PMUXCR2_UART_RTS_B0_GPIO43 0x30000000
+#define MPC85xx_PMUXCR2_UART_CTS_B1_SIM_PD 0x04000000
+#define MPC85xx_PMUXCR2_UART_CTS_B1_SRESET_B 0x08000000
+#define MPC85xx_PMUXCR2_UART_CTS_B1_GPIO44 0x0C000000
+#define MPC85xx_PMUXCR2_UART_RTS_B1_PPS_LED 0x01000000
+#define MPC85xx_PMUXCR2_UART_RTS_B1_RSVD 0x02000000
+#define MPC85xx_PMUXCR2_UART_RTS_B1_GPIO45 0x03000000
+#define MPC85xx_PMUXCR2_TRIG_OUT_ASLEEP 0x00400000
+#define MPC85xx_PMUXCR2_TRIG_OUT_DSP_TRST_B 0x00800000
+#define MPC85xx_PMUXCR2_ANT1_TIMER5 0x00100000
+#define MPC85xx_PMUXCR2_ANT1_TSEC_1588 0x00200000
+#define MPC85xx_PMUXCR2_ANT1_GPIO95_19 0x00300000
+#define MPC85xx_PMUXCR2_ANT1_TX_RX_FRAME_MAX3_LOCK 0x00040000
+#define MPC85xx_PMUXCR2_ANT1_TX_RX_FRAME_RSVD 0x00080000
+#define MPC85xx_PMUXCR2_ANT1_TX_RX_FRAME_GPIO80_20 0x000C0000
+#define MPC85xx_PMUXCR2_ANT1_DIO0_3_SPI3_CS0 0x00010000
+#define MPC85xx_PMUXCR2_ANT1_DIO0_3_ANT2_DO_3 0x00020000
+#define MPC85xx_PMUXCR2_ANT1_DIO0_3_GPIO81_84 0x00030000
+#define MPC85xx_PMUXCR2_ANT1_DIO4_7_SPI4 0x00004000
+#define MPC85xx_PMUXCR2_ANT1_DIO4_7_ANT2_DO4_7 0x00008000
+#define MPC85xx_PMUXCR2_ANT1_DIO4_7_GPIO85_88 0x0000C000
+#define MPC85xx_PMUXCR2_ANT1_DIO8_9_MAX2_1_LOCK 0x00001000
+#define MPC85xx_PMUXCR2_ANT1_DIO8_9_ANT2_DO8_9 0x00002000
+#define MPC85xx_PMUXCR2_ANT1_DIO8_9_GPIO21_22 0x00003000
+#define MPC85xx_PMUXCR2_ANT1_DIO10_11_TIMER6_7 0x00000400
+#define MPC85xx_PMUXCR2_ANT1_DIO10_11_ANT2_DO10_11 0x00000800
+#define MPC85xx_PMUXCR2_ANT1_DIO10_11_GPIO23_24 0x00000C00
+#define MPC85xx_PMUXCR2_ANT2_RSVD 0x00000100
+#define MPC85xx_PMUXCR2_ANT2_GPO90_91_DMA 0x00000300
+#define MPC85xx_PMUXCR2_ANT2_ENABLE_DIO0_10_USB 0x00000040
+#define MPC85xx_PMUXCR2_ANT2_ENABLE_DIO0_10_GPIO 0x000000C0
+#define MPC85xx_PMUXCR2_ANT2_DIO11_RSVD 0x00000010
+#define MPC85xx_PMUXCR2_ANT2_DIO11_TIMER8 0x00000020
+#define MPC85xx_PMUXCR2_ANT2_DIO11_GPIO61 0x00000030
+#define MPC85xx_PMUXCR2_ANT3_AGC_GPO53 0x00000004
+#define MPC85xx_PMUXCR2_ANT3_DO_TDM 0x00000001
+#define MPC85xx_PMUXCR2_ANT3_DO_GPIO46_49 0x00000002
+#endif
+ u32 pmuxcr3;
+#if defined(CONFIG_BSC9131)
+#define MPC85xx_PMUXCR3_ANT3_DO4_5_TDM 0x40000000
+#define MPC85xx_PMUXCR3_ANT3_DO4_5_GPIO_50_51 0x80000000
+#define MPC85xx_PMUXCR3_ANT3_DO6_7_TRIG_IN_SRESET_B 0x10000000
+#define MPC85xx_PMUXCR3_ANT3_DO6_7_GPIO_52_53 0x20000000
+#define MPC85xx_PMUXCR3_ANT3_DO8_MCP_B 0x04000000
+#define MPC85xx_PMUXCR3_ANT3_DO8_GPIO54 0x08000000
+#define MPC85xx_PMUXCR3_ANT3_DO9_10_CKSTP_IN_OUT 0x01000000
+#define MPC85xx_PMUXCR3_ANT3_DO9_10_GPIO55_56 0x02000000
+#define MPC85xx_PMUXCR3_ANT3_DO11_IRQ_OUT 0x00400000
+#define MPC85xx_PMUXCR3_ANT3_DO11_GPIO57 0x00800000
+#define MPC85xx_PMUXCR3_SPI2_CS2_GPO93 0x00100000
+#define MPC85xx_PMUXCR3_SPI2_CS3_GPO94 0x00040000
+#define MPC85xx_PMUXCR3_ANT2_AGC_RSVD 0x00010000
+#define MPC85xx_PMUXCR3_ANT2_GPO89 0x00030000
+#endif
+#ifdef CONFIG_BSC9132
+#define MPC85xx_PMUXCR3_USB_SEL_MASK 0x0000ff00
+#define MPC85xx_PMUXCR3_UART2_SEL 0x00005000
+#define MPC85xx_PMUXCR3_UART3_SEL_MASK 0xc0000000
+#define MPC85xx_PMUXCR3_UART3_SEL 0x40000000
+#endif
+ u32 pmuxcr4;
+#else
+ u8 res6[8];
+#endif
+ u32 devdisr; /* Device disable control */
+#define MPC85xx_DEVDISR_PCI1 0x80000000
+#define MPC85xx_DEVDISR_PCI2 0x40000000
+#define MPC85xx_DEVDISR_PCIE 0x20000000
+#define MPC85xx_DEVDISR_LBC 0x08000000
+#define MPC85xx_DEVDISR_PCIE2 0x04000000
+#define MPC85xx_DEVDISR_PCIE3 0x02000000
+#define MPC85xx_DEVDISR_SEC 0x01000000
+#define MPC85xx_DEVDISR_SRIO 0x00080000
+#define MPC85xx_DEVDISR_RMSG 0x00040000
+#define MPC85xx_DEVDISR_DDR 0x00010000
+#define MPC85xx_DEVDISR_CPU 0x00008000
+#define MPC85xx_DEVDISR_CPU0 MPC85xx_DEVDISR_CPU
+#define MPC85xx_DEVDISR_TB 0x00004000
+#define MPC85xx_DEVDISR_TB0 MPC85xx_DEVDISR_TB
+#define MPC85xx_DEVDISR_CPU1 0x00002000
+#define MPC85xx_DEVDISR_TB1 0x00001000
+#define MPC85xx_DEVDISR_DMA 0x00000400
+#define MPC85xx_DEVDISR_TSEC1 0x00000080
+#define MPC85xx_DEVDISR_TSEC2 0x00000040
+#define MPC85xx_DEVDISR_TSEC3 0x00000020
+#define MPC85xx_DEVDISR_TSEC4 0x00000010
+#define MPC85xx_DEVDISR_I2C 0x00000004
+#define MPC85xx_DEVDISR_DUART 0x00000002
+ u8 res7[12];
+ u32 powmgtcsr; /* Power management status & control */
+ u8 res8[12];
+ u32 mcpsumr; /* Machine check summary */
+ u8 res9[12];
+ u32 pvr; /* Processor version */
+ u32 svr; /* System version */
+ u8 res10[8];
+ u32 rstcr; /* Reset control */
+#if defined(CONFIG_MPC8568)||defined(CONFIG_MPC8569)
+ u8 res11a[76];
+ par_io_t qe_par_io[7];
+ u8 res11b[1600];
+#elif defined(CONFIG_P1012) || defined(CONFIG_P1021) || defined(CONFIG_P1025)
+ u8 res11a[12];
+ u32 iovselsr;
+ u8 res11b[60];
+ par_io_t qe_par_io[3];
+ u8 res11c[1496];
+#else
+ u8 res11a[1868];
+#endif
+ u32 clkdvdr; /* Clock Divide register */
+ u8 res12[1532];
+ u32 clkocr; /* Clock out select */
+ u8 res13[12];
+ u32 ddrdllcr; /* DDR DLL control */
+ u8 res14[12];
+ u32 lbcdllcr; /* LBC DLL control */
+#if defined(CONFIG_BSC9131)
+ u8 res15[12];
+ u32 halt_req_mask;
+#define HALTED_TO_HALT_REQ_MASK_0 0x80000000
+ u8 res18[232];
+#else
+ u8 res15[248];
+#endif
+ u32 lbiuiplldcr0; /* LBIU PLL Debug Reg 0 */
+ u32 lbiuiplldcr1; /* LBIU PLL Debug Reg 1 */
+ u32 ddrioovcr; /* DDR IO Override Control */
+ u32 tsec12ioovcr; /* eTSEC 1/2 IO override control */
+ u32 tsec34ioovcr; /* eTSEC 3/4 IO override control */
+ u8 res16[52];
+ u32 sdhcdcr; /* SDHC debug control register */
+ u8 res17[61592];
+} ccsr_gur_t;
+#endif
+
+#define SDHCDCR_CD_INV 0x80000000 /* invert SDHC card detect */
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+#define MAX_SERDES 4
+#define SRDS_MAX_LANES 8
+#define SRDS_MAX_BANK 2
+typedef struct serdes_corenet {
+ struct {
+ u32 rstctl; /* Reset Control Register */
+#define SRDS_RSTCTL_RST 0x80000000
+#define SRDS_RSTCTL_RSTDONE 0x40000000
+#define SRDS_RSTCTL_RSTERR 0x20000000
+#define SRDS_RSTCTL_SWRST 0x10000000
+#define SRDS_RSTCTL_SDPD 0x00000020
+ u32 pllcr0; /* PLL Control Register 0 */
+#define SRDS_PLLCR0_POFF 0x80000000
+#define SRDS_PLLCR0_RFCK_SEL_MASK 0x70000000
+#define SRDS_PLLCR0_RFCK_SEL_100 0x00000000
+#define SRDS_PLLCR0_RFCK_SEL_125 0x10000000
+#define SRDS_PLLCR0_RFCK_SEL_156_25 0x20000000
+#define SRDS_PLLCR0_RFCK_SEL_150 0x30000000
+#define SRDS_PLLCR0_RFCK_SEL_161_13 0x40000000
+#define SRDS_PLLCR0_RFCK_SEL_122_88 0x50000000
+#define SRDS_PLLCR0_FRATE_SEL_MASK 0x000f0000
+#define SRDS_PLLCR0_FRATE_SEL_5 0x00000000
+#define SRDS_PLLCR0_FRATE_SEL_3_75 0x00050000
+#define SRDS_PLLCR0_FRATE_SEL_5_15 0x00060000
+#define SRDS_PLLCR0_FRATE_SEL_4 0x00070000
+#define SRDS_PLLCR0_FRATE_SEL_3_12 0x00090000
+#define SRDS_PLLCR0_FRATE_SEL_3 0x000a0000
+ u32 pllcr1; /* PLL Control Register 1 */
+#define SRDS_PLLCR1_PLL_BWSEL 0x08000000
+ u32 res_0c; /* 0x00c */
+ u32 pllcr3;
+ u32 pllcr4;
+ u8 res_18[0x20-0x18];
+ } bank[2];
+ u8 res_40[0x90-0x40];
+ u32 srdstcalcr; /* 0x90 TX Calibration Control */
+ u8 res_94[0xa0-0x94];
+ u32 srdsrcalcr; /* 0xa0 RX Calibration Control */
+ u8 res_a4[0xb0-0xa4];
+ u32 srdsgr0; /* 0xb0 General Register 0 */
+ u8 res_b4[0xe0-0xb4];
+ u32 srdspccr0; /* 0xe0 Protocol Converter Config 0 */
+ u32 srdspccr1; /* 0xe4 Protocol Converter Config 1 */
+ u32 srdspccr2; /* 0xe8 Protocol Converter Config 2 */
+ u32 srdspccr3; /* 0xec Protocol Converter Config 3 */
+ u32 srdspccr4; /* 0xf0 Protocol Converter Config 4 */
+ u8 res_f4[0x100-0xf4];
+ struct {
+ u32 lnpssr; /* 0x100, 0x120, ..., 0x1e0 */
+ u8 res_104[0x120-0x104];
+ } srdslnpssr[8];
+ u8 res_200[0x800-0x200];
+ struct {
+ u32 gcr0; /* 0x800 General Control Register 0 */
+ u32 gcr1; /* 0x804 General Control Register 1 */
+ u32 gcr2; /* 0x808 General Control Register 2 */
+ u32 res_80c;
+ u32 recr0; /* 0x810 Receive Equalization Control */
+ u32 res_814;
+ u32 tecr0; /* 0x818 Transmit Equalization Control */
+ u32 res_81c;
+ u32 ttlcr0; /* 0x820 Transition Tracking Loop Ctrl 0 */
+ u8 res_824[0x840-0x824];
+ } lane[8]; /* Lane A, B, C, D, E, F, G, H */
+ u8 res_a00[0x1000-0xa00]; /* from 0xa00 to 0xfff */
+} serdes_corenet_t;
+
+#else /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+#define SRDS_MAX_LANES 18
+#define SRDS_MAX_BANK 3
+typedef struct serdes_corenet {
+ struct {
+ u32 rstctl; /* Reset Control Register */
+#define SRDS_RSTCTL_RST 0x80000000
+#define SRDS_RSTCTL_RSTDONE 0x40000000
+#define SRDS_RSTCTL_RSTERR 0x20000000
+#define SRDS_RSTCTL_SDPD 0x00000020
+ u32 pllcr0; /* PLL Control Register 0 */
+#define SRDS_PLLCR0_RFCK_SEL_MASK 0x70000000
+#define SRDS_PLLCR0_PVCOCNT_EN 0x02000000
+#define SRDS_PLLCR0_RFCK_SEL_100 0x00000000
+#define SRDS_PLLCR0_RFCK_SEL_125 0x10000000
+#define SRDS_PLLCR0_RFCK_SEL_156_25 0x20000000
+#define SRDS_PLLCR0_RFCK_SEL_150 0x30000000
+#define SRDS_PLLCR0_RFCK_SEL_161_13 0x40000000
+#define SRDS_PLLCR0_FRATE_SEL_MASK 0x00030000
+#define SRDS_PLLCR0_FRATE_SEL_5 0x00000000
+#define SRDS_PLLCR0_FRATE_SEL_6_25 0x00010000
+ u32 pllcr1; /* PLL Control Register 1 */
+#define SRDS_PLLCR1_PLL_BWSEL 0x08000000
+ u32 res[5];
+ } bank[3];
+ u32 res1[12];
+ u32 srdstcalcr; /* TX Calibration Control */
+ u32 res2[3];
+ u32 srdsrcalcr; /* RX Calibration Control */
+ u32 res3[3];
+ u32 srdsgr0; /* General Register 0 */
+ u32 res4[11];
+ u32 srdspccr0; /* Protocol Converter Config 0 */
+ u32 srdspccr1; /* Protocol Converter Config 1 */
+ u32 srdspccr2; /* Protocol Converter Config 2 */
+#define SRDS_PCCR2_RST_XGMII1 0x00800000
+#define SRDS_PCCR2_RST_XGMII2 0x00400000
+ u32 res5[197];
+ struct serdes_lane {
+ u32 gcr0; /* General Control Register 0 */
+#define SRDS_GCR0_RRST 0x00400000
+#define SRDS_GCR0_1STLANE 0x00010000
+#define SRDS_GCR0_UOTHL 0x00100000
+ u32 gcr1; /* General Control Register 1 */
+#define SRDS_GCR1_REIDL_CTL_MASK 0x001f0000
+#define SRDS_GCR1_REIDL_CTL_PCIE 0x00100000
+#define SRDS_GCR1_REIDL_CTL_SRIO 0x00000000
+#define SRDS_GCR1_REIDL_CTL_SGMII 0x00040000
+#define SRDS_GCR1_OPAD_CTL 0x04000000
+ u32 res1[4];
+ u32 tecr0; /* TX Equalization Control Reg 0 */
+#define SRDS_TECR0_TEQ_TYPE_MASK 0x30000000
+#define SRDS_TECR0_TEQ_TYPE_2LVL 0x10000000
+ u32 res3;
+ u32 ttlcr0; /* Transition Tracking Loop Ctrl 0 */
+#define SRDS_TTLCR0_FLT_SEL_MASK 0x3f000000
+#define SRDS_TTLCR0_FLT_SEL_KFR_26 0x10000000
+#define SRDS_TTLCR0_FLT_SEL_KPH_28 0x08000000
+#define SRDS_TTLCR0_FLT_SEL_750PPM 0x03000000
+#define SRDS_TTLCR0_PM_DIS 0x00004000
+#define SRDS_TTLCR0_FREQOVD_EN 0x00000001
+ u32 res4[7];
+ } lane[24];
+ u32 res6[384];
+} serdes_corenet_t;
+#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+enum {
+ FSL_SRDS_B1_LANE_A = 0,
+ FSL_SRDS_B1_LANE_B = 1,
+ FSL_SRDS_B1_LANE_C = 2,
+ FSL_SRDS_B1_LANE_D = 3,
+ FSL_SRDS_B1_LANE_E = 4,
+ FSL_SRDS_B1_LANE_F = 5,
+ FSL_SRDS_B1_LANE_G = 6,
+ FSL_SRDS_B1_LANE_H = 7,
+ FSL_SRDS_B1_LANE_I = 8,
+ FSL_SRDS_B1_LANE_J = 9,
+ FSL_SRDS_B2_LANE_A = 16,
+ FSL_SRDS_B2_LANE_B = 17,
+ FSL_SRDS_B2_LANE_C = 18,
+ FSL_SRDS_B2_LANE_D = 19,
+ FSL_SRDS_B3_LANE_A = 20,
+ FSL_SRDS_B3_LANE_B = 21,
+ FSL_SRDS_B3_LANE_C = 22,
+ FSL_SRDS_B3_LANE_D = 23,
+};
+
+/* Security Engine Block (MS = Most Sig., LS = Least Sig.) */
+#if CONFIG_SYS_FSL_SEC_COMPAT >= 4
+typedef struct ccsr_sec {
+ u32 res0;
+ u32 mcfgr; /* Master CFG Register */
+ u8 res1[0x8];
+ struct {
+ u32 ms; /* Job Ring LIODN Register, MS */
+ u32 ls; /* Job Ring LIODN Register, LS */
+ } jrliodnr[4];
+ u8 res2[0x30];
+ struct {
+ u32 ms; /* RTIC LIODN Register, MS */
+ u32 ls; /* RTIC LIODN Register, LS */
+ } rticliodnr[4];
+ u8 res3[0x1c];
+ u32 decorr; /* DECO Request Register */
+ struct {
+ u32 ms; /* DECO LIODN Register, MS */
+ u32 ls; /* DECO LIODN Register, LS */
+ } decoliodnr[8];
+ u8 res4[0x40];
+ u32 dar; /* DECO Avail Register */
+ u32 drr; /* DECO Reset Register */
+ u8 res5[0xe78];
+ u32 crnr_ms; /* CHA Revision Number Register, MS */
+ u32 crnr_ls; /* CHA Revision Number Register, LS */
+ u32 ctpr_ms; /* Compile Time Parameters Register, MS */
+ u32 ctpr_ls; /* Compile Time Parameters Register, LS */
+ u8 res6[0x10];
+ u32 far_ms; /* Fault Address Register, MS */
+ u32 far_ls; /* Fault Address Register, LS */
+ u32 falr; /* Fault Address LIODN Register */
+ u32 fadr; /* Fault Address Detail Register */
+ u8 res7[0x4];
+ u32 csta; /* CAAM Status Register */
+ u8 res8[0x8];
+ u32 rvid; /* Run Time Integrity Checking Version ID Reg.*/
+ u32 ccbvid; /* CHA Cluster Block Version ID Register */
+ u32 chavid_ms; /* CHA Version ID Register, MS */
+ u32 chavid_ls; /* CHA Version ID Register, LS */
+ u32 chanum_ms; /* CHA Number Register, MS */
+ u32 chanum_ls; /* CHA Number Register, LS */
+ u32 secvid_ms; /* SEC Version ID Register, MS */
+ u32 secvid_ls; /* SEC Version ID Register, LS */
+ u8 res9[0x6020];
+ u32 qilcr_ms; /* Queue Interface LIODN CFG Register, MS */
+ u32 qilcr_ls; /* Queue Interface LIODN CFG Register, LS */
+ u8 res10[0x8fd8];
+} ccsr_sec_t;
+
+#define SEC_CTPR_MS_AXI_LIODN 0x08000000
+#define SEC_CTPR_MS_QI 0x02000000
+#define SEC_RVID_MA 0x0f000000
+#define SEC_CHANUM_MS_JRNUM_MASK 0xf0000000
+#define SEC_CHANUM_MS_JRNUM_SHIFT 28
+#define SEC_CHANUM_MS_DECONUM_MASK 0x0f000000
+#define SEC_CHANUM_MS_DECONUM_SHIFT 24
+#define SEC_SECVID_MS_IPID_MASK 0xffff0000
+#define SEC_SECVID_MS_IPID_SHIFT 16
+#define SEC_SECVID_MS_MAJ_REV_MASK 0x0000ff00
+#define SEC_SECVID_MS_MAJ_REV_SHIFT 8
+#define SEC_CCBVID_ERA_MASK 0xff000000
+#define SEC_CCBVID_ERA_SHIFT 24
+#endif
+
+typedef struct ccsr_qman {
+#ifdef CONFIG_SYS_FSL_QMAN_V3
+ u8 res0[0x200];
+#else
+ struct {
+ u32 qcsp_lio_cfg; /* 0x0 - SW Portal n LIO cfg */
+ u32 qcsp_io_cfg; /* 0x4 - SW Portal n IO cfg */
+ u32 res;
+ u32 qcsp_dd_cfg; /* 0xc - SW Portal n Dynamic Debug cfg */
+ } qcsp[32];
+#endif
+ /* Not actually reserved, but irrelevant to u-boot */
+ u8 res[0xbf8 - 0x200];
+ u32 ip_rev_1;
+ u32 ip_rev_2;
+ u32 fqd_bare; /* FQD Extended Base Addr Register */
+ u32 fqd_bar; /* FQD Base Addr Register */
+ u8 res1[0x8];
+ u32 fqd_ar; /* FQD Attributes Register */
+ u8 res2[0xc];
+ u32 pfdr_bare; /* PFDR Extended Base Addr Register */
+ u32 pfdr_bar; /* PFDR Base Addr Register */
+ u8 res3[0x8];
+ u32 pfdr_ar; /* PFDR Attributes Register */
+ u8 res4[0x4c];
+ u32 qcsp_bare; /* QCSP Extended Base Addr Register */
+ u32 qcsp_bar; /* QCSP Base Addr Register */
+ u8 res5[0x78];
+ u32 ci_sched_cfg; /* Initiator Scheduling Configuration */
+ u32 srcidr; /* Source ID Register */
+ u32 liodnr; /* LIODN Register */
+ u8 res6[4];
+ u32 ci_rlm_cfg; /* Initiator Read Latency Monitor Cfg */
+ u32 ci_rlm_avg; /* Initiator Read Latency Monitor Avg */
+ u8 res7[0x2e8];
+#ifdef CONFIG_SYS_FSL_QMAN_V3
+ struct {
+ u32 qcsp_lio_cfg; /* 0x0 - SW Portal n LIO cfg */
+ u32 qcsp_io_cfg; /* 0x4 - SW Portal n IO cfg */
+ u32 res;
+ u32 qcsp_dd_cfg; /* 0xc - SW Portal n Dynamic Debug cfg*/
+ } qcsp[50];
+#endif
+} ccsr_qman_t;
+
+typedef struct ccsr_bman {
+ /* Not actually reserved, but irrelevant to u-boot */
+ u8 res[0xbf8];
+ u32 ip_rev_1;
+ u32 ip_rev_2;
+ u32 fbpr_bare; /* FBPR Extended Base Addr Register */
+ u32 fbpr_bar; /* FBPR Base Addr Register */
+ u8 res1[0x8];
+ u32 fbpr_ar; /* FBPR Attributes Register */
+ u8 res2[0xf0];
+ u32 srcidr; /* Source ID Register */
+ u32 liodnr; /* LIODN Register */
+ u8 res7[0x2f4];
+} ccsr_bman_t;
+
+typedef struct ccsr_pme {
+ u8 res0[0x804];
+ u32 liodnbr; /* LIODN Base Register */
+ u8 res1[0x1f8];
+ u32 srcidr; /* Source ID Register */
+ u8 res2[8];
+ u32 liodnr; /* LIODN Register */
+ u8 res3[0x1e8];
+ u32 pm_ip_rev_1; /* PME IP Block Revision Reg 1*/
+ u32 pm_ip_rev_2; /* PME IP Block Revision Reg 1*/
+ u8 res4[0x400];
+} ccsr_pme_t;
+
+#ifdef CONFIG_SYS_FSL_USB_DUAL_PHY_ENABLE
+struct ccsr_usb_port_ctrl {
+ u32 ctrl;
+ u32 drvvbuscfg;
+ u32 pwrfltcfg;
+ u32 sts;
+ u8 res_14[0xc];
+ u32 bistcfg;
+ u32 biststs;
+ u32 abistcfg;
+ u32 abiststs;
+ u8 res_30[0x10];
+ u32 xcvrprg;
+ u32 anaprg;
+ u32 anadrv;
+ u32 anasts;
+};
+
+typedef struct ccsr_usb_phy {
+ u32 id;
+ struct ccsr_usb_port_ctrl port1;
+ u8 res_50[0xc];
+ u32 tvr;
+ u32 pllprg[4];
+ u8 res_70[0x4];
+ u32 anaccfg;
+ u32 dbg;
+ u8 res_7c[0x4];
+ struct ccsr_usb_port_ctrl port2;
+ u8 res_dc[0x334];
+} ccsr_usb_phy_t;
+
+#define CONFIG_SYS_FSL_USB_CTRL_PHY_EN (1 << 0)
+#define CONFIG_SYS_FSL_USB_DRVVBUS_CR_EN (1 << 1)
+#define CONFIG_SYS_FSL_USB_PWRFLT_CR_EN (1 << 1)
+#define CONFIG_SYS_FSL_USB_PLLPRG2_PHY2_CLK_EN (1 << 0)
+#define CONFIG_SYS_FSL_USB_PLLPRG2_PHY1_CLK_EN (1 << 1)
+#define CONFIG_SYS_FSL_USB_PLLPRG2_MFI (5 << 16)
+#define CONFIG_SYS_FSL_USB_PLLPRG2_PLL_EN (1 << 21)
+#else
+typedef struct ccsr_usb_phy {
+ u8 res0[0x18];
+ u32 usb_enable_override;
+ u8 res[0xe4];
+} ccsr_usb_phy_t;
+#define CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE 1
+#endif
+
+#ifdef CONFIG_SYS_FSL_RAID_ENGINE
+struct ccsr_raide {
+ u8 res0[0x543];
+ u32 liodnbr; /* LIODN Base Register */
+ u8 res1[0xab8];
+ struct {
+ struct {
+ u32 cfg0; /* cfg register 0 */
+ u32 cfg1; /* cfg register 1 */
+ u8 res1[0x3f8];
+ } ring[2];
+ u8 res[0x800];
+ } jq[2];
+};
+#endif
+
+#ifdef CONFIG_SYS_DPAA_RMAN
+struct ccsr_rman {
+ u8 res0[0xf64];
+ u32 mmliodnbr; /* Message Manager LIODN Base Register */
+ u32 mmitar; /* RMAN Inbound Translation Address Register */
+ u32 mmitdr; /* RMAN Inbound Translation Data Register */
+ u8 res4[0x1f090];
+};
+#endif
+
+#ifdef CONFIG_SYS_PMAN
+struct ccsr_pman {
+ u8 res_00[0x40];
+ u32 poes1; /* PMAN Operation Error Status Register 1 */
+ u32 poes2; /* PMAN Operation Error Status Register 2 */
+ u32 poeah; /* PMAN Operation Error Address High */
+ u32 poeal; /* PMAN Operation Error Address Low */
+ u8 res_50[0x50];
+ u32 pr1; /* PMAN Revision Register 1 */
+ u32 pr2; /* PMAN Revision Register 2 */
+ u8 res_a8[0x8];
+ u32 pcap; /* PMAN Capabilities Register */
+ u8 res_b4[0xc];
+ u32 pc1; /* PMAN Control Register 1 */
+ u32 pc2; /* PMAN Control Register 2 */
+ u32 pc3; /* PMAN Control Register 3 */
+ u32 pc4; /* PMAN Control Register 4 */
+ u32 pc5; /* PMAN Control Register 5 */
+ u32 pc6; /* PMAN Control Register 6 */
+ u8 res_d8[0x8];
+ u32 ppa1; /* PMAN Prefetch Attributes Register 1 */
+ u32 ppa2; /* PMAN Prefetch Attributes Register 2 */
+ u8 res_e8[0x8];
+ u32 pics; /* PMAN Interrupt Control and Status */
+ u8 res_f4[0xf0c];
+};
+#endif
+
+#ifdef CONFIG_FSL_CORENET
+#define CONFIG_SYS_FSL_CORENET_CCM_OFFSET 0x0000
+#ifdef CONFIG_SYS_PMAN
+#define CONFIG_SYS_FSL_CORENET_PMAN1_OFFSET 0x4000
+#define CONFIG_SYS_FSL_CORENET_PMAN2_OFFSET 0x5000
+#define CONFIG_SYS_FSL_CORENET_PMAN3_OFFSET 0x6000
+#endif
+#define CONFIG_SYS_MPC8xxx_DDR_OFFSET 0x8000
+#define CONFIG_SYS_MPC8xxx_DDR2_OFFSET 0x9000
+#define CONFIG_SYS_MPC8xxx_DDR3_OFFSET 0xA000
+#define CONFIG_SYS_FSL_CORENET_CLK_OFFSET 0xE1000
+#define CONFIG_SYS_FSL_CORENET_RCPM_OFFSET 0xE2000
+#define CONFIG_SYS_FSL_CORENET_SERDES_OFFSET 0xEA000
+#define CONFIG_SYS_FSL_CORENET_SERDES2_OFFSET 0xEB000
+#define CONFIG_SYS_FSL_CPC_OFFSET 0x10000
+#define CONFIG_SYS_MPC85xx_DMA1_OFFSET 0x100000
+#define CONFIG_SYS_MPC85xx_DMA2_OFFSET 0x101000
+#define CONFIG_SYS_MPC85xx_DMA_OFFSET CONFIG_SYS_MPC85xx_DMA1_OFFSET
+#define CONFIG_SYS_MPC85xx_ESPI_OFFSET 0x110000
+#define CONFIG_SYS_MPC85xx_ESDHC_OFFSET 0x114000
+#define CONFIG_SYS_MPC85xx_LBC_OFFSET 0x124000
+#define CONFIG_SYS_MPC85xx_IFC_OFFSET 0x124000
+#define CONFIG_SYS_MPC85xx_GPIO_OFFSET 0x130000
+#define CONFIG_SYS_FSL_CORENET_RMAN_OFFSET 0x1e0000
+#if defined(CONFIG_SYS_FSL_QORIQ_CHASSIS2) && !defined(CONFIG_PPC_B4860)\
+ && !defined(CONFIG_PPC_B4420)
+#define CONFIG_SYS_MPC85xx_PCIE1_OFFSET 0x240000
+#define CONFIG_SYS_MPC85xx_PCIE2_OFFSET 0x250000
+#define CONFIG_SYS_MPC85xx_PCIE3_OFFSET 0x260000
+#define CONFIG_SYS_MPC85xx_PCIE4_OFFSET 0x270000
+#else
+#define CONFIG_SYS_MPC85xx_PCIE1_OFFSET 0x200000
+#define CONFIG_SYS_MPC85xx_PCIE2_OFFSET 0x201000
+#define CONFIG_SYS_MPC85xx_PCIE3_OFFSET 0x202000
+#define CONFIG_SYS_MPC85xx_PCIE4_OFFSET 0x203000
+#endif
+#define CONFIG_SYS_MPC85xx_USB1_OFFSET 0x210000
+#define CONFIG_SYS_MPC85xx_USB2_OFFSET 0x211000
+#define CONFIG_SYS_MPC85xx_USB_OFFSET CONFIG_SYS_MPC85xx_USB1_OFFSET
+#define CONFIG_SYS_MPC85xx_USB1_PHY_OFFSET 0x214000
+#define CONFIG_SYS_MPC85xx_USB2_PHY_OFFSET 0x214100
+#define CONFIG_SYS_MPC85xx_SATA1_OFFSET 0x220000
+#define CONFIG_SYS_MPC85xx_SATA2_OFFSET 0x221000
+#define CONFIG_SYS_FSL_SEC_OFFSET 0x300000
+#define CONFIG_SYS_FSL_CORENET_PME_OFFSET 0x316000
+#define CONFIG_SYS_FSL_QMAN_OFFSET 0x318000
+#define CONFIG_SYS_FSL_BMAN_OFFSET 0x31a000
+#define CONFIG_SYS_FSL_RAID_ENGINE_OFFSET 0x320000
+#define CONFIG_SYS_FSL_FM1_OFFSET 0x400000
+#define CONFIG_SYS_FSL_FM1_RX0_1G_OFFSET 0x488000
+#define CONFIG_SYS_FSL_FM1_RX1_1G_OFFSET 0x489000
+#define CONFIG_SYS_FSL_FM1_RX2_1G_OFFSET 0x48a000
+#define CONFIG_SYS_FSL_FM1_RX3_1G_OFFSET 0x48b000
+#define CONFIG_SYS_FSL_FM1_RX4_1G_OFFSET 0x48c000
+#define CONFIG_SYS_FSL_FM1_RX5_1G_OFFSET 0x48d000
+#define CONFIG_SYS_FSL_FM1_RX0_10G_OFFSET 0x490000
+#define CONFIG_SYS_FSL_FM1_RX1_10G_OFFSET 0x491000
+#define CONFIG_SYS_FSL_FM1_DTSEC1_OFFSET 0x4e0000
+#define CONFIG_SYS_FSL_FM2_OFFSET 0x500000
+#define CONFIG_SYS_FSL_FM2_RX0_1G_OFFSET 0x588000
+#define CONFIG_SYS_FSL_FM2_RX1_1G_OFFSET 0x589000
+#define CONFIG_SYS_FSL_FM2_RX2_1G_OFFSET 0x58a000
+#define CONFIG_SYS_FSL_FM2_RX3_1G_OFFSET 0x58b000
+#define CONFIG_SYS_FSL_FM2_RX4_1G_OFFSET 0x58c000
+#define CONFIG_SYS_FSL_FM2_RX5_1G_OFFSET 0x58d000
+#define CONFIG_SYS_FSL_FM2_RX0_10G_OFFSET 0x590000
+#define CONFIG_SYS_FSL_FM2_RX1_10G_OFFSET 0x591000
+#define CONFIG_SYS_FSL_CLUSTER_1_L2_OFFSET 0xC20000
+#else
+#define CONFIG_SYS_MPC85xx_ECM_OFFSET 0x0000
+#define CONFIG_SYS_MPC8xxx_DDR_OFFSET 0x2000
+#define CONFIG_SYS_MPC85xx_LBC_OFFSET 0x5000
+#define CONFIG_SYS_MPC8xxx_DDR2_OFFSET 0x6000
+#define CONFIG_SYS_MPC85xx_ESPI_OFFSET 0x7000
+#define CONFIG_SYS_MPC85xx_PCI1_OFFSET 0x8000
+#define CONFIG_SYS_MPC85xx_PCIX_OFFSET 0x8000
+#define CONFIG_SYS_MPC85xx_PCI2_OFFSET 0x9000
+#define CONFIG_SYS_MPC85xx_PCIX2_OFFSET 0x9000
+#define CONFIG_SYS_MPC85xx_PCIE1_OFFSET 0xa000
+#define CONFIG_SYS_MPC85xx_PCIE2_OFFSET 0x9000
+#if defined(CONFIG_MPC8572) || defined(CONFIG_P2020)
+#define CONFIG_SYS_MPC85xx_PCIE3_OFFSET 0x8000
+#else
+#define CONFIG_SYS_MPC85xx_PCIE3_OFFSET 0xb000
+#endif
+#define CONFIG_SYS_MPC85xx_GPIO_OFFSET 0xF000
+#define CONFIG_SYS_MPC85xx_SATA1_OFFSET 0x18000
+#define CONFIG_SYS_MPC85xx_SATA2_OFFSET 0x19000
+#define CONFIG_SYS_MPC85xx_IFC_OFFSET 0x1e000
+#define CONFIG_SYS_MPC85xx_L2_OFFSET 0x20000
+#define CONFIG_SYS_MPC85xx_DMA_OFFSET 0x21000
+#define CONFIG_SYS_MPC85xx_USB_OFFSET 0x22000
+#define CONFIG_SYS_MPC85xx_USB2_OFFSET 0x23000
+#ifdef CONFIG_TSECV2
+#define CONFIG_SYS_TSEC1_OFFSET 0xB0000
+#else
+#define CONFIG_SYS_TSEC1_OFFSET 0x24000
+#endif
+#define CONFIG_SYS_MDIO1_OFFSET 0x24000
+#define CONFIG_SYS_MPC85xx_ESDHC_OFFSET 0x2e000
+#define CONFIG_SYS_FSL_SEC_OFFSET 0x30000
+#define CONFIG_SYS_MPC85xx_SERDES2_OFFSET 0xE3100
+#define CONFIG_SYS_MPC85xx_SERDES1_OFFSET 0xE3000
+#define CONFIG_SYS_SNVS_OFFSET 0xE6000
+#define CONFIG_SYS_SFP_OFFSET 0xE7000
+#define CONFIG_SYS_MPC85xx_CPM_OFFSET 0x80000
+#define CONFIG_SYS_FSL_QMAN_OFFSET 0x88000
+#define CONFIG_SYS_FSL_BMAN_OFFSET 0x8a000
+#define CONFIG_SYS_FSL_FM1_OFFSET 0x100000
+#define CONFIG_SYS_FSL_FM1_RX0_1G_OFFSET 0x188000
+#define CONFIG_SYS_FSL_FM1_RX1_1G_OFFSET 0x189000
+#define CONFIG_SYS_FSL_FM1_DTSEC1_OFFSET 0x1e0000
+#endif
+
+#define CONFIG_SYS_MPC85xx_PIC_OFFSET 0x40000
+#define CONFIG_SYS_MPC85xx_GUTS_OFFSET 0xE0000
+#define CONFIG_SYS_FSL_SRIO_OFFSET 0xC0000
+
+#define CONFIG_SYS_FSL_CPC_ADDR \
+ (CONFIG_SYS_CCSRBAR + CONFIG_SYS_FSL_CPC_OFFSET)
+#define CONFIG_SYS_FSL_QMAN_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_QMAN_OFFSET)
+#define CONFIG_SYS_FSL_BMAN_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_BMAN_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_PME_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_PME_OFFSET)
+#define CONFIG_SYS_FSL_RAID_ENGINE_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_RAID_ENGINE_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_RMAN_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_RMAN_OFFSET)
+#define CONFIG_SYS_MPC85xx_GUTS_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_GUTS_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_CCM_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_CCM_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_CLK_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_CLK_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_RCPM_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_RCPM_OFFSET)
+#define CONFIG_SYS_MPC85xx_ECM_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_ECM_OFFSET)
+#define CONFIG_SYS_MPC8xxx_DDR_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR_OFFSET)
+#define CONFIG_SYS_MPC8xxx_DDR2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR2_OFFSET)
+#define CONFIG_SYS_MPC8xxx_DDR3_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR3_OFFSET)
+#define CONFIG_SYS_LBC_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_LBC_OFFSET)
+#define CONFIG_SYS_IFC_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_IFC_OFFSET)
+#define CONFIG_SYS_MPC85xx_ESPI_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_ESPI_OFFSET)
+#define CONFIG_SYS_MPC85xx_PCIX_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIX_OFFSET)
+#define CONFIG_SYS_MPC85xx_PCIX2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIX2_OFFSET)
+#define CONFIG_SYS_MPC85xx_GPIO_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_GPIO_OFFSET)
+#define CONFIG_SYS_MPC85xx_SATA1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SATA1_OFFSET)
+#define CONFIG_SYS_MPC85xx_SATA2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SATA2_OFFSET)
+#define CONFIG_SYS_MPC85xx_L2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_L2_OFFSET)
+#define CONFIG_SYS_MPC85xx_DMA_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DMA_OFFSET)
+#define CONFIG_SYS_MPC85xx_ESDHC_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_ESDHC_OFFSET)
+#define CONFIG_SYS_MPC8xxx_PIC_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PIC_OFFSET)
+#define CONFIG_SYS_MPC85xx_CPM_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_CPM_OFFSET)
+#define CONFIG_SYS_MPC85xx_SERDES1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SERDES1_OFFSET)
+#define CONFIG_SYS_MPC85xx_SERDES2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_SERDES2_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_SERDES_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES_OFFSET)
+#define CONFIG_SYS_FSL_CORENET_SERDES2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CORENET_SERDES2_OFFSET)
+#define CONFIG_SYS_MPC85xx_USB_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_USB_OFFSET)
+#define CONFIG_SYS_MPC85xx_USB1_PHY_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_USB1_PHY_OFFSET)
+#define CONFIG_SYS_MPC85xx_USB2_PHY_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_USB2_PHY_OFFSET)
+#define CONFIG_SYS_FSL_SEC_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_SEC_OFFSET)
+#define CONFIG_SYS_FSL_FM1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_FM1_OFFSET)
+#define CONFIG_SYS_FSL_FM1_DTSEC1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_FM1_DTSEC1_OFFSET)
+#define CONFIG_SYS_FSL_FM2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_FM2_OFFSET)
+#define CONFIG_SYS_FSL_SRIO_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_SRIO_OFFSET)
+
+#define CONFIG_SYS_PCI1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCI1_OFFSET)
+#define CONFIG_SYS_PCI2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCI2_OFFSET)
+#define CONFIG_SYS_PCIE1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIE1_OFFSET)
+#define CONFIG_SYS_PCIE2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIE2_OFFSET)
+#define CONFIG_SYS_PCIE3_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIE3_OFFSET)
+#define CONFIG_SYS_PCIE4_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_PCIE4_OFFSET)
+
+#define TSEC_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_TSEC1_OFFSET)
+#define MDIO_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MDIO1_OFFSET)
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+struct ccsr_cluster_l2 {
+ u32 l2csr0; /* 0x000 L2 cache control and status register 0 */
+ u32 l2csr1; /* 0x004 L2 cache control and status register 1 */
+ u32 l2cfg0; /* 0x008 L2 cache configuration register 0 */
+ u8 res_0c[500];/* 0x00c - 0x1ff */
+ u32 l2pir0; /* 0x200 L2 cache partitioning ID register 0 */
+ u8 res_204[4];
+ u32 l2par0; /* 0x208 L2 cache partitioning allocation register 0 */
+ u32 l2pwr0; /* 0x20c L2 cache partitioning way register 0 */
+ u32 l2pir1; /* 0x210 L2 cache partitioning ID register 1 */
+ u8 res_214[4];
+ u32 l2par1; /* 0x218 L2 cache partitioning allocation register 1 */
+ u32 l2pwr1; /* 0x21c L2 cache partitioning way register 1 */
+ u32 u2pir2; /* 0x220 L2 cache partitioning ID register 2 */
+ u8 res_224[4];
+ u32 l2par2; /* 0x228 L2 cache partitioning allocation register 2 */
+ u32 l2pwr2; /* 0x22c L2 cache partitioning way register 2 */
+ u32 l2pir3; /* 0x230 L2 cache partitioning ID register 3 */
+ u8 res_234[4];
+ u32 l2par3; /* 0x238 L2 cache partitining allocation register 3 */
+ u32 l2pwr3; /* 0x23c L2 cache partitining way register 3 */
+ u32 l2pir4; /* 0x240 L2 cache partitioning ID register 3 */
+ u8 res244[4];
+ u32 l2par4; /* 0x248 L2 cache partitioning allocation register 3 */
+ u32 l2pwr4; /* 0x24c L2 cache partitioning way register 3 */
+ u32 l2pir5; /* 0x250 L2 cache partitioning ID register 3 */
+ u8 res_254[4];
+ u32 l2par5; /* 0x258 L2 cache partitioning allocation register 3 */
+ u32 l2pwr5; /* 0x25c L2 cache partitioning way register 3 */
+ u32 l2pir6; /* 0x260 L2 cache partitioning ID register 3 */
+ u8 res_264[4];
+ u32 l2par6; /* 0x268 L2 cache partitioning allocation register 3 */
+ u32 l2pwr6; /* 0x26c L2 cache partitioning way register 3 */
+ u32 l2pir7; /* 0x270 L2 cache partitioning ID register 3 */
+ u8 res274[4];
+ u32 l2par7; /* 0x278 L2 cache partitioning allocation register 3 */
+ u32 l2pwr7; /* 0x27c L2 cache partitioning way register 3 */
+ u8 res_280[0xb80]; /* 0x280 - 0xdff */
+ u32 l2errinjhi; /* 0xe00 L2 cache error injection mask high */
+ u32 l2errinjlo; /* 0xe04 L2 cache error injection mask low */
+ u32 l2errinjctl;/* 0xe08 L2 cache error injection control */
+ u8 res_e0c[20]; /* 0xe0c - 0x01f */
+ u32 l2captdatahi; /* 0xe20 L2 cache error capture data high */
+ u32 l2captdatalo; /* 0xe24 L2 cache error capture data low */
+ u32 l2captecc; /* 0xe28 L2 cache error capture ECC syndrome */
+ u8 res_e2c[20]; /* 0xe2c - 0xe3f */
+ u32 l2errdet; /* 0xe40 L2 cache error detect */
+ u32 l2errdis; /* 0xe44 L2 cache error disable */
+ u32 l2errinten; /* 0xe48 L2 cache error interrupt enable */
+ u32 l2errattr; /* 0xe4c L2 cache error attribute */
+ u32 l2erreaddr; /* 0xe50 L2 cache error extended address */
+ u32 l2erraddr; /* 0xe54 L2 cache error address */
+ u32 l2errctl; /* 0xe58 L2 cache error control */
+};
+#define CONFIG_SYS_FSL_CLUSTER_1_L2 \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_FSL_CLUSTER_1_L2_OFFSET)
+#endif /* CONFIG_SYS_FSL_QORIQ_CHASSIS2 */
+
+#define CONFIG_SYS_DCSR_DCFG_OFFSET 0X20000
+struct dcsr_dcfg_regs {
+ u8 res_0[0x520];
+ u32 ecccr1;
+#define DCSR_DCFG_ECC_DISABLE_USB1 0x00008000
+#define DCSR_DCFG_ECC_DISABLE_USB2 0x00004000
+ u8 res_524[0x1000 - 0x524]; /* 0x524 - 0x1000 */
+};
+#endif /*__IMMAP_85xx__*/
diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/immap_86xx.h
new file mode 100644
index 0000000..2a704fe
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_86xx.h
@@ -0,0 +1,1289 @@
+/*
+ * MPC86xx Internal Memory Map
+ *
+ * Copyright 2004, 2011 Freescale Semiconductor
+ * Jeff Brown (Jeffrey@freescale.com)
+ * Srikanth Srinivasan (srikanth.srinivasan@freescale.com)
+ *
+ */
+
+#ifndef __IMMAP_86xx__
+#define __IMMAP_86xx__
+
+#include <asm/types.h>
+#include <asm/fsl_dma.h>
+#include <asm/fsl_lbc.h>
+#include <asm/fsl_i2c.h>
+
+/* Local-Access Registers and MCM Registers(0x0000-0x2000) */
+typedef struct ccsr_local_mcm {
+ uint ccsrbar; /* 0x0 - Control Configuration Status Registers Base Address Register */
+ char res1[4];
+ uint altcbar; /* 0x8 - Alternate Configuration Base Address Register */
+ char res2[4];
+ uint altcar; /* 0x10 - Alternate Configuration Attribute Register */
+ char res3[12];
+ uint bptr; /* 0x20 - Boot Page Translation Register */
+ char res4[3044];
+ uint lawbar0; /* 0xc08 - Local Access Window 0 Base Address Register */
+ char res5[4];
+ uint lawar0; /* 0xc10 - Local Access Window 0 Attributes Register */
+ char res6[20];
+ uint lawbar1; /* 0xc28 - Local Access Window 1 Base Address Register */
+ char res7[4];
+ uint lawar1; /* 0xc30 - Local Access Window 1 Attributes Register */
+ char res8[20];
+ uint lawbar2; /* 0xc48 - Local Access Window 2 Base Address Register */
+ char res9[4];
+ uint lawar2; /* 0xc50 - Local Access Window 2 Attributes Register */
+ char res10[20];
+ uint lawbar3; /* 0xc68 - Local Access Window 3 Base Address Register */
+ char res11[4];
+ uint lawar3; /* 0xc70 - Local Access Window 3 Attributes Register */
+ char res12[20];
+ uint lawbar4; /* 0xc88 - Local Access Window 4 Base Address Register */
+ char res13[4];
+ uint lawar4; /* 0xc90 - Local Access Window 4 Attributes Register */
+ char res14[20];
+ uint lawbar5; /* 0xca8 - Local Access Window 5 Base Address Register */
+ char res15[4];
+ uint lawar5; /* 0xcb0 - Local Access Window 5 Attributes Register */
+ char res16[20];
+ uint lawbar6; /* 0xcc8 - Local Access Window 6 Base Address Register */
+ char res17[4];
+ uint lawar6; /* 0xcd0 - Local Access Window 6 Attributes Register */
+ char res18[20];
+ uint lawbar7; /* 0xce8 - Local Access Window 7 Base Address Register */
+ char res19[4];
+ uint lawar7; /* 0xcf0 - Local Access Window 7 Attributes Register */
+ char res20[20];
+ uint lawbar8; /* 0xd08 - Local Access Window 8 Base Address Register */
+ char res21[4];
+ uint lawar8; /* 0xd10 - Local Access Window 8 Attributes Register */
+ char res22[20];
+ uint lawbar9; /* 0xd28 - Local Access Window 9 Base Address Register */
+ char res23[4];
+ uint lawar9; /* 0xd30 - Local Access Window 9 Attributes Register */
+ char res24[716];
+ uint abcr; /* 0x1000 - MCM CCB Address Configuration Register */
+ char res25[4];
+ uint dbcr; /* 0x1008 - MCM MPX data bus Configuration Register */
+ char res26[4];
+ uint pcr; /* 0x1010 - MCM CCB Port Configuration Register */
+ char res27[44];
+ uint hpmr0; /* 0x1040 - MCM HPM Threshold Count Register 0 */
+ uint hpmr1; /* 0x1044 - MCM HPM Threshold Count Register 1 */
+ uint hpmr2; /* 0x1048 - MCM HPM Threshold Count Register 2 */
+ uint hpmr3; /* 0x104c - MCM HPM Threshold Count Register 3 */
+ char res28[16];
+ uint hpmr4; /* 0x1060 - MCM HPM Threshold Count Register 4 */
+ uint hpmr5; /* 0x1064 - MCM HPM Threshold Count Register 5 */
+ uint hpmccr; /* 0x1068 - MCM HPM Cycle Count Register */
+ char res29[3476];
+ uint edr; /* 0x1e00 - MCM Error Detect Register */
+ char res30[4];
+ uint eer; /* 0x1e08 - MCM Error Enable Register */
+ uint eatr; /* 0x1e0c - MCM Error Attributes Capture Register */
+ uint eladr; /* 0x1e10 - MCM Error Low Address Capture Register */
+ uint ehadr; /* 0x1e14 - MCM Error High Address Capture Register */
+ char res31[488];
+} ccsr_local_mcm_t;
+
+/* DDR memory controller registers(0x2000-0x3000) and (0x6000-0x7000) */
+
+typedef struct ccsr_ddr {
+ uint cs0_bnds; /* 0x2000 - DDR Chip Select 0 Memory Bounds */
+ char res1[4];
+ uint cs1_bnds; /* 0x2008 - DDR Chip Select 1 Memory Bounds */
+ char res2[4];
+ uint cs2_bnds; /* 0x2010 - DDR Chip Select 2 Memory Bounds */
+ char res3[4];
+ uint cs3_bnds; /* 0x2018 - DDR Chip Select 3 Memory Bounds */
+ char res4[4];
+ uint cs4_bnds; /* 0x2020 - DDR Chip Select 4 Memory Bounds */
+ char res5[4];
+ uint cs5_bnds; /* 0x2028 - DDR Chip Select 5 Memory Bounds */
+ char res6[84];
+ uint cs0_config; /* 0x2080 - DDR Chip Select Configuration */
+ uint cs1_config; /* 0x2084 - DDR Chip Select Configuration */
+ uint cs2_config; /* 0x2088 - DDR Chip Select Configuration */
+ uint cs3_config; /* 0x208c - DDR Chip Select Configuration */
+ uint cs4_config; /* 0x2090 - DDR Chip Select Configuration */
+ uint cs5_config; /* 0x2094 - DDR Chip Select Configuration */
+ char res7[104];
+ uint timing_cfg_3; /* 0x2100 - DDR SDRAM Timing Configuration Register 3 */
+ uint timing_cfg_0; /* 0x2104 - DDR SDRAM Timing Configuration Register 0 */
+ uint timing_cfg_1; /* 0x2108 - DDR SDRAM Timing Configuration Register 1 */
+ uint timing_cfg_2; /* 0x210c - DDR SDRAM Timing Configuration Register 2 */
+ uint sdram_cfg; /* 0x2110 - DDR SDRAM Control Configuration 1 */
+ uint sdram_cfg_2; /* 0x2114 - DDR SDRAM Control Configuration 2 */
+ uint sdram_mode; /* 0x2118 - DDR SDRAM Mode Configuration 1 */
+ uint sdram_mode_2; /* 0x211c - DDR SDRAM Mode Configuration 2 */
+ uint sdram_mode_cntl; /* 0x2120 - DDR SDRAM Mode Control */
+ uint sdram_interval; /* 0x2124 - DDR SDRAM Interval Configuration */
+ uint sdram_data_init; /* 0x2128 - DDR SDRAM Data Initialization */
+ char res8[4];
+ uint sdram_clk_cntl; /* 0x2130 - DDR SDRAM Clock Control */
+ char res9[12];
+ uint sdram_ocd_cntl; /* 0x2140 - DDR SDRAM OCD Control */
+ uint sdram_ocd_status; /* 0x2144 - DDR SDRAM OCD Status */
+ uint init_addr; /* 0x2148 - DDR training initialzation address */
+ uint init_ext_addr; /* 0x214C - DDR training initialzation extended address */
+ char res10[2728];
+ uint ip_rev1; /* 0x2BF8 - DDR IP Block Revision 1 */
+ uint ip_rev2; /* 0x2BFC - DDR IP Block Revision 2 */
+ char res11[512];
+ uint data_err_inject_hi; /* 0x2e00 - DDR Memory Data Path Error Injection Mask High */
+ uint data_err_inject_lo; /* 0x2e04 - DDR Memory Data Path Error Injection Mask Low */
+ uint ecc_err_inject; /* 0x2e08 - DDR Memory Data Path Error Injection Mask ECC */
+ char res12[20];
+ uint capture_data_hi; /* 0x2e20 - DDR Memory Data Path Read Capture High */
+ uint capture_data_lo; /* 0x2e24 - DDR Memory Data Path Read Capture Low */
+ uint capture_ecc; /* 0x2e28 - DDR Memory Data Path Read Capture ECC */
+ char res13[20];
+ uint err_detect; /* 0x2e40 - DDR Memory Error Detect */
+ uint err_disable; /* 0x2e44 - DDR Memory Error Disable */
+ uint err_int_en; /* 0x2e48 - DDR Memory Error Interrupt Enable */
+ uint capture_attributes; /* 0x2e4c - DDR Memory Error Attributes Capture */
+ uint capture_address; /* 0x2e50 - DDR Memory Error Address Capture */
+ uint capture_ext_address; /* 0x2e54 - DDR Memory Error Extended Address Capture */
+ uint err_sbe; /* 0x2e58 - DDR Memory Single-Bit ECC Error Management */
+ char res14[164];
+ uint debug_1; /* 0x2f00 */
+ uint debug_2;
+ uint debug_3;
+ uint debug_4;
+ uint debug_5;
+ char res15[236];
+} ccsr_ddr_t;
+
+
+/* Daul I2C Registers(0x3000-0x4000) */
+typedef struct ccsr_i2c {
+ struct fsl_i2c i2c[2];
+ u8 res[4096 - 2 * sizeof(struct fsl_i2c)];
+} ccsr_i2c_t;
+
+/* DUART Registers(0x4000-0x5000) */
+typedef struct ccsr_duart {
+ char res1[1280];
+ u_char urbr1_uthr1_udlb1;/* 0x4500 - URBR1, UTHR1, UDLB1 with the same address offset of 0x04500 */
+ u_char uier1_udmb1; /* 0x4501 - UIER1, UDMB1 with the same address offset of 0x04501 */
+ u_char uiir1_ufcr1_uafr1;/* 0x4502 - UIIR1, UFCR1, UAFR1 with the same address offset of 0x04502 */
+ u_char ulcr1; /* 0x4503 - UART1 Line Control Register */
+ u_char umcr1; /* 0x4504 - UART1 Modem Control Register */
+ u_char ulsr1; /* 0x4505 - UART1 Line Status Register */
+ u_char umsr1; /* 0x4506 - UART1 Modem Status Register */
+ u_char uscr1; /* 0x4507 - UART1 Scratch Register */
+ char res2[8];
+ u_char udsr1; /* 0x4510 - UART1 DMA Status Register */
+ char res3[239];
+ u_char urbr2_uthr2_udlb2;/* 0x4600 - URBR2, UTHR2, UDLB2 with the same address offset of 0x04600 */
+ u_char uier2_udmb2; /* 0x4601 - UIER2, UDMB2 with the same address offset of 0x04601 */
+ u_char uiir2_ufcr2_uafr2;/* 0x4602 - UIIR2, UFCR2, UAFR2 with the same address offset of 0x04602 */
+ u_char ulcr2; /* 0x4603 - UART2 Line Control Register */
+ u_char umcr2; /* 0x4604 - UART2 Modem Control Register */
+ u_char ulsr2; /* 0x4605 - UART2 Line Status Register */
+ u_char umsr2; /* 0x4606 - UART2 Modem Status Register */
+ u_char uscr2; /* 0x4607 - UART2 Scratch Register */
+ char res4[8];
+ u_char udsr2; /* 0x4610 - UART2 DMA Status Register */
+ char res5[2543];
+} ccsr_duart_t;
+
+/* PCI Express Registers(0x8000-0x9000) and (0x9000-0xA000) */
+typedef struct ccsr_pex {
+ uint cfg_addr; /* 0x8000 - PEX Configuration Address Register */
+ uint cfg_data; /* 0x8004 - PEX Configuration Data Register */
+ char res1[4];
+ uint out_comp_to; /* 0x800C - PEX Outbound Completion Timeout Register */
+ char res2[16];
+ uint pme_msg_det; /* 0x8020 - PEX PME & message detect register */
+ uint pme_msg_int_en; /* 0x8024 - PEX PME & message interrupt enable register */
+ uint pme_msg_dis; /* 0x8028 - PEX PME & message disable register */
+ uint pm_command; /* 0x802c - PEX PM Command register */
+ char res3[3016];
+ uint block_rev1; /* 0x8bf8 - PEX Block Revision register 1 */
+ uint block_rev2; /* 0x8bfc - PEX Block Revision register 2 */
+ uint potar0; /* 0x8c00 - PEX Outbound Transaction Address Register 0 */
+ uint potear0; /* 0x8c04 - PEX Outbound Translation Extended Address Register 0 */
+ char res4[8];
+ uint powar0; /* 0x8c10 - PEX Outbound Window Attributes Register 0 */
+ char res5[12];
+ uint potar1; /* 0x8c20 - PEX Outbound Transaction Address Register 1 */
+ uint potear1; /* 0x8c24 - PEX Outbound Translation Extended Address Register 1 */
+ uint powbar1; /* 0x8c28 - PEX Outbound Window Base Address Register 1 */
+ char res6[4];
+ uint powar1; /* 0x8c30 - PEX Outbound Window Attributes Register 1 */
+ char res7[12];
+ uint potar2; /* 0x8c40 - PEX Outbound Transaction Address Register 2 */
+ uint potear2; /* 0x8c44 - PEX Outbound Translation Extended Address Register 2 */
+ uint powbar2; /* 0x8c48 - PEX Outbound Window Base Address Register 2 */
+ char res8[4];
+ uint powar2; /* 0x8c50 - PEX Outbound Window Attributes Register 2 */
+ char res9[12];
+ uint potar3; /* 0x8c60 - PEX Outbound Transaction Address Register 3 */
+ uint potear3; /* 0x8c64 - PEX Outbound Translation Extended Address Register 3 */
+ uint powbar3; /* 0x8c68 - PEX Outbound Window Base Address Register 3 */
+ char res10[4];
+ uint powar3; /* 0x8c70 - PEX Outbound Window Attributes Register 3 */
+ char res11[12];
+ uint potar4; /* 0x8c80 - PEX Outbound Transaction Address Register 4 */
+ uint potear4; /* 0x8c84 - PEX Outbound Translation Extended Address Register 4 */
+ uint powbar4; /* 0x8c88 - PEX Outbound Window Base Address Register 4 */
+ char res12[4];
+ uint powar4; /* 0x8c90 - PEX Outbound Window Attributes Register 4 */
+ char res13[12];
+ char res14[256];
+ uint pitar3; /* 0x8da0 - PEX Inbound Translation Address Register 3 */
+ char res15[4];
+ uint piwbar3; /* 0x8da8 - PEX Inbound Window Base Address Register 3 */
+ uint piwbear3; /* 0x8dac - PEX Inbound Window Base Extended Address Register 3 */
+ uint piwar3; /* 0x8db0 - PEX Inbound Window Attributes Register 3 */
+ char res16[12];
+ uint pitar2; /* 0x8dc0 - PEX Inbound Translation Address Register 2 */
+ char res17[4];
+ uint piwbar2; /* 0x8dc8 - PEX Inbound Window Base Address Register 2 */
+ uint piwbear2; /* 0x8dcc - PEX Inbound Window Base Extended Address Register 2 */
+ uint piwar2; /* 0x8dd0 - PEX Inbound Window Attributes Register 2 */
+ char res18[12];
+ uint pitar1; /* 0x8de0 - PEX Inbound Translation Address Register 1 */
+ char res19[4];
+ uint piwbar1; /* 0x8de8 - PEX Inbound Window Base Address Register 1 */
+ uint piwbear1;
+ uint piwar1; /* 0x8df0 - PEX Inbound Window Attributes Register 1 */
+ char res20[12];
+ uint pedr; /* 0x8e00 - PEX Error Detect Register */
+ char res21[4];
+ uint peer; /* 0x8e08 - PEX Error Interrupt Enable Register */
+ char res22[4];
+ uint pecdr; /* 0x8e10 - PEX Error Disable Register */
+ char res23[12];
+ uint peer_stat; /* 0x8e20 - PEX Error Capture Status Register */
+ char res24[4];
+ uint perr_cap0; /* 0x8e28 - PEX Error Capture Register 0 */
+ uint perr_cap1; /* 0x8e2c - PEX Error Capture Register 1 */
+ uint perr_cap2; /* 0x8e30 - PEX Error Capture Register 2 */
+ uint perr_cap3; /* 0x8e34 - PEX Error Capture Register 3 */
+ char res25[452];
+ char res26[4];
+} ccsr_pex_t;
+
+/* Hyper Transport Register Block (0xA000-0xB000) */
+typedef struct ccsr_ht {
+ uint hcfg_addr; /* 0xa000 - HT Configuration Address register */
+ uint hcfg_data; /* 0xa004 - HT Configuration Data register */
+ char res1[3064];
+ uint howtar0; /* 0xac00 - HT Outbound Window 0 Translation register */
+ char res2[12];
+ uint howar0; /* 0xac10 - HT Outbound Window 0 Attributes register */
+ char res3[12];
+ uint howtar1; /* 0xac20 - HT Outbound Window 1 Translation register */
+ char res4[4];
+ uint howbar1; /* 0xac28 - HT Outbound Window 1 Base Address register */
+ char res5[4];
+ uint howar1; /* 0xac30 - HT Outbound Window 1 Attributes register */
+ char res6[12];
+ uint howtar2; /* 0xac40 - HT Outbound Window 2 Translation register */
+ char res7[4];
+ uint howbar2; /* 0xac48 - HT Outbound Window 2 Base Address register */
+ char res8[4];
+ uint howar2; /* 0xac50 - HT Outbound Window 2 Attributes register */
+ char res9[12];
+ uint howtar3; /* 0xac60 - HT Outbound Window 3 Translation register */
+ char res10[4];
+ uint howbar3; /* 0xac68 - HT Outbound Window 3 Base Address register */
+ char res11[4];
+ uint howar3; /* 0xac70 - HT Outbound Window 3 Attributes register */
+ char res12[12];
+ uint howtar4; /* 0xac80 - HT Outbound Window 4 Translation register */
+ char res13[4];
+ uint howbar4; /* 0xac88 - HT Outbound Window 4 Base Address register */
+ char res14[4];
+ uint howar4; /* 0xac90 - HT Outbound Window 4 Attributes register */
+ char res15[236];
+ uint hiwtar4; /* 0xad80 - HT Inbound Window 4 Translation register */
+ char res16[4];
+ uint hiwbar4; /* 0xad88 - HT Inbound Window 4 Base Address register */
+ char res17[4];
+ uint hiwar4; /* 0xad90 - HT Inbound Window 4 Attributes register */
+ char res18[12];
+ uint hiwtar3; /* 0xada0 - HT Inbound Window 3 Translation register */
+ char res19[4];
+ uint hiwbar3; /* 0xada8 - HT Inbound Window 3 Base Address register */
+ char res20[4];
+ uint hiwar3; /* 0xadb0 - HT Inbound Window 3 Attributes register */
+ char res21[12];
+ uint hiwtar2; /* 0xadc0 - HT Inbound Window 2 Translation register */
+ char res22[4];
+ uint hiwbar2; /* 0xadc8 - HT Inbound Window 2 Base Address register */
+ char res23[4];
+ uint hiwar2; /* 0xadd0 - HT Inbound Window 2 Attributes register */
+ char res24[12];
+ uint hiwtar1; /* 0xade0 - HT Inbound Window 1 Translation register */
+ char res25[4];
+ uint hiwbar1; /* 0xade8 - HT Inbound Window 1 Base Address register */
+ char res26[4];
+ uint hiwar1; /* 0xadf0 - HT Inbound Window 1 Attributes register */
+ char res27[12];
+ uint hedr; /* 0xae00 - HT Error Detect register */
+ char res28[4];
+ uint heier; /* 0xae08 - HT Error Interrupt Enable register */
+ char res29[4];
+ uint hecdr; /* 0xae10 - HT Error Capture Disbale register */
+ char res30[12];
+ uint hecsr; /* 0xae20 - HT Error Capture Status register */
+ char res31[4];
+ uint hec0; /* 0xae28 - HT Error Capture 0 register */
+ uint hec1; /* 0xae2c - HT Error Capture 1 register */
+ uint hec2; /* 0xae30 - HT Error Capture 2 register */
+ char res32[460];
+} ccsr_ht_t;
+
+/* DMA Registers(0x2_1000-0x2_2000) */
+typedef struct ccsr_dma {
+ char res1[256];
+ struct fsl_dma dma[4];
+ uint dgsr; /* 0x21300 - DMA General Status Register */
+ char res2[3324];
+} ccsr_dma_t;
+
+/* tsec1-4: 24000-28000 */
+typedef struct ccsr_tsec {
+ uint id; /* 0x24000 - Controller ID Register */
+ char res1[12];
+ uint ievent; /* 0x24010 - Interrupt Event Register */
+ uint imask; /* 0x24014 - Interrupt Mask Register */
+ uint edis; /* 0x24018 - Error Disabled Register */
+ char res2[4];
+ uint ecntrl; /* 0x24020 - Ethernet Control Register */
+ char res2_1[4];
+ uint ptv; /* 0x24028 - Pause Time Value Register */
+ uint dmactrl; /* 0x2402c - DMA Control Register */
+ uint tbipa; /* 0x24030 - TBI PHY Address Register */
+ char res3[88];
+ uint fifo_tx_thr; /* 0x2408c - FIFO transmit threshold register */
+ char res4[8];
+ uint fifo_tx_starve; /* 0x24098 - FIFO transmit starve register */
+ uint fifo_tx_starve_shutoff;/* 0x2409c - FIFO transmit starve shutoff register */
+ char res4_1[4];
+ uint fifo_rx_pause; /* 0x240a4 - FIFO receive pause threshold register */
+ uint fifo_rx_alarm; /* 0x240a8 - FIFO receive alarm threshold register */
+ char res5[84];
+ uint tctrl; /* 0x24100 - Transmit Control Register */
+ uint tstat; /* 0x24104 - Transmit Status Register */
+ uint dfvlan; /* 0x24108 - Default VLAN control word */
+ char res6[4];
+ uint txic; /* 0x24110 - Transmit interrupt coalescing Register */
+ uint tqueue; /* 0x24114 - Transmit Queue Control Register */
+ char res7[40];
+ uint tr03wt; /* 0x24140 - TxBD Rings 0-3 round-robin weightings */
+ uint tw47wt; /* 0x24144 - TxBD Rings 4-7 round-robin weightings */
+ char res8[52];
+ uint tbdbph; /* 0x2417c - Transmit Data Buffer Pointer High Register */
+ char res9[4];
+ uint tbptr0; /* 0x24184 - Transmit Buffer Descriptor Pointer for Ring 0 */
+ char res10[4];
+ uint tbptr1; /* 0x2418C - Transmit Buffer Descriptor Pointer for Ring 1 */
+ char res11[4];
+ uint tbptr2; /* 0x24194 - Transmit Buffer Descriptor Pointer for Ring 2 */
+ char res12[4];
+ uint tbptr3; /* 0x2419C - Transmit Buffer Descriptor Pointer for Ring 3 */
+ char res13[4];
+ uint tbptr4; /* 0x241A4 - Transmit Buffer Descriptor Pointer for Ring 4 */
+ char res14[4];
+ uint tbptr5; /* 0x241AC - Transmit Buffer Descriptor Pointer for Ring 5 */
+ char res15[4];
+ uint tbptr6; /* 0x241B4 - Transmit Buffer Descriptor Pointer for Ring 6 */
+ char res16[4];
+ uint tbptr7; /* 0x241BC - Transmit Buffer Descriptor Pointer for Ring 7 */
+ char res17[64];
+ uint tbaseh; /* 0x24200 - Transmit Descriptor Base Address High Register */
+ uint tbase0; /* 0x24204 - Transmit Descriptor Base Address Register of Ring 0 */
+ char res18[4];
+ uint tbase1; /* 0x2420C - Transmit Descriptor base address of Ring 1 */
+ char res19[4];
+ uint tbase2; /* 0x24214 - Transmit Descriptor base address of Ring 2 */
+ char res20[4];
+ uint tbase3; /* 0x2421C - Transmit Descriptor base address of Ring 3 */
+ char res21[4];
+ uint tbase4; /* 0x24224 - Transmit Descriptor base address of Ring 4 */
+ char res22[4];
+ uint tbase5; /* 0x2422C - Transmit Descriptor base address of Ring 5 */
+ char res23[4];
+ uint tbase6; /* 0x24234 - Transmit Descriptor base address of Ring 6 */
+ char res24[4];
+ uint tbase7; /* 0x2423C - Transmit Descriptor base address of Ring 7 */
+ char res25[192];
+ uint rctrl; /* 0x24300 - Receive Control Register */
+ uint rstat; /* 0x24304 - Receive Status Register */
+ char res26[8];
+ uint rxic; /* 0x24310 - Receive Interrupt Coalecing Register */
+ uint rqueue; /* 0x24314 - Receive queue control register */
+ char res27[24];
+ uint rbifx; /* 0x24330 - Receive bit field extract control Register */
+ uint rqfar; /* 0x24334 - Receive queue filing table address Register */
+ uint rqfcr; /* 0x24338 - Receive queue filing table control Register */
+ uint rqfpr; /* 0x2433c - Receive queue filing table property Register */
+ uint mrblr; /* 0x24340 - Maximum Receive Buffer Length Register */
+ char res28[56];
+ uint rbdbph; /* 0x2437C - Receive Data Buffer Pointer High */
+ char res29[4];
+ uint rbptr0; /* 0x24384 - Receive Buffer Descriptor Pointer for Ring 0 */
+ char res30[4];
+ uint rbptr1; /* 0x2438C - Receive Buffer Descriptor Pointer for Ring 1 */
+ char res31[4];
+ uint rbptr2; /* 0x24394 - Receive Buffer Descriptor Pointer for Ring 2 */
+ char res32[4];
+ uint rbptr3; /* 0x2439C - Receive Buffer Descriptor Pointer for Ring 3 */
+ char res33[4];
+ uint rbptr4; /* 0x243A4 - Receive Buffer Descriptor Pointer for Ring 4 */
+ char res34[4];
+ uint rbptr5; /* 0x243AC - Receive Buffer Descriptor Pointer for Ring 5 */
+ char res35[4];
+ uint rbptr6; /* 0x243B4 - Receive Buffer Descriptor Pointer for Ring 6 */
+ char res36[4];
+ uint rbptr7; /* 0x243BC - Receive Buffer Descriptor Pointer for Ring 7 */
+ char res37[64];
+ uint rbaseh; /* 0x24400 - Receive Descriptor Base Address High 0 */
+ uint rbase0; /* 0x24404 - Receive Descriptor Base Address of Ring 0 */
+ char res38[4];
+ uint rbase1; /* 0x2440C - Receive Descriptor Base Address of Ring 1 */
+ char res39[4];
+ uint rbase2; /* 0x24414 - Receive Descriptor Base Address of Ring 2 */
+ char res40[4];
+ uint rbase3; /* 0x2441C - Receive Descriptor Base Address of Ring 3 */
+ char res41[4];
+ uint rbase4; /* 0x24424 - Receive Descriptor Base Address of Ring 4 */
+ char res42[4];
+ uint rbase5; /* 0x2442C - Receive Descriptor Base Address of Ring 5 */
+ char res43[4];
+ uint rbase6; /* 0x24434 - Receive Descriptor Base Address of Ring 6 */
+ char res44[4];
+ uint rbase7; /* 0x2443C - Receive Descriptor Base Address of Ring 7 */
+ char res45[192];
+ uint maccfg1; /* 0x24500 - MAC Configuration 1 Register */
+ uint maccfg2; /* 0x24504 - MAC Configuration 2 Register */
+ uint ipgifg; /* 0x24508 - Inter Packet Gap/Inter Frame Gap Register */
+ uint hafdup; /* 0x2450c - Half Duplex Register */
+ uint maxfrm; /* 0x24510 - Maximum Frame Length Register */
+ char res46[12];
+ uint miimcfg; /* 0x24520 - MII Management Configuration Register */
+ uint miimcom; /* 0x24524 - MII Management Command Register */
+ uint miimadd; /* 0x24528 - MII Management Address Register */
+ uint miimcon; /* 0x2452c - MII Management Control Register */
+ uint miimstat; /* 0x24530 - MII Management Status Register */
+ uint miimind; /* 0x24534 - MII Management Indicator Register */
+ uint ifctrl; /* 0x24538 - Interface Contrl Register */
+ uint ifstat; /* 0x2453c - Interface Status Register */
+ uint macstnaddr1; /* 0x24540 - Station Address Part 1 Register */
+ uint macstnaddr2; /* 0x24544 - Station Address Part 2 Register */
+ uint mac01addr1; /* 0x24548 - MAC exact match address 1, part 1 */
+ uint mac01addr2; /* 0x2454C - MAC exact match address 1, part 2 */
+ uint mac02addr1; /* 0x24550 - MAC exact match address 2, part 1 */
+ uint mac02addr2; /* 0x24554 - MAC exact match address 2, part 2 */
+ uint mac03addr1; /* 0x24558 - MAC exact match address 3, part 1 */
+ uint mac03addr2; /* 0x2455C - MAC exact match address 3, part 2 */
+ uint mac04addr1; /* 0x24560 - MAC exact match address 4, part 1 */
+ uint mac04addr2; /* 0x24564 - MAC exact match address 4, part 2 */
+ uint mac05addr1; /* 0x24568 - MAC exact match address 5, part 1 */
+ uint mac05addr2; /* 0x2456C - MAC exact match address 5, part 2 */
+ uint mac06addr1; /* 0x24570 - MAC exact match address 6, part 1 */
+ uint mac06addr2; /* 0x24574 - MAC exact match address 6, part 2 */
+ uint mac07addr1; /* 0x24578 - MAC exact match address 7, part 1 */
+ uint mac07addr2; /* 0x2457C - MAC exact match address 7, part 2 */
+ uint mac08addr1; /* 0x24580 - MAC exact match address 8, part 1 */
+ uint mac08addr2; /* 0x24584 - MAC exact match address 8, part 2 */
+ uint mac09addr1; /* 0x24588 - MAC exact match address 9, part 1 */
+ uint mac09addr2; /* 0x2458C - MAC exact match address 9, part 2 */
+ uint mac10addr1; /* 0x24590 - MAC exact match address 10, part 1 */
+ uint mac10addr2; /* 0x24594 - MAC exact match address 10, part 2 */
+ uint mac11addr1; /* 0x24598 - MAC exact match address 11, part 1 */
+ uint mac11addr2; /* 0x2459C - MAC exact match address 11, part 2 */
+ uint mac12addr1; /* 0x245A0 - MAC exact match address 12, part 1 */
+ uint mac12addr2; /* 0x245A4 - MAC exact match address 12, part 2 */
+ uint mac13addr1; /* 0x245A8 - MAC exact match address 13, part 1 */
+ uint mac13addr2; /* 0x245AC - MAC exact match address 13, part 2 */
+ uint mac14addr1; /* 0x245B0 - MAC exact match address 14, part 1 */
+ uint mac14addr2; /* 0x245B4 - MAC exact match address 14, part 2 */
+ uint mac15addr1; /* 0x245B8 - MAC exact match address 15, part 1 */
+ uint mac15addr2; /* 0x245BC - MAC exact match address 15, part 2 */
+ char res48[192];
+ uint tr64; /* 0x24680 - Transmit and Receive 64-byte Frame Counter */
+ uint tr127; /* 0x24684 - Transmit and Receive 65-127 byte Frame Counter */
+ uint tr255; /* 0x24688 - Transmit and Receive 128-255 byte Frame Counter */
+ uint tr511; /* 0x2468c - Transmit and Receive 256-511 byte Frame Counter */
+ uint tr1k; /* 0x24690 - Transmit and Receive 512-1023 byte Frame Counter */
+ uint trmax; /* 0x24694 - Transmit and Receive 1024-1518 byte Frame Counter */
+ uint trmgv; /* 0x24698 - Transmit and Receive 1519-1522 byte Good VLAN Frame */
+ uint rbyt; /* 0x2469c - Receive Byte Counter */
+ uint rpkt; /* 0x246a0 - Receive Packet Counter */
+ uint rfcs; /* 0x246a4 - Receive FCS Error Counter */
+ uint rmca; /* 0x246a8 - Receive Multicast Packet Counter */
+ uint rbca; /* 0x246ac - Receive Broadcast Packet Counter */
+ uint rxcf; /* 0x246b0 - Receive Control Frame Packet Counter */
+ uint rxpf; /* 0x246b4 - Receive Pause Frame Packet Counter */
+ uint rxuo; /* 0x246b8 - Receive Unknown OP Code Counter */
+ uint raln; /* 0x246bc - Receive Alignment Error Counter */
+ uint rflr; /* 0x246c0 - Receive Frame Length Error Counter */
+ uint rcde; /* 0x246c4 - Receive Code Error Counter */
+ uint rcse; /* 0x246c8 - Receive Carrier Sense Error Counter */
+ uint rund; /* 0x246cc - Receive Undersize Packet Counter */
+ uint rovr; /* 0x246d0 - Receive Oversize Packet Counter */
+ uint rfrg; /* 0x246d4 - Receive Fragments Counter */
+ uint rjbr; /* 0x246d8 - Receive Jabber Counter */
+ uint rdrp; /* 0x246dc - Receive Drop Counter */
+ uint tbyt; /* 0x246e0 - Transmit Byte Counter Counter */
+ uint tpkt; /* 0x246e4 - Transmit Packet Counter */
+ uint tmca; /* 0x246e8 - Transmit Multicast Packet Counter */
+ uint tbca; /* 0x246ec - Transmit Broadcast Packet Counter */
+ uint txpf; /* 0x246f0 - Transmit Pause Control Frame Counter */
+ uint tdfr; /* 0x246f4 - Transmit Deferral Packet Counter */
+ uint tedf; /* 0x246f8 - Transmit Excessive Deferral Packet Counter */
+ uint tscl; /* 0x246fc - Transmit Single Collision Packet Counter */
+ uint tmcl; /* 0x24700 - Transmit Multiple Collision Packet Counter */
+ uint tlcl; /* 0x24704 - Transmit Late Collision Packet Counter */
+ uint txcl; /* 0x24708 - Transmit Excessive Collision Packet Counter */
+ uint tncl; /* 0x2470c - Transmit Total Collision Counter */
+ char res49[4];
+ uint tdrp; /* 0x24714 - Transmit Drop Frame Counter */
+ uint tjbr; /* 0x24718 - Transmit Jabber Frame Counter */
+ uint tfcs; /* 0x2471c - Transmit FCS Error Counter */
+ uint txcf; /* 0x24720 - Transmit Control Frame Counter */
+ uint tovr; /* 0x24724 - Transmit Oversize Frame Counter */
+ uint tund; /* 0x24728 - Transmit Undersize Frame Counter */
+ uint tfrg; /* 0x2472c - Transmit Fragments Frame Counter */
+ uint car1; /* 0x24730 - Carry Register One */
+ uint car2; /* 0x24734 - Carry Register Two */
+ uint cam1; /* 0x24738 - Carry Mask Register One */
+ uint cam2; /* 0x2473c - Carry Mask Register Two */
+ uint rrej; /* 0x24740 - Receive filer rejected packet counter */
+ char res50[188];
+ uint iaddr0; /* 0x24800 - Indivdual address register 0 */
+ uint iaddr1; /* 0x24804 - Indivdual address register 1 */
+ uint iaddr2; /* 0x24808 - Indivdual address register 2 */
+ uint iaddr3; /* 0x2480c - Indivdual address register 3 */
+ uint iaddr4; /* 0x24810 - Indivdual address register 4 */
+ uint iaddr5; /* 0x24814 - Indivdual address register 5 */
+ uint iaddr6; /* 0x24818 - Indivdual address register 6 */
+ uint iaddr7; /* 0x2481c - Indivdual address register 7 */
+ char res51[96];
+ uint gaddr0; /* 0x24880 - Global address register 0 */
+ uint gaddr1; /* 0x24884 - Global address register 1 */
+ uint gaddr2; /* 0x24888 - Global address register 2 */
+ uint gaddr3; /* 0x2488c - Global address register 3 */
+ uint gaddr4; /* 0x24890 - Global address register 4 */
+ uint gaddr5; /* 0x24894 - Global address register 5 */
+ uint gaddr6; /* 0x24898 - Global address register 6 */
+ uint gaddr7; /* 0x2489c - Global address register 7 */
+ char res52[352];
+ uint fifocfg; /* 0x24A00 - FIFO interface configuration register */
+ char res53[500];
+ uint attr; /* 0x24BF8 - DMA Attribute register */
+ uint attreli; /* 0x24BFC - DMA Attribute extract length and index register */
+ char res54[1024];
+} ccsr_tsec_t;
+
+/* PIC Registers(0x4_0000-0x6_1000) */
+
+typedef struct ccsr_pic {
+ char res1[64];
+ uint ipidr0; /* 0x40040 - Interprocessor Interrupt Dispatch Register 0 */
+ char res2[12];
+ uint ipidr1; /* 0x40050 - Interprocessor Interrupt Dispatch Register 1 */
+ char res3[12];
+ uint ipidr2; /* 0x40060 - Interprocessor Interrupt Dispatch Register 2 */
+ char res4[12];
+ uint ipidr3; /* 0x40070 - Interprocessor Interrupt Dispatch Register 3 */
+ char res5[12];
+ uint ctpr; /* 0x40080 - Current Task Priority Register */
+ char res6[12];
+ uint whoami; /* 0x40090 - Who Am I Register */
+ char res7[12];
+ uint iack; /* 0x400a0 - Interrupt Acknowledge Register */
+ char res8[12];
+ uint eoi; /* 0x400b0 - End Of Interrupt Register */
+ char res9[3916];
+ uint frr; /* 0x41000 - Feature Reporting Register */
+ char res10[28];
+ uint gcr; /* 0x41020 - Global Configuration Register */
+#define MPC86xx_PICGCR_RST 0x80000000
+#define MPC86xx_PICGCR_MODE 0x20000000
+ char res11[92];
+ uint vir; /* 0x41080 - Vendor Identification Register */
+ char res12[12];
+ uint pir; /* 0x41090 - Processor Initialization Register */
+ char res13[12];
+ uint ipivpr0; /* 0x410a0 - IPI Vector/Priority Register 0 */
+ char res14[12];
+ uint ipivpr1; /* 0x410b0 - IPI Vector/Priority Register 1 */
+ char res15[12];
+ uint ipivpr2; /* 0x410c0 - IPI Vector/Priority Register 2 */
+ char res16[12];
+ uint ipivpr3; /* 0x410d0 - IPI Vector/Priority Register 3 */
+ char res17[12];
+ uint svr; /* 0x410e0 - Spurious Vector Register */
+ char res18[12];
+ uint tfrr; /* 0x410f0 - Timer Frequency Reporting Register */
+ char res19[12];
+ uint gtccr0; /* 0x41100 - Global Timer Current Count Register 0 */
+ char res20[12];
+ uint gtbcr0; /* 0x41110 - Global Timer Base Count Register 0 */
+ char res21[12];
+ uint gtvpr0; /* 0x41120 - Global Timer Vector/Priority Register 0 */
+ char res22[12];
+ uint gtdr0; /* 0x41130 - Global Timer Destination Register 0 */
+ char res23[12];
+ uint gtccr1; /* 0x41140 - Global Timer Current Count Register 1 */
+ char res24[12];
+ uint gtbcr1; /* 0x41150 - Global Timer Base Count Register 1 */
+ char res25[12];
+ uint gtvpr1; /* 0x41160 - Global Timer Vector/Priority Register 1 */
+ char res26[12];
+ uint gtdr1; /* 0x41170 - Global Timer Destination Register 1 */
+ char res27[12];
+ uint gtccr2; /* 0x41180 - Global Timer Current Count Register 2 */
+ char res28[12];
+ uint gtbcr2; /* 0x41190 - Global Timer Base Count Register 2 */
+ char res29[12];
+ uint gtvpr2; /* 0x411a0 - Global Timer Vector/Priority Register 2 */
+ char res30[12];
+ uint gtdr2; /* 0x411b0 - Global Timer Destination Register 2 */
+ char res31[12];
+ uint gtccr3; /* 0x411c0 - Global Timer Current Count Register 3 */
+ char res32[12];
+ uint gtbcr3; /* 0x411d0 - Global Timer Base Count Register 3 */
+ char res33[12];
+ uint gtvpr3; /* 0x411e0 - Global Timer Vector/Priority Register 3 */
+ char res34[12];
+ uint gtdr3; /* 0x411f0 - Global Timer Destination Register 3 */
+ char res35[268];
+ uint tcr; /* 0x41300 - Timer Control Register */
+ char res36[12];
+ uint irqsr0; /* 0x41310 - IRQ_OUT Summary Register 0 */
+ char res37[12];
+ uint irqsr1; /* 0x41320 - IRQ_OUT Summary Register 1 */
+ char res38[12];
+ uint cisr0; /* 0x41330 - Critical Interrupt Summary Register 0 */
+ char res39[12];
+ uint cisr1; /* 0x41340 - Critical Interrupt Summary Register 1 */
+ char res40[12];
+ uint pm0mr0; /* 0x41350 - Performance monitor 0 mask register 0 */
+ char res41[12];
+ uint pm0mr1; /* 0x41360 - Performance monitor 0 mask register 1 */
+ char res42[12];
+ uint pm1mr0; /* 0x41370 - Performance monitor 1 mask register 0 */
+ char res43[12];
+ uint pm1mr1; /* 0x41380 - Performance monitor 1 mask register 1 */
+ char res44[12];
+ uint pm2mr0; /* 0x41390 - Performance monitor 2 mask register 0 */
+ char res45[12];
+ uint pm2mr1; /* 0x413A0 - Performance monitor 2 mask register 1 */
+ char res46[12];
+ uint pm3mr0; /* 0x413B0 - Performance monitor 3 mask register 0 */
+ char res47[12];
+ uint pm3mr1; /* 0x413C0 - Performance monitor 3 mask register 1 */
+ char res48[60];
+ uint msgr0; /* 0x41400 - Message Register 0 */
+ char res49[12];
+ uint msgr1; /* 0x41410 - Message Register 1 */
+ char res50[12];
+ uint msgr2; /* 0x41420 - Message Register 2 */
+ char res51[12];
+ uint msgr3; /* 0x41430 - Message Register 3 */
+ char res52[204];
+ uint mer; /* 0x41500 - Message Enable Register */
+ char res53[12];
+ uint msr; /* 0x41510 - Message Status Register */
+ char res54[60140];
+ uint eivpr0; /* 0x50000 - External Interrupt Vector/Priority Register 0 */
+ char res55[12];
+ uint eidr0; /* 0x50010 - External Interrupt Destination Register 0 */
+ char res56[12];
+ uint eivpr1; /* 0x50020 - External Interrupt Vector/Priority Register 1 */
+ char res57[12];
+ uint eidr1; /* 0x50030 - External Interrupt Destination Register 1 */
+ char res58[12];
+ uint eivpr2; /* 0x50040 - External Interrupt Vector/Priority Register 2 */
+ char res59[12];
+ uint eidr2; /* 0x50050 - External Interrupt Destination Register 2 */
+ char res60[12];
+ uint eivpr3; /* 0x50060 - External Interrupt Vector/Priority Register 3 */
+ char res61[12];
+ uint eidr3; /* 0x50070 - External Interrupt Destination Register 3 */
+ char res62[12];
+ uint eivpr4; /* 0x50080 - External Interrupt Vector/Priority Register 4 */
+ char res63[12];
+ uint eidr4; /* 0x50090 - External Interrupt Destination Register 4 */
+ char res64[12];
+ uint eivpr5; /* 0x500a0 - External Interrupt Vector/Priority Register 5 */
+ char res65[12];
+ uint eidr5; /* 0x500b0 - External Interrupt Destination Register 5 */
+ char res66[12];
+ uint eivpr6; /* 0x500c0 - External Interrupt Vector/Priority Register 6 */
+ char res67[12];
+ uint eidr6; /* 0x500d0 - External Interrupt Destination Register 6 */
+ char res68[12];
+ uint eivpr7; /* 0x500e0 - External Interrupt Vector/Priority Register 7 */
+ char res69[12];
+ uint eidr7; /* 0x500f0 - External Interrupt Destination Register 7 */
+ char res70[12];
+ uint eivpr8; /* 0x50100 - External Interrupt Vector/Priority Register 8 */
+ char res71[12];
+ uint eidr8; /* 0x50110 - External Interrupt Destination Register 8 */
+ char res72[12];
+ uint eivpr9; /* 0x50120 - External Interrupt Vector/Priority Register 9 */
+ char res73[12];
+ uint eidr9; /* 0x50130 - External Interrupt Destination Register 9 */
+ char res74[12];
+ uint eivpr10; /* 0x50140 - External Interrupt Vector/Priority Register 10 */
+ char res75[12];
+ uint eidr10; /* 0x50150 - External Interrupt Destination Register 10 */
+ char res76[12];
+ uint eivpr11; /* 0x50160 - External Interrupt Vector/Priority Register 11 */
+ char res77[12];
+ uint eidr11; /* 0x50170 - External Interrupt Destination Register 11 */
+ char res78[140];
+ uint iivpr0; /* 0x50200 - Internal Interrupt Vector/Priority Register 0 */
+ char res79[12];
+ uint iidr0; /* 0x50210 - Internal Interrupt Destination Register 0 */
+ char res80[12];
+ uint iivpr1; /* 0x50220 - Internal Interrupt Vector/Priority Register 1 */
+ char res81[12];
+ uint iidr1; /* 0x50230 - Internal Interrupt Destination Register 1 */
+ char res82[12];
+ uint iivpr2; /* 0x50240 - Internal Interrupt Vector/Priority Register 2 */
+ char res83[12];
+ uint iidr2; /* 0x50250 - Internal Interrupt Destination Register 2 */
+ char res84[12];
+ uint iivpr3; /* 0x50260 - Internal Interrupt Vector/Priority Register 3 */
+ char res85[12];
+ uint iidr3; /* 0x50270 - Internal Interrupt Destination Register 3 */
+ char res86[12];
+ uint iivpr4; /* 0x50280 - Internal Interrupt Vector/Priority Register 4 */
+ char res87[12];
+ uint iidr4; /* 0x50290 - Internal Interrupt Destination Register 4 */
+ char res88[12];
+ uint iivpr5; /* 0x502a0 - Internal Interrupt Vector/Priority Register 5 */
+ char res89[12];
+ uint iidr5; /* 0x502b0 - Internal Interrupt Destination Register 5 */
+ char res90[12];
+ uint iivpr6; /* 0x502c0 - Internal Interrupt Vector/Priority Register 6 */
+ char res91[12];
+ uint iidr6; /* 0x502d0 - Internal Interrupt Destination Register 6 */
+ char res92[12];
+ uint iivpr7; /* 0x502e0 - Internal Interrupt Vector/Priority Register 7 */
+ char res93[12];
+ uint iidr7; /* 0x502f0 - Internal Interrupt Destination Register 7 */
+ char res94[12];
+ uint iivpr8; /* 0x50300 - Internal Interrupt Vector/Priority Register 8 */
+ char res95[12];
+ uint iidr8; /* 0x50310 - Internal Interrupt Destination Register 8 */
+ char res96[12];
+ uint iivpr9; /* 0x50320 - Internal Interrupt Vector/Priority Register 9 */
+ char res97[12];
+ uint iidr9; /* 0x50330 - Internal Interrupt Destination Register 9 */
+ char res98[12];
+ uint iivpr10; /* 0x50340 - Internal Interrupt Vector/Priority Register 10 */
+ char res99[12];
+ uint iidr10; /* 0x50350 - Internal Interrupt Destination Register 10 */
+ char res100[12];
+ uint iivpr11; /* 0x50360 - Internal Interrupt Vector/Priority Register 11 */
+ char res101[12];
+ uint iidr11; /* 0x50370 - Internal Interrupt Destination Register 11 */
+ char res102[12];
+ uint iivpr12; /* 0x50380 - Internal Interrupt Vector/Priority Register 12 */
+ char res103[12];
+ uint iidr12; /* 0x50390 - Internal Interrupt Destination Register 12 */
+ char res104[12];
+ uint iivpr13; /* 0x503a0 - Internal Interrupt Vector/Priority Register 13 */
+ char res105[12];
+ uint iidr13; /* 0x503b0 - Internal Interrupt Destination Register 13 */
+ char res106[12];
+ uint iivpr14; /* 0x503c0 - Internal Interrupt Vector/Priority Register 14 */
+ char res107[12];
+ uint iidr14; /* 0x503d0 - Internal Interrupt Destination Register 14 */
+ char res108[12];
+ uint iivpr15; /* 0x503e0 - Internal Interrupt Vector/Priority Register 15 */
+ char res109[12];
+ uint iidr15; /* 0x503f0 - Internal Interrupt Destination Register 15 */
+ char res110[12];
+ uint iivpr16; /* 0x50400 - Internal Interrupt Vector/Priority Register 16 */
+ char res111[12];
+ uint iidr16; /* 0x50410 - Internal Interrupt Destination Register 16 */
+ char res112[12];
+ uint iivpr17; /* 0x50420 - Internal Interrupt Vector/Priority Register 17 */
+ char res113[12];
+ uint iidr17; /* 0x50430 - Internal Interrupt Destination Register 17 */
+ char res114[12];
+ uint iivpr18; /* 0x50440 - Internal Interrupt Vector/Priority Register 18 */
+ char res115[12];
+ uint iidr18; /* 0x50450 - Internal Interrupt Destination Register 18 */
+ char res116[12];
+ uint iivpr19; /* 0x50460 - Internal Interrupt Vector/Priority Register 19 */
+ char res117[12];
+ uint iidr19; /* 0x50470 - Internal Interrupt Destination Register 19 */
+ char res118[12];
+ uint iivpr20; /* 0x50480 - Internal Interrupt Vector/Priority Register 20 */
+ char res119[12];
+ uint iidr20; /* 0x50490 - Internal Interrupt Destination Register 20 */
+ char res120[12];
+ uint iivpr21; /* 0x504a0 - Internal Interrupt Vector/Priority Register 21 */
+ char res121[12];
+ uint iidr21; /* 0x504b0 - Internal Interrupt Destination Register 21 */
+ char res122[12];
+ uint iivpr22; /* 0x504c0 - Internal Interrupt Vector/Priority Register 22 */
+ char res123[12];
+ uint iidr22; /* 0x504d0 - Internal Interrupt Destination Register 22 */
+ char res124[12];
+ uint iivpr23; /* 0x504e0 - Internal Interrupt Vector/Priority Register 23 */
+ char res125[12];
+ uint iidr23; /* 0x504f0 - Internal Interrupt Destination Register 23 */
+ char res126[12];
+ uint iivpr24; /* 0x50500 - Internal Interrupt Vector/Priority Register 24 */
+ char res127[12];
+ uint iidr24; /* 0x50510 - Internal Interrupt Destination Register 24 */
+ char res128[12];
+ uint iivpr25; /* 0x50520 - Internal Interrupt Vector/Priority Register 25 */
+ char res129[12];
+ uint iidr25; /* 0x50530 - Internal Interrupt Destination Register 25 */
+ char res130[12];
+ uint iivpr26; /* 0x50540 - Internal Interrupt Vector/Priority Register 26 */
+ char res131[12];
+ uint iidr26; /* 0x50550 - Internal Interrupt Destination Register 26 */
+ char res132[12];
+ uint iivpr27; /* 0x50560 - Internal Interrupt Vector/Priority Register 27 */
+ char res133[12];
+ uint iidr27; /* 0x50570 - Internal Interrupt Destination Register 27 */
+ char res134[12];
+ uint iivpr28; /* 0x50580 - Internal Interrupt Vector/Priority Register 28 */
+ char res135[12];
+ uint iidr28; /* 0x50590 - Internal Interrupt Destination Register 28 */
+ char res136[12];
+ uint iivpr29; /* 0x505a0 - Internal Interrupt Vector/Priority Register 29 */
+ char res137[12];
+ uint iidr29; /* 0x505b0 - Internal Interrupt Destination Register 29 */
+ char res138[12];
+ uint iivpr30; /* 0x505c0 - Internal Interrupt Vector/Priority Register 30 */
+ char res139[12];
+ uint iidr30; /* 0x505d0 - Internal Interrupt Destination Register 30 */
+ char res140[12];
+ uint iivpr31; /* 0x505e0 - Internal Interrupt Vector/Priority Register 31 */
+ char res141[12];
+ uint iidr31; /* 0x505f0 - Internal Interrupt Destination Register 31 */
+ char res142[4108];
+ uint mivpr0; /* 0x51600 - Messaging Interrupt Vector/Priority Register 0 */
+ char res143[12];
+ uint midr0; /* 0x51610 - Messaging Interrupt Destination Register 0 */
+ char res144[12];
+ uint mivpr1; /* 0x51620 - Messaging Interrupt Vector/Priority Register 1 */
+ char res145[12];
+ uint midr1; /* 0x51630 - Messaging Interrupt Destination Register 1 */
+ char res146[12];
+ uint mivpr2; /* 0x51640 - Messaging Interrupt Vector/Priority Register 2 */
+ char res147[12];
+ uint midr2; /* 0x51650 - Messaging Interrupt Destination Register 2 */
+ char res148[12];
+ uint mivpr3; /* 0x51660 - Messaging Interrupt Vector/Priority Register 3 */
+ char res149[12];
+ uint midr3; /* 0x51670 - Messaging Interrupt Destination Register 3 */
+ char res150[59852];
+ uint ipi0dr0; /* 0x60040 - Processor 0 Interprocessor Interrupt Dispatch Register 0 */
+ char res151[12];
+ uint ipi0dr1; /* 0x60050 - Processor 0 Interprocessor Interrupt Dispatch Register 1 */
+ char res152[12];
+ uint ipi0dr2; /* 0x60060 - Processor 0 Interprocessor Interrupt Dispatch Register 2 */
+ char res153[12];
+ uint ipi0dr3; /* 0x60070 - Processor 0 Interprocessor Interrupt Dispatch Register 3 */
+ char res154[12];
+ uint ctpr0; /* 0x60080 - Current Task Priority Register for Processor 0 */
+ char res155[12];
+ uint whoami0; /* 0x60090 - Who Am I Register for Processor 0 */
+ char res156[12];
+ uint iack0; /* 0x600a0 - Interrupt Acknowledge Register for Processor 0 */
+ char res157[12];
+ uint eoi0; /* 0x600b0 - End Of Interrupt Register for Processor 0 */
+ char res158[3916];
+} ccsr_pic_t;
+
+/* RapidIO Registers(0xc_0000-0xe_0000) */
+
+typedef struct ccsr_rio {
+ uint didcar; /* 0xc0000 - Device Identity Capability Register */
+ uint dicar; /* 0xc0004 - Device Information Capability Register */
+ uint aidcar; /* 0xc0008 - Assembly Identity Capability Register */
+ uint aicar; /* 0xc000c - Assembly Information Capability Register */
+ uint pefcar; /* 0xc0010 - Processing Element Features Capability Register */
+ uint spicar; /* 0xc0014 - Switch Port Information Capability Register */
+ uint socar; /* 0xc0018 - Source Operations Capability Register */
+ uint docar; /* 0xc001c - Destination Operations Capability Register */
+ char res1[32];
+ uint msr; /* 0xc0040 - Mailbox Command And Status Register */
+ uint pwdcsr; /* 0xc0044 - Port-Write and Doorbell Command And Status Register */
+ char res2[4];
+ uint pellccsr; /* 0xc004c - Processing Element Logic Layer Control Command and Status Register */
+ char res3[12];
+ uint lcsbacsr; /* 0xc005c - Local Configuration Space Base Address Command and Status Register */
+ uint bdidcsr; /* 0xc0060 - Base Device ID Command and Status Register */
+ char res4[4];
+ uint hbdidlcsr; /* 0xc0068 - Host Base Device ID Lock Command and Status Register */
+ uint ctcsr; /* 0xc006c - Component Tag Command and Status Register */
+ char res5[144];
+ uint pmbh0csr; /* 0xc0100 - 8/16 LP-LVDS Port Maintenance Block Header 0 Command and Status Register */
+ char res6[28];
+ uint pltoccsr; /* 0xc0120 - Port Link Time-out Control Command and Status Register */
+ uint prtoccsr; /* 0xc0124 - Port Response Time-out Control Command and Status Register */
+ char res7[20];
+ uint pgccsr; /* 0xc013c - Port General Command and Status Register */
+ uint plmreqcsr; /* 0xc0140 - Port Link Maintenance Request Command and Status Register */
+ uint plmrespcsr; /* 0xc0144 - Port Link Maintenance Response Command and Status Register */
+ uint plascsr; /* 0xc0148 - Port Local Ackid Status Command and Status Register */
+ char res8[12];
+ uint pescsr; /* 0xc0158 - Port Error and Status Command and Status Register */
+ uint pccsr; /* 0xc015c - Port Control Command and Status Register */
+ char res9[1184];
+ uint erbh; /* 0xc0600 - Error Reporting Block Header Register */
+ char res10[4];
+ uint ltledcsr; /* 0xc0608 - Logical/Transport layer error detect status register */
+ uint ltleecsr; /* 0xc060c - Logical/Transport layer error enable register */
+ char res11[4];
+ uint ltlaccsr; /* 0xc0614 - Logical/Transport layer addresss capture register */
+ uint ltldidccsr; /* 0xc0618 - Logical/Transport layer device ID capture register */
+ uint ltlcccsr; /* 0xc061c - Logical/Transport layer control capture register */
+ char res12[32];
+ uint edcsr; /* 0xc0640 - Port 0 error detect status register */
+ uint erecsr; /* 0xc0644 - Port 0 error rate enable status register */
+ uint ecacsr; /* 0xc0648 - Port 0 error capture attributes register */
+ uint pcseccsr0; /* 0xc064c - Port 0 packet/control symbol error capture register 0 */
+ uint peccsr1; /* 0xc0650 - Port 0 error capture command and status register 1 */
+ uint peccsr2; /* 0xc0654 - Port 0 error capture command and status register 2 */
+ uint peccsr3; /* 0xc0658 - Port 0 error capture command and status register 3 */
+ char res13[12];
+ uint ercsr; /* 0xc0668 - Port 0 error rate command and status register */
+ uint ertcsr; /* 0xc066C - Port 0 error rate threshold status register*/
+ char res14[63892];
+ uint llcr; /* 0xd0004 - Logical Layer Configuration Register */
+ char res15[12];
+ uint epwisr; /* 0xd0010 - Error / Port-Write Interrupt Status Register */
+ char res16[12];
+ uint lretcr; /* 0xd0020 - Logical Retry Error Threshold Configuration Register */
+ char res17[92];
+ uint pretcr; /* 0xd0080 - Physical Retry Erorr Threshold Configuration Register */
+ char res18[124];
+ uint adidcsr; /* 0xd0100 - Port 0 Alt. Device ID Command and Status Register */
+ char res19[28];
+ uint ptaacr; /* 0xd0120 - Port 0 Pass-Through/Accept-All Configuration Register */
+ char res20[12];
+ uint iecsr; /* 0xd0130 - Port 0 Implementation Error Status Register */
+ char res21[12];
+ uint pcr; /* 0xd0140 - Port 0 Phsyical Configuration RegisterRegister */
+ char res22[20];
+ uint slcsr; /* 0xd0158 - Port 0 Serial Link Command and Status Register */
+ char res23[4];
+ uint sleir; /* 0xd0160 - Port 0 Serial Link Error Injection Register */
+ char res24[2716];
+ uint rowtar0; /* 0xd0c00 - RapidIO Outbound Window Translation Address Register 0 */
+ uint rowtear0; /* 0xd0c04 - RapidIO Outbound Window Translation Ext. Address Register 0 */
+ char res25[8];
+ uint rowar0; /* 0xd0c10 - RapidIO Outbound Attributes Register 0 */
+ char res26[12];
+ uint rowtar1; /* 0xd0c20 - RapidIO Outbound Window Translation Address Register 1 */
+ uint rowtear1; /* 0xd0c24 - RapidIO Outbound Window Translation Ext. Address Register 1 */
+ uint rowbar1; /* 0xd0c28 - RapidIO Outbound Window Base Address Register 1 */
+ char res27[4];
+ uint rowar1; /* 0xd0c30 - RapidIO Outbound Attributes Register 1 */
+ uint rows1r1; /* 0xd0c34 - RapidIO Outbound Window Segment 1 Register 1 */
+ uint rows2r1; /* 0xd0c38 - RapidIO Outbound Window Segment 2 Register 1 */
+ uint rows3r1; /* 0xd0c3c - RapidIO Outbound Window Segment 3 Register 1 */
+ uint rowtar2; /* 0xd0c40 - RapidIO Outbound Window Translation Address Register 2 */
+ uint rowtear2; /* 0xd0c44 - RapidIO Outbound Window Translation Ext. Address Register 2 */
+ uint rowbar2; /* 0xd0c48 - RapidIO Outbound Window Base Address Register 2 */
+ char res28[4];
+ uint rowar2; /* 0xd0c50 - RapidIO Outbound Attributes Register 2 */
+ uint rows1r2; /* 0xd0c54 - RapidIO Outbound Window Segment 1 Register 2 */
+ uint rows2r2; /* 0xd0c58 - RapidIO Outbound Window Segment 2 Register 2 */
+ uint rows3r2; /* 0xd0c5c - RapidIO Outbound Window Segment 3 Register 2 */
+ uint rowtar3; /* 0xd0c60 - RapidIO Outbound Window Translation Address Register 3 */
+ uint rowtear3; /* 0xd0c64 - RapidIO Outbound Window Translation Ext. Address Register 3 */
+ uint rowbar3; /* 0xd0c68 - RapidIO Outbound Window Base Address Register 3 */
+ char res29[4];
+ uint rowar3; /* 0xd0c70 - RapidIO Outbound Attributes Register 3 */
+ uint rows1r3; /* 0xd0c74 - RapidIO Outbound Window Segment 1 Register 3 */
+ uint rows2r3; /* 0xd0c78 - RapidIO Outbound Window Segment 2 Register 3 */
+ uint rows3r3; /* 0xd0c7c - RapidIO Outbound Window Segment 3 Register 3 */
+ uint rowtar4; /* 0xd0c80 - RapidIO Outbound Window Translation Address Register 4 */
+ uint rowtear4; /* 0xd0c84 - RapidIO Outbound Window Translation Ext. Address Register 4 */
+ uint rowbar4; /* 0xd0c88 - RapidIO Outbound Window Base Address Register 4 */
+ char res30[4];
+ uint rowar4; /* 0xd0c90 - RapidIO Outbound Attributes Register 4 */
+ uint rows1r4; /* 0xd0c94 - RapidIO Outbound Window Segment 1 Register 4 */
+ uint rows2r4; /* 0xd0c98 - RapidIO Outbound Window Segment 2 Register 4 */
+ uint rows3r4; /* 0xd0c9c - RapidIO Outbound Window Segment 3 Register 4 */
+ uint rowtar5; /* 0xd0ca0 - RapidIO Outbound Window Translation Address Register 5 */
+ uint rowtear5; /* 0xd0ca4 - RapidIO Outbound Window Translation Ext. Address Register 5 */
+ uint rowbar5; /* 0xd0ca8 - RapidIO Outbound Window Base Address Register 5 */
+ char res31[4];
+ uint rowar5; /* 0xd0cb0 - RapidIO Outbound Attributes Register 5 */
+ uint rows1r5; /* 0xd0cb4 - RapidIO Outbound Window Segment 1 Register 5 */
+ uint rows2r5; /* 0xd0cb8 - RapidIO Outbound Window Segment 2 Register 5 */
+ uint rows3r5; /* 0xd0cbc - RapidIO Outbound Window Segment 3 Register 5 */
+ uint rowtar6; /* 0xd0cc0 - RapidIO Outbound Window Translation Address Register 6 */
+ uint rowtear6; /* 0xd0cc4 - RapidIO Outbound Window Translation Ext. Address Register 6 */
+ uint rowbar6; /* 0xd0cc8 - RapidIO Outbound Window Base Address Register 6 */
+ char res32[4];
+ uint rowar6; /* 0xd0cd0 - RapidIO Outbound Attributes Register 6 */
+ uint rows1r6; /* 0xd0cd4 - RapidIO Outbound Window Segment 1 Register 6 */
+ uint rows2r6; /* 0xd0cd8 - RapidIO Outbound Window Segment 2 Register 6 */
+ uint rows3r6; /* 0xd0cdc - RapidIO Outbound Window Segment 3 Register 6 */
+ uint rowtar7; /* 0xd0ce0 - RapidIO Outbound Window Translation Address Register 7 */
+ uint rowtear7; /* 0xd0ce4 - RapidIO Outbound Window Translation Ext. Address Register 7 */
+ uint rowbar7; /* 0xd0ce8 - RapidIO Outbound Window Base Address Register 7 */
+ char res33[4];
+ uint rowar7; /* 0xd0cf0 - RapidIO Outbound Attributes Register 7 */
+ uint rows1r7; /* 0xd0cf4 - RapidIO Outbound Window Segment 1 Register 7 */
+ uint rows2r7; /* 0xd0cf8 - RapidIO Outbound Window Segment 2 Register 7 */
+ uint rows3r7; /* 0xd0cfc - RapidIO Outbound Window Segment 3 Register 7 */
+ uint rowtar8; /* 0xd0d00 - RapidIO Outbound Window Translation Address Register 8 */
+ uint rowtear8; /* 0xd0d04 - RapidIO Outbound Window Translation Ext. Address Register 8 */
+ uint rowbar8; /* 0xd0d08 - RapidIO Outbound Window Base Address Register 8 */
+ char res34[4];
+ uint rowar8; /* 0xd0d10 - RapidIO Outbound Attributes Register 8 */
+ uint rows1r8; /* 0xd0d14 - RapidIO Outbound Window Segment 1 Register 8 */
+ uint rows2r8; /* 0xd0d18 - RapidIO Outbound Window Segment 2 Register 8 */
+ uint rows3r8; /* 0xd0d1c - RapidIO Outbound Window Segment 3 Register 8 */
+ char res35[64];
+ uint riwtar4; /* 0xd0d60 - RapidIO Inbound Window Translation Address Register 4 */
+ uint riwbar4; /* 0xd0d68 - RapidIO Inbound Window Base Address Register 4 */
+ char res36[4];
+ uint riwar4; /* 0xd0d70 - RapidIO Inbound Attributes Register 4 */
+ char res37[12];
+ uint riwtar3; /* 0xd0d80 - RapidIO Inbound Window Translation Address Register 3 */
+ char res38[4];
+ uint riwbar3; /* 0xd0d88 - RapidIO Inbound Window Base Address Register 3 */
+ char res39[4];
+ uint riwar3; /* 0xd0d90 - RapidIO Inbound Attributes Register 3 */
+ char res40[12];
+ uint riwtar2; /* 0xd0da0 - RapidIO Inbound Window Translation Address Register 2 */
+ char res41[4];
+ uint riwbar2; /* 0xd0da8 - RapidIO Inbound Window Base Address Register 2 */
+ char res42[4];
+ uint riwar2; /* 0xd0db0 - RapidIO Inbound Attributes Register 2 */
+ char res43[12];
+ uint riwtar1; /* 0xd0dc0 - RapidIO Inbound Window Translation Address Register 1 */
+ char res44[4];
+ uint riwbar1; /* 0xd0dc8 - RapidIO Inbound Window Base Address Register 1 */
+ char res45[4];
+ uint riwar1; /* 0xd0dd0 - RapidIO Inbound Attributes Register 1 */
+ char res46[12];
+ uint riwtar0; /* 0xd0de0 - RapidIO Inbound Window Translation Address Register 0 */
+ char res47[12];
+ uint riwar0; /* 0xd0df0 - RapidIO Inbound Attributes Register 0 */
+ char res48[12];
+ uint pnfedr; /* 0xd0e00 - Port Notification/Fatal Error Detect Register */
+ uint pnfedir; /* 0xd0e04 - Port Notification/Fatal Error Detect Register */
+ uint pnfeier; /* 0xd0e08 - Port Notification/Fatal Error Interrupt Enable Register */
+ uint pecr; /* 0xd0e0c - Port Error Control Register */
+ uint pepcsr0; /* 0xd0e10 - Port Error Packet/Control Symbol Register 0 */
+ uint pepr1; /* 0xd0e14 - Port Error Packet Register 1 */
+ uint pepr2; /* 0xd0e18 - Port Error Packet Register 2 */
+ char res49[4];
+ uint predr; /* 0xd0e20 - Port Recoverable Error Detect Register */
+ char res50[4];
+ uint pertr; /* 0xd0e28 - Port Error Recovery Threshold Register */
+ uint prtr; /* 0xd0e2c - Port Retry Threshold Register */
+ char res51[8656];
+ uint omr; /* 0xd3000 - Outbound Mode Register */
+ uint osr; /* 0xd3004 - Outbound Status Register */
+ uint eodqtpar; /* 0xd3008 - Extended Outbound Descriptor Queue Tail Pointer Address Register */
+ uint odqtpar; /* 0xd300c - Outbound Descriptor Queue Tail Pointer Address Register */
+ uint eosar; /* 0xd3010 - Extended Outbound Unit Source Address Register */
+ uint osar; /* 0xd3014 - Outbound Unit Source Address Register */
+ uint odpr; /* 0xd3018 - Outbound Destination Port Register */
+ uint odatr; /* 0xd301c - Outbound Destination Attributes Register */
+ uint odcr; /* 0xd3020 - Outbound Doubleword Count Register */
+ uint eodqhpar; /* 0xd3024 - Extended Outbound Descriptor Queue Head Pointer Address Register */
+ uint odqhpar; /* 0xd3028 - Outbound Descriptor Queue Head Pointer Address Register */
+ uint oretr; /* 0xd302C - Outbound Retry Error Threshold Register */
+ uint omgr; /* 0xd3030 - Outbound Multicast Group Register */
+ uint omlr; /* 0xd3034 - Outbound Multicast List Register */
+ char res52[40];
+ uint imr; /* 0xd3060 - Outbound Mode Register */
+ uint isr; /* 0xd3064 - Inbound Status Register */
+ uint eidqtpar; /* 0xd3068 - Extended Inbound Descriptor Queue Tail Pointer Address Register */
+ uint idqtpar; /* 0xd306c - Inbound Descriptor Queue Tail Pointer Address Register */
+ uint eifqhpar; /* 0xd3070 - Extended Inbound Frame Queue Head Pointer Address Register */
+ uint ifqhpar; /* 0xd3074 - Inbound Frame Queue Head Pointer Address Register */
+ uint imirir; /* 0xd3078 - Inbound Maximum Interrutp Report Interval Register */
+ char res53[900];
+ uint oddmr; /* 0xd3400 - Outbound Doorbell Mode Register */
+ uint oddsr; /* 0xd3404 - Outbound Doorbell Status Register */
+ char res54[16];
+ uint oddpr; /* 0xd3418 - Outbound Doorbell Destination Port Register */
+ uint oddatr; /* 0xd341C - Outbound Doorbell Destination Attributes Register */
+ char res55[12];
+ uint oddretr; /* 0xd342C - Outbound Doorbell Retry Threshold Configuration Register */
+ char res56[48];
+ uint idmr; /* 0xd3460 - Inbound Doorbell Mode Register */
+ uint idsr; /* 0xd3464 - Inbound Doorbell Status Register */
+ uint iedqtpar; /* 0xd3468 - Extended Inbound Doorbell Queue Tail Pointer Address Register */
+ uint iqtpar; /* 0xd346c - Inbound Doorbell Queue Tail Pointer Address Register */
+ uint iedqhpar; /* 0xd3470 - Extended Inbound Doorbell Queue Head Pointer Address Register */
+ uint idqhpar; /* 0xd3474 - Inbound Doorbell Queue Head Pointer Address Register */
+ uint idmirir; /* 0xd3478 - Inbound Doorbell Max Interrupt Report Interval Register */
+ char res57[100];
+ uint pwmr; /* 0xd34e0 - Port-Write Mode Register */
+ uint pwsr; /* 0xd34e4 - Port-Write Status Register */
+ uint epwqbar; /* 0xd34e8 - Extended Port-Write Queue Base Address Register */
+ uint pwqbar; /* 0xd34ec - Port-Write Queue Base Address Register */
+ char res58[51984];
+} ccsr_rio_t;
+
+/* Global Utilities Register Block(0xe_0000-0xf_ffff) */
+typedef struct ccsr_gur {
+ uint porpllsr; /* 0xe0000 - POR PLL ratio status register */
+ uint porbmsr; /* 0xe0004 - POR boot mode status register */
+ uint porimpscr; /* 0xe0008 - POR I/O impedance status and control register */
+ uint pordevsr; /* 0xe000c - POR I/O device status regsiter */
+ uint pordbgmsr; /* 0xe0010 - POR debug mode status register */
+ char res1[12];
+ uint gpporcr; /* 0xe0020 - General-purpose POR configuration register */
+ char res2[12];
+ uint gpiocr; /* 0xe0030 - GPIO control register */
+ char res3[12];
+ uint gpoutdr; /* 0xe0040 - General-purpose output data register */
+ char res4[12];
+ uint gpindr; /* 0xe0050 - General-purpose input data register */
+ char res5[12];
+ uint pmuxcr; /* 0xe0060 - Alternate function signal multiplex control */
+ char res6[12];
+ uint devdisr; /* 0xe0070 - Device disable control */
+ char res7[12];
+ uint powmgtcsr; /* 0xe0080 - Power management status and control register */
+ char res8[12];
+ uint mcpsumr; /* 0xe0090 - Machine check summary register */
+ uint rstrscr; /* 0xe0094 - Reset request status and control register */
+ char res9[8];
+ uint pvr; /* 0xe00a0 - Processor version register */
+ uint svr; /* 0xe00a4 - System version register */
+ char res10a[8];
+ uint rstcr; /* 0xe00b0 - Reset control register */
+ char res10b[1868];
+ uint clkdvdr; /* 0xe0800 - Clock Divide register */
+ char res10c[796];
+ uint ddr1clkdr; /* 0xe0b20 - DDRC1 Clock Disable register */
+ char res10d[4];
+ uint ddr2clkdr; /* 0xe0b28 - DDRC2 Clock Disable register */
+ char res10e[724];
+ uint clkocr; /* 0xe0e00 - Clock out select register */
+ char res11[12];
+ uint ddrdllcr; /* 0xe0e10 - DDR DLL control register */
+ char res12[12];
+ uint lbcdllcr; /* 0xe0e20 - LBC DLL control register */
+ char res13a[224];
+ uint srds1cr0; /* 0xe0f04 - SerDes1 control register 0 */
+ char res13b[4];
+ uint srds1cr1; /* 0xe0f08 - SerDes1 control register 1 */
+ char res14[24];
+ uint ddrioovcr; /* 0xe0f24 - DDR IO Overdrive Control register */
+ char res15a[24];
+ uint srds2cr0; /* 0xe0f40 - SerDes2 control register 0 */
+ uint srds2cr1; /* 0xe0f44 - SerDes2 control register 1 */
+ char res16[184];
+} ccsr_gur_t;
+
+#define MPC8610_PORBMSR_HA 0x00070000
+#define MPC8610_PORBMSR_HA_SHIFT 16
+#define MPC8641_PORBMSR_HA 0x00060000
+#define MPC8641_PORBMSR_HA_SHIFT 17
+#define MPC8610_PORDEVSR_IO_SEL 0x00380000
+#define MPC8610_PORDEVSR_IO_SEL_SHIFT 19
+#define MPC8641_PORDEVSR_IO_SEL 0x000F0000
+#define MPC8641_PORDEVSR_IO_SEL_SHIFT 16
+#define MPC86xx_PORDEVSR_CORE1TE 0x00000080 /* ASMP (Core1 addr trans) */
+#define MPC86xx_DEVDISR_PCIEX1 0x80000000
+#define MPC86xx_DEVDISR_PCIEX2 0x40000000
+#define MPC86xx_DEVDISR_PCI1 0x80000000
+#define MPC86xx_DEVDISR_PCIE1 0x40000000
+#define MPC86xx_DEVDISR_PCIE2 0x20000000
+#define MPC86xx_DEVDISR_SRIO 0x00080000
+#define MPC86xx_DEVDISR_RMSG 0x00040000
+#define MPC86xx_DEVDISR_CPU0 0x00008000
+#define MPC86xx_DEVDISR_CPU1 0x00004000
+#define MPC86xx_RSTCR_HRST_REQ 0x00000002
+
+/*
+ * Watchdog register block(0xe_4000-0xe_4fff)
+ */
+typedef struct ccsr_wdt {
+ uint res0;
+ uint swcrr; /* System watchdog control register */
+ uint swcnr; /* System watchdog count register */
+ char res1[2];
+ ushort swsrr; /* System watchdog service register */
+ char res2[4080];
+} ccsr_wdt_t;
+
+typedef struct immap {
+ ccsr_local_mcm_t im_local_mcm;
+ ccsr_ddr_t im_ddr1;
+ ccsr_i2c_t im_i2c;
+ ccsr_duart_t im_duart;
+ fsl_lbc_t im_lbc;
+ ccsr_ddr_t im_ddr2;
+ char res1[4096];
+ ccsr_pex_t im_pex1;
+ ccsr_pex_t im_pex2;
+ ccsr_ht_t im_ht;
+ char res2[90112];
+ ccsr_dma_t im_dma;
+ char res3[8192];
+ ccsr_tsec_t im_tsec1;
+ ccsr_tsec_t im_tsec2;
+ ccsr_tsec_t im_tsec3;
+ ccsr_tsec_t im_tsec4;
+ char res4[98304];
+ ccsr_pic_t im_pic;
+ char res5[389120];
+ ccsr_rio_t im_rio;
+ ccsr_gur_t im_gur;
+ char res6[12288];
+ ccsr_wdt_t im_wdt;
+} immap_t;
+
+extern immap_t *immr;
+
+#define CONFIG_SYS_MPC8xxx_DDR_OFFSET 0x2000
+#define CONFIG_SYS_MPC8xxx_DDR_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR_OFFSET)
+#define CONFIG_SYS_MPC8xxx_DDR2_OFFSET 0x6000
+#define CONFIG_SYS_MPC8xxx_DDR2_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC8xxx_DDR2_OFFSET)
+#define CONFIG_SYS_MPC86xx_DMA_OFFSET 0x21000
+#define CONFIG_SYS_MPC86xx_DMA_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_DMA_OFFSET)
+#define CONFIG_SYS_MPC86xx_PIC_OFFSET 0x40000
+#define CONFIG_SYS_MPC8xxx_PIC_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_PIC_OFFSET)
+
+
+#define CONFIG_SYS_MPC86xx_PCI1_OFFSET 0x8000
+#ifdef CONFIG_MPC8610
+#define CONFIG_SYS_MPC86xx_PCIE1_OFFSET 0xa000
+#else
+#define CONFIG_SYS_MPC86xx_PCIE1_OFFSET 0x8000
+#endif
+#define CONFIG_SYS_MPC86xx_PCIE2_OFFSET 0x9000
+
+#define CONFIG_SYS_PCI1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_PCI1_OFFSET)
+#define CONFIG_SYS_PCI2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_PCI2_OFFSET)
+#define CONFIG_SYS_PCIE1_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_PCIE1_OFFSET)
+#define CONFIG_SYS_PCIE2_ADDR \
+ (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_PCIE2_OFFSET)
+
+#define CONFIG_SYS_TSEC1_OFFSET 0x24000
+#define CONFIG_SYS_MDIO1_OFFSET 0x24000
+#define CONFIG_SYS_LBC_ADDR (&((immap_t *)CONFIG_SYS_IMMR)->im_lbc)
+
+#define TSEC_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_TSEC1_OFFSET)
+#define MDIO_BASE_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MDIO1_OFFSET)
+
+#endif /*__IMMAP_86xx__*/
diff --git a/arch/powerpc/include/asm/immap_qe.h b/arch/powerpc/include/asm/immap_qe.h
new file mode 100644
index 0000000..f0b989a
--- /dev/null
+++ b/arch/powerpc/include/asm/immap_qe.h
@@ -0,0 +1,585 @@
+/*
+ * QUICC Engine (QE) Internal Memory Map.
+ * The Internal Memory Map for devices with QE on them. This
+ * is the superset of all QE devices (8360, etc.).
+ *
+ * Copyright (c) 2006-2009, 2011 Freescale Semiconductor, Inc.
+ * Author: Shlomi Gridih <gridish@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __IMMAP_QE_H__
+#define __IMMAP_QE_H__
+
+#ifdef CONFIG_MPC83xx
+#if defined(CONFIG_MPC8360)
+#define QE_MURAM_SIZE 0xc000UL
+#define MAX_QE_RISC 2
+#define QE_NUM_OF_SNUM 28
+#elif defined(CONFIG_MPC832x) || defined(CONFIG_MPC8309)
+#define QE_MURAM_SIZE 0x4000UL
+#define MAX_QE_RISC 1
+#define QE_NUM_OF_SNUM 28
+#endif
+#endif
+
+/* QE I-RAM */
+typedef struct qe_iram {
+ u32 iadd; /* I-RAM Address Register */
+ u32 idata; /* I-RAM Data Register */
+ u8 res0[0x4];
+ u32 iready;
+ u8 res1[0x70];
+} __attribute__ ((packed)) qe_iram_t;
+
+/* QE Interrupt Controller */
+typedef struct qe_ic {
+ u32 qicr;
+ u32 qivec;
+ u32 qripnr;
+ u32 qipnr;
+ u32 qipxcc;
+ u32 qipycc;
+ u32 qipwcc;
+ u32 qipzcc;
+ u32 qimr;
+ u32 qrimr;
+ u32 qicnr;
+ u8 res0[0x4];
+ u32 qiprta;
+ u32 qiprtb;
+ u8 res1[0x4];
+ u32 qricr;
+ u8 res2[0x20];
+ u32 qhivec;
+ u8 res3[0x1C];
+} __attribute__ ((packed)) qe_ic_t;
+
+/* Communications Processor */
+typedef struct cp_qe {
+ u32 cecr; /* QE command register */
+ u32 ceccr; /* QE controller configuration register */
+ u32 cecdr; /* QE command data register */
+ u8 res0[0xA];
+ u16 ceter; /* QE timer event register */
+ u8 res1[0x2];
+ u16 cetmr; /* QE timers mask register */
+ u32 cetscr; /* QE time-stamp timer control register */
+ u32 cetsr1; /* QE time-stamp register 1 */
+ u32 cetsr2; /* QE time-stamp register 2 */
+ u8 res2[0x8];
+ u32 cevter; /* QE virtual tasks event register */
+ u32 cevtmr; /* QE virtual tasks mask register */
+ u16 cercr; /* QE RAM control register */
+ u8 res3[0x2];
+ u8 res4[0x24];
+ u16 ceexe1; /* QE external request 1 event register */
+ u8 res5[0x2];
+ u16 ceexm1; /* QE external request 1 mask register */
+ u8 res6[0x2];
+ u16 ceexe2; /* QE external request 2 event register */
+ u8 res7[0x2];
+ u16 ceexm2; /* QE external request 2 mask register */
+ u8 res8[0x2];
+ u16 ceexe3; /* QE external request 3 event register */
+ u8 res9[0x2];
+ u16 ceexm3; /* QE external request 3 mask register */
+ u8 res10[0x2];
+ u16 ceexe4; /* QE external request 4 event register */
+ u8 res11[0x2];
+ u16 ceexm4; /* QE external request 4 mask register */
+ u8 res12[0x2];
+ u8 res13[0x280];
+} __attribute__ ((packed)) cp_qe_t;
+
+/* QE Multiplexer */
+typedef struct qe_mux {
+ u32 cmxgcr; /* CMX general clock route register */
+ u32 cmxsi1cr_l; /* CMX SI1 clock route low register */
+ u32 cmxsi1cr_h; /* CMX SI1 clock route high register */
+ u32 cmxsi1syr; /* CMX SI1 SYNC route register */
+ u32 cmxucr1; /* CMX UCC1, UCC3 clock route register */
+ u32 cmxucr2; /* CMX UCC5, UCC7 clock route register */
+ u32 cmxucr3; /* CMX UCC2, UCC4 clock route register */
+ u32 cmxucr4; /* CMX UCC6, UCC8 clock route register */
+ u32 cmxupcr; /* CMX UPC clock route register */
+ u8 res0[0x1C];
+} __attribute__ ((packed)) qe_mux_t;
+
+/* QE Timers */
+typedef struct qe_timers {
+ u8 gtcfr1; /* Timer 1 2 global configuration register */
+ u8 res0[0x3];
+ u8 gtcfr2; /* Timer 3 4 global configuration register */
+ u8 res1[0xB];
+ u16 gtmdr1; /* Timer 1 mode register */
+ u16 gtmdr2; /* Timer 2 mode register */
+ u16 gtrfr1; /* Timer 1 reference register */
+ u16 gtrfr2; /* Timer 2 reference register */
+ u16 gtcpr1; /* Timer 1 capture register */
+ u16 gtcpr2; /* Timer 2 capture register */
+ u16 gtcnr1; /* Timer 1 counter */
+ u16 gtcnr2; /* Timer 2 counter */
+ u16 gtmdr3; /* Timer 3 mode register */
+ u16 gtmdr4; /* Timer 4 mode register */
+ u16 gtrfr3; /* Timer 3 reference register */
+ u16 gtrfr4; /* Timer 4 reference register */
+ u16 gtcpr3; /* Timer 3 capture register */
+ u16 gtcpr4; /* Timer 4 capture register */
+ u16 gtcnr3; /* Timer 3 counter */
+ u16 gtcnr4; /* Timer 4 counter */
+ u16 gtevr1; /* Timer 1 event register */
+ u16 gtevr2; /* Timer 2 event register */
+ u16 gtevr3; /* Timer 3 event register */
+ u16 gtevr4; /* Timer 4 event register */
+ u16 gtps; /* Timer 1 prescale register */
+ u8 res2[0x46];
+} __attribute__ ((packed)) qe_timers_t;
+
+/* BRG */
+typedef struct qe_brg {
+ u32 brgc1; /* BRG1 configuration register */
+ u32 brgc2; /* BRG2 configuration register */
+ u32 brgc3; /* BRG3 configuration register */
+ u32 brgc4; /* BRG4 configuration register */
+ u32 brgc5; /* BRG5 configuration register */
+ u32 brgc6; /* BRG6 configuration register */
+ u32 brgc7; /* BRG7 configuration register */
+ u32 brgc8; /* BRG8 configuration register */
+ u32 brgc9; /* BRG9 configuration register */
+ u32 brgc10; /* BRG10 configuration register */
+ u32 brgc11; /* BRG11 configuration register */
+ u32 brgc12; /* BRG12 configuration register */
+ u32 brgc13; /* BRG13 configuration register */
+ u32 brgc14; /* BRG14 configuration register */
+ u32 brgc15; /* BRG15 configuration register */
+ u32 brgc16; /* BRG16 configuration register */
+ u8 res0[0x40];
+} __attribute__ ((packed)) qe_brg_t;
+
+/* SPI */
+typedef struct spi {
+ u8 res0[0x20];
+ u32 spmode; /* SPI mode register */
+ u8 res1[0x2];
+ u8 spie; /* SPI event register */
+ u8 res2[0x1];
+ u8 res3[0x2];
+ u8 spim; /* SPI mask register */
+ u8 res4[0x1];
+ u8 res5[0x1];
+ u8 spcom; /* SPI command register */
+ u8 res6[0x2];
+ u32 spitd; /* SPI transmit data register (cpu mode) */
+ u32 spird; /* SPI receive data register (cpu mode) */
+ u8 res7[0x8];
+} __attribute__ ((packed)) spi_t;
+
+/* SI */
+typedef struct si1 {
+ u16 siamr1; /* SI1 TDMA mode register */
+ u16 sibmr1; /* SI1 TDMB mode register */
+ u16 sicmr1; /* SI1 TDMC mode register */
+ u16 sidmr1; /* SI1 TDMD mode register */
+ u8 siglmr1_h; /* SI1 global mode register high */
+ u8 res0[0x1];
+ u8 sicmdr1_h; /* SI1 command register high */
+ u8 res2[0x1];
+ u8 sistr1_h; /* SI1 status register high */
+ u8 res3[0x1];
+ u16 sirsr1_h; /* SI1 RAM shadow address register high */
+ u8 sitarc1; /* SI1 RAM counter Tx TDMA */
+ u8 sitbrc1; /* SI1 RAM counter Tx TDMB */
+ u8 sitcrc1; /* SI1 RAM counter Tx TDMC */
+ u8 sitdrc1; /* SI1 RAM counter Tx TDMD */
+ u8 sirarc1; /* SI1 RAM counter Rx TDMA */
+ u8 sirbrc1; /* SI1 RAM counter Rx TDMB */
+ u8 sircrc1; /* SI1 RAM counter Rx TDMC */
+ u8 sirdrc1; /* SI1 RAM counter Rx TDMD */
+ u8 res4[0x8];
+ u16 siemr1; /* SI1 TDME mode register 16 bits */
+ u16 sifmr1; /* SI1 TDMF mode register 16 bits */
+ u16 sigmr1; /* SI1 TDMG mode register 16 bits */
+ u16 sihmr1; /* SI1 TDMH mode register 16 bits */
+ u8 siglmg1_l; /* SI1 global mode register low 8 bits */
+ u8 res5[0x1];
+ u8 sicmdr1_l; /* SI1 command register low 8 bits */
+ u8 res6[0x1];
+ u8 sistr1_l; /* SI1 status register low 8 bits */
+ u8 res7[0x1];
+ u16 sirsr1_l; /* SI1 RAM shadow address register low 16 bits */
+ u8 siterc1; /* SI1 RAM counter Tx TDME 8 bits */
+ u8 sitfrc1; /* SI1 RAM counter Tx TDMF 8 bits */
+ u8 sitgrc1; /* SI1 RAM counter Tx TDMG 8 bits */
+ u8 sithrc1; /* SI1 RAM counter Tx TDMH 8 bits */
+ u8 sirerc1; /* SI1 RAM counter Rx TDME 8 bits */
+ u8 sirfrc1; /* SI1 RAM counter Rx TDMF 8 bits */
+ u8 sirgrc1; /* SI1 RAM counter Rx TDMG 8 bits */
+ u8 sirhrc1; /* SI1 RAM counter Rx TDMH 8 bits */
+ u8 res8[0x8];
+ u32 siml1; /* SI1 multiframe limit register */
+ u8 siedm1; /* SI1 extended diagnostic mode register */
+ u8 res9[0xBB];
+} __attribute__ ((packed)) si1_t;
+
+/* SI Routing Tables */
+typedef struct sir {
+ u8 tx[0x400];
+ u8 rx[0x400];
+ u8 res0[0x800];
+} __attribute__ ((packed)) sir_t;
+
+/* USB Controller. */
+typedef struct usb_ctlr {
+ u8 usb_usmod;
+ u8 usb_usadr;
+ u8 usb_uscom;
+ u8 res1[1];
+ u16 usb_usep1;
+ u16 usb_usep2;
+ u16 usb_usep3;
+ u16 usb_usep4;
+ u8 res2[4];
+ u16 usb_usber;
+ u8 res3[2];
+ u16 usb_usbmr;
+ u8 res4[1];
+ u8 usb_usbs;
+ u16 usb_ussft;
+ u8 res5[2];
+ u16 usb_usfrn;
+ u8 res6[0x22];
+} __attribute__ ((packed)) usb_t;
+
+/* MCC */
+typedef struct mcc {
+ u32 mcce; /* MCC event register */
+ u32 mccm; /* MCC mask register */
+ u32 mccf; /* MCC configuration register */
+ u32 merl; /* MCC emergency request level register */
+ u8 res0[0xF0];
+} __attribute__ ((packed)) mcc_t;
+
+/* QE UCC Slow */
+typedef struct ucc_slow {
+ u32 gumr_l; /* UCCx general mode register (low) */
+ u32 gumr_h; /* UCCx general mode register (high) */
+ u16 upsmr; /* UCCx protocol-specific mode register */
+ u8 res0[0x2];
+ u16 utodr; /* UCCx transmit on demand register */
+ u16 udsr; /* UCCx data synchronization register */
+ u16 ucce; /* UCCx event register */
+ u8 res1[0x2];
+ u16 uccm; /* UCCx mask register */
+ u8 res2[0x1];
+ u8 uccs; /* UCCx status register */
+ u8 res3[0x24];
+ u16 utpt;
+ u8 guemr; /* UCC general extended mode register */
+ u8 res4[0x200 - 0x091];
+} __attribute__ ((packed)) ucc_slow_t;
+
+typedef struct ucc_mii_mng {
+ u32 miimcfg; /* MII management configuration reg */
+ u32 miimcom; /* MII management command reg */
+ u32 miimadd; /* MII management address reg */
+ u32 miimcon; /* MII management control reg */
+ u32 miimstat; /* MII management status reg */
+ u32 miimind; /* MII management indication reg */
+ u32 ifctl; /* interface control reg */
+ u32 ifstat; /* interface statux reg */
+} __attribute__ ((packed))uec_mii_t;
+
+typedef struct ucc_ethernet {
+ u32 maccfg1; /* mac configuration reg. 1 */
+ u32 maccfg2; /* mac configuration reg. 2 */
+ u32 ipgifg; /* interframe gap reg. */
+ u32 hafdup; /* half-duplex reg. */
+ u8 res1[0x10];
+ u32 miimcfg; /* MII management configuration reg */
+ u32 miimcom; /* MII management command reg */
+ u32 miimadd; /* MII management address reg */
+ u32 miimcon; /* MII management control reg */
+ u32 miimstat; /* MII management status reg */
+ u32 miimind; /* MII management indication reg */
+ u32 ifctl; /* interface control reg */
+ u32 ifstat; /* interface statux reg */
+ u32 macstnaddr1; /* mac station address part 1 reg */
+ u32 macstnaddr2; /* mac station address part 2 reg */
+ u8 res2[0x8];
+ u32 uempr; /* UCC Ethernet Mac parameter reg */
+ u32 utbipar; /* UCC tbi address reg */
+ u16 uescr; /* UCC Ethernet statistics control reg */
+ u8 res3[0x180 - 0x15A];
+ u32 tx64; /* Total number of frames (including bad
+ * frames) transmitted that were exactly
+ * of the minimal length (64 for un tagged,
+ * 68 for tagged, or with length exactly
+ * equal to the parameter MINLength */
+ u32 tx127; /* Total number of frames (including bad
+ * frames) transmitted that were between
+ * MINLength (Including FCS length==4)
+ * and 127 octets */
+ u32 tx255; /* Total number of frames (including bad
+ * frames) transmitted that were between
+ * 128 (Including FCS length==4) and 255
+ * octets */
+ u32 rx64; /* Total number of frames received including
+ * bad frames that were exactly of the
+ * mninimal length (64 bytes) */
+ u32 rx127; /* Total number of frames (including bad
+ * frames) received that were between
+ * MINLength (Including FCS length==4)
+ * and 127 octets */
+ u32 rx255; /* Total number of frames (including
+ * bad frames) received that were between
+ * 128 (Including FCS length==4) and 255
+ * octets */
+ u32 txok; /* Total number of octets residing in frames
+ * that where involved in succesfull
+ * transmission */
+ u16 txcf; /* Total number of PAUSE control frames
+ * transmitted by this MAC */
+ u8 res4[0x2];
+ u32 tmca; /* Total number of frames that were transmitted
+ * succesfully with the group address bit set
+ * that are not broadcast frames */
+ u32 tbca; /* Total number of frames transmitted
+ * succesfully that had destination address
+ * field equal to the broadcast address */
+ u32 rxfok; /* Total number of frames received OK */
+ u32 rxbok; /* Total number of octets received OK */
+ u32 rbyt; /* Total number of octets received including
+ * octets in bad frames. Must be implemented
+ * in HW because it includes octets in frames
+ * that never even reach the UCC */
+ u32 rmca; /* Total number of frames that were received
+ * succesfully with the group address bit set
+ * that are not broadcast frames */
+ u32 rbca; /* Total number of frames received succesfully
+ * that had destination address equal to the
+ * broadcast address */
+ u32 scar; /* Statistics carry register */
+ u32 scam; /* Statistics caryy mask register */
+ u8 res5[0x200 - 0x1c4];
+} __attribute__ ((packed)) uec_t;
+
+/* QE UCC Fast */
+typedef struct ucc_fast {
+ u32 gumr; /* UCCx general mode register */
+ u32 upsmr; /* UCCx protocol-specific mode register */
+ u16 utodr; /* UCCx transmit on demand register */
+ u8 res0[0x2];
+ u16 udsr; /* UCCx data synchronization register */
+ u8 res1[0x2];
+ u32 ucce; /* UCCx event register */
+ u32 uccm; /* UCCx mask register. */
+ u8 uccs; /* UCCx status register */
+ u8 res2[0x7];
+ u32 urfb; /* UCC receive FIFO base */
+ u16 urfs; /* UCC receive FIFO size */
+ u8 res3[0x2];
+ u16 urfet; /* UCC receive FIFO emergency threshold */
+ u16 urfset; /* UCC receive FIFO special emergency
+ * threshold */
+ u32 utfb; /* UCC transmit FIFO base */
+ u16 utfs; /* UCC transmit FIFO size */
+ u8 res4[0x2];
+ u16 utfet; /* UCC transmit FIFO emergency threshold */
+ u8 res5[0x2];
+ u16 utftt; /* UCC transmit FIFO transmit threshold */
+ u8 res6[0x2];
+ u16 utpt; /* UCC transmit polling timer */
+ u8 res7[0x2];
+ u32 urtry; /* UCC retry counter register */
+ u8 res8[0x4C];
+ u8 guemr; /* UCC general extended mode register */
+ u8 res9[0x100 - 0x091];
+ uec_t ucc_eth;
+} __attribute__ ((packed)) ucc_fast_t;
+
+/* QE UCC */
+typedef struct ucc_common {
+ u8 res1[0x90];
+ u8 guemr;
+ u8 res2[0x200 - 0x091];
+} __attribute__ ((packed)) ucc_common_t;
+
+typedef struct ucc {
+ union {
+ ucc_slow_t slow;
+ ucc_fast_t fast;
+ ucc_common_t common;
+ };
+} __attribute__ ((packed)) ucc_t;
+
+/* MultiPHY UTOPIA POS Controllers (UPC) */
+typedef struct upc {
+ u32 upgcr; /* UTOPIA/POS general configuration register */
+ u32 uplpa; /* UTOPIA/POS last PHY address */
+ u32 uphec; /* ATM HEC register */
+ u32 upuc; /* UTOPIA/POS UCC configuration */
+ u32 updc1; /* UTOPIA/POS device 1 configuration */
+ u32 updc2; /* UTOPIA/POS device 2 configuration */
+ u32 updc3; /* UTOPIA/POS device 3 configuration */
+ u32 updc4; /* UTOPIA/POS device 4 configuration */
+ u32 upstpa; /* UTOPIA/POS STPA threshold */
+ u8 res0[0xC];
+ u32 updrs1_h; /* UTOPIA/POS device 1 rate select */
+ u32 updrs1_l; /* UTOPIA/POS device 1 rate select */
+ u32 updrs2_h; /* UTOPIA/POS device 2 rate select */
+ u32 updrs2_l; /* UTOPIA/POS device 2 rate select */
+ u32 updrs3_h; /* UTOPIA/POS device 3 rate select */
+ u32 updrs3_l; /* UTOPIA/POS device 3 rate select */
+ u32 updrs4_h; /* UTOPIA/POS device 4 rate select */
+ u32 updrs4_l; /* UTOPIA/POS device 4 rate select */
+ u32 updrp1; /* UTOPIA/POS device 1 receive priority low */
+ u32 updrp2; /* UTOPIA/POS device 2 receive priority low */
+ u32 updrp3; /* UTOPIA/POS device 3 receive priority low */
+ u32 updrp4; /* UTOPIA/POS device 4 receive priority low */
+ u32 upde1; /* UTOPIA/POS device 1 event */
+ u32 upde2; /* UTOPIA/POS device 2 event */
+ u32 upde3; /* UTOPIA/POS device 3 event */
+ u32 upde4; /* UTOPIA/POS device 4 event */
+ u16 uprp1;
+ u16 uprp2;
+ u16 uprp3;
+ u16 uprp4;
+ u8 res1[0x8];
+ u16 uptirr1_0; /* Device 1 transmit internal rate 0 */
+ u16 uptirr1_1; /* Device 1 transmit internal rate 1 */
+ u16 uptirr1_2; /* Device 1 transmit internal rate 2 */
+ u16 uptirr1_3; /* Device 1 transmit internal rate 3 */
+ u16 uptirr2_0; /* Device 2 transmit internal rate 0 */
+ u16 uptirr2_1; /* Device 2 transmit internal rate 1 */
+ u16 uptirr2_2; /* Device 2 transmit internal rate 2 */
+ u16 uptirr2_3; /* Device 2 transmit internal rate 3 */
+ u16 uptirr3_0; /* Device 3 transmit internal rate 0 */
+ u16 uptirr3_1; /* Device 3 transmit internal rate 1 */
+ u16 uptirr3_2; /* Device 3 transmit internal rate 2 */
+ u16 uptirr3_3; /* Device 3 transmit internal rate 3 */
+ u16 uptirr4_0; /* Device 4 transmit internal rate 0 */
+ u16 uptirr4_1; /* Device 4 transmit internal rate 1 */
+ u16 uptirr4_2; /* Device 4 transmit internal rate 2 */
+ u16 uptirr4_3; /* Device 4 transmit internal rate 3 */
+ u32 uper1; /* Device 1 port enable register */
+ u32 uper2; /* Device 2 port enable register */
+ u32 uper3; /* Device 3 port enable register */
+ u32 uper4; /* Device 4 port enable register */
+ u8 res2[0x150];
+} __attribute__ ((packed)) upc_t;
+
+/* SDMA */
+typedef struct sdma {
+ u32 sdsr; /* Serial DMA status register */
+ u32 sdmr; /* Serial DMA mode register */
+ u32 sdtr1; /* SDMA system bus threshold register */
+ u32 sdtr2; /* SDMA secondary bus threshold register */
+ u32 sdhy1; /* SDMA system bus hysteresis register */
+ u32 sdhy2; /* SDMA secondary bus hysteresis register */
+ u32 sdta1; /* SDMA system bus address register */
+ u32 sdta2; /* SDMA secondary bus address register */
+ u32 sdtm1; /* SDMA system bus MSNUM register */
+ u32 sdtm2; /* SDMA secondary bus MSNUM register */
+ u8 res0[0x10];
+ u32 sdaqr; /* SDMA address bus qualify register */
+ u32 sdaqmr; /* SDMA address bus qualify mask register */
+ u8 res1[0x4];
+ u32 sdwbcr; /* SDMA CAM entries base register */
+ u8 res2[0x38];
+} __attribute__ ((packed)) sdma_t;
+
+/* Debug Space */
+typedef struct dbg {
+ u32 bpdcr; /* Breakpoint debug command register */
+ u32 bpdsr; /* Breakpoint debug status register */
+ u32 bpdmr; /* Breakpoint debug mask register */
+ u32 bprmrr0; /* Breakpoint request mode risc register 0 */
+ u32 bprmrr1; /* Breakpoint request mode risc register 1 */
+ u8 res0[0x8];
+ u32 bprmtr0; /* Breakpoint request mode trb register 0 */
+ u32 bprmtr1; /* Breakpoint request mode trb register 1 */
+ u8 res1[0x8];
+ u32 bprmir; /* Breakpoint request mode immediate register */
+ u32 bprmsr; /* Breakpoint request mode serial register */
+ u32 bpemr; /* Breakpoint exit mode register */
+ u8 res2[0x48];
+} __attribute__ ((packed)) dbg_t;
+
+/*
+ * RISC Special Registers (Trap and Breakpoint). These are described in
+ * the QE Developer's Handbook.
+*/
+typedef struct rsp {
+ u32 tibcr[16]; /* Trap/instruction breakpoint control regs */
+ u8 res0[64];
+ u32 ibcr0;
+ u32 ibs0;
+ u32 ibcnr0;
+ u8 res1[4];
+ u32 ibcr1;
+ u32 ibs1;
+ u32 ibcnr1;
+ u32 npcr;
+ u32 dbcr;
+ u32 dbar;
+ u32 dbamr;
+ u32 dbsr;
+ u32 dbcnr;
+ u8 res2[12];
+ u32 dbdr_h;
+ u32 dbdr_l;
+ u32 dbdmr_h;
+ u32 dbdmr_l;
+ u32 bsr;
+ u32 bor;
+ u32 bior;
+ u8 res3[4];
+ u32 iatr[4];
+ u32 eccr; /* Exception control configuration register */
+ u32 eicr;
+ u8 res4[0x100-0xf8];
+} __attribute__ ((packed)) rsp_t;
+
+typedef struct qe_immap {
+ qe_iram_t iram; /* I-RAM */
+ qe_ic_t ic; /* Interrupt Controller */
+ cp_qe_t cp; /* Communications Processor */
+ qe_mux_t qmx; /* QE Multiplexer */
+ qe_timers_t qet; /* QE Timers */
+ spi_t spi[0x2]; /* spi */
+ mcc_t mcc; /* mcc */
+ qe_brg_t brg; /* brg */
+ usb_t usb; /* USB */
+ si1_t si1; /* SI */
+ u8 res11[0x800];
+ sir_t sir; /* SI Routing Tables */
+ ucc_t ucc1; /* ucc1 */
+ ucc_t ucc3; /* ucc3 */
+ ucc_t ucc5; /* ucc5 */
+ ucc_t ucc7; /* ucc7 */
+ u8 res12[0x600];
+ upc_t upc1; /* MultiPHY UTOPIA POS Controller 1 */
+ ucc_t ucc2; /* ucc2 */
+ ucc_t ucc4; /* ucc4 */
+ ucc_t ucc6; /* ucc6 */
+ ucc_t ucc8; /* ucc8 */
+ u8 res13[0x600];
+ upc_t upc2; /* MultiPHY UTOPIA POS Controller 2 */
+ sdma_t sdma; /* SDMA */
+ dbg_t dbg; /* Debug Space */
+ rsp_t rsp[0x2]; /* RISC Special Registers
+ * (Trap and Breakpoint) */
+ u8 res14[0x300];
+ u8 res15[0x3A00];
+ u8 res16[0x8000]; /* 0x108000 - 0x110000 */
+ u8 muram[QE_MURAM_SIZE];
+} __attribute__ ((packed)) qe_map_t;
+
+extern qe_map_t *qe_immr;
+
+#endif /* __IMMAP_QE_H__ */
diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
new file mode 100644
index 0000000..792836b
--- /dev/null
+++ b/arch/powerpc/include/asm/interrupt.h
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef INTERRUPT_H
+#define INTERRUPT_H
+
+#if defined(CONFIG_XILINX_440)
+#include <asm/xilinx_irq.h>
+#else
+#include <asm/ppc4xx-uic.h>
+#endif
+
+void pic_enable(void);
+void pic_irq_enable(unsigned int irq);
+void pic_irq_disable(unsigned int irq);
+void pic_irq_ack(unsigned int irq);
+void external_interrupt(struct pt_regs *regs);
+void interrupt_run_handler(int vec);
+
+#endif
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
new file mode 100644
index 0000000..1f12c29
--- /dev/null
+++ b/arch/powerpc/include/asm/io.h
@@ -0,0 +1,320 @@
+/* originally from linux source.
+ * removed the dependencies on CONFIG_ values
+ * removed virt_to_phys stuff (and in fact everything surrounded by #if __KERNEL__)
+ * Modified By Rob Taylor, Flying Pig Systems, 2000
+ */
+
+#ifndef _PPC_IO_H
+#define _PPC_IO_H
+
+#include <linux/config.h>
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_ADDR_MAP
+#include <addr_map.h>
+#endif
+
+#define SIO_CONFIG_RA 0x398
+#define SIO_CONFIG_RD 0x399
+
+#ifndef _IO_BASE
+#define _IO_BASE 0
+#endif
+
+#define readb(addr) in_8((volatile u8 *)(addr))
+#define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
+#if !defined(__BIG_ENDIAN)
+#define readw(addr) (*(volatile u16 *) (addr))
+#define readl(addr) (*(volatile u32 *) (addr))
+#define writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define readw(addr) in_le16((volatile u16 *)(addr))
+#define readl(addr) in_le32((volatile u32 *)(addr))
+#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
+#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
+#endif
+
+/*
+ * The insw/outsw/insl/outsl macros don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case. - paulus
+ */
+#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define outsb(port, buf, ns) _outsb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+#define inb(port) in_8((u8 *)((port)+_IO_BASE))
+#define outb(val, port) out_8((u8 *)((port)+_IO_BASE), (val))
+#if !defined(__BIG_ENDIAN)
+#define inw(port) in_be16((u16 *)((port)+_IO_BASE))
+#define outw(val, port) out_be16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port) in_be32((u32 *)((port)+_IO_BASE))
+#define outl(val, port) out_be32((u32 *)((port)+_IO_BASE), (val))
+#else
+#define inw(port) in_le16((u16 *)((port)+_IO_BASE))
+#define outw(val, port) out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port) in_le32((u32 *)((port)+_IO_BASE))
+#define outl(val, port) out_le32((u32 *)((port)+_IO_BASE), (val))
+#endif
+
+#define inb_p(port) in_8((u8 *)((port)+_IO_BASE))
+#define outb_p(val, port) out_8((u8 *)((port)+_IO_BASE), (val))
+#define inw_p(port) in_le16((u16 *)((port)+_IO_BASE))
+#define outw_p(val, port) out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl_p(port) in_le32((u32 *)((port)+_IO_BASE))
+#define outl_p(val, port) out_le32((u32 *)((port)+_IO_BASE), (val))
+
+extern void _insb(volatile u8 *port, void *buf, int ns);
+extern void _outsb(volatile u8 *port, const void *buf, int ns);
+extern void _insw(volatile u16 *port, void *buf, int ns);
+extern void _outsw(volatile u16 *port, const void *buf, int ns);
+extern void _insl(volatile u32 *port, void *buf, int nl);
+extern void _outsl(volatile u32 *port, const void *buf, int nl);
+extern void _insw_ns(volatile u16 *port, void *buf, int ns);
+extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
+extern void _insl_ns(volatile u32 *port, void *buf, int nl);
+extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
+
+/*
+ * The *_ns versions below don't do byte-swapping.
+ * Neither do the standard versions now, these are just here
+ * for older code.
+ */
+#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+
+#define IO_SPACE_LIMIT ~0
+
+#define memset_io(a,b,c) memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
+
+/*
+ * Enforce In-order Execution of I/O:
+ * Acts as a barrier to ensure all previous I/O accesses have
+ * completed before any further ones are issued.
+ */
+static inline void eieio(void)
+{
+ __asm__ __volatile__ ("eieio" : : : "memory");
+}
+
+static inline void sync(void)
+{
+ __asm__ __volatile__ ("sync" : : : "memory");
+}
+
+static inline void isync(void)
+{
+ __asm__ __volatile__ ("isync" : : : "memory");
+}
+
+/* Enforce in-order execution of data I/O.
+ * No distinction between read/write on PPC; use eieio for all three.
+ */
+#define iobarrier_rw() eieio()
+#define iobarrier_r() eieio()
+#define iobarrier_w() eieio()
+
+/*
+ * Non ordered and non-swapping "raw" accessors
+ */
+#define PCI_FIX_ADDR(addr) (addr)
+
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned char *)PCI_FIX_ADDR(addr);
+}
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned short *)PCI_FIX_ADDR(addr);
+}
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned int *)PCI_FIX_ADDR(addr);
+}
+static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
+{
+ *(volatile unsigned char *)PCI_FIX_ADDR(addr) = v;
+}
+static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
+{
+ *(volatile unsigned short *)PCI_FIX_ADDR(addr) = v;
+}
+static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
+{
+ *(volatile unsigned int *)PCI_FIX_ADDR(addr) = v;
+}
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ *
+ * Read operations have additional twi & isync to make sure the read
+ * is actually performed (i.e. the data has come back) before we start
+ * executing any following instructions.
+ */
+extern inline u8 in_8(const volatile unsigned char __iomem *addr)
+{
+ u8 ret;
+
+ __asm__ __volatile__(
+ "sync; lbz%U1%X1 %0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+extern inline void out_8(volatile unsigned char __iomem *addr, u8 val)
+{
+ __asm__ __volatile__("sync;\n"
+ "stb%U0%X0 %1,%0;\n"
+ : "=m" (*addr)
+ : "r" (val));
+}
+
+extern inline u16 in_le16(const volatile unsigned short __iomem *addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("sync; lhbrx %0,0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) :
+ "r" (addr), "m" (*addr));
+ return ret;
+}
+
+extern inline u16 in_be16(const volatile unsigned short __iomem *addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("sync; lhz%U1%X1 %0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+extern inline void out_le16(volatile unsigned short __iomem *addr, u16 val)
+{
+ __asm__ __volatile__("sync; sthbrx %1,0,%2" : "=m" (*addr) :
+ "r" (val), "r" (addr));
+}
+
+extern inline void out_be16(volatile unsigned short __iomem *addr, u16 val)
+{
+ __asm__ __volatile__("sync; sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
+}
+
+extern inline u32 in_le32(const volatile unsigned __iomem *addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("sync; lwbrx %0,0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) :
+ "r" (addr), "m" (*addr));
+ return ret;
+}
+
+extern inline u32 in_be32(const volatile unsigned __iomem *addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("sync; lwz%U1%X1 %0,%1;\n"
+ "twi 0,%0,0;\n"
+ "isync" : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+extern inline void out_le32(volatile unsigned __iomem *addr, u32 val)
+{
+ __asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) :
+ "r" (val), "r" (addr));
+}
+
+extern inline void out_be32(volatile unsigned __iomem *addr, u32 val)
+{
+ __asm__ __volatile__("sync; stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
+}
+
+/* Clear and set bits in one shot. These macros can be used to clear and
+ * set multiple bits in a register using a single call. These macros can
+ * also be used to set a multiple-bit bit pattern using a mask, by
+ * specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+
+#define clrbits(type, addr, clear) \
+ out_##type((addr), in_##type(addr) & ~(clear))
+
+#define setbits(type, addr, set) \
+ out_##type((addr), in_##type(addr) | (set))
+
+#define clrsetbits(type, addr, clear, set) \
+ out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
+
+#define clrbits_be32(addr, clear) clrbits(be32, addr, clear)
+#define setbits_be32(addr, set) setbits(be32, addr, set)
+#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
+
+#define clrbits_le32(addr, clear) clrbits(le32, addr, clear)
+#define setbits_le32(addr, set) setbits(le32, addr, set)
+#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
+
+#define clrbits_be16(addr, clear) clrbits(be16, addr, clear)
+#define setbits_be16(addr, set) setbits(be16, addr, set)
+#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
+
+#define clrbits_le16(addr, clear) clrbits(le16, addr, clear)
+#define setbits_le16(addr, set) setbits(le16, addr, set)
+#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set)
+
+#define clrbits_8(addr, clear) clrbits(8, addr, clear)
+#define setbits_8(addr, set) setbits(8, addr, set)
+#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
+
+/*
+ * Given a physical address and a length, return a virtual address
+ * that can be used to access the memory range with the caching
+ * properties specified by "flags".
+ */
+#define MAP_NOCACHE (0)
+#define MAP_WRCOMBINE (0)
+#define MAP_WRBACK (0)
+#define MAP_WRTHROUGH (0)
+
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+#ifdef CONFIG_ADDR_MAP
+ return addrmap_phys_to_virt(paddr);
+#else
+ return (void *)((unsigned long)paddr);
+#endif
+}
+
+/*
+ * Take down a mapping set up by map_physmem().
+ */
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+
+}
+
+static inline phys_addr_t virt_to_phys(void * vaddr)
+{
+#ifdef CONFIG_ADDR_MAP
+ return addrmap_virt_to_phys(vaddr);
+#else
+ return (phys_addr_t)((unsigned long)vaddr);
+#endif
+}
+
+#endif
diff --git a/arch/powerpc/include/asm/iopin_8260.h b/arch/powerpc/include/asm/iopin_8260.h
new file mode 100644
index 0000000..619f3a8
--- /dev/null
+++ b/arch/powerpc/include/asm/iopin_8260.h
@@ -0,0 +1,168 @@
+/*
+ * MPC8260 I/O port pin manipulation functions
+ */
+
+#ifndef _ASM_IOPIN_8260_H_
+#define _ASM_IOPIN_8260_H_
+
+#include <linux/types.h>
+#include <asm/immap_8260.h>
+
+#ifdef __KERNEL__
+
+typedef
+ struct {
+ u_char port:2; /* port number (A=0, B=1, C=2, D=3) */
+ u_char pin:5; /* port pin (0-31) */
+ u_char flag:1; /* for whatever */
+ }
+iopin_t;
+
+#define IOPIN_PORTA 0
+#define IOPIN_PORTB 1
+#define IOPIN_PORTC 2
+#define IOPIN_PORTD 3
+
+extern __inline__ void
+iopin_set_high(iopin_t *iopin)
+{
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+ datp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_low(iopin_t *iopin)
+{
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+ datp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_high(iopin_t *iopin)
+{
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+ return (datp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_low(iopin_t *iopin)
+{
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdata;
+ return ((datp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_out(iopin_t *iopin)
+{
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+ dirp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_in(iopin_t *iopin)
+{
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+ dirp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_out(iopin_t *iopin)
+{
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+ return (dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_in(iopin_t *iopin)
+{
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdira;
+ return ((dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_odr(iopin_t *iopin)
+{
+ volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+ odrp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_act(iopin_t *iopin)
+{
+ volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+ odrp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_odr(iopin_t *iopin)
+{
+ volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+ return (odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_act(iopin_t *iopin)
+{
+ volatile uint *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_podra;
+ return ((odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_ded(iopin_t *iopin)
+{
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+ parp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_gen(iopin_t *iopin)
+{
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+ parp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_ded(iopin_t *iopin)
+{
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+ return (parp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_gen(iopin_t *iopin)
+{
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_ppara;
+ return ((parp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void
+iopin_set_opt2(iopin_t *iopin)
+{
+ volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+ sorp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void
+iopin_set_opt1(iopin_t *iopin)
+{
+ volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+ sorp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint
+iopin_is_opt2(iopin_t *iopin)
+{
+ volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+ return (sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint
+iopin_is_opt1(iopin_t *iopin)
+{
+ volatile uint *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_psora;
+ return ((sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IOPIN_8260_H_ */
diff --git a/arch/powerpc/include/asm/iopin_85xx.h b/arch/powerpc/include/asm/iopin_85xx.h
new file mode 100644
index 0000000..0f07ba3
--- /dev/null
+++ b/arch/powerpc/include/asm/iopin_85xx.h
@@ -0,0 +1,146 @@
+/*
+ * MPC85xx I/O port pin manipulation functions
+ */
+
+#ifndef _ASM_IOPIN_85xx_H_
+#define _ASM_IOPIN_85xx_H_
+
+#include <linux/types.h>
+#include <asm/immap_85xx.h>
+
+#ifdef __KERNEL__
+
+typedef struct {
+ u_char port:2; /* port number (A=0, B=1, C=2, D=3) */
+ u_char pin:5; /* port pin (0-31) */
+ u_char flag:1; /* for whatever */
+} iopin_t;
+
+#define IOPIN_PORTA 0
+#define IOPIN_PORTB 1
+#define IOPIN_PORTC 2
+#define IOPIN_PORTD 3
+
+extern __inline__ void iopin_set_high (iopin_t * iopin)
+{
+ volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+ datp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_low (iopin_t * iopin)
+{
+ volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+ datp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_high (iopin_t * iopin)
+{
+ volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+ return (datp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_low (iopin_t * iopin)
+{
+ volatile uint *datp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdata;
+ return ((datp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_out (iopin_t * iopin)
+{
+ volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+ dirp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_in (iopin_t * iopin)
+{
+ volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+ dirp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_out (iopin_t * iopin)
+{
+ volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+ return (dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_in (iopin_t * iopin)
+{
+ volatile uint *dirp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.pdira;
+ return ((dirp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_odr (iopin_t * iopin)
+{
+ volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+ odrp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_act (iopin_t * iopin)
+{
+ volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+ odrp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_odr (iopin_t * iopin)
+{
+ volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+ return (odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_act (iopin_t * iopin)
+{
+ volatile uint *odrp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.podra;
+ return ((odrp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_ded (iopin_t * iopin)
+{
+ volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+ parp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_gen (iopin_t * iopin)
+{
+ volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+ parp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_ded (iopin_t * iopin)
+{
+ volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+ return (parp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_gen (iopin_t * iopin)
+{
+ volatile uint *parp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.ppara;
+ return ((parp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+extern __inline__ void iopin_set_opt2 (iopin_t * iopin)
+{
+ volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+ sorp[iopin->port * 8] |= (1 << (31 - iopin->pin));
+}
+
+extern __inline__ void iopin_set_opt1 (iopin_t * iopin)
+{
+ volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+ sorp[iopin->port * 8] &= ~(1 << (31 - iopin->pin));
+}
+
+extern __inline__ uint iopin_is_opt2 (iopin_t * iopin)
+{
+ volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+ return (sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1;
+}
+
+extern __inline__ uint iopin_is_opt1 (iopin_t * iopin)
+{
+ volatile uint *sorp = &((ccsr_cpm_t *) CONFIG_SYS_MPC85xx_CPM_ADDR)->im_cpm_iop.psora;
+ return ((sorp[iopin->port * 8] >> (31 - iopin->pin)) & 1) ^ 1;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IOPIN_85xx_H_ */
diff --git a/arch/powerpc/include/asm/iopin_8xx.h b/arch/powerpc/include/asm/iopin_8xx.h
new file mode 100644
index 0000000..3a2a682
--- /dev/null
+++ b/arch/powerpc/include/asm/iopin_8xx.h
@@ -0,0 +1,395 @@
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8xx I/O port pin manipulation functions
+ * Roughly based on iopin_8260.h
+ */
+
+#ifndef _ASM_IOPIN_8XX_H_
+#define _ASM_IOPIN_8XX_H_
+
+#include <linux/types.h>
+#include <asm/8xx_immap.h>
+
+#ifdef __KERNEL__
+
+typedef struct {
+ u_char port:2; /* port number (A=0, B=1, C=2, D=3) */
+ u_char pin:5; /* port pin (0-31) */
+ u_char flag:1; /* for whatever */
+} iopin_t;
+
+#define IOPIN_PORTA 0
+#define IOPIN_PORTB 1
+#define IOPIN_PORTC 2
+#define IOPIN_PORTD 3
+
+extern __inline__ void
+iopin_set_high(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+ *datp |= (1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+ *datp |= (1 << (31 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+ *datp |= (1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+ *datp |= (1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ void
+iopin_set_low(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+ *datp &= ~(1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+ *datp &= ~(1 << (31 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+ *datp &= ~(1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+ *datp &= ~(1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ uint
+iopin_is_high(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+ return (*datp >> (15 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+ return (*datp >> (31 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+ return (*datp >> (15 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+ return (*datp >> (15 - iopin->pin)) & 1;
+ }
+ return 0;
+}
+
+extern __inline__ uint
+iopin_is_low(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padat;
+ return ((*datp >> (15 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdat;
+ return ((*datp >> (31 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdat;
+ return ((*datp >> (15 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *datp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat;
+ return ((*datp >> (15 - iopin->pin)) & 1) ^ 1;
+ }
+ return 0;
+}
+
+extern __inline__ void
+iopin_set_out(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+ *dirp |= (1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+ *dirp |= (1 << (31 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+ *dirp |= (1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+ *dirp |= (1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ void
+iopin_set_in(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+ *dirp &= ~(1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+ *dirp &= ~(1 << (31 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+ *dirp &= ~(1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+ *dirp &= ~(1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ uint
+iopin_is_out(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+ return (*dirp >> (15 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+ return (*dirp >> (31 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+ return (*dirp >> (15 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+ return (*dirp >> (15 - iopin->pin)) & 1;
+ }
+ return 0;
+}
+
+extern __inline__ uint
+iopin_is_in(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_padir;
+ return ((*dirp >> (15 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbdir;
+ return ((*dirp >> (31 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcdir;
+ return ((*dirp >> (15 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *dirp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir;
+ return ((*dirp >> (15 - iopin->pin)) & 1) ^ 1;
+ }
+ return 0;
+}
+
+extern __inline__ void
+iopin_set_odr(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+ *odrp |= (1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+ *odrp |= (1 << (31 - iopin->pin));
+ }
+}
+
+extern __inline__ void
+iopin_set_act(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+ *odrp &= ~(1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+ *odrp &= ~(1 << (31 - iopin->pin));
+ }
+}
+
+extern __inline__ uint
+iopin_is_odr(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+ return (*odrp >> (15 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+ return (*odrp >> (31 - iopin->pin)) & 1;
+ }
+ return 0;
+}
+
+extern __inline__ uint
+iopin_is_act(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_paodr;
+ return ((*odrp >> (15 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile ushort *odrp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbodr;
+ return ((*odrp >> (31 - iopin->pin)) & 1) ^ 1;
+ }
+ return 0;
+}
+
+extern __inline__ void
+iopin_set_ded(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+ *parp |= (1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+ *parp |= (1 << (31 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+ *parp |= (1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+ *parp |= (1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ void
+iopin_set_gen(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+ *parp &= ~(1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+ *parp &= ~(1 << (31 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+ *parp &= ~(1 << (15 - iopin->pin));
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+ *parp &= ~(1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ uint
+iopin_is_ded(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+ return (*parp >> (15 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+ return (*parp >> (31 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+ return (*parp >> (15 - iopin->pin)) & 1;
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+ return (*parp >> (15 - iopin->pin)) & 1;
+ }
+ return 0;
+}
+
+extern __inline__ uint
+iopin_is_gen(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTA) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_papar;
+ return ((*parp >> (15 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTB) {
+ volatile uint *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_cpm.cp_pbpar;
+ return ((*parp >> (31 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcpar;
+ return ((*parp >> (15 - iopin->pin)) & 1) ^ 1;
+ } else if (iopin->port == IOPIN_PORTD) {
+ volatile ushort *parp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar;
+ return ((*parp >> (15 - iopin->pin)) & 1) ^ 1;
+ }
+ return 0;
+}
+
+extern __inline__ void
+iopin_set_opt2(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+ *sorp |= (1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ void
+iopin_set_opt1(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+ *sorp &= ~(1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ uint
+iopin_is_opt2(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+ return (*sorp >> (15 - iopin->pin)) & 1;
+ }
+ return 0;
+}
+
+extern __inline__ uint
+iopin_is_opt1(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *sorp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcso;
+ return ((*sorp >> (15 - iopin->pin)) & 1) ^ 1;
+ }
+ return 0;
+}
+
+extern __inline__ void
+iopin_set_falledge(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+ *intp |= (1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ void
+iopin_set_anyedge(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+ *intp &= ~(1 << (15 - iopin->pin));
+ }
+}
+
+extern __inline__ uint
+iopin_is_falledge(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+ return (*intp >> (15 - iopin->pin)) & 1;
+ }
+ return 0;
+}
+
+extern __inline__ uint
+iopin_is_anyedge(iopin_t *iopin)
+{
+ if (iopin->port == IOPIN_PORTC) {
+ volatile ushort *intp = &((immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pcint;
+ return ((*intp >> (15 - iopin->pin)) & 1) ^ 1;
+ }
+ return 0;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IOPIN_8XX_H_ */
diff --git a/arch/powerpc/include/asm/m8260_pci.h b/arch/powerpc/include/asm/m8260_pci.h
new file mode 100644
index 0000000..45f01de
--- /dev/null
+++ b/arch/powerpc/include/asm/m8260_pci.h
@@ -0,0 +1,166 @@
+
+#ifndef _PPC_KERNEL_M8260_PCI_H
+#define _PPC_KERNEL_M8260_PCI_H
+
+#define M8265_PCIBR0 0x101ac
+#define M8265_PCIBR1 0x101b0
+#define M8265_PCIMSK0 0x101c4
+#define M8265_PCIMSK1 0x101c8
+
+/* Bit definitions for PCIBR registers */
+
+#define PCIBR_ENABLE 0x00000001
+
+/* Bit definitions for PCIMSK registers */
+
+#define PCIMSK_32KB 0xFFFF8000 /* Size of window, smallest */
+#define PCIMSK_64KB 0xFFFF0000
+#define PCIMSK_128KB 0xFFFE0000
+#define PCIMSK_256KB 0xFFFC0000
+#define PCIMSK_512KB 0xFFF80000
+#define PCIMSK_1MB 0xFFF00000
+#define PCIMSK_2MB 0xFFE00000
+#define PCIMSK_4MB 0xFFC00000
+#define PCIMSK_8MB 0xFF800000
+#define PCIMSK_16MB 0xFF000000
+#define PCIMSK_32MB 0xFE000000
+#define PCIMSK_64MB 0xFC000000
+#define PCIMSK_128MB 0xF8000000
+#define PCIMSK_256MB 0xF0000000
+#define PCIMSK_512MB 0xE0000000
+#define PCIMSK_1GB 0xC0000000 /* Size of window, largest */
+
+
+#define M826X_SCCR_PCI_MODE_EN 0x100
+
+
+/*
+ * Outbound ATU registers (3 sets). These registers control how 60x bus (local)
+ * addresses are translated to PCI addresses when the MPC826x is a PCI bus
+ * master (initiator).
+ */
+
+#define POTAR_REG0 0x10800 /* PCI Outbound Translation Addr registers */
+#define POTAR_REG1 0x10818
+#define POTAR_REG2 0x10830
+
+#define POBAR_REG0 0x10808 /* PCI Outbound Base Addr registers */
+#define POBAR_REG1 0x10820
+#define POBAR_REG2 0x10838
+
+#define POCMR_REG0 0x10810 /* PCI Outbound Comparison Mask registers */
+#define POCMR_REG1 0x10828
+#define POCMR_REG2 0x10840
+
+/* Bit definitions for POMCR registers */
+
+#define POCMR_MASK_4KB 0x000FFFFF
+#define POCMR_MASK_8KB 0x000FFFFE
+#define POCMR_MASK_16KB 0x000FFFFC
+#define POCMR_MASK_32KB 0x000FFFF8
+#define POCMR_MASK_64KB 0x000FFFF0
+#define POCMR_MASK_128KB 0x000FFFE0
+#define POCMR_MASK_256KB 0x000FFFC0
+#define POCMR_MASK_512KB 0x000FFF80
+#define POCMR_MASK_1MB 0x000FFF00
+#define POCMR_MASK_2MB 0x000FFE00
+#define POCMR_MASK_4MB 0x000FFC00
+#define POCMR_MASK_8MB 0x000FF800
+#define POCMR_MASK_16MB 0x000FF000
+#define POCMR_MASK_32MB 0x000FE000
+#define POCMR_MASK_64MB 0x000FC000
+#define POCMR_MASK_128MB 0x000F8000
+#define POCMR_MASK_256MB 0x000F0000
+#define POCMR_MASK_512MB 0x000E0000
+#define POCMR_MASK_1GB 0x000C0000
+
+#define POCMR_ENABLE 0x80000000
+#define POCMR_PCI_IO 0x40000000
+#define POCMR_PREFETCH_EN 0x20000000
+
+/* Soft PCI reset */
+
+#define PCI_GCR_REG 0x10880
+
+/* Bit definitions for PCI_GCR registers */
+
+#define PCIGCR_PCI_BUS_EN 0x1
+
+/*
+ * Inbound ATU registers (2 sets). These registers control how PCI addresses
+ * are translated to 60x bus (local) addresses when the MPC826x is a PCI bus target.
+ */
+
+#define PITAR_REG1 0x108D0
+#define PIBAR_REG1 0x108D8
+#define PICMR_REG1 0x108E0
+#define PITAR_REG0 0x108E8
+#define PIBAR_REG0 0x108F0
+#define PICMR_REG0 0x108F8
+
+/* Bit definitions for PCI Inbound Comparison Mask registers */
+
+#define PICMR_MASK_4KB 0x000FFFFF
+#define PICMR_MASK_8KB 0x000FFFFE
+#define PICMR_MASK_16KB 0x000FFFFC
+#define PICMR_MASK_32KB 0x000FFFF8
+#define PICMR_MASK_64KB 0x000FFFF0
+#define PICMR_MASK_128KB 0x000FFFE0
+#define PICMR_MASK_256KB 0x000FFFC0
+#define PICMR_MASK_512KB 0x000FFF80
+#define PICMR_MASK_1MB 0x000FFF00
+#define PICMR_MASK_2MB 0x000FFE00
+#define PICMR_MASK_4MB 0x000FFC00
+#define PICMR_MASK_8MB 0x000FF800
+#define PICMR_MASK_16MB 0x000FF000
+#define PICMR_MASK_32MB 0x000FE000
+#define PICMR_MASK_64MB 0x000FC000
+#define PICMR_MASK_128MB 0x000F8000
+#define PICMR_MASK_256MB 0x000F0000
+#define PICMR_MASK_512MB 0x000E0000
+#define PICMR_MASK_1GB 0x000C0000
+
+#define PICMR_ENABLE 0x80000000
+#define PICMR_NO_SNOOP_EN 0x40000000
+#define PICMR_PREFETCH_EN 0x20000000
+
+/* PCI error Registers */
+
+#define PCI_ERROR_STATUS_REG 0x10884
+#define PCI_ERROR_MASK_REG 0x10888
+#define PCI_ERROR_CONTROL_REG 0x1088C
+#define PCI_ERROR_ADRS_CAPTURE_REG 0x10890
+#define PCI_ERROR_DATA_CAPTURE_REG 0x10898
+#define PCI_ERROR_CTRL_CAPTURE_REG 0x108A0
+
+/* PCI error Register bit defines */
+
+#define PCI_ERROR_PCI_ADDR_PAR 0x00000001
+#define PCI_ERROR_PCI_DATA_PAR_WR 0x00000002
+#define PCI_ERROR_PCI_DATA_PAR_RD 0x00000004
+#define PCI_ERROR_PCI_NO_RSP 0x00000008
+#define PCI_ERROR_PCI_TAR_ABT 0x00000010
+#define PCI_ERROR_PCI_SERR 0x00000020
+#define PCI_ERROR_PCI_PERR_RD 0x00000040
+#define PCI_ERROR_PCI_PERR_WR 0x00000080
+#define PCI_ERROR_I2O_OFQO 0x00000100
+#define PCI_ERROR_I2O_IPQO 0x00000200
+#define PCI_ERROR_IRA 0x00000400
+#define PCI_ERROR_NMI 0x00000800
+#define PCI_ERROR_I2O_DBMC 0x00001000
+
+/*
+ * Register pair used to generate configuration cycles on the PCI bus
+ * and access the MPC826x's own PCI configuration registers.
+ */
+
+#define PCI_CFG_ADDR_REG 0x10900
+#define PCI_CFG_DATA_REG 0x10904
+
+/* Bus parking decides where the bus control sits when idle */
+/* If modifying memory controllers for PCI park on the core */
+
+#define PPC_ACR_BUS_PARK_CORE 0x6
+#define PPC_ACR_BUS_PARK_PCI 0x3
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/powerpc/include/asm/mc146818rtc.h b/arch/powerpc/include/asm/mc146818rtc.h
new file mode 100644
index 0000000..5f806c4
--- /dev/null
+++ b/arch/powerpc/include/asm/mc146818rtc.h
@@ -0,0 +1,27 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_PPC_MC146818RTC_H
+#define __ASM_PPC_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#endif /* __ASM_PPC_MC146818RTC_H */
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
new file mode 100644
index 0000000..b700a3a
--- /dev/null
+++ b/arch/powerpc/include/asm/mmu.h
@@ -0,0 +1,791 @@
+/*
+ * PowerPC memory management structures
+ */
+
+#ifndef _PPC_MMU_H_
+#define _PPC_MMU_H_
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* Hardware Page Table Entry */
+typedef struct _PTE {
+#ifdef CONFIG_PPC64BRIDGE
+ unsigned long long vsid:52;
+ unsigned long api:5;
+ unsigned long :5;
+ unsigned long h:1;
+ unsigned long v:1;
+ unsigned long long rpn:52;
+#else /* CONFIG_PPC64BRIDGE */
+ unsigned long v:1; /* Entry is valid */
+ unsigned long vsid:24; /* Virtual segment identifier */
+ unsigned long h:1; /* Hash algorithm indicator */
+ unsigned long api:6; /* Abbreviated page index */
+ unsigned long rpn:20; /* Real (physical) page number */
+#endif /* CONFIG_PPC64BRIDGE */
+ unsigned long :3; /* Unused */
+ unsigned long r:1; /* Referenced */
+ unsigned long c:1; /* Changed */
+ unsigned long w:1; /* Write-thru cache mode */
+ unsigned long i:1; /* Cache inhibited */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page protection */
+} PTE;
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX 0 /* Supervisor read/write, User none */
+#define PP_RWRX 1 /* Supervisor read/write, User read */
+#define PP_RWRW 2 /* Supervisor read/write, User read/write */
+#define PP_RXRX 3 /* Supervisor read, User read */
+
+/* Segment Register */
+typedef struct _SEGREG {
+ unsigned long t:1; /* Normal or I/O type */
+ unsigned long ks:1; /* Supervisor 'key' (normally 0) */
+ unsigned long kp:1; /* User 'key' (normally 1) */
+ unsigned long n:1; /* No-execute */
+ unsigned long :4; /* Unused */
+ unsigned long vsid:24; /* Virtual Segment Identifier */
+} SEGREG;
+
+/* Block Address Translation (BAT) Registers */
+typedef struct _P601_BATU { /* Upper part of BAT for 601 processor */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+ unsigned long :8; /* unused */
+ unsigned long w:1;
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long ks:1; /* Supervisor key (normally 0) */
+ unsigned long kp:1; /* User key (normally 1) */
+ unsigned long pp:2; /* Page access protections */
+} P601_BATU;
+
+typedef struct _BATU { /* Upper part of BAT (all except 601) */
+#ifdef CONFIG_PPC64BRIDGE
+ unsigned long long bepi:47;
+#else /* CONFIG_PPC64BRIDGE */
+ unsigned long bepi:15; /* Effective page index (virtual address) */
+#endif /* CONFIG_PPC64BRIDGE */
+ unsigned long :4; /* Unused */
+ unsigned long bl:11; /* Block size mask */
+ unsigned long vs:1; /* Supervisor valid */
+ unsigned long vp:1; /* User valid */
+} BATU;
+
+typedef struct _P601_BATL { /* Lower part of BAT for 601 processor */
+ unsigned long brpn:15; /* Real page index (physical address) */
+ unsigned long :10; /* Unused */
+ unsigned long v:1; /* Valid bit */
+ unsigned long bl:6; /* Block size mask */
+} P601_BATL;
+
+typedef struct _BATL { /* Lower part of BAT (all except 601) */
+#ifdef CONFIG_PPC64BRIDGE
+ unsigned long long brpn:47;
+#else /* CONFIG_PPC64BRIDGE */
+ unsigned long brpn:15; /* Real page index (physical address) */
+#endif /* CONFIG_PPC64BRIDGE */
+ unsigned long :10; /* Unused */
+ unsigned long w:1; /* Write-thru cache */
+ unsigned long i:1; /* Cache inhibit */
+ unsigned long m:1; /* Memory coherence */
+ unsigned long g:1; /* Guarded (MBZ in IBAT) */
+ unsigned long :1; /* Unused */
+ unsigned long pp:2; /* Page access protections */
+} BATL;
+
+typedef struct _BAT {
+ BATU batu; /* Upper register */
+ BATL batl; /* Lower register */
+} BAT;
+
+typedef struct _P601_BAT {
+ P601_BATU batu; /* Upper register */
+ P601_BATL batl; /* Lower register */
+} P601_BAT;
+
+/*
+ * Simulated two-level MMU. This structure is used by the kernel
+ * to keep track of MMU mappings and is used to update/maintain
+ * the hardware HASH table which is really a cache of mappings.
+ *
+ * The simulated structures mimic the hardware available on other
+ * platforms, notably the 80x86 and 680x0.
+ */
+
+typedef struct _pte {
+ unsigned long page_num:20;
+ unsigned long flags:12; /* Page flags (some unused bits) */
+} pte;
+
+#define PD_SHIFT (10+12) /* Page directory */
+#define PD_MASK 0x02FF
+#define PT_SHIFT (12) /* Page Table */
+#define PT_MASK 0x02FF
+#define PG_SHIFT (12) /* Page Entry */
+
+
+/* MMU context */
+
+typedef struct _MMU_context {
+ SEGREG segs[16]; /* Segment registers */
+ pte **pmap; /* Two-level page-map structure */
+} MMU_context;
+
+extern void _tlbie(unsigned long va); /* invalidate a TLB entry */
+extern void _tlbia(void); /* invalidate all TLB entries */
+
+#ifdef CONFIG_ADDR_MAP
+extern void init_addr_map(void);
+#endif
+
+typedef enum {
+ IBAT0 = 0, IBAT1, IBAT2, IBAT3,
+ DBAT0, DBAT1, DBAT2, DBAT3,
+#ifdef CONFIG_HIGH_BATS
+ IBAT4, IBAT5, IBAT6, IBAT7,
+ DBAT4, DBAT5, DBAT6, DBAT7
+#endif
+} ppc_bat_t;
+
+extern int read_bat(ppc_bat_t bat, unsigned long *upper, unsigned long *lower);
+extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower);
+extern void print_bats(void);
+
+#endif /* __ASSEMBLY__ */
+
+#define BATU_VS 0x00000002
+#define BATU_VP 0x00000001
+#define BATU_INVALID 0x00000000
+
+#define BATL_WRITETHROUGH 0x00000040
+#define BATL_CACHEINHIBIT 0x00000020
+#define BATL_MEMCOHERENCE 0x00000010
+#define BATL_GUARDEDSTORAGE 0x00000008
+#define BATL_NO_ACCESS 0x00000000
+
+#define BATL_PP_MSK 0x00000003
+#define BATL_PP_00 0x00000000 /* No access */
+#define BATL_PP_01 0x00000001 /* Read-only */
+#define BATL_PP_10 0x00000002 /* Read-write */
+#define BATL_PP_11 0x00000003
+
+#define BATL_PP_NO_ACCESS BATL_PP_00
+#define BATL_PP_RO BATL_PP_01
+#define BATL_PP_RW BATL_PP_10
+
+/* BAT Block size values */
+#define BATU_BL_128K 0x00000000
+#define BATU_BL_256K 0x00000004
+#define BATU_BL_512K 0x0000000c
+#define BATU_BL_1M 0x0000001c
+#define BATU_BL_2M 0x0000003c
+#define BATU_BL_4M 0x0000007c
+#define BATU_BL_8M 0x000000fc
+#define BATU_BL_16M 0x000001fc
+#define BATU_BL_32M 0x000003fc
+#define BATU_BL_64M 0x000007fc
+#define BATU_BL_128M 0x00000ffc
+#define BATU_BL_256M 0x00001ffc
+
+/* Block lengths for processors that support extended block length */
+#ifdef HID0_XBSEN
+#define BATU_BL_512M 0x00003ffc
+#define BATU_BL_1G 0x00007ffc
+#define BATU_BL_2G 0x0000fffc
+#define BATU_BL_4G 0x0001fffc
+#define BATU_BL_MAX BATU_BL_4G
+#else
+#define BATU_BL_MAX BATU_BL_256M
+#endif
+
+/* BAT Access Protection */
+#define BPP_XX 0x00 /* No access */
+#define BPP_RX 0x01 /* Read only */
+#define BPP_RW 0x02 /* Read/write */
+
+/* Macros to get values from BATs, once data is in the BAT register format */
+#define BATU_VALID(x) (x & 0x3)
+#define BATU_VADDR(x) (x & 0xfffe0000)
+#define BATL_PADDR(x) ((phys_addr_t)((x & 0xfffe0000) \
+ | ((x & 0x0e00ULL) << 24) \
+ | ((x & 0x04ULL) << 30)))
+#define BATU_SIZE(x) (1ULL << (fls((x & BATU_BL_MAX) >> 2) + 17))
+
+/* bytes into BATU_BL */
+#define TO_BATU_BL(x) \
+ (u32)((((1ull << __ilog2_u64((u64)x)) / (128 * 1024)) - 1) * 4)
+
+/* Used to set up SDR1 register */
+#define HASH_TABLE_SIZE_64K 0x00010000
+#define HASH_TABLE_SIZE_128K 0x00020000
+#define HASH_TABLE_SIZE_256K 0x00040000
+#define HASH_TABLE_SIZE_512K 0x00080000
+#define HASH_TABLE_SIZE_1M 0x00100000
+#define HASH_TABLE_SIZE_2M 0x00200000
+#define HASH_TABLE_SIZE_4M 0x00400000
+#define HASH_TABLE_MASK_64K 0x000
+#define HASH_TABLE_MASK_128K 0x001
+#define HASH_TABLE_MASK_256K 0x003
+#define HASH_TABLE_MASK_512K 0x007
+#define HASH_TABLE_MASK_1M 0x00F
+#define HASH_TABLE_MASK_2M 0x01F
+#define HASH_TABLE_MASK_4M 0x03F
+
+/* Control/status registers for the MPC8xx.
+ * A write operation to these registers causes serialized access.
+ * During software tablewalk, the registers used perform mask/shift-add
+ * operations when written/read. A TLB entry is created when the Mx_RPN
+ * is written, and the contents of several registers are used to
+ * create the entry.
+ */
+#define MI_CTR 784 /* Instruction TLB control register */
+#define MI_GPM 0x80000000 /* Set domain manager mode */
+#define MI_PPM 0x40000000 /* Set subpage protection */
+#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */
+#define MI_RESETVAL 0x00000000 /* Value of register at reset */
+
+/* These are the Ks and Kp from the PowerPC books. For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define MI_AP 786
+#define MI_Ks 0x80000000 /* Should not be set */
+#define MI_Kp 0x40000000 /* Should always be set */
+
+/* The effective page number register. When read, contains the information
+ * about the last instruction TLB miss. When MI_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define MI_EPN 787
+#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */
+#define MI_EVALID 0x00000200 /* Entry is valid */
+#define MI_ASIDMASK 0x0000000f /* ASID match value */
+ /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the instruction TLB, it contains bits that get loaded into the
+ * TLB entry when the MI_RPN is written.
+ */
+#define MI_TWC 789
+#define MI_APG 0x000001e0 /* Access protection group (0) */
+#define MI_GUARDED 0x00000010 /* Guarded storage */
+#define MI_PSMASK 0x0000000c /* Mask of page size bits */
+#define MI_PS8MEG 0x0000000c /* 8M page size */
+#define MI_PS512K 0x00000004 /* 512K page size */
+#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */
+#define MI_SVALID 0x00000001 /* Segment entry is valid */
+ /* Reset value is undefined */
+
+/* Real page number. Defined by the pte. Writing this register
+ * causes a TLB entry to be created for the instruction TLB, using
+ * additional information from the MI_EPN, and MI_TWC registers.
+ */
+#define MI_RPN 790
+
+/* Define an RPN value for mapping kernel memory to large virtual
+ * pages for boot initialization. This has real page number of 0,
+ * large page size, shared page, cache enabled, and valid.
+ * Also mark all subpages valid and write access.
+ */
+#define MI_BOOTINIT 0x000001fd
+
+#define MD_CTR 792 /* Data TLB control register */
+#define MD_GPM 0x80000000 /* Set domain manager mode */
+#define MD_PPM 0x40000000 /* Set subpage protection */
+#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */
+#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */
+#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */
+#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */
+#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */
+#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */
+#define MD_RESETVAL 0x04000000 /* Value of register at reset */
+
+#define M_CASID 793 /* Address space ID (context) to match */
+#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */
+
+
+/* These are the Ks and Kp from the PowerPC books. For proper operation,
+ * Ks = 0, Kp = 1.
+ */
+#define MD_AP 794
+#define MD_Ks 0x80000000 /* Should not be set */
+#define MD_Kp 0x40000000 /* Should always be set */
+
+/* The effective page number register. When read, contains the information
+ * about the last instruction TLB miss. When MD_RPN is written, bits in
+ * this register are used to create the TLB entry.
+ */
+#define MD_EPN 795
+#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */
+#define MD_EVALID 0x00000200 /* Entry is valid */
+#define MD_ASIDMASK 0x0000000f /* ASID match value */
+ /* Reset value is undefined */
+
+/* The pointer to the base address of the first level page table.
+ * During a software tablewalk, reading this register provides the address
+ * of the entry associated with MD_EPN.
+ */
+#define M_TWB 796
+#define M_L1TB 0xfffff000 /* Level 1 table base address */
+#define M_L1INDX 0x00000ffc /* Level 1 index, when read */
+ /* Reset value is undefined */
+
+/* A "level 1" or "segment" or whatever you want to call it register.
+ * For the data TLB, it contains bits that get loaded into the TLB entry
+ * when the MD_RPN is written. It is also provides the hardware assist
+ * for finding the PTE address during software tablewalk.
+ */
+#define MD_TWC 797
+#define MD_L2TB 0xfffff000 /* Level 2 table base address */
+#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */
+#define MD_APG 0x000001e0 /* Access protection group (0) */
+#define MD_GUARDED 0x00000010 /* Guarded storage */
+#define MD_PSMASK 0x0000000c /* Mask of page size bits */
+#define MD_PS8MEG 0x0000000c /* 8M page size */
+#define MD_PS512K 0x00000004 /* 512K page size */
+#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */
+#define MD_WT 0x00000002 /* Use writethrough page attribute */
+#define MD_SVALID 0x00000001 /* Segment entry is valid */
+ /* Reset value is undefined */
+
+
+/* Real page number. Defined by the pte. Writing this register
+ * causes a TLB entry to be created for the data TLB, using
+ * additional information from the MD_EPN, and MD_TWC registers.
+ */
+#define MD_RPN 798
+
+/* This is a temporary storage register that could be used to save
+ * a processor working register during a tablewalk.
+ */
+#define M_TW 799
+
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified,
+ * 64-entry, fully-associative TLB which is maintained totally under
+ * software control. In addition, the instruction side has a
+ * hardware-managed, 4-entry, fully- associative TLB which serves as a
+ * first level to the shared TLB. These two TLBs are known as the UTLB
+ * and ITLB, respectively.
+ */
+
+#define PPC4XX_TLB_SIZE 64
+
+/*
+ * TLB entries are defined by a "high" tag portion and a "low" data
+ * portion. On all architectures, the data portion is 32-bits.
+ *
+ * TLB entries are managed entirely under software control by reading,
+ * writing, and searchoing using the 4xx-specific tlbre, tlbwr, and tlbsx
+ * instructions.
+ */
+
+/*
+ * FSL Book-E support
+ */
+
+#define MAS0_TLBSEL_MSK 0x30000000
+#define MAS0_TLBSEL(x) (((x) << 28) & MAS0_TLBSEL_MSK)
+#define MAS0_ESEL_MSK 0x0FFF0000
+#define MAS0_ESEL(x) (((x) << 16) & MAS0_ESEL_MSK)
+#define MAS0_NV(x) ((x) & 0x00000FFF)
+
+#define MAS1_VALID 0x80000000
+#define MAS1_IPROT 0x40000000
+#define MAS1_TID(x) (((x) << 16) & 0x3FFF0000)
+#define MAS1_TS 0x00001000
+#define MAS1_TSIZE(x) (((x) << 7) & 0x00000F80)
+#define TSIZE_TO_BYTES(x) (1ULL << ((x) + 10))
+
+#define MAS2_EPN 0xFFFFF000
+#define MAS2_X0 0x00000040
+#define MAS2_X1 0x00000020
+#define MAS2_W 0x00000010
+#define MAS2_I 0x00000008
+#define MAS2_M 0x00000004
+#define MAS2_G 0x00000002
+#define MAS2_E 0x00000001
+
+#define MAS3_RPN 0xFFFFF000
+#define MAS3_U0 0x00000200
+#define MAS3_U1 0x00000100
+#define MAS3_U2 0x00000080
+#define MAS3_U3 0x00000040
+#define MAS3_UX 0x00000020
+#define MAS3_SX 0x00000010
+#define MAS3_UW 0x00000008
+#define MAS3_SW 0x00000004
+#define MAS3_UR 0x00000002
+#define MAS3_SR 0x00000001
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_TIDDSEL 0x000F0000
+#define MAS4_TSIZED(x) MAS1_TSIZE(x)
+#define MAS4_X0D 0x00000040
+#define MAS4_X1D 0x00000020
+#define MAS4_WD 0x00000010
+#define MAS4_ID 0x00000008
+#define MAS4_MD 0x00000004
+#define MAS4_GD 0x00000002
+#define MAS4_ED 0x00000001
+
+#define MAS6_SPID0 0x3FFF0000
+#define MAS6_SPID1 0x00007FFE
+#define MAS6_SAS 0x00000001
+#define MAS6_SPID MAS6_SPID0
+
+#define MAS7_RPN 0xFFFFFFFF
+
+#define FSL_BOOKE_MAS0(tlbsel,esel,nv) \
+ (MAS0_TLBSEL(tlbsel) | MAS0_ESEL(esel) | MAS0_NV(nv))
+#define FSL_BOOKE_MAS1(v,iprot,tid,ts,tsize) \
+ ((((v) << 31) & MAS1_VALID) |\
+ (((iprot) << 30) & MAS1_IPROT) |\
+ (MAS1_TID(tid)) |\
+ (((ts) << 12) & MAS1_TS) |\
+ (MAS1_TSIZE(tsize)))
+#define FSL_BOOKE_MAS2(epn, wimge) \
+ (((epn) & MAS3_RPN) | (wimge))
+#define FSL_BOOKE_MAS3(rpn, user, perms) \
+ (((rpn) & MAS3_RPN) | (user) | (perms))
+#define FSL_BOOKE_MAS7(rpn) \
+ (((u64)(rpn)) >> 32)
+
+#define BOOKE_PAGESZ_1K 0
+#define BOOKE_PAGESZ_2K 1
+#define BOOKE_PAGESZ_4K 2
+#define BOOKE_PAGESZ_8K 3
+#define BOOKE_PAGESZ_16K 4
+#define BOOKE_PAGESZ_32K 5
+#define BOOKE_PAGESZ_64K 6
+#define BOOKE_PAGESZ_128K 7
+#define BOOKE_PAGESZ_256K 8
+#define BOOKE_PAGESZ_512K 9
+#define BOOKE_PAGESZ_1M 10
+#define BOOKE_PAGESZ_2M 11
+#define BOOKE_PAGESZ_4M 12
+#define BOOKE_PAGESZ_8M 13
+#define BOOKE_PAGESZ_16M 14
+#define BOOKE_PAGESZ_32M 15
+#define BOOKE_PAGESZ_64M 16
+#define BOOKE_PAGESZ_128M 17
+#define BOOKE_PAGESZ_256M 18
+#define BOOKE_PAGESZ_512M 19
+#define BOOKE_PAGESZ_1G 20
+#define BOOKE_PAGESZ_2G 21
+#define BOOKE_PAGESZ_4G 22
+#define BOOKE_PAGESZ_8G 23
+#define BOOKE_PAGESZ_16GB 24
+#define BOOKE_PAGESZ_32GB 25
+#define BOOKE_PAGESZ_64GB 26
+#define BOOKE_PAGESZ_128GB 27
+#define BOOKE_PAGESZ_256GB 28
+#define BOOKE_PAGESZ_512GB 29
+#define BOOKE_PAGESZ_1TB 30
+#define BOOKE_PAGESZ_2TB 31
+
+#define TLBIVAX_ALL 4
+#define TLBIVAX_TLB0 0
+#define TLBIVAX_TLB1 8
+
+#ifdef CONFIG_E500
+#ifndef __ASSEMBLY__
+extern void set_tlb(u8 tlb, u32 epn, u64 rpn,
+ u8 perms, u8 wimge,
+ u8 ts, u8 esel, u8 tsize, u8 iprot);
+extern void disable_tlb(u8 esel);
+extern void invalidate_tlb(u8 tlb);
+extern void init_tlbs(void);
+extern int find_tlb_idx(void *addr, u8 tlbsel);
+extern void init_used_tlb_cams(void);
+extern int find_free_tlbcam(void);
+extern void print_tlbcam(void);
+
+extern unsigned int setup_ddr_tlbs(unsigned int memsize_in_meg);
+extern void clear_ddr_tlbs(unsigned int memsize_in_meg);
+
+extern void write_tlb(u32 _mas0, u32 _mas1, u32 _mas2, u32 _mas3, u32 _mas7);
+
+#define SET_TLB_ENTRY(_tlb, _epn, _rpn, _perms, _wimge, _ts, _esel, _sz, _iprot) \
+ { .mas0 = FSL_BOOKE_MAS0(_tlb, _esel, 0), \
+ .mas1 = FSL_BOOKE_MAS1(1, _iprot, 0, _ts, _sz), \
+ .mas2 = FSL_BOOKE_MAS2(_epn, _wimge), \
+ .mas3 = FSL_BOOKE_MAS3(_rpn, 0, _perms), \
+ .mas7 = FSL_BOOKE_MAS7(_rpn), }
+
+struct fsl_e_tlb_entry {
+ u32 mas0;
+ u32 mas1;
+ u32 mas2;
+ u32 mas3;
+ u32 mas7;
+};
+
+extern struct fsl_e_tlb_entry tlb_table[];
+extern int num_tlb_entries;
+#endif
+#endif
+
+#ifdef CONFIG_E300
+#define LAWAR_EN 0x80000000
+#define LAWAR_SIZE 0x0000003F
+
+#define LAWAR_TRGT_IF_PCI 0x00000000
+#define LAWAR_TRGT_IF_PCI1 0x00000000
+#define LAWAR_TRGT_IF_PCIX 0x00000000
+#define LAWAR_TRGT_IF_PCI2 0x00100000
+#define LAWAR_TRGT_IF_PCIE1 0x00200000
+#define LAWAR_TRGT_IF_PCIE2 0x00100000
+#define LAWAR_TRGT_IF_PCIE3 0x00300000
+#define LAWAR_TRGT_IF_LBC 0x00400000
+#define LAWAR_TRGT_IF_CCSR 0x00800000
+#define LAWAR_TRGT_IF_DDR_INTERLEAVED 0x00B00000
+#define LAWAR_TRGT_IF_RIO 0x00c00000
+#define LAWAR_TRGT_IF_DDR 0x00f00000
+#define LAWAR_TRGT_IF_DDR1 0x00f00000
+#define LAWAR_TRGT_IF_DDR2 0x01600000
+
+#define LAWAR_SIZE_BASE 0xa
+#define LAWAR_SIZE_4K (LAWAR_SIZE_BASE+1)
+#define LAWAR_SIZE_8K (LAWAR_SIZE_BASE+2)
+#define LAWAR_SIZE_16K (LAWAR_SIZE_BASE+3)
+#define LAWAR_SIZE_32K (LAWAR_SIZE_BASE+4)
+#define LAWAR_SIZE_64K (LAWAR_SIZE_BASE+5)
+#define LAWAR_SIZE_128K (LAWAR_SIZE_BASE+6)
+#define LAWAR_SIZE_256K (LAWAR_SIZE_BASE+7)
+#define LAWAR_SIZE_512K (LAWAR_SIZE_BASE+8)
+#define LAWAR_SIZE_1M (LAWAR_SIZE_BASE+9)
+#define LAWAR_SIZE_2M (LAWAR_SIZE_BASE+10)
+#define LAWAR_SIZE_4M (LAWAR_SIZE_BASE+11)
+#define LAWAR_SIZE_8M (LAWAR_SIZE_BASE+12)
+#define LAWAR_SIZE_16M (LAWAR_SIZE_BASE+13)
+#define LAWAR_SIZE_32M (LAWAR_SIZE_BASE+14)
+#define LAWAR_SIZE_64M (LAWAR_SIZE_BASE+15)
+#define LAWAR_SIZE_128M (LAWAR_SIZE_BASE+16)
+#define LAWAR_SIZE_256M (LAWAR_SIZE_BASE+17)
+#define LAWAR_SIZE_512M (LAWAR_SIZE_BASE+18)
+#define LAWAR_SIZE_1G (LAWAR_SIZE_BASE+19)
+#define LAWAR_SIZE_2G (LAWAR_SIZE_BASE+20)
+#define LAWAR_SIZE_4G (LAWAR_SIZE_BASE+21)
+#define LAWAR_SIZE_8G (LAWAR_SIZE_BASE+22)
+#define LAWAR_SIZE_16G (LAWAR_SIZE_BASE+23)
+#define LAWAR_SIZE_32G (LAWAR_SIZE_BASE+24)
+#endif
+
+#ifdef CONFIG_440
+/* General */
+#define TLB_VALID 0x00000200
+
+/* Supported page sizes */
+
+#define SZ_1K 0x00000000
+#define SZ_4K 0x00000010
+#define SZ_16K 0x00000020
+#define SZ_64K 0x00000030
+#define SZ_256K 0x00000040
+#define SZ_1M 0x00000050
+#define SZ_16M 0x00000070
+#define SZ_256M 0x00000090
+
+/* Storage attributes */
+#define SA_W 0x00000800 /* Write-through */
+#define SA_I 0x00000400 /* Caching inhibited */
+#define SA_M 0x00000200 /* Memory coherence */
+#define SA_G 0x00000100 /* Guarded */
+#define SA_E 0x00000080 /* Endian */
+/* Some additional macros for combinations often used */
+#define SA_IG (SA_I | SA_G)
+
+/* Access control */
+#define AC_X 0x00000024 /* Execute */
+#define AC_W 0x00000012 /* Write */
+#define AC_R 0x00000009 /* Read */
+/* Some additional macros for combinations often used */
+#define AC_RW (AC_R | AC_W)
+#define AC_RWX (AC_R | AC_W | AC_X)
+
+/* Some handy macros */
+
+#define EPN(e) ((e) & 0xfffffc00)
+#define TLB0(epn,sz) ((EPN((epn)) | (sz) | TLB_VALID ))
+#define TLB1(rpn,erpn) (((rpn) & 0xfffffc00) | (erpn))
+#define TLB2(a) ((a) & 0x00000fbf)
+
+#define tlbtab_start\
+ mflr r1 ;\
+ bl 0f ;
+
+#define tlbtab_end\
+ .long 0, 0, 0 ;\
+0: mflr r0 ;\
+ mtlr r1 ;\
+ blr ;
+
+#define tlbentry(epn,sz,rpn,erpn,attr)\
+ .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr)
+
+/*----------------------------------------------------------------------------+
+| TLB specific defines.
++----------------------------------------------------------------------------*/
+#define TLB_256MB_ALIGN_MASK 0xFF0000000ULL
+#define TLB_16MB_ALIGN_MASK 0xFFF000000ULL
+#define TLB_1MB_ALIGN_MASK 0xFFFF00000ULL
+#define TLB_256KB_ALIGN_MASK 0xFFFFC0000ULL
+#define TLB_64KB_ALIGN_MASK 0xFFFFF0000ULL
+#define TLB_16KB_ALIGN_MASK 0xFFFFFC000ULL
+#define TLB_4KB_ALIGN_MASK 0xFFFFFF000ULL
+#define TLB_1KB_ALIGN_MASK 0xFFFFFFC00ULL
+#define TLB_256MB_SIZE 0x10000000
+#define TLB_16MB_SIZE 0x01000000
+#define TLB_1MB_SIZE 0x00100000
+#define TLB_256KB_SIZE 0x00040000
+#define TLB_64KB_SIZE 0x00010000
+#define TLB_16KB_SIZE 0x00004000
+#define TLB_4KB_SIZE 0x00001000
+#define TLB_1KB_SIZE 0x00000400
+
+#define TLB_WORD0_EPN_MASK 0xFFFFFC00
+#define TLB_WORD0_EPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD0_EPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD0_V_MASK 0x00000200
+#define TLB_WORD0_V_ENABLE 0x00000200
+#define TLB_WORD0_V_DISABLE 0x00000000
+#define TLB_WORD0_TS_MASK 0x00000100
+#define TLB_WORD0_TS_1 0x00000100
+#define TLB_WORD0_TS_0 0x00000000
+#define TLB_WORD0_SIZE_MASK 0x000000F0
+#define TLB_WORD0_SIZE_1KB 0x00000000
+#define TLB_WORD0_SIZE_4KB 0x00000010
+#define TLB_WORD0_SIZE_16KB 0x00000020
+#define TLB_WORD0_SIZE_64KB 0x00000030
+#define TLB_WORD0_SIZE_256KB 0x00000040
+#define TLB_WORD0_SIZE_1MB 0x00000050
+#define TLB_WORD0_SIZE_16MB 0x00000070
+#define TLB_WORD0_SIZE_256MB 0x00000090
+#define TLB_WORD0_TPAR_MASK 0x0000000F
+#define TLB_WORD0_TPAR_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0)
+#define TLB_WORD0_TPAR_DECODE(n) ((((unsigned long)(n))>>0)&0x0F)
+
+#define TLB_WORD1_RPN_MASK 0xFFFFFC00
+#define TLB_WORD1_RPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD1_RPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00)
+#define TLB_WORD1_PAR1_MASK 0x00000300
+#define TLB_WORD1_PAR1_ENCODE(n) ((((unsigned long)(n))&0x03)<<8)
+#define TLB_WORD1_PAR1_DECODE(n) ((((unsigned long)(n))>>8)&0x03)
+#define TLB_WORD1_PAR1_0 0x00000000
+#define TLB_WORD1_PAR1_1 0x00000100
+#define TLB_WORD1_PAR1_2 0x00000200
+#define TLB_WORD1_PAR1_3 0x00000300
+#define TLB_WORD1_ERPN_MASK 0x0000000F
+#define TLB_WORD1_ERPN_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0)
+#define TLB_WORD1_ERPN_DECODE(n) ((((unsigned long)(n))>>0)&0x0F)
+
+#define TLB_WORD2_PAR2_MASK 0xC0000000
+#define TLB_WORD2_PAR2_ENCODE(n) ((((unsigned long)(n))&0x03)<<30)
+#define TLB_WORD2_PAR2_DECODE(n) ((((unsigned long)(n))>>30)&0x03)
+#define TLB_WORD2_PAR2_0 0x00000000
+#define TLB_WORD2_PAR2_1 0x40000000
+#define TLB_WORD2_PAR2_2 0x80000000
+#define TLB_WORD2_PAR2_3 0xC0000000
+#define TLB_WORD2_U0_MASK 0x00008000
+#define TLB_WORD2_U0_ENABLE 0x00008000
+#define TLB_WORD2_U0_DISABLE 0x00000000
+#define TLB_WORD2_U1_MASK 0x00004000
+#define TLB_WORD2_U1_ENABLE 0x00004000
+#define TLB_WORD2_U1_DISABLE 0x00000000
+#define TLB_WORD2_U2_MASK 0x00002000
+#define TLB_WORD2_U2_ENABLE 0x00002000
+#define TLB_WORD2_U2_DISABLE 0x00000000
+#define TLB_WORD2_U3_MASK 0x00001000
+#define TLB_WORD2_U3_ENABLE 0x00001000
+#define TLB_WORD2_U3_DISABLE 0x00000000
+#define TLB_WORD2_W_MASK 0x00000800
+#define TLB_WORD2_W_ENABLE 0x00000800
+#define TLB_WORD2_W_DISABLE 0x00000000
+#define TLB_WORD2_I_MASK 0x00000400
+#define TLB_WORD2_I_ENABLE 0x00000400
+#define TLB_WORD2_I_DISABLE 0x00000000
+#define TLB_WORD2_M_MASK 0x00000200
+#define TLB_WORD2_M_ENABLE 0x00000200
+#define TLB_WORD2_M_DISABLE 0x00000000
+#define TLB_WORD2_G_MASK 0x00000100
+#define TLB_WORD2_G_ENABLE 0x00000100
+#define TLB_WORD2_G_DISABLE 0x00000000
+#define TLB_WORD2_E_MASK 0x00000080
+#define TLB_WORD2_E_ENABLE 0x00000080
+#define TLB_WORD2_E_DISABLE 0x00000000
+#define TLB_WORD2_UX_MASK 0x00000020
+#define TLB_WORD2_UX_ENABLE 0x00000020
+#define TLB_WORD2_UX_DISABLE 0x00000000
+#define TLB_WORD2_UW_MASK 0x00000010
+#define TLB_WORD2_UW_ENABLE 0x00000010
+#define TLB_WORD2_UW_DISABLE 0x00000000
+#define TLB_WORD2_UR_MASK 0x00000008
+#define TLB_WORD2_UR_ENABLE 0x00000008
+#define TLB_WORD2_UR_DISABLE 0x00000000
+#define TLB_WORD2_SX_MASK 0x00000004
+#define TLB_WORD2_SX_ENABLE 0x00000004
+#define TLB_WORD2_SX_DISABLE 0x00000000
+#define TLB_WORD2_SW_MASK 0x00000002
+#define TLB_WORD2_SW_ENABLE 0x00000002
+#define TLB_WORD2_SW_DISABLE 0x00000000
+#define TLB_WORD2_SR_MASK 0x00000001
+#define TLB_WORD2_SR_ENABLE 0x00000001
+#define TLB_WORD2_SR_DISABLE 0x00000000
+
+/*----------------------------------------------------------------------------+
+| Following instructions are not available in Book E mode of the GNU assembler.
++----------------------------------------------------------------------------*/
+#define DCCCI(ra,rb) .long 0x7c000000|\
+ (ra<<16)|(rb<<11)|(454<<1)
+
+#define ICCCI(ra,rb) .long 0x7c000000|\
+ (ra<<16)|(rb<<11)|(966<<1)
+
+#define DCREAD(rt,ra,rb) .long 0x7c000000|\
+ (rt<<21)|(ra<<16)|(rb<<11)|(486<<1)
+
+#define ICREAD(ra,rb) .long 0x7c000000|\
+ (ra<<16)|(rb<<11)|(998<<1)
+
+#define TLBSX(rt,ra,rb) .long 0x7c000000|\
+ (rt<<21)|(ra<<16)|(rb<<11)|(914<<1)
+
+#define TLBWE(rs,ra,ws) .long 0x7c000000|\
+ (rs<<21)|(ra<<16)|(ws<<11)|(978<<1)
+
+#define TLBRE(rt,ra,ws) .long 0x7c000000|\
+ (rt<<21)|(ra<<16)|(ws<<11)|(946<<1)
+
+#define TLBSXDOT(rt,ra,rb) .long 0x7c000001|\
+ (rt<<21)|(ra<<16)|(rb<<11)|(914<<1)
+
+#define MSYNC .long 0x7c000000|\
+ (598<<1)
+
+#define MBAR_INST .long 0x7c000000|\
+ (854<<1)
+
+#ifndef __ASSEMBLY__
+/* Prototypes */
+void mttlb1(unsigned long index, unsigned long value);
+void mttlb2(unsigned long index, unsigned long value);
+void mttlb3(unsigned long index, unsigned long value);
+unsigned long mftlb1(unsigned long index);
+unsigned long mftlb2(unsigned long index);
+unsigned long mftlb3(unsigned long index);
+
+void program_tlb(u64 phys_addr, u32 virt_addr, u32 size, u32 tlb_word2_i_value);
+void remove_tlb(u32 vaddr, u32 size);
+void change_tlb(u32 vaddr, u32 size, u32 tlb_word2_i_value);
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_440 */
+#endif /* _PPC_MMU_H_ */
diff --git a/arch/powerpc/include/asm/mp.h b/arch/powerpc/include/asm/mp.h
new file mode 100644
index 0000000..9188ede
--- /dev/null
+++ b/arch/powerpc/include/asm/mp.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _ASM_MP_H_
+#define _ASM_MP_H_
+
+#include <lmb.h>
+
+void setup_mp(void);
+void cpu_mp_lmb_reserve(struct lmb *lmb);
+u32 determine_mp_bootpg(unsigned int *pagesize);
+int is_core_disabled(int nr);
+
+#ifdef CONFIG_E6500
+#define thread_to_core(x) (x >> 1)
+#else
+#define thread_to_core(x) (x)
+#endif
+
+#endif
diff --git a/arch/powerpc/include/asm/mpc512x.h b/arch/powerpc/include/asm/mpc512x.h
new file mode 100644
index 0000000..960e229
--- /dev/null
+++ b/arch/powerpc/include/asm/mpc512x.h
@@ -0,0 +1,58 @@
+/*
+ * include/asm-ppc/mpc512x.h
+ *
+ * Prototypes, etc. for the Freescale MPC512x embedded cpu chips
+ *
+ * 2009 (C) Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef __ASMPPC_MPC512X_H
+#define __ASMPPC_MPC512X_H
+
+/*
+ * macros for manipulating CSx_START/STOP
+ */
+#define CSAW_START(start) ((start) & 0xFFFF0000)
+#define CSAW_STOP(start, size) (((start) + (size) - 1) >> 16)
+
+/*
+ * Inlines
+ */
+
+/*
+ * According to MPC5121e RM, configuring local access windows should
+ * be followed by a dummy read of the config register that was
+ * modified last and an isync.
+ */
+static inline void sync_law(volatile void *addr)
+{
+ in_be32(addr);
+ __asm__ __volatile__ ("isync");
+}
+
+/*
+ * Prototypes
+ */
+extern long int fixed_sdram(ddr512x_config_t *mddrc_config,
+ u32 *dram_init_seq, int seq_sz);
+extern int mpc5121_diu_init(void);
+extern void ide_set_reset(int idereset);
+
+#endif /* __ASMPPC_MPC512X_H */
diff --git a/arch/powerpc/include/asm/mpc8349_pci.h b/arch/powerpc/include/asm/mpc8349_pci.h
new file mode 100644
index 0000000..7a1adba
--- /dev/null
+++ b/arch/powerpc/include/asm/mpc8349_pci.h
@@ -0,0 +1,168 @@
+#ifndef _PPC_KERNEL_MPC8349_PCI_H
+#define _PPC_KERNEL_MPC8349_PCI_H
+
+
+#define M8265_PCIBR0 0x101ac
+#define M8265_PCIBR1 0x101b0
+#define M8265_PCIMSK0 0x101c4
+#define M8265_PCIMSK1 0x101c8
+
+/* Bit definitions for PCIBR registers */
+
+#define PCIBR_ENABLE 0x00000001
+
+/* Bit definitions for PCIMSK registers */
+
+#define PCIMSK_32KB 0xFFFF8000 /* Size of window, smallest */
+#define PCIMSK_64KB 0xFFFF0000
+#define PCIMSK_128KB 0xFFFE0000
+#define PCIMSK_256KB 0xFFFC0000
+#define PCIMSK_512KB 0xFFF80000
+#define PCIMSK_1MB 0xFFF00000
+#define PCIMSK_2MB 0xFFE00000
+#define PCIMSK_4MB 0xFFC00000
+#define PCIMSK_8MB 0xFF800000
+#define PCIMSK_16MB 0xFF000000
+#define PCIMSK_32MB 0xFE000000
+#define PCIMSK_64MB 0xFC000000
+#define PCIMSK_128MB 0xF8000000
+#define PCIMSK_256MB 0xF0000000
+#define PCIMSK_512MB 0xE0000000
+#define PCIMSK_1GB 0xC0000000 /* Size of window, largest */
+
+
+#define M826X_SCCR_PCI_MODE_EN 0x100
+
+
+/*
+ * Outbound ATU registers (3 sets). These registers control how 60x bus
+ * (local) addresses are translated to PCI addresses when the MPC826x is
+ * a PCI bus master (initiator).
+ */
+
+#define POTAR_REG0 0x10800 /* PCI Outbound Translation Addr registers */
+#define POTAR_REG1 0x10818
+#define POTAR_REG2 0x10830
+
+#define POBAR_REG0 0x10808 /* PCI Outbound Base Addr registers */
+#define POBAR_REG1 0x10820
+#define POBAR_REG2 0x10838
+
+#define POCMR_REG0 0x10810 /* PCI Outbound Comparison Mask registers */
+#define POCMR_REG1 0x10828
+#define POCMR_REG2 0x10840
+
+/* Bit definitions for POMCR registers */
+
+#define POCMR_MASK_4KB 0x000FFFFF
+#define POCMR_MASK_8KB 0x000FFFFE
+#define POCMR_MASK_16KB 0x000FFFFC
+#define POCMR_MASK_32KB 0x000FFFF8
+#define POCMR_MASK_64KB 0x000FFFF0
+#define POCMR_MASK_128KB 0x000FFFE0
+#define POCMR_MASK_256KB 0x000FFFC0
+#define POCMR_MASK_512KB 0x000FFF80
+#define POCMR_MASK_1MB 0x000FFF00
+#define POCMR_MASK_2MB 0x000FFE00
+#define POCMR_MASK_4MB 0x000FFC00
+#define POCMR_MASK_8MB 0x000FF800
+#define POCMR_MASK_16MB 0x000FF000
+#define POCMR_MASK_32MB 0x000FE000
+#define POCMR_MASK_64MB 0x000FC000
+#define POCMR_MASK_128MB 0x000F8000
+#define POCMR_MASK_256MB 0x000F0000
+#define POCMR_MASK_512MB 0x000E0000
+#define POCMR_MASK_1GB 0x000C0000
+
+#define POCMR_ENABLE 0x80000000
+#define POCMR_PCI_IO 0x40000000
+#define POCMR_PREFETCH_EN 0x20000000
+#define POCMR_PCI2 0x10000000
+
+/* Soft PCI reset */
+
+#define PCI_GCR_REG 0x10880
+
+/* Bit definitions for PCI_GCR registers */
+
+#define PCIGCR_PCI_BUS_EN 0x1
+
+/*
+ * Inbound ATU registers (2 sets). These registers control how PCI
+ * addresses are translated to 60x bus (local) addresses when the
+ * MPC826x is a PCI bus target.
+ */
+
+#define PITAR_REG1 0x108D0
+#define PIBAR_REG1 0x108D8
+#define PICMR_REG1 0x108E0
+#define PITAR_REG0 0x108E8
+#define PIBAR_REG0 0x108F0
+#define PICMR_REG0 0x108F8
+
+/* Bit definitions for PCI Inbound Comparison Mask registers */
+
+#define PICMR_MASK_4KB 0x000FFFFF
+#define PICMR_MASK_8KB 0x000FFFFE
+#define PICMR_MASK_16KB 0x000FFFFC
+#define PICMR_MASK_32KB 0x000FFFF8
+#define PICMR_MASK_64KB 0x000FFFF0
+#define PICMR_MASK_128KB 0x000FFFE0
+#define PICMR_MASK_256KB 0x000FFFC0
+#define PICMR_MASK_512KB 0x000FFF80
+#define PICMR_MASK_1MB 0x000FFF00
+#define PICMR_MASK_2MB 0x000FFE00
+#define PICMR_MASK_4MB 0x000FFC00
+#define PICMR_MASK_8MB 0x000FF800
+#define PICMR_MASK_16MB 0x000FF000
+#define PICMR_MASK_32MB 0x000FE000
+#define PICMR_MASK_64MB 0x000FC000
+#define PICMR_MASK_128MB 0x000F8000
+#define PICMR_MASK_256MB 0x000F0000
+#define PICMR_MASK_512MB 0x000E0000
+#define PICMR_MASK_1GB 0x000C0000
+
+#define PICMR_ENABLE 0x80000000
+#define PICMR_NO_SNOOP_EN 0x40000000
+#define PICMR_PREFETCH_EN 0x20000000
+
+/* PCI error Registers */
+
+#define PCI_ERROR_STATUS_REG 0x10884
+#define PCI_ERROR_MASK_REG 0x10888
+#define PCI_ERROR_CONTROL_REG 0x1088C
+#define PCI_ERROR_ADRS_CAPTURE_REG 0x10890
+#define PCI_ERROR_DATA_CAPTURE_REG 0x10898
+#define PCI_ERROR_CTRL_CAPTURE_REG 0x108A0
+
+/* PCI error Register bit defines */
+
+#define PCI_ERROR_PCI_ADDR_PAR 0x00000001
+#define PCI_ERROR_PCI_DATA_PAR_WR 0x00000002
+#define PCI_ERROR_PCI_DATA_PAR_RD 0x00000004
+#define PCI_ERROR_PCI_NO_RSP 0x00000008
+#define PCI_ERROR_PCI_TAR_ABT 0x00000010
+#define PCI_ERROR_PCI_SERR 0x00000020
+#define PCI_ERROR_PCI_PERR_RD 0x00000040
+#define PCI_ERROR_PCI_PERR_WR 0x00000080
+#define PCI_ERROR_I2O_OFQO 0x00000100
+#define PCI_ERROR_I2O_IPQO 0x00000200
+#define PCI_ERROR_IRA 0x00000400
+#define PCI_ERROR_NMI 0x00000800
+#define PCI_ERROR_I2O_DBMC 0x00001000
+
+/*
+ * Register pair used to generate configuration cycles on the PCI bus
+ * and access the MPC826x's own PCI configuration registers.
+ */
+
+#define PCI_CFG_ADDR_REG 0x10900
+#define PCI_CFG_DATA_REG 0x10904
+
+/* Bus parking decides where the bus control sits when idle */
+/* If modifying memory controllers for PCI park on the core */
+
+#define PPC_ACR_BUS_PARK_CORE 0x6
+#define PPC_ACR_BUS_PARK_PCI 0x3
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/powerpc/include/asm/mpc85xx_gpio.h b/arch/powerpc/include/asm/mpc85xx_gpio.h
new file mode 100644
index 0000000..2aed514
--- /dev/null
+++ b/arch/powerpc/include/asm/mpc85xx_gpio.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2010 eXMeritus, A Boeing Company
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef POWERPC_ASM_MPC85XX_GPIO_H_
+#define POWERPC_ASM_MPC85XX_GPIO_H_
+
+# include <asm/immap_85xx.h>
+
+/*
+ * The following internal functions are an MPC85XX-specific GPIO API which
+ * allows setting and querying multiple GPIOs in a single operation.
+ *
+ * All of these look relatively large, but the arguments are almost always
+ * constants, so they compile down to just a few instructions and a
+ * memory-mapped IO operation or two.
+ */
+static inline void mpc85xx_gpio_set(unsigned int mask,
+ unsigned int dir, unsigned int val)
+{
+ ccsr_gpio_t *gpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR + 0xc00);
+
+ /* First mask off the unwanted parts of "dir" and "val" */
+ dir &= mask;
+ val &= mask;
+
+ /* Now read in the values we're supposed to preserve */
+ dir |= (in_be32(&gpio->gpdir) & ~mask);
+ val |= (in_be32(&gpio->gpdat) & ~mask);
+
+ /*
+ * Poke the new output values first, then set the direction. This
+ * helps to avoid transient data when switching from input to output
+ * and vice versa.
+ */
+ out_be32(&gpio->gpdat, val);
+ out_be32(&gpio->gpdir, dir);
+}
+
+static inline void mpc85xx_gpio_set_in(unsigned int gpios)
+{
+ mpc85xx_gpio_set(gpios, 0x00000000, 0x00000000);
+}
+
+static inline void mpc85xx_gpio_set_low(unsigned int gpios)
+{
+ mpc85xx_gpio_set(gpios, 0xFFFFFFFF, 0x00000000);
+}
+
+static inline void mpc85xx_gpio_set_high(unsigned int gpios)
+{
+ mpc85xx_gpio_set(gpios, 0xFFFFFFFF, 0xFFFFFFFF);
+}
+
+static inline unsigned int mpc85xx_gpio_get(unsigned int mask)
+{
+ ccsr_gpio_t *gpio = (void *)(CONFIG_SYS_MPC85xx_GPIO_ADDR + 0xc00);
+
+ /* Read the requested values */
+ return in_be32(&gpio->gpdat) & mask;
+}
+
+/*
+ * These implement the generic Linux GPIO API on top of the other functions
+ * in this header.
+ */
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+ /* Compatibility shim */
+ return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+ /* Compatibility shim */
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ mpc85xx_gpio_set_in(1U << gpio);
+ return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ if (value)
+ mpc85xx_gpio_set_high(1U << gpio);
+ else
+ mpc85xx_gpio_set_low(1U << gpio);
+ return 0;
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return !!mpc85xx_gpio_get(1U << gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ if (value)
+ mpc85xx_gpio_set_high(1U << gpio);
+ else
+ mpc85xx_gpio_set_low(1U << gpio);
+}
+
+static inline int gpio_is_valid(int gpio)
+{
+ return (gpio >= 0) && (gpio < 32);
+}
+
+#endif /* not POWERPC_ASM_MPC85XX_GPIO_H_ */
diff --git a/arch/powerpc/include/asm/mpc8xxx_spi.h b/arch/powerpc/include/asm/mpc8xxx_spi.h
new file mode 100644
index 0000000..b0082af
--- /dev/null
+++ b/arch/powerpc/include/asm/mpc8xxx_spi.h
@@ -0,0 +1,49 @@
+/*
+ * Freescale non-CPM SPI Controller
+ *
+ * Copyright 2008 Qstreams Networks, Inc.
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, Version 2, incorporated
+ * herein by reference.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * Version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _ASM_MPC8XXX_SPI_H_
+#define _ASM_MPC8XXX_SPI_H_
+
+#include <asm/types.h>
+
+#if defined(CONFIG_MPC8308) || \
+ defined(CONFIG_MPC8313) || \
+ defined(CONFIG_MPC8315) || \
+ defined(CONFIG_MPC834x) || \
+ defined(CONFIG_MPC837x)
+
+typedef struct spi8xxx {
+ u8 res0[0x20]; /* 0x0-0x01f reserved */
+ u32 mode; /* mode register */
+ u32 event; /* event register */
+ u32 mask; /* mask register */
+ u32 com; /* command register */
+ u32 tx; /* transmit register */
+ u32 rx; /* receive register */
+ u8 res1[0xFC8]; /* fill up to 0x1000 */
+} spi8xxx_t;
+
+#endif
+
+#endif /* _ASM_MPC8XXX_SPI_H_ */
diff --git a/arch/powerpc/include/asm/pci_io.h b/arch/powerpc/include/asm/pci_io.h
new file mode 100644
index 0000000..9b738c3
--- /dev/null
+++ b/arch/powerpc/include/asm/pci_io.h
@@ -0,0 +1,43 @@
+/* originally from linux source (asm-ppc/io.h).
+ * Sanity added by Rob Taylor, Flying Pig Systems, 2000
+ */
+#ifndef _PCI_IO_H_
+#define _PCI_IO_H_
+
+#include "io.h"
+
+
+#define pci_read_le16(addr, dest) \
+ __asm__ __volatile__("lhbrx %0,0,%1" : "=r" (dest) : \
+ "r" (addr), "m" (*addr));
+
+#define pci_write_le16(addr, val) \
+ __asm__ __volatile__("sthbrx %1,0,%2" : "=m" (*addr) : \
+ "r" (val), "r" (addr));
+
+
+#define pci_read_le32(addr, dest) \
+ __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (dest) : \
+ "r" (addr), "m" (*addr));
+
+#define pci_write_le32(addr, val) \
+__asm__ __volatile__("stwbrx %1,0,%2" : "=m" (*addr) : \
+ "r" (val), "r" (addr));
+
+#define pci_readb(addr,b) ((b) = *(volatile u8 *) (addr))
+#define pci_writeb(b,addr) ((*(volatile u8 *) (addr)) = (b))
+
+#if !defined(__BIG_ENDIAN)
+#define pci_readw(addr,b) ((b) = *(volatile u16 *) (addr))
+#define pci_readl(addr,b) ((b) = *(volatile u32 *) (addr))
+#define pci_writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define pci_writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define pci_readw(addr,b) pci_read_le16((volatile u16 *)(addr),(b))
+#define pci_readl(addr,b) pci_read_le32((volatile u32 *)(addr),(b))
+#define pci_writew(b,addr) pci_write_le16((volatile u16 *)(addr),(b))
+#define pci_writel(b,addr) pci_write_le32((volatile u32 *)(addr),(b))
+#endif
+
+
+#endif /* _PCI_IO_H_ */
diff --git a/arch/powerpc/include/asm/pnp.h b/arch/powerpc/include/asm/pnp.h
new file mode 100644
index 0000000..22ceba2
--- /dev/null
+++ b/arch/powerpc/include/asm/pnp.h
@@ -0,0 +1,643 @@
+/* 11/02/95 */
+/*----------------------------------------------------------------------------*/
+/* Plug and Play header definitions */
+/*----------------------------------------------------------------------------*/
+
+/* Structure map for PnP on PowerPC Reference Platform */
+/* See Plug and Play ISA Specification, Version 1.0, May 28, 1993. It */
+/* (or later versions) is available on Compuserve in the PLUGPLAY area. */
+/* This code has extensions to that specification, namely new short and */
+/* long tag types for platform dependent information */
+
+/* Warning: LE notation used throughout this file */
+
+/* For enum's: if given in hex then they are bit significant, i.e. */
+/* only one bit is on for each enum */
+
+#ifndef _PNP_
+#define _PNP_
+
+#ifndef __ASSEMBLY__
+#define MAX_MEM_REGISTERS 9
+#define MAX_IO_PORTS 20
+#define MAX_IRQS 7
+/*#define MAX_DMA_CHANNELS 7*/
+
+/* Interrupt controllers */
+
+#define PNPinterrupt0 "PNP0000" /* AT Interrupt Controller */
+#define PNPinterrupt1 "PNP0001" /* EISA Interrupt Controller */
+#define PNPinterrupt2 "PNP0002" /* MCA Interrupt Controller */
+#define PNPinterrupt3 "PNP0003" /* APIC */
+#define PNPExtInt "IBM000D" /* PowerPC Extended Interrupt Controller */
+
+/* Timers */
+
+#define PNPtimer0 "PNP0100" /* AT Timer */
+#define PNPtimer1 "PNP0101" /* EISA Timer */
+#define PNPtimer2 "PNP0102" /* MCA Timer */
+
+/* DMA controllers */
+
+#define PNPdma0 "PNP0200" /* AT DMA Controller */
+#define PNPdma1 "PNP0201" /* EISA DMA Controller */
+#define PNPdma2 "PNP0202" /* MCA DMA Controller */
+
+/* start of August 15, 1994 additions */
+/* CMOS */
+#define PNPCMOS "IBM0009" /* CMOS */
+
+/* L2 Cache */
+#define PNPL2 "IBM0007" /* L2 Cache */
+
+/* NVRAM */
+#define PNPNVRAM "IBM0008" /* NVRAM */
+
+/* Power Management */
+#define PNPPM "IBM0005" /* Power Management */
+/* end of August 15, 1994 additions */
+
+/* Keyboards */
+
+#define PNPkeyboard0 "PNP0300" /* IBM PC/XT KB Cntlr (83 key, no mouse) */
+#define PNPkeyboard1 "PNP0301" /* Olivetti ICO (102 key) */
+#define PNPkeyboard2 "PNP0302" /* IBM PC/AT KB Cntlr (84 key) */
+#define PNPkeyboard3 "PNP0303" /* IBM Enhanced (101/2 key, PS/2 mouse) */
+#define PNPkeyboard4 "PNP0304" /* Nokia 1050 KB Cntlr */
+#define PNPkeyboard5 "PNP0305" /* Nokia 9140 KB Cntlr */
+#define PNPkeyboard6 "PNP0306" /* Standard Japanese KB Cntlr */
+#define PNPkeyboard7 "PNP0307" /* Microsoft Windows (R) KB Cntlr */
+
+/* Parallel port controllers */
+
+#define PNPparallel0 "PNP0400" /* Standard LPT Parallel Port */
+#define PNPparallel1 "PNP0401" /* ECP Parallel Port */
+#define PNPepp "IBM001C" /* EPP Parallel Port */
+
+/* Serial port controllers */
+
+#define PNPserial0 "PNP0500" /* Standard PC Serial port */
+#define PNPSerial1 "PNP0501" /* 16550A Compatible Serial port */
+
+/* Disk controllers */
+
+#define PNPdisk0 "PNP0600" /* Generic ESDI/IDE/ATA Compat HD Cntlr */
+#define PNPdisk1 "PNP0601" /* Plus Hardcard II */
+#define PNPdisk2 "PNP0602" /* Plus Hardcard IIXL/EZ */
+
+/* Diskette controllers */
+
+#define PNPdiskette0 "PNP0700" /* PC Standard Floppy Disk Controller */
+
+/* Display controllers */
+
+#define PNPdisplay0 "PNP0900" /* VGA Compatible */
+#define PNPdisplay1 "PNP0901" /* Video Seven VGA */
+#define PNPdisplay2 "PNP0902" /* 8514/A Compatible */
+#define PNPdisplay3 "PNP0903" /* Trident VGA */
+#define PNPdisplay4 "PNP0904" /* Cirrus Logic Laptop VGA */
+#define PNPdisplay5 "PNP0905" /* Cirrus Logic VGA */
+#define PNPdisplay6 "PNP0906" /* Tseng ET4000 or ET4000/W32 */
+#define PNPdisplay7 "PNP0907" /* Western Digital VGA */
+#define PNPdisplay8 "PNP0908" /* Western Digital Laptop VGA */
+#define PNPdisplay9 "PNP0909" /* S3 */
+#define PNPdisplayA "PNP090A" /* ATI Ultra Pro/Plus (Mach 32) */
+#define PNPdisplayB "PNP090B" /* ATI Ultra (Mach 8) */
+#define PNPdisplayC "PNP090C" /* XGA Compatible */
+#define PNPdisplayD "PNP090D" /* ATI VGA Wonder */
+#define PNPdisplayE "PNP090E" /* Weitek P9000 Graphics Adapter */
+#define PNPdisplayF "PNP090F" /* Oak Technology VGA */
+
+/* Peripheral busses */
+
+#define PNPbuses0 "PNP0A00" /* ISA Bus */
+#define PNPbuses1 "PNP0A01" /* EISA Bus */
+#define PNPbuses2 "PNP0A02" /* MCA Bus */
+#define PNPbuses3 "PNP0A03" /* PCI Bus */
+#define PNPbuses4 "PNP0A04" /* VESA/VL Bus */
+
+/* RTC, BIOS, planar devices */
+
+#define PNPspeaker0 "PNP0800" /* AT Style Speaker Sound */
+#define PNPrtc0 "PNP0B00" /* AT RTC */
+#define PNPpnpbios0 "PNP0C00" /* PNP BIOS (only created by root enum) */
+#define PNPpnpbios1 "PNP0C01" /* System Board Memory Device */
+#define PNPpnpbios2 "PNP0C02" /* Math Coprocessor */
+#define PNPpnpbios3 "PNP0C03" /* PNP BIOS Event Notification Interrupt */
+
+/* PCMCIA controller */
+
+#define PNPpcmcia0 "PNP0E00" /* Intel 82365 Compatible PCMCIA Cntlr */
+
+/* Mice */
+
+#define PNPmouse0 "PNP0F00" /* Microsoft Bus Mouse */
+#define PNPmouse1 "PNP0F01" /* Microsoft Serial Mouse */
+#define PNPmouse2 "PNP0F02" /* Microsoft Inport Mouse */
+#define PNPmouse3 "PNP0F03" /* Microsoft PS/2 Mouse */
+#define PNPmouse4 "PNP0F04" /* Mousesystems Mouse */
+#define PNPmouse5 "PNP0F05" /* Mousesystems 3 Button Mouse - COM2 */
+#define PNPmouse6 "PNP0F06" /* Genius Mouse - COM1 */
+#define PNPmouse7 "PNP0F07" /* Genius Mouse - COM2 */
+#define PNPmouse8 "PNP0F08" /* Logitech Serial Mouse */
+#define PNPmouse9 "PNP0F09" /* Microsoft Ballpoint Serial Mouse */
+#define PNPmouseA "PNP0F0A" /* Microsoft PNP Mouse */
+#define PNPmouseB "PNP0F0B" /* Microsoft PNP Ballpoint Mouse */
+
+/* Modems */
+
+#define PNPmodem0 "PNP9000" /* Specific IDs TBD */
+
+/* Network controllers */
+
+#define PNPnetworkC9 "PNP80C9" /* IBM Token Ring */
+#define PNPnetworkCA "PNP80CA" /* IBM Token Ring II */
+#define PNPnetworkCB "PNP80CB" /* IBM Token Ring II/Short */
+#define PNPnetworkCC "PNP80CC" /* IBM Token Ring 4/16Mbs */
+#define PNPnetwork27 "PNP8327" /* IBM Token Ring (All types) */
+#define PNPnetworket "IBM0010" /* IBM Ethernet used by Power PC */
+#define PNPneteisaet "IBM2001" /* IBM Ethernet EISA adapter */
+#define PNPAMD79C970 "IBM0016" /* AMD 79C970 (PCI Ethernet) */
+
+/* SCSI controllers */
+
+#define PNPscsi0 "PNPA000" /* Adaptec 154x Compatible SCSI Cntlr */
+#define PNPscsi1 "PNPA001" /* Adaptec 174x Compatible SCSI Cntlr */
+#define PNPscsi2 "PNPA002" /* Future Domain 16-700 Compat SCSI Cntlr*/
+#define PNPscsi3 "PNPA003" /* Panasonic CDROM Adapter (SBPro/SB16) */
+#define PNPscsiF "IBM000F" /* NCR 810 SCSI Controller */
+#define PNPscsi825 "IBM001B" /* NCR 825 SCSI Controller */
+#define PNPscsi875 "IBM0018" /* NCR 875 SCSI Controller */
+
+/* Sound/Video, Multimedia */
+
+#define PNPmm0 "PNPB000" /* Sound Blaster Compatible Sound Device */
+#define PNPmm1 "PNPB001" /* MS Windows Sound System Compat Device */
+#define PNPmmF "IBM000E" /* Crystal CS4231 Audio Device */
+#define PNPv7310 "IBM0015" /* ASCII V7310 Video Capture Device */
+#define PNPmm4232 "IBM0017" /* Crystal CS4232 Audio Device */
+#define PNPpmsyn "IBM001D" /* YMF 289B chip (Yamaha) */
+#define PNPgp4232 "IBM0012" /* Crystal CS4232 Game Port */
+#define PNPmidi4232 "IBM0013" /* Crystal CS4232 MIDI */
+
+/* Operator Panel */
+#define PNPopctl "IBM000B" /* Operator's panel */
+
+/* Service Processor */
+#define PNPsp "IBM0011" /* IBM Service Processor */
+#define PNPLTsp "IBM001E" /* Lightning/Terlingua Support Processor */
+#define PNPLTmsp "IBM001F" /* Lightning/Terlingua Mini-SP */
+
+/* Memory Controller */
+#define PNPmemctl "IBM000A" /* Memory controller */
+
+/* Graphics Assist */
+#define PNPg_assist "IBM0014" /* Graphics Assist */
+
+/* Miscellaneous Device Controllers */
+#define PNPtablet "IBM0019" /* IBM Tablet Controller */
+
+/* PNP Packet Handles */
+
+#define S1_Packet 0x0A /* Version resource */
+#define S2_Packet 0x15 /* Logical DEVID (without flags) */
+#define S2_Packet_flags 0x16 /* Logical DEVID (with flags) */
+#define S3_Packet 0x1C /* Compatible device ID */
+#define S4_Packet 0x22 /* IRQ resource (without flags) */
+#define S4_Packet_flags 0x23 /* IRQ resource (with flags) */
+#define S5_Packet 0x2A /* DMA resource */
+#define S6_Packet 0x30 /* Depend funct start (w/o priority) */
+#define S6_Packet_priority 0x31 /* Depend funct start (w/ priority) */
+#define S7_Packet 0x38 /* Depend funct end */
+#define S8_Packet 0x47 /* I/O port resource (w/o fixed loc) */
+#define S9_Packet_fixed 0x4B /* I/O port resource (w/ fixed loc) */
+#define S14_Packet 0x71 /* Vendor defined */
+#define S15_Packet 0x78 /* End of resource (w/o checksum) */
+#define S15_Packet_checksum 0x79 /* End of resource (w/ checksum) */
+#define L1_Packet 0x81 /* Memory range */
+#define L1_Shadow 0x20 /* Memory is shadowable */
+#define L1_32bit_mem 0x18 /* 32-bit memory only */
+#define L1_8_16bit_mem 0x10 /* 8- and 16-bit supported */
+#define L1_Decode_Hi 0x04 /* decode supports high address */
+#define L1_Cache 0x02 /* read cacheable, write-through */
+#define L1_Writeable 0x01 /* Memory is writeable */
+#define L2_Packet 0x82 /* ANSI ID string */
+#define L3_Packet 0x83 /* Unicode ID string */
+#define L4_Packet 0x84 /* Vendor defined */
+#define L5_Packet 0x85 /* Large I/O */
+#define L6_Packet 0x86 /* 32-bit Fixed Loc Mem Range Desc */
+#define END_TAG 0x78 /* End of resource */
+#define DF_START_TAG 0x30 /* Dependent function start */
+#define DF_START_TAG_priority 0x31 /* Dependent function start */
+#define DF_END_TAG 0x38 /* Dependent function end */
+#define SUBOPTIMAL_CONFIGURATION 0x2 /* Priority byte sub optimal config */
+
+/* Device Base Type Codes */
+
+typedef enum _PnP_BASE_TYPE {
+ Reserved = 0,
+ MassStorageDevice = 1,
+ NetworkInterfaceController = 2,
+ DisplayController = 3,
+ MultimediaController = 4,
+ MemoryController = 5,
+ BridgeController = 6,
+ CommunicationsDevice = 7,
+ SystemPeripheral = 8,
+ InputDevice = 9,
+ ServiceProcessor = 0x0A, /* 11/2/95 */
+ } PnP_BASE_TYPE;
+
+/* Device Sub Type Codes */
+
+typedef enum _PnP_SUB_TYPE {
+ SCSIController = 0,
+ IDEController = 1,
+ FloppyController = 2,
+ IPIController = 3,
+ OtherMassStorageController = 0x80,
+
+ EthernetController = 0,
+ TokenRingController = 1,
+ FDDIController = 2,
+ OtherNetworkController = 0x80,
+
+ VGAController= 0,
+ SVGAController= 1,
+ XGAController= 2,
+ OtherDisplayController = 0x80,
+
+ VideoController = 0,
+ AudioController = 1,
+ OtherMultimediaController = 0x80,
+
+ RAM = 0,
+ FLASH = 1,
+ OtherMemoryDevice = 0x80,
+
+ HostProcessorBridge = 0,
+ ISABridge = 1,
+ EISABridge = 2,
+ MicroChannelBridge = 3,
+ PCIBridge = 4,
+ PCMCIABridge = 5,
+ VMEBridge = 6,
+ OtherBridgeDevice = 0x80,
+
+ RS232Device = 0,
+ ATCompatibleParallelPort = 1,
+ OtherCommunicationsDevice = 0x80,
+
+ ProgrammableInterruptController = 0,
+ DMAController = 1,
+ SystemTimer = 2,
+ RealTimeClock = 3,
+ L2Cache = 4,
+ NVRAM = 5,
+ PowerManagement = 6,
+ CMOS = 7,
+ OperatorPanel = 8,
+ ServiceProcessorClass1 = 9,
+ ServiceProcessorClass2 = 0xA,
+ ServiceProcessorClass3 = 0xB,
+ GraphicAssist = 0xC,
+ SystemPlanar = 0xF, /* 10/5/95 */
+ OtherSystemPeripheral = 0x80,
+
+ KeyboardController = 0,
+ Digitizer = 1,
+ MouseController = 2,
+ TabletController = 3, /* 10/27/95 */
+ OtherInputController = 0x80,
+
+ GeneralMemoryController = 0,
+ } PnP_SUB_TYPE;
+
+/* Device Interface Type Codes */
+
+typedef enum _PnP_INTERFACE {
+ General = 0,
+ GeneralSCSI = 0,
+ GeneralIDE = 0,
+ ATACompatible = 1,
+
+ GeneralFloppy = 0,
+ Compatible765 = 1,
+ NS398_Floppy = 2, /* NS Super I/O wired to use index
+ register at port 398 and data
+ register at port 399 */
+ NS26E_Floppy = 3, /* Ports 26E and 26F */
+ NS15C_Floppy = 4, /* Ports 15C and 15D */
+ NS2E_Floppy = 5, /* Ports 2E and 2F */
+ CHRP_Floppy = 6, /* CHRP Floppy in PR*P system */
+
+ GeneralIPI = 0,
+
+ GeneralEther = 0,
+ GeneralToken = 0,
+ GeneralFDDI = 0,
+
+ GeneralVGA = 0,
+ GeneralSVGA = 0,
+ GeneralXGA = 0,
+
+ GeneralVideo = 0,
+ GeneralAudio = 0,
+ CS4232Audio = 1, /* CS 4232 Plug 'n Play Configured */
+
+ GeneralRAM = 0,
+ GeneralFLASH = 0,
+ PCIMemoryController = 0, /* PCI Config Method */
+ RS6KMemoryController = 1, /* RS6K Config Method */
+
+ GeneralHostBridge = 0,
+ GeneralISABridge = 0,
+ GeneralEISABridge = 0,
+ GeneralMCABridge = 0,
+ GeneralPCIBridge = 0,
+ PCIBridgeDirect = 0,
+ PCIBridgeIndirect = 1,
+ PCIBridgeRS6K = 2,
+ GeneralPCMCIABridge = 0,
+ GeneralVMEBridge = 0,
+
+ GeneralRS232 = 0,
+ COMx = 1,
+ Compatible16450 = 2,
+ Compatible16550 = 3,
+ NS398SerPort = 4, /* NS Super I/O wired to use index
+ register at port 398 and data
+ register at port 399 */
+ NS26ESerPort = 5, /* Ports 26E and 26F */
+ NS15CSerPort = 6, /* Ports 15C and 15D */
+ NS2ESerPort = 7, /* Ports 2E and 2F */
+
+ GeneralParPort = 0,
+ LPTx = 1,
+ NS398ParPort = 2, /* NS Super I/O wired to use index
+ register at port 398 and data
+ register at port 399 */
+ NS26EParPort = 3, /* Ports 26E and 26F */
+ NS15CParPort = 4, /* Ports 15C and 15D */
+ NS2EParPort = 5, /* Ports 2E and 2F */
+
+ GeneralPIC = 0,
+ ISA_PIC = 1,
+ EISA_PIC = 2,
+ MPIC = 3,
+ RS6K_PIC = 4,
+
+ GeneralDMA = 0,
+ ISA_DMA = 1,
+ EISA_DMA = 2,
+
+ GeneralTimer = 0,
+ ISA_Timer = 1,
+ EISA_Timer = 2,
+ GeneralRTC = 0,
+ ISA_RTC = 1,
+
+ StoreThruOnly = 1,
+ StoreInEnabled = 2,
+ RS6KL2Cache = 3,
+
+ IndirectNVRAM = 0, /* Indirectly addressed */
+ DirectNVRAM = 1, /* Memory Mapped */
+ IndirectNVRAM24 = 2, /* Indirectly addressed - 24 bit */
+
+ GeneralPowerManagement = 0,
+ EPOWPowerManagement = 1,
+ PowerControl = 2, /* d1378 */
+
+ GeneralCMOS = 0,
+
+ GeneralOPPanel = 0,
+ HarddiskLight = 1,
+ CDROMLight = 2,
+ PowerLight = 3,
+ KeyLock = 4,
+ ANDisplay = 5, /* AlphaNumeric Display */
+ SystemStatusLED = 6, /* 3 digit 7 segment LED */
+ CHRP_SystemStatusLED = 7, /* CHRP LEDs in PR*P system */
+
+ GeneralServiceProcessor = 0,
+
+ TransferData = 1,
+ IGMC32 = 2,
+ IGMC64 = 3,
+
+ GeneralSystemPlanar = 0, /* 10/5/95 */
+
+ } PnP_INTERFACE;
+
+/* PnP resources */
+
+/* Compressed ASCII is 5 bits per char; 00001=A ... 11010=Z */
+
+typedef struct _SERIAL_ID {
+ unsigned char VendorID0; /* Bit(7)=0 */
+ /* Bits(6:2)=1st character in */
+ /* compressed ASCII */
+ /* Bits(1:0)=2nd character in */
+ /* compressed ASCII bits(4:3) */
+ unsigned char VendorID1; /* Bits(7:5)=2nd character in */
+ /* compressed ASCII bits(2:0) */
+ /* Bits(4:0)=3rd character in */
+ /* compressed ASCII */
+ unsigned char VendorID2; /* Product number - vendor assigned */
+ unsigned char VendorID3; /* Product number - vendor assigned */
+
+/* Serial number is to provide uniqueness if more than one board of same */
+/* type is in system. Must be "FFFFFFFF" if feature not supported. */
+
+ unsigned char Serial0; /* Unique serial number bits (7:0) */
+ unsigned char Serial1; /* Unique serial number bits (15:8) */
+ unsigned char Serial2; /* Unique serial number bits (23:16) */
+ unsigned char Serial3; /* Unique serial number bits (31:24) */
+ unsigned char Checksum;
+ } SERIAL_ID;
+
+typedef enum _PnPItemName {
+ Unused = 0,
+ PnPVersion = 1,
+ LogicalDevice = 2,
+ CompatibleDevice = 3,
+ IRQFormat = 4,
+ DMAFormat = 5,
+ StartDepFunc = 6,
+ EndDepFunc = 7,
+ IOPort = 8,
+ FixedIOPort = 9,
+ Res1 = 10,
+ Res2 = 11,
+ Res3 = 12,
+ SmallVendorItem = 14,
+ EndTag = 15,
+ MemoryRange = 1,
+ ANSIIdentifier = 2,
+ UnicodeIdentifier = 3,
+ LargeVendorItem = 4,
+ MemoryRange32 = 5,
+ MemoryRangeFixed32 = 6,
+ } PnPItemName;
+
+/* Define a bunch of access functions for the bits in the tag field */
+
+/* Tag type - 0 = small; 1 = large */
+#define tag_type(t) (((t) & 0x80)>>7)
+#define set_tag_type(t,v) (t = (t & 0x7f) | ((v)<<7))
+
+/* Small item name is 4 bits - one of PnPItemName enum above */
+#define tag_small_item_name(t) (((t) & 0x78)>>3)
+#define set_tag_small_item_name(t,v) (t = (t & 0x07) | ((v)<<3))
+
+/* Small item count is 3 bits - count of further bytes in packet */
+#define tag_small_count(t) ((t) & 0x07)
+#define set_tag_count(t,v) (t = (t & 0x78) | (v))
+
+/* Large item name is 7 bits - one of PnPItemName enum above */
+#define tag_large_item_name(t) ((t) & 0x7f)
+#define set_tag_large_item_name(t,v) (t = (t | 0x80) | (v))
+
+/* a PnP resource is a bunch of contiguous TAG packets ending with an end tag */
+
+typedef union _PnP_TAG_PACKET {
+ struct _S1_Pack{ /* VERSION PACKET */
+ unsigned char Tag; /* small tag = 0x0a */
+ unsigned char Version[2]; /* PnP version, Vendor version */
+ } S1_Pack;
+
+ struct _S2_Pack{ /* LOGICAL DEVICE ID PACKET */
+ unsigned char Tag; /* small tag = 0x15 or 0x16 */
+ unsigned char DevId[4]; /* Logical device id */
+ unsigned char Flags[2]; /* bit(0) boot device; */
+ /* bit(7:1) cmd in range x31-x37 */
+ /* bit(7:0) cmd in range x28-x3f (opt)*/
+ } S2_Pack;
+
+ struct _S3_Pack{ /* COMPATIBLE DEVICE ID PACKET */
+ unsigned char Tag; /* small tag = 0x1c */
+ unsigned char CompatId[4]; /* Compatible device id */
+ } S3_Pack;
+
+ struct _S4_Pack{ /* IRQ PACKET */
+ unsigned char Tag; /* small tag = 0x22 or 0x23 */
+ unsigned char IRQMask[2]; /* bit(0) is IRQ0, ...; */
+ /* bit(0) is IRQ8 ... */
+ unsigned char IRQInfo; /* optional; assume bit(0)=1; else */
+ /* bit(0) - high true edge sensitive */
+ /* bit(1) - low true edge sensitive */
+ /* bit(2) - high true level sensitive*/
+ /* bit(3) - low true level sensitive */
+ /* bit(7:4) - must be 0 */
+ } S4_Pack;
+
+ struct _S5_Pack{ /* DMA PACKET */
+ unsigned char Tag; /* small tag = 0x2a */
+ unsigned char DMAMask; /* bit(0) is channel 0 ... */
+ unsigned char DMAInfo;
+ } S5_Pack;
+
+ struct _S6_Pack{ /* START DEPENDENT FUNCTION PACKET */
+ unsigned char Tag; /* small tag = 0x30 or 0x31 */
+ unsigned char Priority; /* Optional; if missing then x01; else*/
+ /* x00 = best possible */
+ /* x01 = acceptible */
+ /* x02 = sub-optimal but functional */
+ } S6_Pack;
+
+ struct _S7_Pack{ /* END DEPENDENT FUNCTION PACKET */
+ unsigned char Tag; /* small tag = 0x38 */
+ } S7_Pack;
+
+ struct _S8_Pack{ /* VARIABLE I/O PORT PACKET */
+ unsigned char Tag; /* small tag x47 */
+ unsigned char IOInfo; /* x0 = decode only bits(9:0); */
+#define ISAAddr16bit 0x01 /* x01 = decode bits(15:0) */
+ unsigned char RangeMin[2]; /* Min base address */
+ unsigned char RangeMax[2]; /* Max base address */
+ unsigned char IOAlign; /* base alignmt, incr in 1B blocks */
+ unsigned char IONum; /* number of contiguous I/O ports */
+ } S8_Pack;
+
+ struct _S9_Pack{ /* FIXED I/O PORT PACKET */
+ unsigned char Tag; /* small tag = 0x4b */
+ unsigned char Range[2]; /* base address 10 bits */
+ unsigned char IONum; /* number of contiguous I/O ports */
+ } S9_Pack;
+
+ struct _S14_Pack{ /* VENDOR DEFINED PACKET */
+ unsigned char Tag; /* small tag = 0x7m m = 1-7 */
+ union _S14_Data{
+ unsigned char Data[7]; /* Vendor defined */
+ struct _S14_PPCPack{ /* Pr*p s14 pack */
+ unsigned char Type; /* 00=non-IBM */
+ unsigned char PPCData[6]; /* Vendor defined */
+ } S14_PPCPack;
+ } S14_Data;
+ } S14_Pack;
+
+ struct _S15_Pack{ /* END PACKET */
+ unsigned char Tag; /* small tag = 0x78 or 0x79 */
+ unsigned char Check; /* optional - checksum */
+ } S15_Pack;
+
+ struct _L1_Pack{ /* MEMORY RANGE PACKET */
+ unsigned char Tag; /* large tag = 0x81 */
+ unsigned char Count0; /* x09 */
+ unsigned char Count1; /* x00 */
+ unsigned char Data[9]; /* a variable array of bytes, */
+ /* count in tag */
+ } L1_Pack;
+
+ struct _L2_Pack{ /* ANSI ID STRING PACKET */
+ unsigned char Tag; /* large tag = 0x82 */
+ unsigned char Count0; /* Length of string */
+ unsigned char Count1;
+ unsigned char Identifier[1]; /* a variable array of bytes, */
+ /* count in tag */
+ } L2_Pack;
+
+ struct _L3_Pack{ /* UNICODE ID STRING PACKET */
+ unsigned char Tag; /* large tag = 0x83 */
+ unsigned char Count0; /* Length + 2 of string */
+ unsigned char Count1;
+ unsigned char Country0; /* TBD */
+ unsigned char Country1; /* TBD */
+ unsigned char Identifier[1]; /* a variable array of bytes, */
+ /* count in tag */
+ } L3_Pack;
+
+ struct _L4_Pack{ /* VENDOR DEFINED PACKET */
+ unsigned char Tag; /* large tag = 0x84 */
+ unsigned char Count0;
+ unsigned char Count1;
+ union _L4_Data{
+ unsigned char Data[1]; /* a variable array of bytes, */
+ /* count in tag */
+ struct _L4_PPCPack{ /* Pr*p L4 packet */
+ unsigned char Type; /* 00=non-IBM */
+ unsigned char PPCData[1]; /* a variable array of bytes, */
+ /* count in tag */
+ } L4_PPCPack;
+ } L4_Data;
+ } L4_Pack;
+
+ struct _L5_Pack{
+ unsigned char Tag; /* large tag = 0x85 */
+ unsigned char Count0; /* Count = 17 */
+ unsigned char Count1;
+ unsigned char Data[17];
+ } L5_Pack;
+
+ struct _L6_Pack{
+ unsigned char Tag; /* large tag = 0x86 */
+ unsigned char Count0; /* Count = 9 */
+ unsigned char Count1;
+ unsigned char Data[9];
+ } L6_Pack;
+
+ } PnP_TAG_PACKET;
+
+#endif /* __ASSEMBLY__ */
+#endif /* ndef _PNP_ */
diff --git a/arch/powerpc/include/asm/posix_types.h b/arch/powerpc/include/asm/posix_types.h
new file mode 100644
index 0000000..9170728
--- /dev/null
+++ b/arch/powerpc/include/asm/posix_types.h
@@ -0,0 +1,109 @@
+#ifndef _PPC_POSIX_TYPES_H
+#define _PPC_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned int __kernel_dev_t;
+typedef unsigned int __kernel_ino_t;
+typedef unsigned int __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef long __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned int __kernel_old_uid_t;
+typedef unsigned int __kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+#endif
+
+typedef struct {
+ int val[2];
+} __kernel_fsid_t;
+
+#ifndef __GNUC__
+
+#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define __FD_ZERO(set) \
+ ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+
+#else /* __GNUC__ */
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+/* With GNU C, use inline functions instead so args are evaluated only once: */
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+{
+ unsigned int *tmp = (unsigned int *)p->fds_bits;
+ int i;
+
+ if (__builtin_constant_p(__FDSET_LONGS)) {
+ switch (__FDSET_LONGS) {
+ case 8:
+ tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+ tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+ return;
+ }
+ }
+ i = __FDSET_LONGS;
+ while (i) {
+ i--;
+ *tmp = 0;
+ tmp++;
+ }
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#endif /* __GNUC__ */
+#endif /* _PPC_POSIX_TYPES_H */
diff --git a/arch/powerpc/include/asm/ppc405.h b/arch/powerpc/include/asm/ppc405.h
new file mode 100644
index 0000000..892848a
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc405.h
@@ -0,0 +1,76 @@
+/*----------------------------------------------------------------------------+
+| This source code is dual-licensed. You may use it under the terms of the
+| GNU General Public License version 2, or under the license below.
+|
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1999
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+
+#ifndef __PPC405_H__
+#define __PPC405_H__
+
+/* Define bits and masks for real-mode storage attribute control registers */
+#define PPC_128MB_SACR_BIT(addr) ((addr) >> 27)
+#define PPC_128MB_SACR_VALUE(addr) PPC_REG_VAL(PPC_128MB_SACR_BIT(addr),1)
+
+#define CONFIG_SYS_DCACHE_SIZE (16 << 10) /* For AMCC 405 CPUs */
+
+/* DCR registers */
+#define PLB0_ACR 0x0087
+
+/* SDR registers */
+#define SDR0_PINSTP 0x0040
+
+/* CPR registers */
+#define CPR0_CLKUPD 0x0020
+#define CPR0_PLLC 0x0040
+#define CPR0_PLLD 0x0060
+#define CPR0_CPUD 0x0080
+#define CPR0_PLBD 0x00a0
+#define CPR0_OPBD0 0x00c0
+#define CPR0_PERD 0x00e0
+
+/*
+ * DMA
+ */
+#define DMA_DCR_BASE 0x0100
+#define DMACR0 (DMA_DCR_BASE + 0x00) /* DMA channel control reg 0 */
+#define DMACT0 (DMA_DCR_BASE + 0x01) /* DMA count reg 0 */
+#define DMADA0 (DMA_DCR_BASE + 0x02) /* DMA destination address reg 0 */
+#define DMASA0 (DMA_DCR_BASE + 0x03) /* DMA source address reg 0 */
+#define DMASB0 (DMA_DCR_BASE + 0x04) /* DMA sg descriptor addr 0 */
+#define DMACR1 (DMA_DCR_BASE + 0x08) /* DMA channel control reg 1 */
+#define DMACT1 (DMA_DCR_BASE + 0x09) /* DMA count reg 1 */
+#define DMADA1 (DMA_DCR_BASE + 0x0a) /* DMA destination address reg 1 */
+#define DMASA1 (DMA_DCR_BASE + 0x0b) /* DMA source address reg 1 */
+#define DMASB1 (DMA_DCR_BASE + 0x0c) /* DMA sg descriptor addr 1 */
+#define DMACR2 (DMA_DCR_BASE + 0x10) /* DMA channel control reg 2 */
+#define DMACT2 (DMA_DCR_BASE + 0x11) /* DMA count reg 2 */
+#define DMADA2 (DMA_DCR_BASE + 0x12) /* DMA destination address reg 2 */
+#define DMASA2 (DMA_DCR_BASE + 0x13) /* DMA source address reg 2 */
+#define DMASB2 (DMA_DCR_BASE + 0x14) /* DMA sg descriptor addr 2 */
+#define DMACR3 (DMA_DCR_BASE + 0x18) /* DMA channel control reg 3 */
+#define DMACT3 (DMA_DCR_BASE + 0x19) /* DMA count reg 3 */
+#define DMADA3 (DMA_DCR_BASE + 0x1a) /* DMA destination address reg 3 */
+#define DMASA3 (DMA_DCR_BASE + 0x1b) /* DMA source address reg 3 */
+#define DMASB3 (DMA_DCR_BASE + 0x1c) /* DMA sg descriptor addr 3 */
+#define DMASR (DMA_DCR_BASE + 0x20) /* DMA status reg */
+#define DMASGC (DMA_DCR_BASE + 0x23) /* DMA scatter/gather command reg*/
+#define DMAADR (DMA_DCR_BASE + 0x24) /* DMA address decode reg */
+
+#endif /* __PPC405_H__ */
diff --git a/arch/powerpc/include/asm/ppc405cr.h b/arch/powerpc/include/asm/ppc405cr.h
new file mode 100644
index 0000000..01078f7
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc405cr.h
@@ -0,0 +1,105 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC405CR_H_
+#define _PPC405CR_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_SDRAM /* IBM SDRAM controller */
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+/* DCR's */
+#define DCP0_CFGADDR 0x0014 /* Decompression controller addr reg */
+#define DCP0_CFGDATA 0x0015 /* Decompression controller data reg */
+#define OCM0_ISCNTL 0x0019 /* OCM I-side control reg */
+#define OCM0_DSARC 0x001a /* OCM D-side address compare */
+#define OCM0_DSCNTL 0x001b /* OCM D-side control */
+#define CPC0_PLLMR 0x00b0 /* PLL mode register */
+#define CPC0_CR0 0x00b1 /* chip control register 0 */
+#define CPC0_CR1 0x00b2 /* chip control register 1 */
+#define CPC0_PSR 0x00b4 /* chip pin strapping reg */
+#define CPC0_EIRR 0x00b6 /* ext interrupt routing reg */
+#define CPC0_SR 0x00b8 /* Power management status */
+#define CPC0_ER 0x00b9 /* Power management enable */
+#define CPC0_FR 0x00ba /* Power management force */
+#define CPC0_ECR 0x00aa /* edge conditioner register */
+
+#define PLLMR_FWD_DIV_MASK 0xE0000000 /* Forward Divisor */
+#define PLLMR_FWD_DIV_BYPASS 0xE0000000
+#define PLLMR_FWD_DIV_3 0xA0000000
+#define PLLMR_FWD_DIV_4 0x80000000
+#define PLLMR_FWD_DIV_6 0x40000000
+
+#define PLLMR_FB_DIV_MASK 0x1E000000 /* Feedback Divisor */
+#define PLLMR_FB_DIV_1 0x02000000
+#define PLLMR_FB_DIV_2 0x04000000
+#define PLLMR_FB_DIV_3 0x06000000
+#define PLLMR_FB_DIV_4 0x08000000
+
+#define PLLMR_TUNING_MASK 0x01F80000
+
+#define PLLMR_CPU_TO_PLB_MASK 0x00060000 /* CPU:PLB Frequency Divisor */
+#define PLLMR_CPU_PLB_DIV_1 0x00000000
+#define PLLMR_CPU_PLB_DIV_2 0x00020000
+#define PLLMR_CPU_PLB_DIV_3 0x00040000
+#define PLLMR_CPU_PLB_DIV_4 0x00060000
+
+#define PLLMR_OPB_TO_PLB_MASK 0x00018000 /* OPB:PLB Frequency Divisor */
+#define PLLMR_OPB_PLB_DIV_1 0x00000000
+#define PLLMR_OPB_PLB_DIV_2 0x00008000
+#define PLLMR_OPB_PLB_DIV_3 0x00010000
+#define PLLMR_OPB_PLB_DIV_4 0x00018000
+
+#define PLLMR_PCI_TO_PLB_MASK 0x00006000 /* PCI:PLB Frequency Divisor */
+#define PLLMR_PCI_PLB_DIV_1 0x00000000
+#define PLLMR_PCI_PLB_DIV_2 0x00002000
+#define PLLMR_PCI_PLB_DIV_3 0x00004000
+#define PLLMR_PCI_PLB_DIV_4 0x00006000
+
+#define PLLMR_EXB_TO_PLB_MASK 0x00001800 /* External Bus:PLB Divisor */
+#define PLLMR_EXB_PLB_DIV_2 0x00000000
+#define PLLMR_EXB_PLB_DIV_3 0x00000800
+#define PLLMR_EXB_PLB_DIV_4 0x00001000
+#define PLLMR_EXB_PLB_DIV_5 0x00001800
+
+/* definitions for PPC405GPr (new mode strapping) */
+#define PLLMR_FWDB_DIV_MASK 0x00000007 /* Forward Divisor B */
+
+#define PSR_PLL_FWD_MASK 0xC0000000
+#define PSR_PLL_FDBACK_MASK 0x30000000
+#define PSR_PLL_TUNING_MASK 0x0E000000
+#define PSR_PLB_CPU_MASK 0x01800000
+#define PSR_OPB_PLB_MASK 0x00600000
+#define PSR_PCI_PLB_MASK 0x00180000
+#define PSR_EB_PLB_MASK 0x00060000
+#define PSR_ROM_WIDTH_MASK 0x00018000
+#define PSR_ROM_LOC 0x00004000
+#define PSR_PCI_ASYNC_EN 0x00001000
+#define PSR_PERCLK_SYNC_MODE_EN 0x00000800 /* PPC405GPr only */
+#define PSR_PCI_ARBIT_EN 0x00000400
+#define PSR_NEW_MODE_EN 0x00000020 /* PPC405GPr only */
+
+#endif /* _PPC405CR_H_ */
diff --git a/arch/powerpc/include/asm/ppc405ep.h b/arch/powerpc/include/asm/ppc405ep.h
new file mode 100644
index 0000000..9691604
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc405ep.h
@@ -0,0 +1,252 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC405EP_H_
+#define _PPC405EP_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_SDRAM /* IBM SDRAM controller */
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+/* DCR */
+#define OCM0_ISCNTL 0x0019 /* OCM I-side control reg */
+#define OCM0_DSARC 0x001a /* OCM D-side address compare */
+#define OCM0_DSCNTL 0x001b /* OCM D-side control */
+#define CPC0_PLLMR0 0x00f0 /* PLL mode register 0 */
+#define CPC0_BOOT 0x00f1 /* Clock status register */
+#define CPC0_CR1 0x00f2 /* Chip Control 1 register */
+#define CPC0_EPCTL 0x00f3 /* EMAC to PHY control register */
+#define CPC0_PLLMR1 0x00f4 /* PLL mode register 1 */
+#define CPC0_UCR 0x00f5 /* UART control register */
+#define CPC0_SRR 0x00f6 /* Soft Reset register */
+#define CPC0_PCI 0x00f9 /* PCI control register */
+
+/* Defines for CPC0_EPCTL register */
+#define CPC0_EPCTL_E0NFE 0x80000000
+#define CPC0_EPCTL_E1NFE 0x40000000
+
+/* Defines for CPC0_PCI Register */
+#define CPC0_PCI_SPE 0x00000010 /* PCIINT/WE select */
+#define CPC0_PCI_HOST_CFG_EN 0x00000008 /* PCI host config Enable */
+#define CPC0_PCI_ARBIT_EN 0x00000001 /* PCI Internal Arb Enabled */
+
+/* Defines for CPC0_BOOR Register */
+#define CPC0_BOOT_SEP 0x00000002 /* serial EEPROM present */
+
+/* Bit definitions */
+#define PLLMR0_CPU_DIV_MASK 0x00300000 /* CPU clock divider */
+#define PLLMR0_CPU_DIV_BYPASS 0x00000000
+#define PLLMR0_CPU_DIV_2 0x00100000
+#define PLLMR0_CPU_DIV_3 0x00200000
+#define PLLMR0_CPU_DIV_4 0x00300000
+
+#define PLLMR0_CPU_TO_PLB_MASK 0x00030000 /* CPU:PLB Frequency Divisor */
+#define PLLMR0_CPU_PLB_DIV_1 0x00000000
+#define PLLMR0_CPU_PLB_DIV_2 0x00010000
+#define PLLMR0_CPU_PLB_DIV_3 0x00020000
+#define PLLMR0_CPU_PLB_DIV_4 0x00030000
+
+#define PLLMR0_OPB_TO_PLB_MASK 0x00003000 /* OPB:PLB Frequency Divisor */
+#define PLLMR0_OPB_PLB_DIV_1 0x00000000
+#define PLLMR0_OPB_PLB_DIV_2 0x00001000
+#define PLLMR0_OPB_PLB_DIV_3 0x00002000
+#define PLLMR0_OPB_PLB_DIV_4 0x00003000
+
+#define PLLMR0_EXB_TO_PLB_MASK 0x00000300 /* External Bus:PLB Divisor */
+#define PLLMR0_EXB_PLB_DIV_2 0x00000000
+#define PLLMR0_EXB_PLB_DIV_3 0x00000100
+#define PLLMR0_EXB_PLB_DIV_4 0x00000200
+#define PLLMR0_EXB_PLB_DIV_5 0x00000300
+
+#define PLLMR0_MAL_TO_PLB_MASK 0x00000030 /* MAL:PLB Divisor */
+#define PLLMR0_MAL_PLB_DIV_1 0x00000000
+#define PLLMR0_MAL_PLB_DIV_2 0x00000010
+#define PLLMR0_MAL_PLB_DIV_3 0x00000020
+#define PLLMR0_MAL_PLB_DIV_4 0x00000030
+
+#define PLLMR0_PCI_TO_PLB_MASK 0x00000003 /* PCI:PLB Frequency Divisor */
+#define PLLMR0_PCI_PLB_DIV_1 0x00000000
+#define PLLMR0_PCI_PLB_DIV_2 0x00000001
+#define PLLMR0_PCI_PLB_DIV_3 0x00000002
+#define PLLMR0_PCI_PLB_DIV_4 0x00000003
+
+#define PLLMR1_SSCS_MASK 0x80000000 /* Select system clock source */
+#define PLLMR1_PLLR_MASK 0x40000000 /* PLL reset */
+#define PLLMR1_FBMUL_MASK 0x00F00000 /* PLL feedback multiplier value */
+
+#define PLLMR1_FWDVA_MASK 0x00070000 /* PLL forward divider A value */
+#define PLLMR1_FWDVB_MASK 0x00007000 /* PLL forward divider B value */
+#define PLLMR1_TUNING_MASK 0x000003FF /* PLL tune bits */
+
+/* Defines for CPC0_PLLMR1 Register fields */
+#define PLL_ACTIVE 0x80000000
+#define CPC0_PLLMR1_SSCS 0x80000000
+#define PLL_RESET 0x40000000
+#define CPC0_PLLMR1_PLLR 0x40000000
+/* Feedback multiplier */
+#define PLL_FBKDIV 0x00F00000
+#define CPC0_PLLMR1_FBDV 0x00F00000
+#define PLL_FBKDIV_16 0x00000000
+#define PLL_FBKDIV_1 0x00100000
+#define PLL_FBKDIV_2 0x00200000
+#define PLL_FBKDIV_3 0x00300000
+#define PLL_FBKDIV_4 0x00400000
+#define PLL_FBKDIV_5 0x00500000
+#define PLL_FBKDIV_6 0x00600000
+#define PLL_FBKDIV_7 0x00700000
+#define PLL_FBKDIV_8 0x00800000
+#define PLL_FBKDIV_9 0x00900000
+#define PLL_FBKDIV_10 0x00A00000
+#define PLL_FBKDIV_11 0x00B00000
+#define PLL_FBKDIV_12 0x00C00000
+#define PLL_FBKDIV_13 0x00D00000
+#define PLL_FBKDIV_14 0x00E00000
+#define PLL_FBKDIV_15 0x00F00000
+/* Forward A divisor */
+#define PLL_FWDDIVA 0x00070000
+#define CPC0_PLLMR1_FWDVA 0x00070000
+#define PLL_FWDDIVA_8 0x00000000
+#define PLL_FWDDIVA_7 0x00010000
+#define PLL_FWDDIVA_6 0x00020000
+#define PLL_FWDDIVA_5 0x00030000
+#define PLL_FWDDIVA_4 0x00040000
+#define PLL_FWDDIVA_3 0x00050000
+#define PLL_FWDDIVA_2 0x00060000
+#define PLL_FWDDIVA_1 0x00070000
+/* Forward B divisor */
+#define PLL_FWDDIVB 0x00007000
+#define CPC0_PLLMR1_FWDVB 0x00007000
+#define PLL_FWDDIVB_8 0x00000000
+#define PLL_FWDDIVB_7 0x00001000
+#define PLL_FWDDIVB_6 0x00002000
+#define PLL_FWDDIVB_5 0x00003000
+#define PLL_FWDDIVB_4 0x00004000
+#define PLL_FWDDIVB_3 0x00005000
+#define PLL_FWDDIVB_2 0x00006000
+#define PLL_FWDDIVB_1 0x00007000
+/* PLL tune bits */
+#define PLL_TUNE_MASK 0x000003FF
+#define PLL_TUNE_2_M_3 0x00000133 /* 2 <= M <= 3 */
+#define PLL_TUNE_4_M_6 0x00000134 /* 3 < M <= 6 */
+#define PLL_TUNE_7_M_10 0x00000138 /* 6 < M <= 10 */
+#define PLL_TUNE_11_M_14 0x0000013C /* 10 < M <= 14 */
+#define PLL_TUNE_15_M_40 0x0000023E /* 14 < M <= 40 */
+#define PLL_TUNE_VCO_LOW 0x00000000 /* 500MHz <= VCO <= 800MHz */
+#define PLL_TUNE_VCO_HI 0x00000080 /* 800MHz < VCO <= 1000MHz */
+
+/* Defines for CPC0_PLLMR0 Register fields */
+/* CPU divisor */
+#define PLL_CPUDIV 0x00300000
+#define CPC0_PLLMR0_CCDV 0x00300000
+#define PLL_CPUDIV_1 0x00000000
+#define PLL_CPUDIV_2 0x00100000
+#define PLL_CPUDIV_3 0x00200000
+#define PLL_CPUDIV_4 0x00300000
+/* PLB divisor */
+#define PLL_PLBDIV 0x00030000
+#define CPC0_PLLMR0_CBDV 0x00030000
+#define PLL_PLBDIV_1 0x00000000
+#define PLL_PLBDIV_2 0x00010000
+#define PLL_PLBDIV_3 0x00020000
+#define PLL_PLBDIV_4 0x00030000
+/* OPB divisor */
+#define PLL_OPBDIV 0x00003000
+#define CPC0_PLLMR0_OPDV 0x00003000
+#define PLL_OPBDIV_1 0x00000000
+#define PLL_OPBDIV_2 0x00001000
+#define PLL_OPBDIV_3 0x00002000
+#define PLL_OPBDIV_4 0x00003000
+/* EBC divisor */
+#define PLL_EXTBUSDIV 0x00000300
+#define CPC0_PLLMR0_EPDV 0x00000300
+#define PLL_EXTBUSDIV_2 0x00000000
+#define PLL_EXTBUSDIV_3 0x00000100
+#define PLL_EXTBUSDIV_4 0x00000200
+#define PLL_EXTBUSDIV_5 0x00000300
+/* MAL divisor */
+#define PLL_MALDIV 0x00000030
+#define CPC0_PLLMR0_MPDV 0x00000030
+#define PLL_MALDIV_1 0x00000000
+#define PLL_MALDIV_2 0x00000010
+#define PLL_MALDIV_3 0x00000020
+#define PLL_MALDIV_4 0x00000030
+/* PCI divisor */
+#define PLL_PCIDIV 0x00000003
+#define CPC0_PLLMR0_PPFD 0x00000003
+#define PLL_PCIDIV_1 0x00000000
+#define PLL_PCIDIV_2 0x00000001
+#define PLL_PCIDIV_3 0x00000002
+#define PLL_PCIDIV_4 0x00000003
+
+/*
+ * PLL settings for 266MHz CPU, 133MHz PLB/SDRAM, 66MHz EBC, 33MHz PCI,
+ * assuming a 33.3MHz input clock to the 405EP.
+ */
+#define PLLMR0_266_133_66 (PLL_CPUDIV_1 | PLL_PLBDIV_2 | \
+ PLL_OPBDIV_2 | PLL_EXTBUSDIV_2 | \
+ PLL_MALDIV_1 | PLL_PCIDIV_4)
+#define PLLMR1_266_133_66 (PLL_FBKDIV_8 | \
+ PLL_FWDDIVA_3 | PLL_FWDDIVB_3 | \
+ PLL_TUNE_15_M_40 | PLL_TUNE_VCO_LOW)
+
+#define PLLMR0_133_66_66_33 (PLL_CPUDIV_1 | PLL_PLBDIV_1 | \
+ PLL_OPBDIV_2 | PLL_EXTBUSDIV_4 | \
+ PLL_MALDIV_1 | PLL_PCIDIV_4)
+#define PLLMR1_133_66_66_33 (PLL_FBKDIV_4 | \
+ PLL_FWDDIVA_6 | PLL_FWDDIVB_6 | \
+ PLL_TUNE_15_M_40 | PLL_TUNE_VCO_LOW)
+#define PLLMR0_200_100_50_33 (PLL_CPUDIV_1 | PLL_PLBDIV_2 | \
+ PLL_OPBDIV_2 | PLL_EXTBUSDIV_3 | \
+ PLL_MALDIV_1 | PLL_PCIDIV_4)
+#define PLLMR1_200_100_50_33 (PLL_FBKDIV_6 | \
+ PLL_FWDDIVA_4 | PLL_FWDDIVB_4 | \
+ PLL_TUNE_15_M_40 | PLL_TUNE_VCO_LOW)
+#define PLLMR0_266_133_66_33 (PLL_CPUDIV_1 | PLL_PLBDIV_2 | \
+ PLL_OPBDIV_2 | PLL_EXTBUSDIV_4 | \
+ PLL_MALDIV_1 | PLL_PCIDIV_4)
+#define PLLMR1_266_133_66_33 (PLL_FBKDIV_8 | \
+ PLL_FWDDIVA_3 | PLL_FWDDIVB_3 | \
+ PLL_TUNE_15_M_40 | PLL_TUNE_VCO_LOW)
+#define PLLMR0_266_66_33_33 (PLL_CPUDIV_1 | PLL_PLBDIV_4 | \
+ PLL_OPBDIV_2 | PLL_EXTBUSDIV_2 | \
+ PLL_MALDIV_1 | PLL_PCIDIV_2)
+#define PLLMR1_266_66_33_33 (PLL_FBKDIV_8 | \
+ PLL_FWDDIVA_3 | PLL_FWDDIVB_3 | \
+ PLL_TUNE_15_M_40 | PLL_TUNE_VCO_LOW)
+#define PLLMR0_333_111_55_37 (PLL_CPUDIV_1 | PLL_PLBDIV_3 | \
+ PLL_OPBDIV_2 | PLL_EXTBUSDIV_2 | \
+ PLL_MALDIV_1 | PLL_PCIDIV_3)
+#define PLLMR1_333_111_55_37 (PLL_FBKDIV_10 | \
+ PLL_FWDDIVA_3 | PLL_FWDDIVB_3 | \
+ PLL_TUNE_15_M_40 | PLL_TUNE_VCO_HI)
+#define PLLMR0_333_111_55_111 (PLL_CPUDIV_1 | PLL_PLBDIV_3 | \
+ PLL_OPBDIV_2 | PLL_EXTBUSDIV_2 | \
+ PLL_MALDIV_1 | PLL_PCIDIV_1)
+#define PLLMR1_333_111_55_111 (PLL_FBKDIV_10 | \
+ PLL_FWDDIVA_3 | PLL_FWDDIVB_3 | \
+ PLL_TUNE_15_M_40 | PLL_TUNE_VCO_HI)
+
+#endif /* _PPC405EP_H_ */
diff --git a/arch/powerpc/include/asm/ppc405ex.h b/arch/powerpc/include/asm/ppc405ex.h
new file mode 100644
index 0000000..8070385
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc405ex.h
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC405EX_H_
+#define _PPC405EX_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
+
+#define CONFIG_NAND_NDFC
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0200)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0800)
+
+/* SDR */
+#define SDR0_SDCS0 0x0060
+#define SDR0_UART0 0x0120 /* UART0 Config */
+#define SDR0_UART1 0x0121 /* UART1 Config */
+#define SDR0_SRST 0x0200
+#define SDR0_CUST0 0x4000
+#define SDR0_PFC0 0x4100
+#define SDR0_PFC1 0x4101
+#define SDR0_MFR 0x4300 /* SDR0_MFR reg */
+
+#define SDR0_ECID0 0x0080
+#define SDR0_ECID1 0x0081
+#define SDR0_ECID2 0x0082
+#define SDR0_ECID3 0x0083
+
+#define SDR0_SDCS_SDD (0x80000000 >> 31)
+
+#define SDR0_SRST_DMC (0x80000000 >> 10)
+
+#define SDR0_CUST0_MUX_E_N_G_MASK 0xC0000000 /* Mux_Emac_NDFC_GPIO */
+#define SDR0_CUST0_MUX_EMAC_SEL 0x40000000 /* Emac Selection */
+#define SDR0_CUST0_MUX_NDFC_SEL 0x80000000 /* NDFC Selection */
+#define SDR0_CUST0_MUX_GPIO_SEL 0xC0000000 /* GPIO Selection */
+
+#define SDR0_CUST0_NDFC_EN_MASK 0x20000000 /* NDFC Enable Mask */
+#define SDR0_CUST0_NDFC_ENABLE 0x20000000 /* NDFC Enable */
+#define SDR0_CUST0_NDFC_DISABLE 0x00000000 /* NDFC Disable */
+
+#define SDR0_CUST0_NDFC_BW_MASK 0x10000000 /* NDFC Boot Width */
+#define SDR0_CUST0_NDFC_BW_16_BIT 0x10000000 /* NDFC Boot Width= 16 Bit */
+#define SDR0_CUST0_NDFC_BW_8_BIT 0x00000000 /* NDFC Boot Width= 8 Bit */
+
+#define SDR0_CUST0_NDFC_BP_MASK 0x0F000000 /* NDFC Boot Page */
+#define SDR0_CUST0_NDFC_BP_ENCODE(n) ((((u32)(n)) & 0xF) << 24)
+#define SDR0_CUST0_NDFC_BP_DECODE(n) ((((u32)(n)) >> 24) & 0xF)
+
+#define SDR0_CUST0_NDFC_BAC_MASK 0x00C00000 /* NDFC Boot Address Cycle */
+#define SDR0_CUST0_NDFC_BAC_ENCODE(n) ((((u32)(n)) & 0x3) << 22)
+#define SDR0_CUST0_NDFC_BAC_DECODE(n) ((((u32)(n)) >> 22) & 0x3)
+
+#define SDR0_CUST0_NDFC_ARE_MASK 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_ENABLE 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_DISABLE 0x00000000 /* NDFC Auto Read Disable */
+
+#define SDR0_CUST0_NRB_MASK 0x00100000 /* NDFC Ready / Busy */
+#define SDR0_CUST0_NRB_BUSY 0x00100000 /* Busy */
+#define SDR0_CUST0_NRB_READY 0x00000000 /* Ready */
+
+#define SDR0_PFC1_U1ME 0x02000000
+#define SDR0_PFC1_U0ME 0x00080000
+#define SDR0_PFC1_U0IM 0x00040000
+#define SDR0_PFC1_SIS 0x00020000
+#define SDR0_PFC1_DMAAEN 0x00010000
+#define SDR0_PFC1_DMADEN 0x00008000
+#define SDR0_PFC1_USBEN 0x00004000
+#define SDR0_PFC1_AHBSWAP 0x00000020
+#define SDR0_PFC1_USBBIGEN 0x00000010
+#define SDR0_PFC1_GPT_FREQ 0x0000000f
+
+#endif /* _PPC405EX_H_ */
diff --git a/arch/powerpc/include/asm/ppc405ez.h b/arch/powerpc/include/asm/ppc405ez.h
new file mode 100644
index 0000000..cb8e994
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc405ez.h
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC405EZ_H_
+#define _PPC405EZ_H_
+
+#define CONFIG_NAND_NDFC
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+#define GPIO1_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0800)
+
+/* DCR register */
+#define OCM0_PLBCR1 0x0020 /* OCM PLB3 Bank 1 Config */
+#define OCM0_PLBCR2 0x0021 /* OCM PLB3 Bank 2 Config */
+#define OCM0_PLBBEAR 0x0022 /* OCM PLB3 Bus Error Add */
+#define OCM0_DSRC1 0x0028 /* OCM D-side Bank 1 Config */
+#define OCM0_DSRC2 0x0029 /* OCM D-side Bank 2 Config */
+#define OCM0_ISRC1 0x002A /* OCM I-side Bank 1Config */
+#define OCM0_ISRC2 0x002B /* OCM I-side Bank 2 Config */
+#define OCM0_DISDPC 0x002C /* OCM D-/I-side Data Par Chk */
+
+/* SDR register */
+#define SDR0_NAND0 0x4000
+#define SDR0_ULTRA0 0x4040
+#define SDR0_ULTRA1 0x4050
+#define SDR0_ICINTSTAT 0x4510
+
+/* CPR register */
+#define CPR0_PRIMAD 0x0080
+#define CPR0_PERD0 0x00e0
+#define CPR0_PERD1 0x00e1
+#define CPR0_PERC0 0x0180
+
+#define MAL_DCR_BASE 0x380
+
+#define SDR_NAND0_NDEN 0x80000000
+#define SDR_NAND0_NDBTEN 0x40000000
+#define SDR_NAND0_NDBADR_MASK 0x30000000
+#define SDR_NAND0_NDBPG_MASK 0x0f000000
+#define SDR_NAND0_NDAREN 0x00800000
+#define SDR_NAND0_NDRBEN 0x00400000
+
+#define SDR_ULTRA0_NDGPIOBP 0x80000000
+#define SDR_ULTRA0_CSN_MASK 0x78000000
+#define SDR_ULTRA0_CSNSEL0 0x40000000
+#define SDR_ULTRA0_CSNSEL1 0x20000000
+#define SDR_ULTRA0_CSNSEL2 0x10000000
+#define SDR_ULTRA0_CSNSEL3 0x08000000
+#define SDR_ULTRA0_EBCRDYEN 0x04000000
+#define SDR_ULTRA0_SPISSINEN 0x02000000
+#define SDR_ULTRA0_NFSRSTEN 0x01000000
+
+#define SDR_ULTRA1_LEDNENABLE 0x40000000
+
+#define SDR_ICRX_STAT 0x80000000
+#define SDR_ICTX0_STAT 0x40000000
+#define SDR_ICTX1_STAT 0x20000000
+
+#define CPR_CLKUPD_ENPLLCH_EN 0x40000000 /* Enable CPR PLL Changes */
+#define CPR_CLKUPD_ENDVCH_EN 0x20000000 /* Enable CPR Sys. Div. Changes */
+#define CPR_PERD0_SPIDV_MASK 0x000F0000 /* SPI Clock Divider */
+
+#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
+
+#define PLLD_FBDV_MASK 0x1F000000 /* PLL feedback divider value */
+#define PLLD_FWDVA_MASK 0x000F0000 /* PLL forward divider A value */
+#define PLLD_FWDVB_MASK 0x00000700 /* PLL forward divider B value */
+
+#define PRIMAD_CPUDV_MASK 0x0F000000 /* CPU Clock Divisor Mask */
+#define PRIMAD_PLBDV_MASK 0x000F0000 /* PLB Clock Divisor Mask */
+#define PRIMAD_OPBDV_MASK 0x00000F00 /* OPB Clock Divisor Mask */
+#define PRIMAD_EBCDV_MASK 0x0000000F /* EBC Clock Divisor Mask */
+
+#define PERD0_PWMDV_MASK 0xFF000000 /* PWM Divider Mask */
+#define PERD0_SPIDV_MASK 0x000F0000 /* SPI Divider Mask */
+#define PERD0_U0DV_MASK 0x0000FF00 /* UART 0 Divider Mask */
+#define PERD0_U1DV_MASK 0x000000FF /* UART 1 Divider Mask */
+
+#endif /* _PPC405EZ_H_ */
diff --git a/arch/powerpc/include/asm/ppc405gp.h b/arch/powerpc/include/asm/ppc405gp.h
new file mode 100644
index 0000000..91beeb8
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc405gp.h
@@ -0,0 +1,108 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC405GP_H_
+#define _PPC405GP_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_SDRAM /* IBM SDRAM controller */
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+/* DCR's */
+#define DCP0_CFGADDR 0x0014 /* Decompression controller addr reg */
+#define DCP0_CFGDATA 0x0015 /* Decompression controller data reg */
+#define OCM0_ISCNTL 0x0019 /* OCM I-side control reg */
+#define OCM0_DSARC 0x001a /* OCM D-side address compare */
+#define OCM0_DSCNTL 0x001b /* OCM D-side control */
+#define CPC0_PLLMR 0x00b0 /* PLL mode register */
+#define CPC0_CR0 0x00b1 /* chip control register 0 */
+#define CPC0_CR1 0x00b2 /* chip control register 1 */
+#define CPC0_PSR 0x00b4 /* chip pin strapping reg */
+#define CPC0_EIRR 0x00b6 /* ext interrupt routing reg */
+#define CPC0_SR 0x00b8 /* Power management status */
+#define CPC0_ER 0x00b9 /* Power management enable */
+#define CPC0_FR 0x00ba /* Power management force */
+#define CPC0_ECR 0x00aa /* edge conditioner register */
+
+/* values for kiar register - indirect addressing of these regs */
+#define KCONF 0x40 /* decompression core config register */
+
+#define PLLMR_FWD_DIV_MASK 0xE0000000 /* Forward Divisor */
+#define PLLMR_FWD_DIV_BYPASS 0xE0000000
+#define PLLMR_FWD_DIV_3 0xA0000000
+#define PLLMR_FWD_DIV_4 0x80000000
+#define PLLMR_FWD_DIV_6 0x40000000
+
+#define PLLMR_FB_DIV_MASK 0x1E000000 /* Feedback Divisor */
+#define PLLMR_FB_DIV_1 0x02000000
+#define PLLMR_FB_DIV_2 0x04000000
+#define PLLMR_FB_DIV_3 0x06000000
+#define PLLMR_FB_DIV_4 0x08000000
+
+#define PLLMR_TUNING_MASK 0x01F80000
+
+#define PLLMR_CPU_TO_PLB_MASK 0x00060000 /* CPU:PLB Frequency Divisor */
+#define PLLMR_CPU_PLB_DIV_1 0x00000000
+#define PLLMR_CPU_PLB_DIV_2 0x00020000
+#define PLLMR_CPU_PLB_DIV_3 0x00040000
+#define PLLMR_CPU_PLB_DIV_4 0x00060000
+
+#define PLLMR_OPB_TO_PLB_MASK 0x00018000 /* OPB:PLB Frequency Divisor */
+#define PLLMR_OPB_PLB_DIV_1 0x00000000
+#define PLLMR_OPB_PLB_DIV_2 0x00008000
+#define PLLMR_OPB_PLB_DIV_3 0x00010000
+#define PLLMR_OPB_PLB_DIV_4 0x00018000
+
+#define PLLMR_PCI_TO_PLB_MASK 0x00006000 /* PCI:PLB Frequency Divisor */
+#define PLLMR_PCI_PLB_DIV_1 0x00000000
+#define PLLMR_PCI_PLB_DIV_2 0x00002000
+#define PLLMR_PCI_PLB_DIV_3 0x00004000
+#define PLLMR_PCI_PLB_DIV_4 0x00006000
+
+#define PLLMR_EXB_TO_PLB_MASK 0x00001800 /* External Bus:PLB Divisor */
+#define PLLMR_EXB_PLB_DIV_2 0x00000000
+#define PLLMR_EXB_PLB_DIV_3 0x00000800
+#define PLLMR_EXB_PLB_DIV_4 0x00001000
+#define PLLMR_EXB_PLB_DIV_5 0x00001800
+
+/* definitions for PPC405GPr (new mode strapping) */
+#define PLLMR_FWDB_DIV_MASK 0x00000007 /* Forward Divisor B */
+
+#define PSR_PLL_FWD_MASK 0xC0000000
+#define PSR_PLL_FDBACK_MASK 0x30000000
+#define PSR_PLL_TUNING_MASK 0x0E000000
+#define PSR_PLB_CPU_MASK 0x01800000
+#define PSR_OPB_PLB_MASK 0x00600000
+#define PSR_PCI_PLB_MASK 0x00180000
+#define PSR_EB_PLB_MASK 0x00060000
+#define PSR_ROM_WIDTH_MASK 0x00018000
+#define PSR_ROM_LOC 0x00004000
+#define PSR_PCI_ASYNC_EN 0x00001000
+#define PSR_PERCLK_SYNC_MODE_EN 0x00000800 /* PPC405GPr only */
+#define PSR_PCI_ARBIT_EN 0x00000400
+#define PSR_NEW_MODE_EN 0x00000020 /* PPC405GPr only */
+
+#endif /* _PPC405GP_H_ */
diff --git a/arch/powerpc/include/asm/ppc440.h b/arch/powerpc/include/asm/ppc440.h
new file mode 100644
index 0000000..0da6618
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc440.h
@@ -0,0 +1,190 @@
+/*----------------------------------------------------------------------------+
+| This source code is dual-licensed. You may use it under the terms of the
+| GNU General Public License version 2, or under the license below.
+|
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1999
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+
+/*
+ * (C) Copyright 2006
+ * Sylvie Gohl, AMCC/IBM, gohl.sylvie@fr.ibm.com
+ * Jacqueline Pira-Ferriol, AMCC/IBM, jpira-ferriol@fr.ibm.com
+ * Thierry Roman, AMCC/IBM, thierry_roman@fr.ibm.com
+ * Alain Saurel, AMCC/IBM, alain.saurel@fr.ibm.com
+ * Robert Snyder, AMCC/IBM, rob.snyder@fr.ibm.com
+ *
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __PPC440_H__
+#define __PPC440_H__
+
+#define CONFIG_SYS_DCACHE_SIZE (32 << 10) /* For AMCC 440 CPUs */
+
+/*
+ * DCRs & Related
+ */
+
+/* Memory mapped registers */
+#define PCIL0_CFGADR (CONFIG_SYS_PCI_BASE + 0x0ec00000)
+#define PCIL0_CFGDATA (CONFIG_SYS_PCI_BASE + 0x0ec00004)
+#define PCIL0_CFGBASE (CONFIG_SYS_PCI_BASE + 0x0ec80000)
+#define PCIL0_IOBASE (CONFIG_SYS_PCI_BASE + 0x08000000)
+
+/* DCR registers */
+
+/* CPR register declarations */
+#define CPR0_PLLC 0x0040
+#define CPR0_PLLD 0x0060
+#define CPR0_PRIMAD0 0x0080
+#define CPR0_PRIMBD0 0x00a0
+#define CPR0_OPBD0 0x00c0
+#define CPR0_PERD 0x00e0
+#define CPR0_MALD 0x0100
+#define CPR0_SPCID 0x0120
+#define CPR0_ICFG 0x0140
+
+/* SDR register definations */
+#define SDR0_SDSTP0 0x0020
+#define SDR0_SDSTP1 0x0021
+#define SDR0_PINSTP 0x0040
+#define SDR0_SDCS0 0x0060
+#define SDR0_ECID0 0x0080
+#define SDR0_ECID1 0x0081
+#define SDR0_ECID2 0x0082
+#define SDR0_ECID3 0x0083
+#define SDR0_DDR0 0x00e1
+#define SDR0_EBC 0x0100
+#define SDR0_UART0 0x0120
+#define SDR0_UART1 0x0121
+#define SDR0_UART2 0x0122
+#define SDR0_UART3 0x0123
+#define SDR0_CP440 0x0180
+#define SDR0_XCR 0x01c0
+#define SDR0_XCR0 0x01c0
+#define SDR0_XPLLC 0x01c1
+#define SDR0_XPLLD 0x01c2
+#define SDR0_SRST 0x0200
+#define SDR0_SRST0 SDR0_SRST
+#define SDR0_SRST1 0x0201
+#define SDR0_AMP0 0x0240
+#define SDR0_AMP1 0x0241
+#define SDR0_USB0 0x0320
+#define SDR0_CUST0 0x4000
+#define SDR0_CUST1 0x4002
+#define SDR0_CUST2 0x4004
+#define SDR0_CUST3 0x4006
+#define SDR0_PFC0 0x4100
+#define SDR0_PFC1 0x4101
+#define SDR0_PFC2 0x4102
+#define SDR0_PFC4 0x4104
+#define SDR0_MFR 0x4300
+
+#define SDR0_DDR0_DDRM_DECODE(n) ((((u32)(n)) >> 29) & 0x03)
+
+#define SDR0_PCI0_PAE_MASK (0x80000000 >> 0)
+#define SDR0_XCR0_PAE_MASK (0x80000000 >> 0)
+
+#define SDR0_PFC0_GEIE_MASK 0x00003e00
+#define SDR0_PFC0_GEIE_TRE 0x00003e00
+#define SDR0_PFC0_GEIE_NOTRE 0x00000000
+#define SDR0_PFC0_TRE_MASK (0x80000000 >> 23)
+#define SDR0_PFC0_TRE_DISABLE 0x00000000
+#define SDR0_PFC0_TRE_ENABLE (0x80000000 >> 23)
+
+/*
+ * Core Configuration/MMU configuration for 440
+ */
+#define CCR0_DAPUIB 0x00100000
+#define CCR0_DTB 0x00008000
+
+#define SDR0_SDCS_SDD (0x80000000 >> 31)
+
+/* todo: move this code from macro offsets to struct */
+#define PCIL0_VENDID (PCIL0_CFGBASE + PCI_VENDOR_ID )
+#define PCIL0_DEVID (PCIL0_CFGBASE + PCI_DEVICE_ID )
+#define PCIL0_CMD (PCIL0_CFGBASE + PCI_COMMAND )
+#define PCIL0_STATUS (PCIL0_CFGBASE + PCI_STATUS )
+#define PCIL0_REVID (PCIL0_CFGBASE + PCI_REVISION_ID )
+#define PCIL0_CLS (PCIL0_CFGBASE + PCI_CLASS_CODE)
+#define PCIL0_CACHELS (PCIL0_CFGBASE + PCI_CACHE_LINE_SIZE )
+#define PCIL0_LATTIM (PCIL0_CFGBASE + PCI_LATENCY_TIMER )
+#define PCIL0_HDTYPE (PCIL0_CFGBASE + PCI_HEADER_TYPE )
+#define PCIL0_BIST (PCIL0_CFGBASE + PCI_BIST )
+#define PCIL0_BAR0 (PCIL0_CFGBASE + PCI_BASE_ADDRESS_0 )
+#define PCIL0_BAR1 (PCIL0_CFGBASE + PCI_BASE_ADDRESS_1 )
+#define PCIL0_BAR2 (PCIL0_CFGBASE + PCI_BASE_ADDRESS_2 )
+#define PCIL0_BAR3 (PCIL0_CFGBASE + PCI_BASE_ADDRESS_3 )
+#define PCIL0_BAR4 (PCIL0_CFGBASE + PCI_BASE_ADDRESS_4 )
+#define PCIL0_BAR5 (PCIL0_CFGBASE + PCI_BASE_ADDRESS_5 )
+#define PCIL0_CISPTR (PCIL0_CFGBASE + PCI_CARDBUS_CIS )
+#define PCIL0_SBSYSVID (PCIL0_CFGBASE + PCI_SUBSYSTEM_VENDOR_ID )
+#define PCIL0_SBSYSID (PCIL0_CFGBASE + PCI_SUBSYSTEM_ID )
+#define PCIL0_EROMBA (PCIL0_CFGBASE + PCI_ROM_ADDRESS )
+#define PCIL0_CAP (PCIL0_CFGBASE + PCI_CAPABILITY_LIST )
+#define PCIL0_RES0 (PCIL0_CFGBASE + 0x0035 )
+#define PCIL0_RES1 (PCIL0_CFGBASE + 0x0036 )
+#define PCIL0_RES2 (PCIL0_CFGBASE + 0x0038 )
+#define PCIL0_INTLN (PCIL0_CFGBASE + PCI_INTERRUPT_LINE )
+#define PCIL0_INTPN (PCIL0_CFGBASE + PCI_INTERRUPT_PIN )
+
+#define PCIL0_MINGNT (PCIL0_CFGBASE + PCI_MIN_GNT )
+#define PCIL0_MAXLTNCY (PCIL0_CFGBASE + PCI_MAX_LAT )
+
+#define PCIL0_POM0LAL (PCIL0_CFGBASE + 0x0068)
+#define PCIL0_POM0LAH (PCIL0_CFGBASE + 0x006c)
+#define PCIL0_POM0SA (PCIL0_CFGBASE + 0x0070)
+#define PCIL0_POM0PCIAL (PCIL0_CFGBASE + 0x0074)
+#define PCIL0_POM0PCIAH (PCIL0_CFGBASE + 0x0078)
+#define PCIL0_POM1LAL (PCIL0_CFGBASE + 0x007c)
+#define PCIL0_POM1LAH (PCIL0_CFGBASE + 0x0080)
+#define PCIL0_POM1SA (PCIL0_CFGBASE + 0x0084)
+#define PCIL0_POM1PCIAL (PCIL0_CFGBASE + 0x0088)
+#define PCIL0_POM1PCIAH (PCIL0_CFGBASE + 0x008c)
+#define PCIL0_POM2SA (PCIL0_CFGBASE + 0x0090)
+
+#define PCIL0_PIM0SA (PCIL0_CFGBASE + 0x0098)
+#define PCIL0_PIM0LAL (PCIL0_CFGBASE + 0x009c)
+#define PCIL0_PIM0LAH (PCIL0_CFGBASE + 0x00a0)
+#define PCIL0_PIM1SA (PCIL0_CFGBASE + 0x00a4)
+#define PCIL0_PIM1LAL (PCIL0_CFGBASE + 0x00a8)
+#define PCIL0_PIM1LAH (PCIL0_CFGBASE + 0x00ac)
+#define PCIL0_PIM2SA (PCIL0_CFGBASE + 0x00b0)
+#define PCIL0_PIM2LAL (PCIL0_CFGBASE + 0x00b4)
+#define PCIL0_PIM2LAH (PCIL0_CFGBASE + 0x00b8)
+
+#define PCIL0_STS (PCIL0_CFGBASE + 0x00e0)
+
+#endif /* __PPC440_H__ */
diff --git a/arch/powerpc/include/asm/ppc440ep_gr.h b/arch/powerpc/include/asm/ppc440ep_gr.h
new file mode 100644
index 0000000..e790963
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc440ep_gr.h
@@ -0,0 +1,244 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC440EP_GR_H_
+#define _PPC440EP_GR_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR /* IBM DDR controller */
+
+#define CONFIG_NAND_NDFC
+
+/*
+ * Some SoC specific registers (not common for all 440 SoC's)
+ */
+
+/* Memory mapped registers */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
+#define CONFIG_SYS_NS16550_COM3 (CONFIG_SYS_PERIPHERAL_BASE + 0x0500)
+#define CONFIG_SYS_NS16550_COM4 (CONFIG_SYS_PERIPHERAL_BASE + 0x0600)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0b00)
+#define GPIO1_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0c00)
+
+/* SDR's */
+#define SDR0_PCI0 0x0300
+#define SDR0_SDSTP2 0x4001
+#define SDR0_SDSTP3 0x4003
+
+#define SDR0_SDSTP1_PAE_MASK (0x80000000 >> 21)
+#define SDR0_SDSTP1_PAME_MASK (0x80000000 >> 27)
+
+/* Pin Function Control Register 1 */
+#define SDR0_PFC1_U1ME_MASK 0x02000000 /* UART1 Mode Enable */
+#define SDR0_PFC1_U1ME_DSR_DTR 0x00000000 /* UART1 in DSR/DTR Mode */
+#define SDR0_PFC1_U1ME_CTS_RTS 0x02000000 /* UART1 in CTS/RTS Mode */
+#define SDR0_PFC1_U0ME_MASK 0x00080000 /* UART0 Mode Enable */
+#define SDR0_PFC1_U0ME_DSR_DTR 0x00000000 /* UART0 in DSR/DTR Mode */
+#define SDR0_PFC1_U0ME_CTS_RTS 0x00080000 /* UART0 in CTS/RTS Mode */
+#define SDR0_PFC1_U0IM_MASK 0x00040000 /* UART0 Interface Mode */
+#define SDR0_PFC1_U0IM_8PINS 0x00000000 /* UART0 Interface Mode 8 pins */
+#define SDR0_PFC1_U0IM_4PINS 0x00040000 /* UART0 Interface Mode 4 pins */
+#define SDR0_PFC1_SIS_MASK 0x00020000 /* SCP or IIC1 Selection */
+#define SDR0_PFC1_SIS_SCP_SEL 0x00000000 /* SCP Selected */
+#define SDR0_PFC1_SIS_IIC1_SEL 0x00020000 /* IIC1 Selected */
+#define SDR0_PFC1_UES_MASK 0x00010000 /* USB2D_RX_Active / EBC_Hold
+ Req Selection */
+#define SDR0_PFC1_UES_USB2D_SEL 0x00000000 /* USB2D_RX_Active Selected */
+#define SDR0_PFC1_UES_EBCHR_SEL 0x00010000 /* EBC_Hold Req Selected */
+#define SDR0_PFC1_DIS_MASK 0x00008000 /* DMA_Req(1) / UIC_IRQ(5)
+ Selection */
+#define SDR0_PFC1_DIS_DMAR_SEL 0x00000000 /* DMA_Req(1) Selected */
+#define SDR0_PFC1_DIS_UICIRQ5_SEL 0x00008000 /* UIC_IRQ(5) Selected */
+#define SDR0_PFC1_ERE_MASK 0x00004000 /* EBC Mast.Ext.Req.En./GPIO0(27)
+ Selection */
+#define SDR0_PFC1_ERE_EXTR_SEL 0x00000000 /* EBC Mast.Ext.Req.En.
+ Selected */
+#define SDR0_PFC1_ERE_GPIO0_27_SEL 0x00004000 /* GPIO0(27) Selected */
+#define SDR0_PFC1_UPR_MASK 0x00002000 /* USB2 Device Packet Reject
+ Selection */
+#define SDR0_PFC1_UPR_DISABLE 0x00000000 /* USB2 Device Packet Reject
+ Disable */
+#define SDR0_PFC1_UPR_ENABLE 0x00002000 /* USB2 Device Packet Reject
+ Enable */
+#define SDR0_PFC1_PLB_PME_MASK 0x00001000 /* PLB3/PLB4 Perf. Monitor Enable
+ Selection */
+#define SDR0_PFC1_PLB_PME_PLB3_SEL 0x00000000 /* PLB3 Performance Monitor
+ Enable */
+#define SDR0_PFC1_PLB_PME_PLB4_SEL 0x00001000 /* PLB3 Performance Monitor
+ Enable */
+#define SDR0_PFC1_GFGGI_MASK 0x0000000F /* GPT Frequency Generation
+ Gated In */
+
+/* USB Control Register */
+#define SDR0_USB0_USB_DEVSEL_MASK 0x00000002 /* USB Device Selection */
+#define SDR0_USB0_USB20D_DEVSEL 0x00000000 /* USB2.0 Device Selected */
+#define SDR0_USB0_USB11D_DEVSEL 0x00000002 /* USB1.1 Device Selected */
+#define SDR0_USB0_LEEN_MASK 0x00000001 /* Little Endian selection */
+#define SDR0_USB0_LEEN_DISABLE 0x00000000 /* Little Endian Disable */
+#define SDR0_USB0_LEEN_ENABLE 0x00000001 /* Little Endian Enable */
+
+/* Miscealleneaous Function Reg. */
+#define SDR0_MFR_ETH0_CLK_SEL_MASK 0x08000000 /* Ethernet0 Clock Select */
+#define SDR0_MFR_ETH0_CLK_SEL_EXT 0x00000000
+#define SDR0_MFR_ETH1_CLK_SEL_MASK 0x04000000 /* Ethernet1 Clock Select */
+#define SDR0_MFR_ETH1_CLK_SEL_EXT 0x00000000
+#define SDR0_MFR_ZMII_MODE_MASK 0x03000000 /* ZMII Mode Mask */
+#define SDR0_MFR_ZMII_MODE_MII 0x00000000 /* ZMII Mode MII */
+#define SDR0_MFR_ZMII_MODE_SMII 0x01000000 /* ZMII Mode SMII */
+#define SDR0_MFR_ZMII_MODE_RMII_10M 0x02000000 /* ZMII Mode RMII - 10 Mbs */
+#define SDR0_MFR_ZMII_MODE_RMII_100M 0x03000000 /* ZMII Mode RMII - 100 Mbs */
+#define SDR0_MFR_ZMII_MODE_BIT0 0x02000000 /* ZMII Mode Bit0 */
+#define SDR0_MFR_ZMII_MODE_BIT1 0x01000000 /* ZMII Mode Bit1 */
+#define SDR0_MFR_ZM_ENCODE(n) ((((u32)(n)) & 0x3) << 24)
+#define SDR0_MFR_ZM_DECODE(n) ((((u32)(n)) << 24) & 0x3)
+
+#define SDR0_MFR_ERRATA3_EN0 0x00800000
+#define SDR0_MFR_ERRATA3_EN1 0x00400000
+#define SDR0_MFR_PKT_REJ_MASK 0x00180000 /* Pkt Rej. Enable Mask */
+#define SDR0_MFR_PKT_REJ_EN 0x00180000 /* Pkt Rej. Ena. on both EMAC3 0-1 */
+#define SDR0_MFR_PKT_REJ_EN0 0x00100000 /* Pkt Rej. Enable on EMAC3(0) */
+#define SDR0_MFR_PKT_REJ_EN1 0x00080000 /* Pkt Rej. Enable on EMAC3(1) */
+#define SDR0_MFR_PKT_REJ_POL 0x00200000 /* Packet Reject Polarity */
+
+/* CUST0 Customer Configuration Register0 */
+#define SDR0_CUST0_MUX_E_N_G_MASK 0xC0000000 /* Mux_Emac_NDFC_GPIO */
+#define SDR0_CUST0_MUX_EMAC_SEL 0x40000000 /* Emac Selection */
+#define SDR0_CUST0_MUX_NDFC_SEL 0x80000000 /* NDFC Selection */
+#define SDR0_CUST0_MUX_GPIO_SEL 0xC0000000 /* GPIO Selection */
+
+#define SDR0_CUST0_NDFC_EN_MASK 0x20000000 /* NDFC Enable Mask */
+#define SDR0_CUST0_NDFC_ENABLE 0x20000000 /* NDFC Enable */
+#define SDR0_CUST0_NDFC_DISABLE 0x00000000 /* NDFC Disable */
+
+#define SDR0_CUST0_NDFC_BW_MASK 0x10000000 /* NDFC Boot Width */
+#define SDR0_CUST0_NDFC_BW_16_BIT 0x10000000 /* NDFC Boot Width = 16 Bit */
+#define SDR0_CUST0_NDFC_BW_8_BIT 0x00000000 /* NDFC Boot Width = 8 Bit */
+
+#define SDR0_CUST0_NDFC_BP_MASK 0x0F000000 /* NDFC Boot Page */
+#define SDR0_CUST0_NDFC_BP_ENCODE(n) ((((u32)(n)) & 0xF) << 24)
+#define SDR0_CUST0_NDFC_BP_DECODE(n) ((((u32)(n)) >> 24) & 0xF)
+
+#define SDR0_CUST0_NDFC_BAC_MASK 0x00C00000 /* NDFC Boot Address Cycle */
+#define SDR0_CUST0_NDFC_BAC_ENCODE(n) ((((u32)(n)) & 0x3) << 22)
+#define SDR0_CUST0_NDFC_BAC_DECODE(n) ((((u32)(n)) >> 22) & 0x3)
+
+#define SDR0_CUST0_NDFC_ARE_MASK 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_ENABLE 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_DISABLE 0x00000000 /* NDFC Auto Read Disable */
+
+#define SDR0_CUST0_NRB_MASK 0x00100000 /* NDFC Ready / Busy */
+#define SDR0_CUST0_NRB_BUSY 0x00100000 /* Busy */
+#define SDR0_CUST0_NRB_READY 0x00000000 /* Ready */
+
+#define SDR0_CUST0_NDRSC_MASK 0x0000FFF0 /* NDFC Device Reset Count Mask */
+#define SDR0_CUST0_NDRSC_ENCODE(n) ((((u32)(n)) & 0xFFF) << 4)
+#define SDR0_CUST0_NDRSC_DECODE(n) ((((u32)(n)) >> 4) & 0xFFF)
+
+#define SDR0_CUST0_CHIPSELGAT_MASK 0x0000000F /* Chip Select Gating Mask */
+#define SDR0_CUST0_CHIPSELGAT_DIS 0x00000000 /* Chip Select Gating Disable */
+#define SDR0_CUST0_CHIPSELGAT_ENALL 0x0000000F /*All Chip Select Gating Enable*/
+#define SDR0_CUST0_CHIPSELGAT_EN0 0x00000008 /* Chip Select0 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN1 0x00000004 /* Chip Select1 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN2 0x00000002 /* Chip Select2 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN3 0x00000001 /* Chip Select3 Gating Enable */
+
+#define SDR0_SRST_DMC 0x00200000
+
+#define PLLSYS0_ENG_MASK 0x80000000 /* 0 = SysClk, 1 = PLL VCO */
+#define PLLSYS0_SRC_MASK 0x40000000 /* 0 = PLL A, 1 = PLL B */
+#define PLLSYS0_SEL_MASK 0x38000000 /* 0 = PLL, 1 = CPU, 5 = PerClk */
+#define PLLSYS0_TUNE_MASK 0x07fe0000 /* PLL Tune bits */
+#define PLLSYS0_FB_DIV_MASK 0x0001f000 /* Feedback divisor */
+#define PLLSYS0_FWD_DIV_A_MASK 0x00000f00 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x000000e0 /* Fwd Div B */
+#define PLLSYS0_PRI_DIV_B_MASK 0x0000001c /* PLL Primary Divisor B */
+#define PLLSYS0_OPB_DIV_MASK 0x00000003 /* OPB Divisor */
+
+#define PLLC_ENG_MASK 0x20000000 /* PLL primary forward divisor source */
+#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
+#define PLLD_FBDV_MASK 0x1f000000 /* PLL Feedback Divisor */
+#define PLLD_FWDVA_MASK 0x000f0000 /* PLL Forward Divisor A */
+#define PLLD_FWDVB_MASK 0x00000700 /* PLL Forward Divisor B */
+#define PLLD_LFBDV_MASK 0x0000003f /* PLL Local Feedback Divisor */
+
+#define OPBDDV_MASK 0x03000000 /* OPB Clock Divisor Register */
+#define PERDV_MASK 0x07000000 /* Peripheral Clock Divisor */
+#define PRADV_MASK 0x07000000 /* Primary Divisor A */
+#define PRBDV_MASK 0x07000000 /* Primary Divisor B */
+#define SPCID_MASK 0x03000000 /* Sync PCI Divisor */
+
+/* Strap 1 Register */
+#define PLLSYS1_LF_DIV_MASK 0xfc000000 /* PLL Local Feedback Divisor */
+#define PLLSYS1_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS1_MAL_DIV_MASK 0x00c00000 /* MAL Clk Divisor */
+#define PLLSYS1_RW_MASK 0x00300000 /* ROM width */
+#define PLLSYS1_EAR_MASK 0x00080000 /* ERAP Address reset vector */
+#define PLLSYS1_PAE_MASK 0x00040000 /* PCI arbitor enable */
+#define PLLSYS1_PCHE_MASK 0x00020000 /* PCI host config enable */
+#define PLLSYS1_PISE_MASK 0x00010000 /* PCI init seq. enable */
+#define PLLSYS1_PCWE_MASK 0x00008000 /* PCI local cpu wait enable */
+#define PLLSYS1_PPIM_MASK 0x00007800 /* PCI inbound map */
+#define PLLSYS1_PR64E_MASK 0x00000400 /* PCI init Req64 enable */
+#define PLLSYS1_PXFS_MASK 0x00000300 /* PCI-X Freq Sel */
+#define PLLSYS1_RSVD_MASK 0x00000080 /* RSVD */
+#define PLLSYS1_PDM_MASK 0x00000040 /* PCI-X Driver Mode */
+#define PLLSYS1_EPS_MASK 0x00000038 /* Ethernet Pin Select */
+#define PLLSYS1_RMII_MASK 0x00000004 /* RMII Mode */
+#define PLLSYS1_TRE_MASK 0x00000002 /* GPIO Trace Enable */
+#define PLLSYS1_NTO1_MASK 0x00000001 /* CPU:PLB N-to-1 ratio */
+
+#define CPR0_ICFG_RLI_MASK 0x80000000
+#define CPR0_ICFG_ICS_MASK 0x00000007
+#define CPR0_SPCID_SPCIDV0_MASK 0x03000000
+#define CPR0_SPCID_SPCIDV0_DIV1 0x01000000
+#define CPR0_SPCID_SPCIDV0_DIV2 0x02000000
+#define CPR0_SPCID_SPCIDV0_DIV3 0x03000000
+#define CPR0_SPCID_SPCIDV0_DIV4 0x00000000
+#define CPR0_PERD_PERDV0_MASK 0x07000000
+
+#define PCI_MMIO_LCR_BASE (CONFIG_SYS_PCI_BASE + 0x0f400000) /* Real =>
+ 0x0EF400000 */
+
+/* PCI Master Local Configuration Registers */
+#define PCIL0_PMM0LA (PCI_MMIO_LCR_BASE + 0x00) /* PMM0 Local Address */
+#define PCIL0_PMM0MA (PCI_MMIO_LCR_BASE + 0x04) /* PMM0 Mask/Attribute */
+#define PCIL0_PMM0PCILA (PCI_MMIO_LCR_BASE + 0x08) /* PMM0 PCI Low Address */
+#define PCIL0_PMM0PCIHA (PCI_MMIO_LCR_BASE + 0x0C) /* PMM0 PCI High Address */
+#define PCIL0_PMM1LA (PCI_MMIO_LCR_BASE + 0x10) /* PMM1 Local Address */
+#define PCIL0_PMM1MA (PCI_MMIO_LCR_BASE + 0x14) /* PMM1 Mask/Attribute */
+#define PCIL0_PMM1PCILA (PCI_MMIO_LCR_BASE + 0x18) /* PMM1 PCI Low Address */
+#define PCIL0_PMM1PCIHA (PCI_MMIO_LCR_BASE + 0x1C) /* PMM1 PCI High Address */
+#define PCIL0_PMM2LA (PCI_MMIO_LCR_BASE + 0x20) /* PMM2 Local Address */
+#define PCIL0_PMM2MA (PCI_MMIO_LCR_BASE + 0x24) /* PMM2 Mask/Attribute */
+#define PCIL0_PMM2PCILA (PCI_MMIO_LCR_BASE + 0x28) /* PMM2 PCI Low Address */
+#define PCIL0_PMM2PCIHA (PCI_MMIO_LCR_BASE + 0x2C) /* PMM2 PCI High Address */
+
+/* PCI Target Local Configuration Registers */
+#define PCIL0_PTM1MS (PCI_MMIO_LCR_BASE + 0x30) /* PTM1 Memory Size/
+ Attribute */
+#define PCIL0_PTM1LA (PCI_MMIO_LCR_BASE + 0x34) /* PTM1 Local Addr. Reg */
+#define PCIL0_PTM2MS (PCI_MMIO_LCR_BASE + 0x38) /* PTM2 Memory Size/
+ Attribute */
+#define PCIL0_PTM2LA (PCI_MMIO_LCR_BASE + 0x3C) /* PTM2 Local Addr. Reg */
+
+#endif /* _PPC440EP_GR_H_ */
diff --git a/arch/powerpc/include/asm/ppc440epx_grx.h b/arch/powerpc/include/asm/ppc440epx_grx.h
new file mode 100644
index 0000000..c841f0f
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc440epx_grx.h
@@ -0,0 +1,466 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC440EPX_GRX_H_
+#define _PPC440EPX_GRX_H_
+
+#define CONFIG_SDRAM_PPC4xx_DENALI_DDR2 /* Denali DDR(2) controller */
+
+#define CONFIG_NAND_NDFC
+
+/*
+ * Some SoC specific registers (not common for all 440 SoC's)
+ */
+
+/* Memory mapped registers */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define SPI0_MODE (CONFIG_SYS_PERIPHERAL_BASE + 0x0090)
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
+#define CONFIG_SYS_NS16550_COM3 (CONFIG_SYS_PERIPHERAL_BASE + 0x0500)
+#define CONFIG_SYS_NS16550_COM4 (CONFIG_SYS_PERIPHERAL_BASE + 0x0600)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0b00)
+#define GPIO1_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0c00)
+
+/* DCR */
+#define CPM0_ER 0x00b0
+#define CPM1_ER 0x00f0
+#define PLB3A0_ACR 0x0077
+#define PLB4A0_ACR 0x0081
+#define PLB4A1_ACR 0x0089
+#define OPB2PLB40_BCTRL 0x0350
+#define P4P3BO0_CFG 0x0026
+
+/* SDR */
+#define SDR0_DDRCFG 0x00e0
+#define SDR0_PCI0 0x0300
+#define SDR0_SDSTP2 0x4001
+#define SDR0_SDSTP3 0x4003
+#define SDR0_EMAC0RXST 0x4301
+#define SDR0_EMAC0TXST 0x4302
+#define SDR0_CRYP0 0x4500
+
+#define SDR0_SDSTP1_PAE_MASK (0x80000000 >> 21)
+#define SDR0_SDSTP1_PAME_MASK (0x80000000 >> 27)
+
+/* Pin Function Control Register 1 */
+#define SDR0_PFC1_U1ME_MASK 0x02000000 /* UART1 Mode Enable */
+#define SDR0_PFC1_U1ME_DSR_DTR 0x00000000 /* UART1 in DSR/DTR Mode */
+#define SDR0_PFC1_U1ME_CTS_RTS 0x02000000 /* UART1 in CTS/RTS Mode */
+#define SDR0_PFC1_SELECT_MASK 0x01C00000 /* Ethernet Pin Select
+ EMAC 0 */
+#define SDR0_PFC1_SELECT_CONFIG_1_1 0x00C00000 /* 1xMII using RGMII
+ bridge */
+#define SDR0_PFC1_SELECT_CONFIG_1_2 0x00000000 /* 1xMII using ZMII
+ bridge */
+#define SDR0_PFC1_SELECT_CONFIG_2 0x00C00000 /* 1xGMII using RGMII
+ bridge */
+#define SDR0_PFC1_SELECT_CONFIG_3 0x01000000 /* 1xTBI using RGMII
+ bridge */
+#define SDR0_PFC1_SELECT_CONFIG_4 0x01400000 /* 2xRGMII using RGMII
+ bridge */
+#define SDR0_PFC1_SELECT_CONFIG_5 0x01800000 /* 2xRTBI using RGMII
+ bridge */
+#define SDR0_PFC1_SELECT_CONFIG_6 0x00800000 /* 2xSMII using ZMII
+ bridge */
+#define SDR0_PFC1_U0ME_MASK 0x00080000 /* UART0 Mode Enable */
+#define SDR0_PFC1_U0ME_DSR_DTR 0x00000000 /* UART0 in DSR/DTR Mode */
+#define SDR0_PFC1_U0ME_CTS_RTS 0x00080000 /* UART0 in CTS/RTS Mode */
+#define SDR0_PFC1_U0IM_MASK 0x00040000 /* UART0 Interface Mode */
+#define SDR0_PFC1_U0IM_8PINS 0x00000000 /* UART0 Interface Mode 8 pins */
+#define SDR0_PFC1_U0IM_4PINS 0x00040000 /* UART0 Interface Mode 4 pins */
+#define SDR0_PFC1_SIS_MASK 0x00020000 /* SCP or IIC1 Selection */
+#define SDR0_PFC1_SIS_SCP_SEL 0x00000000 /* SCP Selected */
+#define SDR0_PFC1_SIS_IIC1_SEL 0x00020000 /* IIC1 Selected */
+#define SDR0_PFC1_UES_MASK 0x00010000 /* USB2D_RX_Active / EBC_Hold
+ Req Selection */
+#define SDR0_PFC1_UES_USB2D_SEL 0x00000000 /* USB2D_RX_Active Selected */
+#define SDR0_PFC1_UES_EBCHR_SEL 0x00010000 /* EBC_Hold Req Selected */
+#define SDR0_PFC1_DIS_MASK 0x00008000 /* DMA_Req(1) / UIC_IRQ(5)
+ Selection */
+#define SDR0_PFC1_DIS_DMAR_SEL 0x00000000 /* DMA_Req(1) Selected */
+#define SDR0_PFC1_DIS_UICIRQ5_SEL 0x00008000 /* UIC_IRQ(5) Selected */
+#define SDR0_PFC1_ERE_MASK 0x00004000 /* EBC Mast.Ext.Req.En./GPIO0(27)
+ Selection */
+#define SDR0_PFC1_ERE_EXTR_SEL 0x00000000 /* EBC Mast.Ext.Req.En.
+ Selected */
+#define SDR0_PFC1_ERE_GPIO0_27_SEL 0x00004000 /* GPIO0(27) Selected */
+#define SDR0_PFC1_UPR_MASK 0x00002000 /* USB2 Device Packet Reject
+ Selection */
+#define SDR0_PFC1_UPR_DISABLE 0x00000000 /* USB2 Device Packet Reject
+ Disable */
+#define SDR0_PFC1_UPR_ENABLE 0x00002000 /* USB2 Device Packet Reject
+ Enable */
+#define SDR0_PFC1_PLB_PME_MASK 0x00001000 /* PLB3/PLB4 Perf. Monitor Enable
+ Selection */
+#define SDR0_PFC1_PLB_PME_PLB3_SEL 0x00000000 /* PLB3 Performance Monitor
+ Enable */
+#define SDR0_PFC1_PLB_PME_PLB4_SEL 0x00001000 /* PLB3 Performance Monitor
+ Enable */
+#define SDR0_PFC1_GFGGI_MASK 0x0000000F /* GPT Frequency Generation
+ Gated In */
+
+#define SDR0_PFC2_SELECT_MASK 0xe0000000 /* Ethernet Pin select EMAC1 */
+#define SDR0_PFC2_SELECT_CONFIG_1_1 0x60000000 /* 1xMII using RGMII bridge */
+#define SDR0_PFC2_SELECT_CONFIG_1_2 0x00000000 /* 1xMII using ZMII bridge */
+#define SDR0_PFC2_SELECT_CONFIG_2 0x60000000 /* 1xGMII using RGMII bridge */
+#define SDR0_PFC2_SELECT_CONFIG_3 0x80000000 /* 1xTBI using RGMII bridge */
+#define SDR0_PFC2_SELECT_CONFIG_4 0xa0000000 /* 2xRGMII using RGMII bridge */
+#define SDR0_PFC2_SELECT_CONFIG_5 0xc0000000 /* 2xRTBI using RGMII bridge */
+#define SDR0_PFC2_SELECT_CONFIG_6 0x40000000 /* 2xSMII using ZMII bridge */
+
+#define SDR0_USB2D0CR 0x0320
+#define SDR0_USB2D0CR_USB2DEV_EBC_SEL_MASK 0x00000004 /* USB 2.0 Device/EBC
+ Master Selection */
+#define SDR0_USB2D0CR_USB2DEV_SELECTION 0x00000004 /* USB 2.0 Device Selection*/
+#define SDR0_USB2D0CR_EBC_SELECTION 0x00000000 /* EBC Selection */
+
+#define SDR0_USB2D0CR_USB_DEV_INT_SEL_MASK 0x00000002 /* USB Device Interface
+ Selection */
+#define SDR0_USB2D0CR_USB20D_DEVSEL 0x00000000 /* USB2.0 Device Selected */
+#define SDR0_USB2D0CR_USB11D_DEVSEL 0x00000002 /* USB1.1 Device Selected */
+
+#define SDR0_USB2D0CR_LEEN_MASK 0x00000001 /* Little Endian selection */
+#define SDR0_USB2D0CR_LEEN_DISABLE 0x00000000 /* Little Endian Disable */
+#define SDR0_USB2D0CR_LEEN_ENABLE 0x00000001 /* Little Endian Enable */
+
+/* USB2 Host Control Register */
+#define SDR0_USB2H0CR 0x0340
+#define SDR0_USB2H0CR_WDINT_MASK 0x00000001 /* Host UTMI Word Interface*/
+#define SDR0_USB2H0CR_WDINT_8BIT_60MHZ 0x00000000 /* 8-bit/60MHz */
+#define SDR0_USB2H0CR_WDINT_16BIT_30MHZ 0x00000001 /* 16-bit/30MHz */
+#define SDR0_USB2H0CR_EFLADJ_MASK 0x0000007e /* EHCI Frame Length
+ Adjustment */
+/* USB2PHY0 Control Register */
+#define SDR0_USB2PHY0CR 0x4103
+#define SDR0_USB2PHY0CR_UTMICN_MASK 0x00100000
+
+ /* PHY UTMI interface connection */
+#define SDR0_USB2PHY0CR_UTMICN_DEV 0x00000000 /* Device support */
+#define SDR0_USB2PHY0CR_UTMICN_HOST 0x00100000 /* Host support */
+
+#define SDR0_USB2PHY0CR_DWNSTR_MASK 0x00400000 /* Select downstream port mode */
+#define SDR0_USB2PHY0CR_DWNSTR_DEV 0x00000000 /* Device */
+#define SDR0_USB2PHY0CR_DWNSTR_HOST 0x00400000 /* Host */
+
+/* VBus detect (Device mode only) */
+#define SDR0_USB2PHY0CR_DVBUS_MASK 0x00800000
+/* Pull-up resistance on D+ is disabled */
+#define SDR0_USB2PHY0CR_DVBUS_PURDIS 0x00000000
+/* Pull-up resistance on D+ is enabled */
+#define SDR0_USB2PHY0CR_DVBUS_PUREN 0x00800000
+
+/* PHY UTMI data width and clock select */
+#define SDR0_USB2PHY0CR_WDINT_MASK 0x01000000
+#define SDR0_USB2PHY0CR_WDINT_8BIT_60MHZ 0x00000000 /* 8-bit data/60MHz */
+#define SDR0_USB2PHY0CR_WDINT_16BIT_30MHZ 0x01000000 /* 16-bit data/30MHz */
+
+#define SDR0_USB2PHY0CR_LOOPEN_MASK 0x02000000 /* Loop back test enable */
+#define SDR0_USB2PHY0CR_LOOP_ENABLE 0x00000000 /* Loop back disabled */
+/* Loop back enabled (only test purposes) */
+#define SDR0_USB2PHY0CR_LOOP_DISABLE 0x02000000
+
+/* Force XO block on during a suspend */
+#define SDR0_USB2PHY0CR_XOON_MASK 0x04000000
+#define SDR0_USB2PHY0CR_XO_ON 0x00000000 /* PHY XO block is powered-on */
+/* PHY XO block is powered-off when all ports are suspended */
+#define SDR0_USB2PHY0CR_XO_OFF 0x04000000
+
+#define SDR0_USB2PHY0CR_PWRSAV_MASK 0x08000000 /* Select PHY power-save mode */
+#define SDR0_USB2PHY0CR_PWRSAV_OFF 0x00000000 /* Non-power-save mode */
+#define SDR0_USB2PHY0CR_PWRSAV_ON 0x08000000 /* Power-save mode. Valid only
+ for full-speed operation */
+
+#define SDR0_USB2PHY0CR_XOREF_MASK 0x10000000 /* Select reference clock
+ source */
+#define SDR0_USB2PHY0CR_XOREF_INTERNAL 0x00000000 /* PHY PLL uses chip internal
+ 48M clock as a reference */
+#define SDR0_USB2PHY0CR_XOREF_XO 0x10000000 /* PHY PLL uses internal XO
+ block output as a reference */
+
+#define SDR0_USB2PHY0CR_XOCLK_MASK 0x20000000 /* Select clock for XO
+ block*/
+#define SDR0_USB2PHY0CR_XOCLK_EXTERNAL 0x00000000 /* PHY macro used an external
+ clock */
+#define SDR0_USB2PHY0CR_XOCLK_CRYSTAL 0x20000000 /* PHY macro uses the clock
+ from a crystal */
+
+#define SDR0_USB2PHY0CR_CLKSEL_MASK 0xc0000000 /* Select ref clk freq */
+#define SDR0_USB2PHY0CR_CLKSEL_12MHZ 0x00000000 /* Select ref clk freq
+ = 12 MHz */
+#define SDR0_USB2PHY0CR_CLKSEL_48MHZ 0x40000000 /* Select ref clk freq
+ = 48 MHz */
+#define SDR0_USB2PHY0CR_CLKSEL_24MHZ 0x80000000 /* Select ref clk freq
+ = 24 MHz */
+
+/* USB2.0 Device */
+/*
+ * todo: check if this can be completely removed, only used in
+ * cpu/ppc4xx/usbdev.c. And offsets are completely wrong. This could
+ * never have actually worked. Best probably is to remove this
+ * usbdev.c file completely (and these defines).
+ */
+#define USB2D0_BASE CONFIG_SYS_USB2D0_BASE
+
+#define USB2D0_INTRIN (USB2D0_BASE + 0x00000000)
+
+#define USB2D0_INTRIN (USB2D0_BASE + 0x00000000) /* Interrupt register for
+ Endpoint 0 plus IN Endpoints 1 to 3 */
+#define USB2D0_POWER (USB2D0_BASE + 0x00000000) /* Power management
+ register */
+#define USB2D0_FADDR (USB2D0_BASE + 0x00000000) /* Function address
+ register */
+#define USB2D0_INTRINE (USB2D0_BASE + 0x00000000) /* Interrupt enable
+ register for USB2D0_INTRIN */
+#define USB2D0_INTROUT (USB2D0_BASE + 0x00000000) /* Interrupt register for
+ OUT Endpoints 1 to 3 */
+#define USB2D0_INTRUSBE (USB2D0_BASE + 0x00000000) /* Interrupt enable
+ register for USB2D0_INTRUSB */
+#define USB2D0_INTRUSB (USB2D0_BASE + 0x00000000) /* Interrupt register for
+ common USB interrupts */
+#define USB2D0_INTROUTE (USB2D0_BASE + 0x00000000) /* Interrupt enable
+ register for IntrOut */
+#define USB2D0_TSTMODE (USB2D0_BASE + 0x00000000) /* Enables the USB 2.0
+ test modes */
+#define USB2D0_INDEX (USB2D0_BASE + 0x00000000) /* Index register for
+ selecting the Endpoint status/control registers */
+#define USB2D0_FRAME (USB2D0_BASE + 0x00000000) /* Frame number */
+#define USB2D0_INCSR0 (USB2D0_BASE + 0x00000000) /* Control Status
+ register for Endpoint 0. (Index register set to select Endpoint 0) */
+#define USB2D0_INCSR (USB2D0_BASE + 0x00000000) /* Control Status
+ register for IN Endpoint. (Index register set to select Endpoints 13) */
+#define USB2D0_INMAXP (USB2D0_BASE + 0x00000000) /* Maximum packet
+ size for IN Endpoint. (Index register set to select Endpoints 13) */
+#define USB2D0_OUTCSR (USB2D0_BASE + 0x00000000) /* Control Status
+ register for OUT Endpoint. (Index register set to select Endpoints 13) */
+#define USB2D0_OUTMAXP (USB2D0_BASE + 0x00000000) /* Maximum packet
+ size for OUT Endpoint. (Index register set to select Endpoints 13) */
+#define USB2D0_OUTCOUNT0 (USB2D0_BASE + 0x00000000) /* Number of received
+ bytes in Endpoint 0 FIFO. (Index register set to select Endpoint 0) */
+#define USB2D0_OUTCOUNT (USB2D0_BASE + 0x00000000) /* Number of bytes in
+ OUT Endpoint FIFO. (Index register set to select Endpoints 13) */
+
+/* Miscealleneaous Function Reg. */
+#define SDR0_MFR_ETH0_CLK_SEL_MASK 0x08000000 /* Ethernet0 Clock Select */
+#define SDR0_MFR_ETH0_CLK_SEL_EXT 0x00000000
+#define SDR0_MFR_ETH1_CLK_SEL_MASK 0x04000000 /* Ethernet1 Clock Select */
+#define SDR0_MFR_ETH1_CLK_SEL_EXT 0x00000000
+#define SDR0_MFR_ZMII_MODE_MASK 0x03000000 /* ZMII Mode Mask */
+#define SDR0_MFR_ZMII_MODE_MII 0x00000000 /* ZMII Mode MII */
+#define SDR0_MFR_ZMII_MODE_SMII 0x01000000 /* ZMII Mode SMII */
+#define SDR0_MFR_ZMII_MODE_BIT0 0x02000000 /* ZMII Mode Bit0 */
+#define SDR0_MFR_ZMII_MODE_BIT1 0x01000000 /* ZMII Mode Bit1 */
+#define SDR0_MFR_ZM_ENCODE(n) ((((u32)(n)) & 0x3) << 24)
+#define SDR0_MFR_ZM_DECODE(n) ((((u32)(n)) << 24) & 0x3)
+#define SDR0_MFR_PKT_REJ_MASK 0x00300000 /* Pkt Rej. Enable Mask */
+#define SDR0_MFR_PKT_REJ_EN 0x00300000 /* Pkt Rej. Ena. on both EMAC3 0-1 */
+#define SDR0_MFR_PKT_REJ_EN0 0x00200000 /* Pkt Rej. Enable on EMAC3(0) */
+#define SDR0_MFR_PKT_REJ_EN1 0x00100000 /* Pkt Rej. Enable on EMAC3(1) */
+#define SDR0_MFR_PKT_REJ_POL 0x00080000 /* Packet Reject Polarity */
+
+/* CUST0 Customer Configuration Register0 */
+#define SDR0_CUST0_MUX_E_N_G_MASK 0xC0000000 /* Mux_Emac_NDFC_GPIO */
+#define SDR0_CUST0_MUX_EMAC_SEL 0x40000000 /* Emac Selection */
+#define SDR0_CUST0_MUX_NDFC_SEL 0x80000000 /* NDFC Selection */
+#define SDR0_CUST0_MUX_GPIO_SEL 0xC0000000 /* GPIO Selection */
+
+#define SDR0_CUST0_NDFC_EN_MASK 0x20000000 /* NDFC Enable Mask */
+#define SDR0_CUST0_NDFC_ENABLE 0x20000000 /* NDFC Enable */
+#define SDR0_CUST0_NDFC_DISABLE 0x00000000 /* NDFC Disable */
+
+#define SDR0_CUST0_NDFC_BW_MASK 0x10000000 /* NDFC Boot Width */
+#define SDR0_CUST0_NDFC_BW_16_BIT 0x10000000 /* NDFC Boot Width = 16 Bit */
+#define SDR0_CUST0_NDFC_BW_8_BIT 0x00000000 /* NDFC Boot Width = 8 Bit */
+
+#define SDR0_CUST0_NDFC_BP_MASK 0x0F000000 /* NDFC Boot Page */
+#define SDR0_CUST0_NDFC_BP_ENCODE(n) ((((u32)(n)) & 0xF) << 24)
+#define SDR0_CUST0_NDFC_BP_DECODE(n) ((((u32)(n)) >> 24) & 0xF)
+
+#define SDR0_CUST0_NDFC_BAC_MASK 0x00C00000 /* NDFC Boot Address Cycle */
+#define SDR0_CUST0_NDFC_BAC_ENCODE(n) ((((u32)(n)) & 0x3) << 22)
+#define SDR0_CUST0_NDFC_BAC_DECODE(n) ((((u32)(n)) >> 22) & 0x3)
+
+#define SDR0_CUST0_NDFC_ARE_MASK 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_ENABLE 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_DISABLE 0x00000000 /* NDFC Auto Read Disable */
+
+#define SDR0_CUST0_NRB_MASK 0x00100000 /* NDFC Ready / Busy */
+#define SDR0_CUST0_NRB_BUSY 0x00100000 /* Busy */
+#define SDR0_CUST0_NRB_READY 0x00000000 /* Ready */
+
+#define SDR0_CUST0_NDRSC_MASK 0x0000FFF0 /* NDFC Device Reset Count Mask */
+#define SDR0_CUST0_NDRSC_ENCODE(n) ((((u32)(n)) & 0xFFF) << 4)
+#define SDR0_CUST0_NDRSC_DECODE(n) ((((u32)(n)) >> 4) & 0xFFF)
+
+#define SDR0_CUST0_CHIPSELGAT_MASK 0x0000000F /* Chip Select Gating Mask */
+#define SDR0_CUST0_CHIPSELGAT_DIS 0x00000000 /* Chip Select Gating Disable */
+#define SDR0_CUST0_CHIPSELGAT_ENALL 0x0000000F /*All Chip Select Gating Enable*/
+#define SDR0_CUST0_CHIPSELGAT_EN0 0x00000008 /* Chip Select0 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN1 0x00000004 /* Chip Select1 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN2 0x00000002 /* Chip Select2 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN3 0x00000001 /* Chip Select3 Gating Enable */
+
+#define SDR0_SRST0_BGO 0x80000000 /* PLB to OPB bridge */
+#define SDR0_SRST0_PLB4 0x40000000 /* PLB4 arbiter */
+#define SDR0_SRST0_EBC 0x20000000 /* External bus controller */
+#define SDR0_SRST0_OPB 0x10000000 /* OPB arbiter */
+#define SDR0_SRST0_UART0 0x08000000 /* Universal asynchronous receiver/
+ transmitter 0 */
+#define SDR0_SRST0_UART1 0x04000000 /* Universal asynchronous receiver/
+ transmitter 1 */
+#define SDR0_SRST0_IIC0 0x02000000 /* Inter integrated circuit 0 */
+#define SDR0_SRST0_USB2H 0x01000000 /* USB2.0 Host */
+#define SDR0_SRST0_GPIO 0x00800000 /* General purpose I/O */
+#define SDR0_SRST0_GPT 0x00400000 /* General purpose timer */
+#define SDR0_SRST0_DMC 0x00200000 /* DDR SDRAM memory controller */
+#define SDR0_SRST0_PCI 0x00100000 /* PCI */
+#define SDR0_SRST0_EMAC0 0x00080000 /* Ethernet media access controller 0 */
+#define SDR0_SRST0_EMAC1 0x00040000 /* Ethernet media access controller 1 */
+#define SDR0_SRST0_CPM0 0x00020000 /* Clock and power management */
+#define SDR0_SRST0_ZMII 0x00010000 /* ZMII bridge */
+#define SDR0_SRST0_UIC0 0x00008000 /* Universal interrupt controller 0 */
+#define SDR0_SRST0_UIC1 0x00004000 /* Universal interrupt controller 1 */
+#define SDR0_SRST0_IIC1 0x00002000 /* Inter integrated circuit 1 */
+#define SDR0_SRST0_SCP 0x00001000 /* Serial communications port */
+#define SDR0_SRST0_BGI 0x00000800 /* OPB to PLB bridge */
+#define SDR0_SRST0_DMA 0x00000400 /* Direct memory access controller */
+#define SDR0_SRST0_DMAC 0x00000200 /* DMA channel */
+#define SDR0_SRST0_MAL 0x00000100 /* Media access layer */
+#define SDR0_SRST0_USB2D 0x00000080 /* USB2.0 device */
+#define SDR0_SRST0_GPTR 0x00000040 /* General purpose timer */
+#define SDR0_SRST0_P4P3 0x00000010 /* PLB4 to PLB3 bridge */
+#define SDR0_SRST0_P3P4 0x00000008 /* PLB3 to PLB4 bridge */
+#define SDR0_SRST0_PLB3 0x00000004 /* PLB3 arbiter */
+#define SDR0_SRST0_UART2 0x00000002 /* Universal asynchronous receiver/
+ transmitter 2 */
+#define SDR0_SRST0_UART3 0x00000001 /* Universal asynchronous receiver/
+ transmitter 3 */
+
+#define SDR0_SRST1_NDFC 0x80000000 /* Nand flash controller */
+#define SDR0_SRST1_OPBA1 0x40000000 /* OPB Arbiter attached to PLB4 */
+#define SDR0_SRST1_P4OPB0 0x20000000 /* PLB4 to OPB Bridge0 */
+#define SDR0_SRST1_PLB42OPB0 SDR0_SRST1_P4OPB0
+#define SDR0_SRST1_DMA4 0x10000000 /* DMA to PLB4 */
+#define SDR0_SRST1_DMA4CH 0x08000000 /* DMA Channel to PLB4 */
+#define SDR0_SRST1_OPBA2 0x04000000 /* OPB Arbiter attached to PLB4
+ USB 2.0 Host */
+#define SDR0_SRST1_OPB2PLB40 0x02000000 /* OPB to PLB4 Bridge attached to
+ USB 2.0 Host */
+#define SDR0_SRST1_PLB42OPB1 0x01000000 /* PLB4 to OPB Bridge attached to
+ USB 2.0 Host */
+#define SDR0_SRST1_CPM1 0x00800000 /* Clock and Power management 1 */
+#define SDR0_SRST1_UIC2 0x00400000 /* Universal Interrupt Controller 2*/
+#define SDR0_SRST1_CRYP0 0x00200000 /* Security Engine */
+#define SDR0_SRST1_USB20PHY 0x00100000 /* USB 2.0 Phy */
+#define SDR0_SRST1_USB2HUTMI 0x00080000 /* USB 2.0 Host UTMI Interface */
+#define SDR0_SRST1_USB2HPHY 0x00040000 /* USB 2.0 Host Phy Interface */
+#define SDR0_SRST1_SRAM0 0x00020000 /* Internal SRAM Controller */
+#define SDR0_SRST1_RGMII0 0x00010000 /* RGMII Bridge */
+#define SDR0_SRST1_ETHPLL 0x00008000 /* Ethernet PLL */
+#define SDR0_SRST1_FPU 0x00004000 /* Floating Point Unit */
+#define SDR0_SRST1_KASU0 0x00002000 /* Kasumi Engine */
+
+#define PLLSYS0_ENG_MASK 0x80000000 /* 0 = SysClk, 1 = PLL VCO */
+#define PLLSYS0_SRC_MASK 0x40000000 /* 0 = PLL A, 1 = PLL B */
+#define PLLSYS0_SEL_MASK 0x38000000 /* 0 = PLL, 1 = CPU, 5 = PerClk */
+#define PLLSYS0_TUNE_MASK 0x07fe0000 /* PLL Tune bits */
+#define PLLSYS0_FB_DIV_MASK 0x0001f000 /* Feedback divisor */
+#define PLLSYS0_FWD_DIV_A_MASK 0x00000f00 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x000000e0 /* Fwd Div B */
+#define PLLSYS0_PRI_DIV_B_MASK 0x0000001c /* PLL Primary Divisor B */
+#define PLLSYS0_OPB_DIV_MASK 0x00000003 /* OPB Divisor */
+
+#define PLLC_ENG_MASK 0x20000000 /* PLL primary forward divisor source */
+#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
+#define PLLD_FBDV_MASK 0x1f000000 /* PLL Feedback Divisor */
+#define PLLD_FWDVA_MASK 0x000f0000 /* PLL Forward Divisor A */
+#define PLLD_FWDVB_MASK 0x00000700 /* PLL Forward Divisor B */
+#define PLLD_LFBDV_MASK 0x0000003f /* PLL Local Feedback Divisor */
+
+#define OPBDDV_MASK 0x03000000 /* OPB Clock Divisor Register */
+#define PERDV_MASK 0x07000000 /* Peripheral Clock Divisor */
+#define PRADV_MASK 0x07000000 /* Primary Divisor A */
+#define PRBDV_MASK 0x07000000 /* Primary Divisor B */
+#define SPCID_MASK 0x03000000 /* Sync PCI Divisor */
+
+/* Strap 1 Register */
+#define PLLSYS1_LF_DIV_MASK 0xfc000000 /* PLL Local Feedback Divisor */
+#define PLLSYS1_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS1_MAL_DIV_MASK 0x00c00000 /* MAL Clk Divisor */
+#define PLLSYS1_RW_MASK 0x00300000 /* ROM width */
+#define PLLSYS1_EAR_MASK 0x00080000 /* ERAP Address reset vector */
+#define PLLSYS1_PAE_MASK 0x00040000 /* PCI arbitor enable */
+#define PLLSYS1_PCHE_MASK 0x00020000 /* PCI host config enable */
+#define PLLSYS1_PISE_MASK 0x00010000 /* PCI init seq. enable */
+#define PLLSYS1_PCWE_MASK 0x00008000 /* PCI local cpu wait enable */
+#define PLLSYS1_PPIM_MASK 0x00007800 /* PCI inbound map */
+#define PLLSYS1_PR64E_MASK 0x00000400 /* PCI init Req64 enable */
+#define PLLSYS1_PXFS_MASK 0x00000300 /* PCI-X Freq Sel */
+#define PLLSYS1_RSVD_MASK 0x00000080 /* RSVD */
+#define PLLSYS1_PDM_MASK 0x00000040 /* PCI-X Driver Mode */
+#define PLLSYS1_EPS_MASK 0x00000038 /* Ethernet Pin Select */
+#define PLLSYS1_RMII_MASK 0x00000004 /* RMII Mode */
+#define PLLSYS1_TRE_MASK 0x00000002 /* GPIO Trace Enable */
+#define PLLSYS1_NTO1_MASK 0x00000001 /* CPU:PLB N-to-1 ratio */
+
+#define CPR0_ICFG_RLI_MASK 0x80000000
+#define CPR0_ICFG_ICS_MASK 0x00000007
+#define CPR0_SPCID_SPCIDV0_MASK 0x03000000
+#define CPR0_SPCID_SPCIDV0_DIV1 0x01000000
+#define CPR0_SPCID_SPCIDV0_DIV2 0x02000000
+#define CPR0_SPCID_SPCIDV0_DIV3 0x03000000
+#define CPR0_SPCID_SPCIDV0_DIV4 0x00000000
+#define CPR0_PERD_PERDV0_MASK 0x07000000
+
+#define PCI_MMIO_LCR_BASE (CONFIG_SYS_PCI_BASE + 0x0f400000) /* Real =>
+ 0x0EF400000 */
+
+/* PCI Master Local Configuration Registers */
+#define PCIL0_PMM0LA (PCI_MMIO_LCR_BASE + 0x00) /* PMM0 Local Address */
+#define PCIL0_PMM0MA (PCI_MMIO_LCR_BASE + 0x04) /* PMM0 Mask/Attribute */
+#define PCIL0_PMM0PCILA (PCI_MMIO_LCR_BASE + 0x08) /* PMM0 PCI Low Address */
+#define PCIL0_PMM0PCIHA (PCI_MMIO_LCR_BASE + 0x0C) /* PMM0 PCI High Address */
+#define PCIL0_PMM1LA (PCI_MMIO_LCR_BASE + 0x10) /* PMM1 Local Address */
+#define PCIL0_PMM1MA (PCI_MMIO_LCR_BASE + 0x14) /* PMM1 Mask/Attribute */
+#define PCIL0_PMM1PCILA (PCI_MMIO_LCR_BASE + 0x18) /* PMM1 PCI Low Address */
+#define PCIL0_PMM1PCIHA (PCI_MMIO_LCR_BASE + 0x1C) /* PMM1 PCI High Address */
+#define PCIL0_PMM2LA (PCI_MMIO_LCR_BASE + 0x20) /* PMM2 Local Address */
+#define PCIL0_PMM2MA (PCI_MMIO_LCR_BASE + 0x24) /* PMM2 Mask/Attribute */
+#define PCIL0_PMM2PCILA (PCI_MMIO_LCR_BASE + 0x28) /* PMM2 PCI Low Address */
+#define PCIL0_PMM2PCIHA (PCI_MMIO_LCR_BASE + 0x2C) /* PMM2 PCI High Address */
+
+/* PCI Target Local Configuration Registers */
+#define PCIL0_PTM1MS (PCI_MMIO_LCR_BASE + 0x30) /* PTM1 Memory Size/
+ Attribute */
+#define PCIL0_PTM1LA (PCI_MMIO_LCR_BASE + 0x34) /* PTM1 Local Addr. Reg */
+#define PCIL0_PTM2MS (PCI_MMIO_LCR_BASE + 0x38) /* PTM2 Memory Size/
+ Attribute */
+#define PCIL0_PTM2LA (PCI_MMIO_LCR_BASE + 0x3C) /* PTM2 Local Addr. Reg */
+
+/* 440EPx boot strap options */
+#define BOOT_STRAP_OPTION_A 0x00000000
+#define BOOT_STRAP_OPTION_B 0x00000001
+#define BOOT_STRAP_OPTION_D 0x00000003
+#define BOOT_STRAP_OPTION_E 0x00000004
+
+#endif /* _PPC440EPX_GRX_H_ */
diff --git a/arch/powerpc/include/asm/ppc440gp.h b/arch/powerpc/include/asm/ppc440gp.h
new file mode 100644
index 0000000..3ebe2a1
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc440gp.h
@@ -0,0 +1,72 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC440GP_H_
+#define _PPC440GP_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR /* IBM DDR controller */
+
+/*
+ * Some SoC specific registers (not common for all 440 SoC's)
+ */
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xe0000000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0200)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+#define SDR0_PCI0 0x0300
+
+#define CPC0_STRP1_PAE_MASK (0x80000000 >> 11)
+#define CPC0_STRP1_PISE_MASK (0x80000000 >> 13)
+
+#define CNTRL_DCR_BASE 0x0b0
+
+#define CPC0_SYS0 (CNTRL_DCR_BASE + 0x30) /* System configuration reg 0 */
+#define CPC0_SYS1 (CNTRL_DCR_BASE + 0x31) /* System configuration reg 1 */
+
+#define CPC0_STRP0 (CNTRL_DCR_BASE + 0x34) /* Power-on config reg 0 (RO) */
+#define CPC0_STRP1 (CNTRL_DCR_BASE + 0x35) /* Power-on config reg 1 (RO) */
+
+#define CPC0_GPIO (CNTRL_DCR_BASE + 0x38) /* GPIO config reg (440GP) */
+
+#define CPC0_CR0 (CNTRL_DCR_BASE + 0x3b) /* Control 0 register */
+#define CPC0_CR1 (CNTRL_DCR_BASE + 0x3a) /* Control 1 register */
+
+#define PLLSYS0_TUNE_MASK 0xffc00000 /* PLL TUNE bits */
+#define PLLSYS0_FB_DIV_MASK 0x003c0000 /* Feedback divisor */
+#define PLLSYS0_FWD_DIV_A_MASK 0x00038000 /* Forward divisor A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x00007000 /* Forward divisor B */
+#define PLLSYS0_OPB_DIV_MASK 0x00000c00 /* OPB divisor */
+#define PLLSYS0_EPB_DIV_MASK 0x00000300 /* EPB divisor */
+#define PLLSYS0_EXTSL_MASK 0x00000080 /* PerClk feedback path */
+#define PLLSYS0_RW_MASK 0x00000060 /* ROM width */
+#define PLLSYS0_RL_MASK 0x00000010 /* ROM location */
+#define PLLSYS0_ZMII_SEL_MASK 0x0000000c /* ZMII selection */
+#define PLLSYS0_BYPASS_MASK 0x00000002 /* Bypass PLL */
+#define PLLSYS0_NTO1_MASK 0x00000001 /* CPU:PLB N-to-1 ratio */
+
+#define PCIL0_BRDGOPT1 (PCIL0_CFGBASE + 0x0040)
+#define PCIL0_BRDGOPT2 (PCIL0_CFGBASE + 0x0044)
+
+#endif /* _PPC440GP_H_ */
diff --git a/arch/powerpc/include/asm/ppc440gx.h b/arch/powerpc/include/asm/ppc440gx.h
new file mode 100644
index 0000000..9924525
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc440gx.h
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC440GX_H_
+#define _PPC440GX_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR /* IBM DDR controller */
+
+/*
+ * Some SoC specific registers (not common for all 440 SoC's)
+ */
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xe0000000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0200)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+/* SDR's */
+#define SDR0_PCI0 0x0300
+
+#define SDR0_SDSTP2 0x4001
+#define SDR0_SDSTP3 0x4003
+
+#define SDR0_SDSTP1_PAE_MASK (0x80000000 >> 13)
+#define SDR0_SDSTP1_PISE_MASK (0x80000000 >> 15)
+
+#define SDR0_PFC1_EPS_DECODE(n) ((((u32)(n)) >> 22) & 0x07)
+#define SDR0_PFC1_CTEMS_MASK (0x80000000 >> 11)
+#define SDR0_PFC1_CTEMS_EMS 0x00000000
+#define SDR0_PFC1_CTEMS_CPUTRACE (0x80000000 >> 11)
+
+#define SDR0_MFR_ECS_MASK 0x10000000
+
+#define SDR0_SRST_DMC 0x00200000
+
+#define PLLSYS0_ENG_MASK 0x80000000 /* 0 = SysClk, 1 = PLL VCO */
+#define PLLSYS0_SRC_MASK 0x40000000 /* 0 = PLL A, 1 = PLL B */
+#define PLLSYS0_SEL_MASK 0x38000000 /* 0 = PLL, 1 = CPU, 5 = PerClk */
+#define PLLSYS0_TUNE_MASK 0x07fe0000 /* PLL Tune bits */
+#define PLLSYS0_FB_DIV_MASK 0x0001f000 /* Feedback divisor */
+#define PLLSYS0_FWD_DIV_A_MASK 0x00000f00 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x000000e0 /* Fwd Div B */
+#define PLLSYS0_PRI_DIV_B_MASK 0x0000001c /* PLL Primary Divisor B */
+#define PLLSYS0_OPB_DIV_MASK 0x00000003 /* OPB Divisor */
+
+#define PLLC_ENG_MASK 0x20000000 /* PLL primary forward divisor source */
+#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
+#define PLLD_FBDV_MASK 0x1f000000 /* PLL Feedback Divisor */
+#define PLLD_FWDVA_MASK 0x000f0000 /* PLL Forward Divisor A */
+#define PLLD_FWDVB_MASK 0x00000700 /* PLL Forward Divisor B */
+#define PLLD_LFBDV_MASK 0x0000003f /* PLL Local Feedback Divisor */
+
+#define OPBDDV_MASK 0x03000000 /* OPB Clock Divisor Register */
+#define PERDV_MASK 0x07000000 /* Peripheral Clock Divisor */
+#define PRADV_MASK 0x07000000 /* Primary Divisor A */
+#define PRBDV_MASK 0x07000000 /* Primary Divisor B */
+#define SPCID_MASK 0x03000000 /* Sync PCI Divisor */
+
+/* Strap 1 Register */
+#define PLLSYS1_LF_DIV_MASK 0xfc000000 /* PLL Local Feedback Divisor */
+#define PLLSYS1_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS1_MAL_DIV_MASK 0x00c00000 /* MAL Clk Divisor */
+#define PLLSYS1_RW_MASK 0x00300000 /* ROM width */
+#define PLLSYS1_EAR_MASK 0x00080000 /* ERAP Address reset vector */
+#define PLLSYS1_PAE_MASK 0x00040000 /* PCI arbitor enable */
+#define PLLSYS1_PCHE_MASK 0x00020000 /* PCI host config enable */
+#define PLLSYS1_PISE_MASK 0x00010000 /* PCI init seq. enable */
+#define PLLSYS1_PCWE_MASK 0x00008000 /* PCI local cpu wait enable */
+#define PLLSYS1_PPIM_MASK 0x00007800 /* PCI inbound map */
+#define PLLSYS1_PR64E_MASK 0x00000400 /* PCI init Req64 enable */
+#define PLLSYS1_PXFS_MASK 0x00000300 /* PCI-X Freq Sel */
+#define PLLSYS1_RSVD_MASK 0x00000080 /* RSVD */
+#define PLLSYS1_PDM_MASK 0x00000040 /* PCI-X Driver Mode */
+#define PLLSYS1_EPS_MASK 0x00000038 /* Ethernet Pin Select */
+#define PLLSYS1_RMII_MASK 0x00000004 /* RMII Mode */
+#define PLLSYS1_TRE_MASK 0x00000002 /* GPIO Trace Enable */
+#define PLLSYS1_NTO1_MASK 0x00000001 /* CPU:PLB N-to-1 ratio */
+
+#define PCIL0_BRDGOPT1 (PCIL0_CFGBASE + 0x0040)
+#define PCIL0_BRDGOPT2 (PCIL0_CFGBASE + 0x0044)
+
+#endif /* _PPC440GX_H_ */
diff --git a/arch/powerpc/include/asm/ppc440sp.h b/arch/powerpc/include/asm/ppc440sp.h
new file mode 100644
index 0000000..cc2ff68
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc440sp.h
@@ -0,0 +1,98 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC440SP_H_
+#define _PPC440SP_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
+
+/*
+ * Some SoC specific registers (not common for all 440 SoC's)
+ */
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xf0000000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0200)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+/* SDR's */
+#define SDR0_PCI0 0x0300
+#define SDR0_SDSTP2 0x0022
+#define SDR0_SDSTP3 0x0023
+
+#define SDR0_SDSTP1_PAE_MASK (0x80000000 >> 13)
+#define SDR0_SDSTP1_PISE_MASK (0x80000000 >> 15)
+
+#define SDR0_PFC1_EM_1000 (0x80000000 >> 10)
+
+#define SDR0_MFR_FIXD (0x80000000 >> 3) /* Workaround for PCI/DMA */
+
+#define SDR0_SRST0_DMC 0x00200000
+
+#define PLLSYS0_ENG_MASK 0x80000000 /* 0 = SysClk, 1 = PLL VCO */
+#define PLLSYS0_SRC_MASK 0x40000000 /* 0 = PLL A, 1 = PLL B */
+#define PLLSYS0_SEL_MASK 0x38000000 /* 0 = PLL, 1 = CPU, 5 = PerClk */
+#define PLLSYS0_TUNE_MASK 0x07fe0000 /* PLL Tune bits */
+#define PLLSYS0_FB_DIV_MASK 0x0001f000 /* Feedback divisor */
+#define PLLSYS0_FWD_DIV_A_MASK 0x00000f00 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x000000e0 /* Fwd Div B */
+#define PLLSYS0_PRI_DIV_B_MASK 0x0000001c /* PLL Primary Divisor B */
+#define PLLSYS0_OPB_DIV_MASK 0x00000003 /* OPB Divisor */
+
+#define PLLC_ENG_MASK 0x20000000 /* PLL primary forward divisor source */
+#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
+#define PLLD_FBDV_MASK 0x1f000000 /* PLL Feedback Divisor */
+#define PLLD_FWDVA_MASK 0x000f0000 /* PLL Forward Divisor A */
+#define PLLD_FWDVB_MASK 0x00000700 /* PLL Forward Divisor B */
+#define PLLD_LFBDV_MASK 0x0000003f /* PLL Local Feedback Divisor */
+
+#define OPBDDV_MASK 0x03000000 /* OPB Clock Divisor Register */
+#define PERDV_MASK 0x07000000 /* Peripheral Clock Divisor */
+#define PRADV_MASK 0x07000000 /* Primary Divisor A */
+#define PRBDV_MASK 0x07000000 /* Primary Divisor B */
+#define SPCID_MASK 0x03000000 /* Sync PCI Divisor */
+
+/* Strap 1 Register */
+#define PLLSYS1_LF_DIV_MASK 0xfc000000 /* PLL Local Feedback Divisor */
+#define PLLSYS1_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS1_MAL_DIV_MASK 0x00c00000 /* MAL Clk Divisor */
+#define PLLSYS1_RW_MASK 0x00300000 /* ROM width */
+#define PLLSYS1_EAR_MASK 0x00080000 /* ERAP Address reset vector */
+#define PLLSYS1_PAE_MASK 0x00040000 /* PCI arbitor enable */
+#define PLLSYS1_PCHE_MASK 0x00020000 /* PCI host config enable */
+#define PLLSYS1_PISE_MASK 0x00010000 /* PCI init seq. enable */
+#define PLLSYS1_PCWE_MASK 0x00008000 /* PCI local cpu wait enable */
+#define PLLSYS1_PPIM_MASK 0x00007800 /* PCI inbound map */
+#define PLLSYS1_PR64E_MASK 0x00000400 /* PCI init Req64 enable */
+#define PLLSYS1_PXFS_MASK 0x00000300 /* PCI-X Freq Sel */
+#define PLLSYS1_RSVD_MASK 0x00000080 /* RSVD */
+#define PLLSYS1_PDM_MASK 0x00000040 /* PCI-X Driver Mode */
+#define PLLSYS1_EPS_MASK 0x00000038 /* Ethernet Pin Select */
+#define PLLSYS1_RMII_MASK 0x00000004 /* RMII Mode */
+#define PLLSYS1_TRE_MASK 0x00000002 /* GPIO Trace Enable */
+#define PLLSYS1_NTO1_MASK 0x00000001 /* CPU:PLB N-to-1 ratio */
+
+#define PCIL0_BRDGOPT1 (PCIL0_CFGBASE + 0x0040)
+#define PCIL0_BRDGOPT2 (PCIL0_CFGBASE + 0x0044)
+
+#endif /* _PPC440SP_H_ */
diff --git a/arch/powerpc/include/asm/ppc440spe.h b/arch/powerpc/include/asm/ppc440spe.h
new file mode 100644
index 0000000..d59d7d2
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc440spe.h
@@ -0,0 +1,114 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC440SPE_H_
+#define _PPC440SPE_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
+
+/*
+ * Some SoC specific registers (not common for all 440 SoC's)
+ */
+
+/* Memory mapped register */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xa0000000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0200)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+/* SDR's */
+#define SDR0_PCI0 0x0300
+#define SDR0_SDSTP2 0x0022
+#define SDR0_SDSTP3 0x0023
+
+#define SDR0_SDSTP1_PAE_MASK (0x80000000 >> 13)
+#define SDR0_SDSTP1_PISE_MASK (0x80000000 >> 15)
+#define SDR0_SDSTP1_ERPN_MASK (0x80000000 >> 12)
+#define SDR0_SDSTP1_ERPN_EBC 0
+#define SDR0_SDSTP1_ERPN_PCI (0x80000000 >> 12)
+#define SDR0_SDSTP1_EBCW_MASK (0x80000000 >> 24)
+#define SDR0_SDSTP1_EBCW_8_BITS 0
+#define SDR0_SDSTP1_EBCW_16_BITS (0x80000000 >> 24)
+
+#define SDR0_PFC1_EM_1000 (0x80000000 >> 10)
+
+#define SDR0_MFR_FIXD (0x80000000 >> 3) /* Workaround for PCI/DMA */
+
+#define SDR0_PINSTP_BOOTSTRAP_MASK 0xC0000000 /* Strap Bits */
+#define SDR0_PINSTP_BOOTSTRAP_SETTINGS0 0x00000000 /* Default strap settings 0
+ (EBC boot) */
+#define SDR0_PINSTP_BOOTSTRAP_SETTINGS1 0x40000000 /* Default strap settings 1
+ (PCI boot) */
+#define SDR0_PINSTP_BOOTSTRAP_IIC_54_EN 0x80000000 /* Serial Device Enabled -
+ Addr = 0x54 */
+#define SDR0_PINSTP_BOOTSTRAP_IIC_50_EN 0xC0000000 /* Serial Device Enabled -
+ Addr = 0x50 */
+
+#define SDR0_SRST0_DMC 0x00200000
+
+#define PLLSYS0_ENG_MASK 0x80000000 /* 0 = SysClk, 1 = PLL VCO */
+#define PLLSYS0_SRC_MASK 0x40000000 /* 0 = PLL A, 1 = PLL B */
+#define PLLSYS0_SEL_MASK 0x38000000 /* 0 = PLL, 1 = CPU, 5 = PerClk */
+#define PLLSYS0_TUNE_MASK 0x07fe0000 /* PLL Tune bits */
+#define PLLSYS0_FB_DIV_MASK 0x0001f000 /* Feedback divisor */
+#define PLLSYS0_FWD_DIV_A_MASK 0x00000f00 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x000000e0 /* Fwd Div B */
+#define PLLSYS0_PRI_DIV_B_MASK 0x0000001c /* PLL Primary Divisor B */
+#define PLLSYS0_OPB_DIV_MASK 0x00000003 /* OPB Divisor */
+
+#define PLLC_ENG_MASK 0x20000000 /* PLL primary forward divisor source */
+#define PLLC_SRC_MASK 0x20000000 /* PLL feedback source */
+#define PLLD_FBDV_MASK 0x1f000000 /* PLL Feedback Divisor */
+#define PLLD_FWDVA_MASK 0x000f0000 /* PLL Forward Divisor A */
+#define PLLD_FWDVB_MASK 0x00000700 /* PLL Forward Divisor B */
+#define PLLD_LFBDV_MASK 0x0000003f /* PLL Local Feedback Divisor */
+
+#define OPBDDV_MASK 0x03000000 /* OPB Clock Divisor Register */
+#define PERDV_MASK 0x07000000 /* Peripheral Clock Divisor */
+#define PRADV_MASK 0x07000000 /* Primary Divisor A */
+#define PRBDV_MASK 0x07000000 /* Primary Divisor B */
+#define SPCID_MASK 0x03000000 /* Sync PCI Divisor */
+
+/* Strap 1 Register */
+#define PLLSYS1_LF_DIV_MASK 0xfc000000 /* PLL Local Feedback Divisor */
+#define PLLSYS1_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS1_MAL_DIV_MASK 0x00c00000 /* MAL Clk Divisor */
+#define PLLSYS1_RW_MASK 0x00300000 /* ROM width */
+#define PLLSYS1_EAR_MASK 0x00080000 /* ERAP Address reset vector */
+#define PLLSYS1_PAE_MASK 0x00040000 /* PCI arbitor enable */
+#define PLLSYS1_PCHE_MASK 0x00020000 /* PCI host config enable */
+#define PLLSYS1_PISE_MASK 0x00010000 /* PCI init seq. enable */
+#define PLLSYS1_PCWE_MASK 0x00008000 /* PCI local cpu wait enable */
+#define PLLSYS1_PPIM_MASK 0x00007800 /* PCI inbound map */
+#define PLLSYS1_PR64E_MASK 0x00000400 /* PCI init Req64 enable */
+#define PLLSYS1_PXFS_MASK 0x00000300 /* PCI-X Freq Sel */
+#define PLLSYS1_RSVD_MASK 0x00000080 /* RSVD */
+#define PLLSYS1_PDM_MASK 0x00000040 /* PCI-X Driver Mode */
+#define PLLSYS1_EPS_MASK 0x00000038 /* Ethernet Pin Select */
+#define PLLSYS1_RMII_MASK 0x00000004 /* RMII Mode */
+#define PLLSYS1_TRE_MASK 0x00000002 /* GPIO Trace Enable */
+#define PLLSYS1_NTO1_MASK 0x00000001 /* CPU:PLB N-to-1 ratio */
+
+#define PCIL0_BRDGOPT1 (PCIL0_CFGBASE + 0x0040)
+#define PCIL0_BRDGOPT2 (PCIL0_CFGBASE + 0x0044)
+
+#endif /* _PPC440SPE_H_ */
diff --git a/arch/powerpc/include/asm/ppc460ex_gt.h b/arch/powerpc/include/asm/ppc460ex_gt.h
new file mode 100644
index 0000000..732fcac
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc460ex_gt.h
@@ -0,0 +1,222 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC460EX_GT_H_
+#define _PPC460EX_GT_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
+
+#define CONFIG_NAND_NDFC
+
+/*
+ * Some SoC specific registers
+ */
+
+/* Memory mapped registers */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xef600000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0400)
+#define CONFIG_SYS_NS16550_COM3 (CONFIG_SYS_PERIPHERAL_BASE + 0x0500)
+#define CONFIG_SYS_NS16550_COM4 (CONFIG_SYS_PERIPHERAL_BASE + 0x0600)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0b00)
+#define GPIO1_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0c00)
+
+/* DCR */
+#define AHB_TOP 0x00a4
+#define AHB_BOT 0x00a5
+
+/* SDR */
+#define SDR0_PCI0 0x01c0
+#define SDR0_AHB_CFG 0x0370
+#define SDR0_USB2HOST_CFG 0x0371
+#define SDR0_ETH_PLL 0x4102
+#define SDR0_ETH_CFG 0x4103
+#define SDR0_ETH_STS 0x4104
+
+/*
+ * Register bits and masks
+ */
+#define SDR0_SDSTP1_PAE_MASK (0x80000000 >> 13)
+#define SDR0_SDSTP1_PISE_MASK (0x80000000 >> 15)
+
+/* CUST0 Customer Configuration Register0 */
+#define SDR0_CUST0_MUX_E_N_G_MASK 0xC0000000 /* Mux_Emac_NDFC_GPIO */
+#define SDR0_CUST0_MUX_EMAC_SEL 0x40000000 /* Emac Selection */
+#define SDR0_CUST0_MUX_NDFC_SEL 0x80000000 /* NDFC Selection */
+#define SDR0_CUST0_MUX_GPIO_SEL 0xC0000000 /* GPIO Selection */
+
+#define SDR0_CUST0_NDFC_EN_MASK 0x20000000 /* NDFC Enable Mask */
+#define SDR0_CUST0_NDFC_ENABLE 0x20000000 /* NDFC Enable */
+#define SDR0_CUST0_NDFC_DISABLE 0x00000000 /* NDFC Disable */
+
+#define SDR0_CUST0_NDFC_BW_MASK 0x10000000 /* NDFC Boot Width */
+#define SDR0_CUST0_NDFC_BW_16_BIT 0x10000000 /* NDFC Boot Width = 16 Bit */
+#define SDR0_CUST0_NDFC_BW_8_BIT 0x00000000 /* NDFC Boot Width = 8 Bit */
+
+#define SDR0_CUST0_NDFC_BP_MASK 0x0F000000 /* NDFC Boot Page */
+#define SDR0_CUST0_NDFC_BP_ENCODE(n) ((((u32)(n)) & 0xF) << 24)
+#define SDR0_CUST0_NDFC_BP_DECODE(n) ((((u32)(n)) >> 24) & 0xF)
+
+#define SDR0_CUST0_NDFC_BAC_MASK 0x00C00000 /* NDFC Boot Address Cycle */
+#define SDR0_CUST0_NDFC_BAC_ENCODE(n) ((((u32)(n)) & 0x3) << 22)
+#define SDR0_CUST0_NDFC_BAC_DECODE(n) ((((u32)(n)) >> 22) & 0x3)
+
+#define SDR0_CUST0_NDFC_ARE_MASK 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_ENABLE 0x00200000 /* NDFC Auto Read Enable */
+#define SDR0_CUST0_NDFC_ARE_DISABLE 0x00000000 /* NDFC Auto Read Disable */
+
+#define SDR0_CUST0_NRB_MASK 0x00100000 /* NDFC Ready / Busy */
+#define SDR0_CUST0_NRB_BUSY 0x00100000 /* Busy */
+#define SDR0_CUST0_NRB_READY 0x00000000 /* Ready */
+
+#define SDR0_CUST0_NDRSC_MASK 0x0000FFF0 /* NDFC Device Reset Count Mask */
+#define SDR0_CUST0_NDRSC_ENCODE(n) ((((u32)(n)) & 0xFFF) << 4)
+#define SDR0_CUST0_NDRSC_DECODE(n) ((((u32)(n)) >> 4) & 0xFFF)
+
+#define SDR0_CUST0_CHIPSELGAT_MASK 0x0000000F /* Chip Select Gating Mask */
+#define SDR0_CUST0_CHIPSELGAT_DIS 0x00000000 /* Chip Select Gating Disable */
+#define SDR0_CUST0_CHIPSELGAT_ENALL 0x0000000F /*All Chip Select Gating Enable*/
+#define SDR0_CUST0_CHIPSELGAT_EN0 0x00000008 /* Chip Select0 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN1 0x00000004 /* Chip Select1 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN2 0x00000002 /* Chip Select2 Gating Enable */
+#define SDR0_CUST0_CHIPSELGAT_EN3 0x00000001 /* Chip Select3 Gating Enable */
+
+/* Ethernet PLL Configuration Register (SDR0_ETH_PLL) */
+#define SDR0_ETH_PLL_PLLLOCK 0x80000000 /* Ethernet PLL lock indication */
+
+/* Ethernet Configuration Register (SDR0_ETH_CFG) */
+#define SDR0_ETH_CFG_SGMII3_LPBK 0x00800000 /*SGMII3 port loopback
+ enable */
+#define SDR0_ETH_CFG_SGMII2_LPBK 0x00400000 /*SGMII2 port loopback
+ enable */
+#define SDR0_ETH_CFG_SGMII1_LPBK 0x00200000 /*SGMII1 port loopback
+ enable */
+#define SDR0_ETH_CFG_SGMII0_LPBK 0x00100000 /*SGMII0 port loopback
+ enable */
+#define SDR0_ETH_CFG_SGMII_MASK 0x00070000 /*SGMII Mask */
+#define SDR0_ETH_CFG_SGMII2_ENABLE 0x00040000 /*SGMII2 port enable */
+#define SDR0_ETH_CFG_SGMII1_ENABLE 0x00020000 /*SGMII1 port enable */
+#define SDR0_ETH_CFG_SGMII0_ENABLE 0x00010000 /*SGMII0 port enable */
+#define SDR0_ETH_CFG_TAHOE1_BYPASS 0x00002000 /*TAHOE1 Bypass selector */
+#define SDR0_ETH_CFG_TAHOE0_BYPASS 0x00001000 /*TAHOE0 Bypass selector */
+#define SDR0_ETH_CFG_EMAC3_PHY_CLK_SEL 0x00000800 /*EMAC 3 PHY clock selector*/
+#define SDR0_ETH_CFG_EMAC2_PHY_CLK_SEL 0x00000400 /*EMAC 2 PHY clock selector*/
+#define SDR0_ETH_CFG_EMAC1_PHY_CLK_SEL 0x00000200 /*EMAC 1 PHY clock selector*/
+#define SDR0_ETH_CFG_EMAC0_PHY_CLK_SEL 0x00000100 /*EMAC 0 PHY clock selector*/
+#define SDR0_ETH_CFG_EMAC_2_1_SWAP 0x00000080 /*Swap EMAC2 with EMAC1 */
+#define SDR0_ETH_CFG_EMAC_0_3_SWAP 0x00000040 /*Swap EMAC0 with EMAC3 */
+#define SDR0_ETH_CFG_MDIO_SEL_MASK 0x00000030 /*MDIO source selector mask*/
+#define SDR0_ETH_CFG_MDIO_SEL_EMAC0 0x00000000 /*MDIO source - EMAC0 */
+#define SDR0_ETH_CFG_MDIO_SEL_EMAC1 0x00000010 /*MDIO source - EMAC1 */
+#define SDR0_ETH_CFG_MDIO_SEL_EMAC2 0x00000020 /*MDIO source - EMAC2 */
+#define SDR0_ETH_CFG_MDIO_SEL_EMAC3 0x00000030 /*MDIO source - EMAC3 */
+#define SDR0_ETH_CFG_GMC1_BRIDGE_SEL 0x00000002 /*GMC Port 1 bridge
+ selector */
+#define SDR0_ETH_CFG_GMC0_BRIDGE_SEL 0x00000001 /*GMC Port 0 bridge
+ selector */
+
+#define SDR0_SRST0_BGO 0x80000000 /* PLB to OPB bridge */
+#define SDR0_SRST0_PLB4 0x40000000 /* PLB4 arbiter */
+#define SDR0_SRST0_EBC 0x20000000 /* External bus controller */
+#define SDR0_SRST0_OPB 0x10000000 /* OPB arbiter */
+#define SDR0_SRST0_UART0 0x08000000 /* Universal asynchronous receiver/
+ transmitter 0 */
+#define SDR0_SRST0_UART1 0x04000000 /* Universal asynchronous receiver/
+ transmitter 1 */
+#define SDR0_SRST0_IIC0 0x02000000 /* Inter integrated circuit 0 */
+#define SDR0_SRST0_IIC1 0x01000000 /* Inter integrated circuit 1 */
+#define SDR0_SRST0_GPIO0 0x00800000 /* General purpose I/O 0 */
+#define SDR0_SRST0_GPT 0x00400000 /* General purpose timer */
+#define SDR0_SRST0_DMC 0x00200000 /* DDR SDRAM memory controller */
+#define SDR0_SRST0_PCI 0x00100000 /* PCI */
+#define SDR0_SRST0_CPM0 0x00020000 /* Clock and power management */
+#define SDR0_SRST0_IMU 0x00010000 /* I2O DMA */
+#define SDR0_SRST0_UIC0 0x00008000 /* Universal interrupt controller 0*/
+#define SDR0_SRST0_UIC1 0x00004000 /* Universal interrupt controller 1*/
+#define SDR0_SRST0_SRAM 0x00002000 /* Universal interrupt controller 0*/
+#define SDR0_SRST0_UIC2 0x00001000 /* Universal interrupt controller 2*/
+#define SDR0_SRST0_UIC3 0x00000800 /* Universal interrupt controller 3*/
+#define SDR0_SRST0_OCM 0x00000400 /* Universal interrupt controller 0*/
+#define SDR0_SRST0_UART2 0x00000200 /* Universal asynchronous receiver/
+ transmitter 2 */
+#define SDR0_SRST0_MAL 0x00000100 /* Media access layer */
+#define SDR0_SRST0_GPTR 0x00000040 /* General purpose timer */
+#define SDR0_SRST0_L2CACHE 0x00000004 /* L2 Cache */
+#define SDR0_SRST0_UART3 0x00000002 /* Universal asynchronous receiver/
+ transmitter 3 */
+#define SDR0_SRST0_GPIO1 0x00000001 /* General purpose I/O 1 */
+
+#define SDR0_SRST1_RLL 0x80000000 /* SRIO RLL */
+#define SDR0_SRST1_SCP 0x40000000 /* Serial communications port */
+#define SDR0_SRST1_PLBARB 0x20000000 /* PLB Arbiter */
+#define SDR0_SRST1_EIPPKP 0x10000000 /* EIPPPKP */
+#define SDR0_SRST1_EIP94 0x08000000 /* EIP 94 */
+#define SDR0_SRST1_EMAC0 0x04000000 /* Ethernet media access
+ controller 0 */
+#define SDR0_SRST1_EMAC1 0x02000000 /* Ethernet media access
+ controller 1 */
+#define SDR0_SRST1_EMAC2 0x01000000 /* Ethernet media access
+ controller 2 */
+#define SDR0_SRST1_EMAC3 0x00800000 /* Ethernet media access
+ controller 3 */
+#define SDR0_SRST1_ZMII 0x00400000 /* Ethernet ZMII/RMII/SMII */
+#define SDR0_SRST1_RGMII0 0x00200000 /* Ethernet RGMII/RTBI 0 */
+#define SDR0_SRST1_RGMII1 0x00100000 /* Ethernet RGMII/RTBI 1 */
+#define SDR0_SRST1_DMA4 0x00080000 /* DMA to PLB4 */
+#define SDR0_SRST1_DMA4CH 0x00040000 /* DMA Channel to PLB4 */
+#define SDR0_SRST1_SATAPHY 0x00020000 /* Serial ATA PHY */
+#define SDR0_SRST1_SRIODEV 0x00010000 /* Serial Rapid IO core, PCS, and
+ serdes */
+#define SDR0_SRST1_SRIOPCS 0x00008000 /* Serial Rapid IO core and PCS */
+#define SDR0_SRST1_NDFC 0x00004000 /* Nand flash controller */
+#define SDR0_SRST1_SRIOPLB 0x00002000 /* Serial Rapid IO PLB */
+#define SDR0_SRST1_ETHPLL 0x00001000 /* Ethernet PLL */
+#define SDR0_SRST1_TAHOE1 0x00000800 /* Ethernet Tahoe 1 */
+#define SDR0_SRST1_TAHOE0 0x00000400 /* Ethernet Tahoe 0 */
+#define SDR0_SRST1_SGMII0 0x00000200 /* Ethernet SGMII 0 */
+#define SDR0_SRST1_SGMII1 0x00000100 /* Ethernet SGMII 1 */
+#define SDR0_SRST1_SGMII2 0x00000080 /* Ethernet SGMII 2 */
+#define SDR0_SRST1_AHB 0x00000040 /* PLB4XAHB bridge */
+#define SDR0_SRST1_USBOTGPHY 0x00000020 /* USB 2.0 OTG PHY */
+#define SDR0_SRST1_USBOTG 0x00000010 /* USB 2.0 OTG controller */
+#define SDR0_SRST1_USBHOST 0x00000008 /* USB 2.0 Host controller */
+#define SDR0_SRST1_AHBDMAC 0x00000004 /* AHB DMA controller */
+#define SDR0_SRST1_AHBICM 0x00000002 /* AHB inter-connect matrix */
+#define SDR0_SRST1_SATA 0x00000001 /* Serial ATA controller */
+
+#define PLLSYS0_FWD_DIV_A_MASK 0x000000f0 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x0000000f /* Fwd Div B */
+#define PLLSYS0_FB_DIV_MASK 0x0000ff00 /* Feedback divisor */
+#define PLLSYS0_OPB_DIV_MASK 0x0c000000 /* OPB Divisor */
+#define PLLSYS0_PLBEDV0_DIV_MASK 0xe0000000 /* PLB Early Clock Divisor */
+#define PLLSYS0_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS0_SEL_MASK 0x18000000 /* 0 = PLL, 1 = PerClk */
+
+#define CPR0_ICFG_RLI_MASK 0x80000000
+
+#define CPR0_PLLC_RST 0x80000000
+#define CPR0_PLLC_ENG 0x40000000
+
+#define PCIL0_BRDGOPT1 (PCIL0_CFGBASE + 0x0040)
+#define PCIL0_BRDGOPT2 (PCIL0_CFGBASE + 0x0044)
+
+#endif /* _PPC460EX_GT_H_ */
diff --git a/arch/powerpc/include/asm/ppc460sx.h b/arch/powerpc/include/asm/ppc460sx.h
new file mode 100644
index 0000000..f93ef0e
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc460sx.h
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2010
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC460SX_H_
+#define _PPC460SX_H_
+
+#define CONFIG_SDRAM_PPC4xx_IBM_DDR2 /* IBM DDR(2) controller */
+
+/* Memory mapped registers */
+#define CONFIG_SYS_PERIPHERAL_BASE 0xa0000000 /* Internal Peripherals */
+
+#define CONFIG_SYS_NS16550_COM1 (CONFIG_SYS_PERIPHERAL_BASE + 0x0200)
+#define CONFIG_SYS_NS16550_COM2 (CONFIG_SYS_PERIPHERAL_BASE + 0x0300)
+
+#define GPIO0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0700)
+
+#define SDR0_SRST0_DMC 0x00200000
+
+#define PLLSYS0_FWD_DIV_A_MASK 0x000000f0 /* Fwd Div A */
+#define PLLSYS0_FWD_DIV_B_MASK 0x0000000f /* Fwd Div B */
+#define PLLSYS0_FB_DIV_MASK 0x0000ff00 /* Feedback divisor */
+#define PLLSYS0_OPB_DIV_MASK 0x0c000000 /* OPB Divisor */
+#define PLLSYS0_PLBEDV0_DIV_MASK 0xe0000000 /* PLB Early Clock Divisor */
+#define PLLSYS0_PERCLK_DIV_MASK 0x03000000 /* Peripheral Clk Divisor */
+#define PLLSYS0_SEL_MASK 0x18000000 /* 0 = PLL, 1 = PerClk */
+
+#endif /* _PPC460SX_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-ebc.h b/arch/powerpc/include/asm/ppc4xx-ebc.h
new file mode 100644
index 0000000..75af130
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-ebc.h
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_EBC_H_
+#define _PPC4xx_EBC_H_
+
+/*
+ * Currently there are two register layout versions for the IBM EBC core
+ * used on 4xx PPC's. The following grouping lists the first layout.
+ * Within this group there is a slight variation concerning the bit field
+ * position of the EMPL and EMPH fields:
+ */
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP) || \
+ defined(CONFIG_405EP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define CONFIG_EBC_PPC4xx_IBM_VER1
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP) || \
+ defined(CONFIG_405EP)
+#define EBC_CFG_EMPH_POS 8
+#define EBC_CFG_EMPL_POS 6
+#else
+#define EBC_CFG_EMPH_POS 6
+#define EBC_CFG_EMPL_POS 8
+#endif
+#endif
+
+/*
+ * Define the max number of EBC banks (chip selects)
+ */
+#if defined(CONFIG_405CR) || defined(CONFIG_405GP) || \
+ defined(CONFIG_405EZ) || \
+ defined(CONFIG_440GP) || defined(CONFIG_440GX)
+#define EBC_NUM_BANKS 8
+#endif
+
+#if defined(CONFIG_405EP)
+#define EBC_NUM_BANKS 5
+#endif
+
+#if defined(CONFIG_405EX) || \
+ defined(CONFIG_460SX)
+#define EBC_NUM_BANKS 4
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define EBC_NUM_BANKS 6
+#endif
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_APM821XX)
+#define EBC_NUM_BANKS 3
+#endif
+
+/* Bank Configuration Register */
+#define EBC_BXCR(n) (n)
+#define EBC_BXCR_BANK_SIZE(n) (0x100000 << (((n) & EBC_BXCR_BS_MASK) >> 17))
+
+#define EBC_BXCR_BAS_MASK PPC_REG_VAL(11, 0xFFF)
+#define EBC_BXCR_BAS_ENCODE(n) (((static_cast(u32, n)) & EBC_BXCR_BAS_MASK))
+#define EBC_BXCR_BS_MASK PPC_REG_VAL(14, 0x7)
+#define EBC_BXCR_BS_1MB PPC_REG_VAL(14, 0x0)
+#define EBC_BXCR_BS_2MB PPC_REG_VAL(14, 0x1)
+#define EBC_BXCR_BS_4MB PPC_REG_VAL(14, 0x2)
+#define EBC_BXCR_BS_8MB PPC_REG_VAL(14, 0x3)
+#define EBC_BXCR_BS_16MB PPC_REG_VAL(14, 0x4)
+#define EBC_BXCR_BS_32MB PPC_REG_VAL(14, 0x5)
+#define EBC_BXCR_BS_64MB PPC_REG_VAL(14, 0x6)
+#define EBC_BXCR_BS_128MB PPC_REG_VAL(14, 0x7)
+#define EBC_BXCR_BU_MASK PPC_REG_VAL(16, 0x3)
+#define EBC_BXCR_BU_NONE PPC_REG_VAL(16, 0x0)
+#define EBC_BXCR_BU_R PPC_REG_VAL(16, 0x1)
+#define EBC_BXCR_BU_W PPC_REG_VAL(16, 0x2)
+#define EBC_BXCR_BU_RW PPC_REG_VAL(16, 0x3)
+#define EBC_BXCR_BW_MASK PPC_REG_VAL(18, 0x3)
+#define EBC_BXCR_BW_8BIT PPC_REG_VAL(18, 0x0)
+#define EBC_BXCR_BW_16BIT PPC_REG_VAL(18, 0x1)
+#if defined(CONFIG_EBC_PPC4xx_IBM_VER1)
+#define EBC_BXCR_BW_32BIT PPC_REG_VAL(18, 0x2)
+#else
+#define EBC_BXCR_BW_32BIT PPC_REG_VAL(18, 0x3)
+#endif
+
+/* Bank Access Parameter Register */
+#define EBC_BXAP_BME_ENABLED PPC_REG_VAL(0, 0x1)
+#define EBC_BXAP_BME_DISABLED PPC_REG_VAL(0, 0x0)
+#define EBC_BXAP_TWT_ENCODE(n) PPC_REG_VAL(8, (static_cast(u32, n)) & 0xFF)
+#define EBC_BXAP_FWT_ENCODE(n) PPC_REG_VAL(5, (static_cast(u32, n)) & 0x1F)
+#define EBC_BXAP_BWT_ENCODE(n) PPC_REG_VAL(8, (static_cast(u32, n)) & 0x7)
+#define EBC_BXAP_BCE_DISABLE PPC_REG_VAL(9, 0x0)
+#define EBC_BXAP_BCE_ENABLE PPC_REG_VAL(9, 0x1)
+#define EBC_BXAP_BCT_MASK PPC_REG_VAL(11, 0x3)
+#define EBC_BXAP_BCT_2TRANS PPC_REG_VAL(11, 0x0)
+#define EBC_BXAP_BCT_4TRANS PPC_REG_VAL(11, 0x1)
+#define EBC_BXAP_BCT_8TRANS PPC_REG_VAL(11, 0x2)
+#define EBC_BXAP_BCT_16TRANS PPC_REG_VAL(11, 0x3)
+#define EBC_BXAP_CSN_ENCODE(n) PPC_REG_VAL(13, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_OEN_ENCODE(n) PPC_REG_VAL(15, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_WBN_ENCODE(n) PPC_REG_VAL(17, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_WBF_ENCODE(n) PPC_REG_VAL(19, (static_cast(u32, n)) & 0x3)
+#define EBC_BXAP_TH_ENCODE(n) PPC_REG_VAL(22, (static_cast(u32, n)) & 0x7)
+#define EBC_BXAP_RE_ENABLED PPC_REG_VAL(23, 0x1)
+#define EBC_BXAP_RE_DISABLED PPC_REG_VAL(23, 0x0)
+#define EBC_BXAP_SOR_DELAYED PPC_REG_VAL(24, 0x0)
+#define EBC_BXAP_SOR_NONDELAYED PPC_REG_VAL(24, 0x1)
+#define EBC_BXAP_BEM_WRITEONLY PPC_REG_VAL(25, 0x0)
+#define EBC_BXAP_BEM_RW PPC_REG_VAL(25, 0x1)
+#define EBC_BXAP_PEN_DISABLED PPC_REG_VAL(26, 0x0)
+#define EBC_BXAP_PEN_ENABLED PPC_REG_VAL(26, 0x1)
+
+/* Common fields in EBC0_CFG register */
+#define EBC_CFG_PTD_MASK PPC_REG_VAL(1, 0x1)
+#define EBC_CFG_PTD_ENABLE PPC_REG_VAL(1, 0x0)
+#define EBC_CFG_PTD_DISABLE PPC_REG_VAL(1, 0x1)
+#define EBC_CFG_RTC_MASK PPC_REG_VAL(4, 0x7)
+#define EBC_CFG_RTC_16PERCLK PPC_REG_VAL(4, 0x0)
+#define EBC_CFG_RTC_32PERCLK PPC_REG_VAL(4, 0x1)
+#define EBC_CFG_RTC_64PERCLK PPC_REG_VAL(4, 0x2)
+#define EBC_CFG_RTC_128PERCLK PPC_REG_VAL(4, 0x3)
+#define EBC_CFG_RTC_256PERCLK PPC_REG_VAL(4, 0x4)
+#define EBC_CFG_RTC_512PERCLK PPC_REG_VAL(4, 0x5)
+#define EBC_CFG_RTC_1024PERCLK PPC_REG_VAL(4, 0x6)
+#define EBC_CFG_RTC_2048PERCLK PPC_REG_VAL(4, 0x7)
+#define EBC_CFG_PME_MASK PPC_REG_VAL(14, 0x1)
+#define EBC_CFG_PME_DISABLE PPC_REG_VAL(14, 0x0)
+#define EBC_CFG_PME_ENABLE PPC_REG_VAL(14, 0x1)
+#define EBC_CFG_PMT_MASK PPC_REG_VAL(19, 0x1F)
+#define EBC_CFG_PMT_ENCODE(n) PPC_REG_VAL(19, (static_cast(u32, n)) & 0x1F)
+
+/* Now the two versions of the other bits */
+#if defined(CONFIG_EBC_PPC4xx_IBM_VER1)
+#define EBC_CFG_EBTC_MASK PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_EBTC_HI PPC_REG_VAL(0, 0x0)
+#define EBC_CFG_EBTC_DRIVEN PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_EMPH_MASK PPC_REG_VAL(EBC_CFG_EMPH_POS, 0x3)
+#define EBC_CFG_EMPH_ENCODE(n) PPC_REG_VAL(EBC_CFG_EMPH_POS, \
+ (static_cast(u32, n)) & 0x3)
+#define EBC_CFG_EMPL_MASK PPC_REG_VAL(EBC_CFG_EMPL_POS, 0x3)
+#define EBC_CFG_EMPL_ENCODE(n) PPC_REG_VAL(EBC_CFG_EMPH_POS, \
+ (static_cast(u32, n)) & 0x3)
+#define EBC_CFG_CSTC_MASK PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_CSTC_HI PPC_REG_VAL(9, 0x0)
+#define EBC_CFG_CSTC_DRIVEN PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_BPR_MASK PPC_REG_VAL(11, 0x3)
+#define EBC_CFG_BPR_1DW PPC_REG_VAL(11, 0x0)
+#define EBC_CFG_BPR_2DW PPC_REG_VAL(11, 0x1)
+#define EBC_CFG_BPR_4DW PPC_REG_VAL(11, 0x2)
+#define EBC_CFG_EMS_MASK PPC_REG_VAL(13, 0x3)
+#define EBC_CFG_EMS_8BIT PPC_REG_VAL(13, 0x0)
+#define EBC_CFG_EMS_16BIT PPC_REG_VAL(13, 0x1)
+#define EBC_CFG_EMS_32BIT PPC_REG_VAL(13, 0x2)
+#else
+#define EBC_CFG_LE_MASK PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_LE_UNLOCK PPC_REG_VAL(0, 0x0)
+#define EBC_CFG_LE_LOCK PPC_REG_VAL(0, 0x1)
+#define EBC_CFG_ATC_MASK PPC_REG_VAL(5, 0x1)
+#define EBC_CFG_ATC_HI PPC_REG_VAL(5, 0x0)
+#define EBC_CFG_ATC_PREVIOUS PPC_REG_VAL(5, 0x1)
+#define EBC_CFG_DTC_MASK PPC_REG_VAL(6, 0x1)
+#define EBC_CFG_DTC_HI PPC_REG_VAL(6, 0x0)
+#define EBC_CFG_DTC_PREVIOUS PPC_REG_VAL(6, 0x1)
+#define EBC_CFG_CTC_MASK PPC_REG_VAL(7, 0x1)
+#define EBC_CFG_CTC_HI PPC_REG_VAL(7, 0x0)
+#define EBC_CFG_CTC_PREVIOUS PPC_REG_VAL(7, 0x1)
+#define EBC_CFG_OEO_MASK PPC_REG_VAL(8, 0x1)
+#define EBC_CFG_OEO_HI PPC_REG_VAL(8, 0x0)
+#define EBC_CFG_OEO_PREVIOUS PPC_REG_VAL(8, 0x1)
+#define EBC_CFG_EMC_MASK PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_EMC_NONDEFAULT PPC_REG_VAL(9, 0x0)
+#define EBC_CFG_EMC_DEFAULT PPC_REG_VAL(9, 0x1)
+#define EBC_CFG_PR_MASK PPC_REG_VAL(21, 0x3)
+#define EBC_CFG_PR_16 PPC_REG_VAL(21, 0x0)
+#define EBC_CFG_PR_32 PPC_REG_VAL(21, 0x1)
+#define EBC_CFG_PR_64 PPC_REG_VAL(21, 0x2)
+#define EBC_CFG_PR_128 PPC_REG_VAL(21, 0x3)
+#endif
+
+#endif /* _PPC4xx_EBC_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-emac.h b/arch/powerpc/include/asm/ppc4xx-emac.h
new file mode 100644
index 0000000..a219fa9
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-emac.h
@@ -0,0 +1,555 @@
+/*----------------------------------------------------------------------------+
+| This source code is dual-licensed. You may use it under the terms of the
+| GNU General Public License version 2, or under the license below.
+|
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1999
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+|
+| File Name: enetemac.h
+|
+| Function: Header file for the EMAC3 macro on the 405GP.
+|
+| Author: Mark Wisner
+|
+| Change Activity-
+|
+| Date Description of Change BY
+| --------- --------------------- ---
+| 29-Apr-99 Created MKW
+|
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+| 19-Nov-03 Travis Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+| ported to handle 440GP and 440GX multiple EMACs
++----------------------------------------------------------------------------*/
+
+#ifndef _PPC4XX_ENET_H_
+#define _PPC4XX_ENET_H_
+
+#include <net.h>
+#include "asm/ppc4xx-mal.h"
+
+
+/*-----------------------------------------------------------------------------+
+| General enternet defines. 802 frames are not supported.
++-----------------------------------------------------------------------------*/
+#define ENET_ADDR_LENGTH 6
+#define ENET_ARPTYPE 0x806
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+#define ENET_IPTYPE 0x800
+#define ARP_CACHE_SIZE 5
+
+#define NUM_TX_BUFF 1
+#define NUM_RX_BUFF PKTBUFSRX
+
+struct enet_frame {
+ unsigned char dest_addr[ENET_ADDR_LENGTH];
+ unsigned char source_addr[ENET_ADDR_LENGTH];
+ unsigned short type;
+ unsigned char enet_data[1];
+};
+
+struct arp_entry {
+ unsigned long inet_address;
+ unsigned char mac_address[ENET_ADDR_LENGTH];
+ unsigned long valid;
+ unsigned long sec;
+ unsigned long nsec;
+};
+
+
+/* Statistic Areas */
+#define MAX_ERR_LOG 10
+
+typedef struct emac_stats_st{ /* Statistic Block */
+ int data_len_err;
+ int rx_frames;
+ int rx;
+ int rx_prot_err;
+ int int_err;
+ int pkts_tx;
+ int pkts_rx;
+ int pkts_handled;
+ short tx_err_log[MAX_ERR_LOG];
+ short rx_err_log[MAX_ERR_LOG];
+} EMAC_STATS_ST, *EMAC_STATS_PST;
+
+/* Structure containing variables used by the shared code (4xx_enet.c) */
+typedef struct emac_4xx_hw_st {
+ uint32_t hw_addr; /* EMAC offset */
+ uint32_t tah_addr; /* TAH offset */
+ uint32_t phy_id;
+ uint32_t phy_addr;
+ uint32_t original_fc;
+ uint32_t txcw;
+ uint32_t autoneg_failed;
+ uint32_t emac_ier;
+ volatile mal_desc_t *tx;
+ volatile mal_desc_t *rx;
+ u32 tx_phys;
+ u32 rx_phys;
+ bd_t *bis; /* for eth_init upon mal error */
+ mal_desc_t *alloc_tx_buf;
+ mal_desc_t *alloc_rx_buf;
+ char *txbuf_ptr;
+ uint16_t devnum;
+ int get_link_status;
+ int tbi_compatibility_en;
+ int tbi_compatibility_on;
+ int fc_send_xon;
+ int report_tx_early;
+ int first_init;
+ int tx_err_index;
+ int rx_err_index;
+ int rx_slot; /* MAL Receive Slot */
+ int rx_i_index; /* Receive Interrupt Queue Index */
+ int rx_u_index; /* Receive User Queue Index */
+ int tx_slot; /* MAL Transmit Slot */
+ int tx_i_index; /* Transmit Interrupt Queue Index */
+ int tx_u_index; /* Transmit User Queue Index */
+ int rx_ready[NUM_RX_BUFF]; /* Receive Ready Queue */
+ int tx_run[NUM_TX_BUFF]; /* Transmit Running Queue */
+ int is_receiving; /* sync with eth interrupt */
+ int print_speed; /* print speed message upon start */
+ EMAC_STATS_ST stats;
+} EMAC_4XX_HW_ST, *EMAC_4XX_HW_PST;
+
+
+#if defined(CONFIG_440GX) || defined(CONFIG_460GT)
+#define EMAC_NUM_DEV 4
+#elif (defined(CONFIG_440) || defined(CONFIG_405EP)) && \
+ !defined(CONFIG_440SP) && !defined(CONFIG_440SPE)
+#define EMAC_NUM_DEV 2
+#else
+#define EMAC_NUM_DEV 1
+#endif
+
+#ifdef CONFIG_IBM_EMAC4_V4 /* EMAC4 V4 changed bit setting */
+#define EMAC_STACR_OC_MASK (0x00008000)
+#else
+#define EMAC_STACR_OC_MASK (0x00000000)
+#endif
+
+/*
+ * XMII bridge configurations for those systems (e.g. 405EX(r)) that do
+ * not have a pin function control (PFC) register to otherwise determine
+ * the bridge configuration.
+ */
+#define EMAC_PHY_MODE_NONE 0
+#define EMAC_PHY_MODE_NONE_RGMII 1
+#define EMAC_PHY_MODE_RGMII_NONE 2
+#define EMAC_PHY_MODE_RGMII_RGMII 3
+#define EMAC_PHY_MODE_NONE_GMII 4
+#define EMAC_PHY_MODE_GMII_NONE 5
+#define EMAC_PHY_MODE_NONE_MII 6
+#define EMAC_PHY_MODE_MII_NONE 7
+
+/* ZMII Bridge Register addresses */
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define ZMII0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0D00)
+#else
+#define ZMII0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0780)
+#endif
+#define ZMII0_FER (ZMII0_BASE)
+#define ZMII0_SSR (ZMII0_BASE + 4)
+#define ZMII0_SMIISR (ZMII0_BASE + 8)
+
+/* ZMII FER Register Bit Definitions */
+#define ZMII_FER_DIS (0x0)
+#define ZMII_FER_MDI (0x8)
+#define ZMII_FER_SMII (0x4)
+#define ZMII_FER_RMII (0x2)
+#define ZMII_FER_MII (0x1)
+
+#define ZMII_FER_RSVD11 (0x00200000)
+#define ZMII_FER_RSVD10 (0x00100000)
+#define ZMII_FER_RSVD14_31 (0x0003FFFF)
+
+#define ZMII_FER_V(__x) (((3 - __x) * 4) + 16)
+
+
+/* ZMII Speed Selection Register Bit Definitions */
+#define ZMII0_SSR_SCI (0x4)
+#define ZMII0_SSR_FSS (0x2)
+#define ZMII0_SSR_SP (0x1)
+#define ZMII0_SSR_RSVD16_31 (0x0000FFFF)
+
+#define ZMII0_SSR_V(__x) (((3 - __x) * 4) + 16)
+
+
+/* ZMII SMII Status Register Bit Definitions */
+#define ZMII0_SMIISR_E1 (0x80)
+#define ZMII0_SMIISR_EC (0x40)
+#define ZMII0_SMIISR_EN (0x20)
+#define ZMII0_SMIISR_EJ (0x10)
+#define ZMII0_SMIISR_EL (0x08)
+#define ZMII0_SMIISR_ED (0x04)
+#define ZMII0_SMIISR_ES (0x02)
+#define ZMII0_SMIISR_EF (0x01)
+
+#define ZMII0_SMIISR_V(__x) ((3 - __x) * 8)
+
+/* RGMII Register Addresses */
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define RGMII_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x1000)
+#elif defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define RGMII_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x1500)
+#elif defined(CONFIG_405EX)
+#define RGMII_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0xB00)
+#else
+#define RGMII_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0790)
+#endif
+#define RGMII_FER (RGMII_BASE + 0x00)
+#define RGMII_SSR (RGMII_BASE + 0x04)
+
+#if defined(CONFIG_460GT)
+#define RGMII1_BASE_OFFSET 0x100
+#endif
+
+/* RGMII Function Enable (FER) Register Bit Definitions */
+#define RGMII_FER_DIS (0x00)
+#define RGMII_FER_RTBI (0x04)
+#define RGMII_FER_RGMII (0x05)
+#define RGMII_FER_TBI (0x06)
+#define RGMII_FER_GMII (0x07)
+#define RGMII_FER_MII (RGMII_FER_GMII)
+
+#define RGMII_FER_V(__x) ((__x - 2) * 4)
+
+#define RGMII_FER_MDIO(__x) (1 << (19 - (__x)))
+
+/* RGMII Speed Selection Register Bit Definitions */
+#define RGMII_SSR_SP_10MBPS (0x00)
+#define RGMII_SSR_SP_100MBPS (0x02)
+#define RGMII_SSR_SP_1000MBPS (0x04)
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
+#define RGMII_SSR_V(__x) ((__x) * 8)
+#else
+#define RGMII_SSR_V(__x) ((__x -2) * 8)
+#endif
+
+/*---------------------------------------------------------------------------+
+| TCP/IP Acceleration Hardware (TAH) 440GX Only
++---------------------------------------------------------------------------*/
+#if defined(CONFIG_440GX)
+#define TAH_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0B50)
+#define TAH_REVID (TAH_BASE + 0x0) /* Revision ID (RO)*/
+#define TAH_MR (TAH_BASE + 0x10) /* Mode Register (R/W) */
+#define TAH_SSR0 (TAH_BASE + 0x14) /* Segment Size Reg 0 (R/W) */
+#define TAH_SSR1 (TAH_BASE + 0x18) /* Segment Size Reg 1 (R/W) */
+#define TAH_SSR2 (TAH_BASE + 0x1C) /* Segment Size Reg 2 (R/W) */
+#define TAH_SSR3 (TAH_BASE + 0x20) /* Segment Size Reg 3 (R/W) */
+#define TAH_SSR4 (TAH_BASE + 0x24) /* Segment Size Reg 4 (R/W) */
+#define TAH_SSR5 (TAH_BASE + 0x28) /* Segment Size Reg 5 (R/W) */
+#define TAH_TSR (TAH_BASE + 0x2C) /* Transmit Status Register (RO) */
+
+/* TAH Revision */
+#define TAH_REV_RN_M (0x000FFF00) /* Revision Number */
+#define TAH_REV_BN_M (0x000000FF) /* Branch Revision Number */
+
+#define TAH_REV_RN_V (8)
+#define TAH_REV_BN_V (0)
+
+/* TAH Mode Register */
+#define TAH_MR_CVR (0x80000000) /* Checksum verification on RX */
+#define TAH_MR_SR (0x40000000) /* Software reset */
+#define TAH_MR_ST (0x3F000000) /* Send Threshold */
+#define TAH_MR_TFS (0x00E00000) /* Transmit FIFO size */
+#define TAH_MR_DTFP (0x00100000) /* Disable TX FIFO parity */
+#define TAH_MR_DIG (0x00080000) /* Disable interrupt generation */
+#define TAH_MR_RSVD (0x0007FFFF) /* Reserved */
+
+#define TAH_MR_ST_V (20)
+#define TAH_MR_TFS_V (17)
+
+#define TAH_MR_TFS_2K (0x1) /* Transmit FIFO size 2Kbyte */
+#define TAH_MR_TFS_4K (0x2) /* Transmit FIFO size 4Kbyte */
+#define TAH_MR_TFS_6K (0x3) /* Transmit FIFO size 6Kbyte */
+#define TAH_MR_TFS_8K (0x4) /* Transmit FIFO size 8Kbyte */
+#define TAH_MR_TFS_10K (0x5) /* Transmit FIFO size 10Kbyte (max)*/
+
+
+/* TAH Segment Size Registers 0:5 */
+#define TAH_SSR_RSVD0 (0xC0000000) /* Reserved */
+#define TAH_SSR_SS (0x3FFE0000) /* Segment size in multiples of 2 */
+#define TAH_SSR_RSVD1 (0x0001FFFF) /* Reserved */
+
+/* TAH Transmit Status Register */
+#define TAH_TSR_TFTS (0x80000000) /* Transmit FIFO too small */
+#define TAH_TSR_UH (0x40000000) /* Unrecognized header */
+#define TAH_TSR_NIPF (0x20000000) /* Not IPv4 */
+#define TAH_TSR_IPOP (0x10000000) /* IP option present */
+#define TAH_TSR_NISF (0x08000000) /* No IEEE SNAP format */
+#define TAH_TSR_ILTS (0x04000000) /* IP length too short */
+#define TAH_TSR_IPFP (0x02000000) /* IP fragment present */
+#define TAH_TSR_UP (0x01000000) /* Unsupported protocol */
+#define TAH_TSR_TFP (0x00800000) /* TCP flags present */
+#define TAH_TSR_SUDP (0x00400000) /* Segmentation for UDP */
+#define TAH_TSR_DLM (0x00200000) /* Data length mismatch */
+#define TAH_TSR_SIEEE (0x00100000) /* Segmentation for IEEE */
+#define TAH_TSR_TFPE (0x00080000) /* Transmit FIFO parity error */
+#define TAH_TSR_SSTS (0x00040000) /* Segment size too small */
+#define TAH_TSR_RSVD (0x0003FFFF) /* Reserved */
+#endif /* CONFIG_440GX */
+
+
+/* Ethernet MAC Regsiter Addresses */
+#if defined(CONFIG_440)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define EMAC0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0E00)
+#else
+#define EMAC0_BASE (CONFIG_SYS_PERIPHERAL_BASE + 0x0800)
+#endif
+#else
+#if defined(CONFIG_405EZ) || defined(CONFIG_405EX)
+#define EMAC0_BASE 0xEF600900
+#else
+#define EMAC0_BASE 0xEF600800
+#endif
+#endif
+
+#if defined(CONFIG_440EPX)
+#define EMAC1_BASE 0xEF600F00
+#define EMAC1_MR1 (EMAC1_BASE + 0x04)
+#endif
+
+#define EMAC0_MR0 (EMAC0_BASE)
+#define EMAC0_MR1 (EMAC0_BASE + 0x04)
+#define EMAC0_TMR0 (EMAC0_BASE + 0x08)
+#define EMAC0_TMR1 (EMAC0_BASE + 0x0c)
+#define EMAC0_RXM (EMAC0_BASE + 0x10)
+#define EMAC0_ISR (EMAC0_BASE + 0x14)
+#define EMAC0_IER (EMAC0_BASE + 0x18)
+#define EMAC0_IAH (EMAC0_BASE + 0x1c)
+#define EMAC0_IAL (EMAC0_BASE + 0x20)
+#define EMAC0_PTR (EMAC0_BASE + 0x2c)
+#define EMAC0_PAUSE_TIME_REG EMAC0_PTR
+#define EMAC0_IPGVR (EMAC0_BASE + 0x58)
+#define EMAC0_I_FRAME_GAP_REG EMAC0_IPGVR
+#define EMAC0_STACR (EMAC0_BASE + 0x5c)
+#define EMAC0_TRTR (EMAC0_BASE + 0x60)
+#define EMAC0_RWMR (EMAC0_BASE + 0x64)
+#define EMAC0_RX_HI_LO_WMARK EMAC0_RWMR
+
+/* bit definitions */
+/* MODE REG 0 */
+#define EMAC_MR0_RXI (0x80000000)
+#define EMAC_MR0_TXI (0x40000000)
+#define EMAC_MR0_SRST (0x20000000)
+#define EMAC_MR0_TXE (0x10000000)
+#define EMAC_MR0_RXE (0x08000000)
+#define EMAC_MR0_WKE (0x04000000)
+
+/* on 440GX EMAC_MR1 has a different layout! */
+#if defined(CONFIG_440GX) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
+/* MODE Reg 1 */
+#define EMAC_MR1_FDE (0x80000000)
+#define EMAC_MR1_ILE (0x40000000)
+#define EMAC_MR1_VLE (0x20000000)
+#define EMAC_MR1_EIFC (0x10000000)
+#define EMAC_MR1_APP (0x08000000)
+#define EMAC_MR1_RSVD (0x06000000)
+#define EMAC_MR1_IST (0x01000000)
+#define EMAC_MR1_MF_1000GPCS (0x00C00000)
+#define EMAC_MR1_MF_1000MBPS (0x00800000) /* 0's for 10MBPS */
+#define EMAC_MR1_MF_100MBPS (0x00400000)
+#define EMAC_MR1_RFS_MASK (0x00380000)
+#define EMAC_MR1_RFS_16K (0x00280000)
+#define EMAC_MR1_RFS_8K (0x00200000)
+#define EMAC_MR1_RFS_4K (0x00180000)
+#define EMAC_MR1_RFS_2K (0x00100000)
+#define EMAC_MR1_RFS_1K (0x00080000)
+#define EMAC_MR1_TX_FIFO_MASK (0x00070000)
+#define EMAC_MR1_TX_FIFO_16K (0x00050000)
+#define EMAC_MR1_TX_FIFO_8K (0x00040000)
+#define EMAC_MR1_TX_FIFO_4K (0x00030000)
+#define EMAC_MR1_TX_FIFO_2K (0x00020000)
+#define EMAC_MR1_TX_FIFO_1K (0x00010000)
+#define EMAC_MR1_TR_MULTI (0x00008000) /* 0'x for single packet */
+#define EMAC_MR1_MWSW (0x00007000)
+#define EMAC_MR1_JUMBO_ENABLE (0x00000800)
+#define EMAC_MR1_IPPA (0x000007c0)
+#define EMAC_MR1_IPPA_SET(id) (((id) & 0x1f) << 6)
+#define EMAC_MR1_IPPA_GET(id) (((id) >> 6) & 0x1f)
+#define EMAC_MR1_OBCI_GT100 (0x00000020)
+#define EMAC_MR1_OBCI_100 (0x00000018)
+#define EMAC_MR1_OBCI_83 (0x00000010)
+#define EMAC_MR1_OBCI_66 (0x00000008)
+#define EMAC_MR1_RSVD1 (0x00000007)
+#else /* defined(CONFIG_440GX) */
+/* EMAC_MR1 is the same on 405GP, 405GPr, 405EP, 440GP, 440EP */
+#define EMAC_MR1_FDE 0x80000000
+#define EMAC_MR1_ILE 0x40000000
+#define EMAC_MR1_VLE 0x20000000
+#define EMAC_MR1_EIFC 0x10000000
+#define EMAC_MR1_APP 0x08000000
+#define EMAC_MR1_AEMI 0x02000000
+#define EMAC_MR1_IST 0x01000000
+#define EMAC_MR1_MF_1000MBPS 0x00800000 /* 0's for 10MBPS */
+#define EMAC_MR1_MF_100MBPS 0x00400000
+#define EMAC_MR1_RFS_MASK 0x00300000
+#define EMAC_MR1_RFS_4K 0x00300000
+#define EMAC_MR1_RFS_2K 0x00200000
+#define EMAC_MR1_RFS_1K 0x00100000
+#define EMAC_MR1_RFS_512 0x00000000
+#define EMAC_MR1_TX_FIFO_MASK 0x000c0000
+#define EMAC_MR1_TX_FIFO_2K 0x00080000
+#define EMAC_MR1_TX_FIFO_1K 0x00040000
+#define EMAC_MR1_TX_FIFO_512 0x00000000
+#define EMAC_MR1_TR0_DEPEND 0x00010000 /* 0'x for single packet */
+#define EMAC_MR1_TR0_MULTI 0x00008000
+#define EMAC_MR1_TR1_DEPEND 0x00004000
+#define EMAC_MR1_TR1_MULTI 0x00002000
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define EMAC_MR1_JUMBO_ENABLE 0x00001000
+#endif /* defined(CONFIG_440EP) || defined(CONFIG_440GR) */
+#endif /* defined(CONFIG_440GX) */
+
+#define EMAC_MR1_FIFO_MASK (EMAC_MR1_RFS_MASK | EMAC_MR1_TX_FIFO_MASK)
+#if defined(CONFIG_405EZ)
+/* 405EZ only supports 512 bytes fifos */
+#define EMAC_MR1_FIFO_SIZE (EMAC_MR1_RFS_512 | EMAC_MR1_TX_FIFO_512)
+#else
+/* Set receive fifo to 4k and tx fifo to 2k */
+#define EMAC_MR1_FIFO_SIZE (EMAC_MR1_RFS_4K | EMAC_MR1_TX_FIFO_2K)
+#endif
+
+/* Transmit Mode Register 0 */
+#define EMAC_TMR0_GNP0 (0x80000000)
+#define EMAC_TMR0_GNP1 (0x40000000)
+#define EMAC_TMR0_GNPD (0x20000000)
+#define EMAC_TMR0_FC (0x10000000)
+
+/* Receive Mode Register */
+#define EMAC_RMR_SP (0x80000000)
+#define EMAC_RMR_SFCS (0x40000000)
+#define EMAC_RMR_ARRP (0x20000000)
+#define EMAC_RMR_ARP (0x10000000)
+#define EMAC_RMR_AROP (0x08000000)
+#define EMAC_RMR_ARPI (0x04000000)
+#define EMAC_RMR_PPP (0x02000000)
+#define EMAC_RMR_PME (0x01000000)
+#define EMAC_RMR_PMME (0x00800000)
+#define EMAC_RMR_IAE (0x00400000)
+#define EMAC_RMR_MIAE (0x00200000)
+#define EMAC_RMR_BAE (0x00100000)
+#define EMAC_RMR_MAE (0x00080000)
+
+/* Interrupt Status & enable Regs */
+#define EMAC_ISR_OVR (0x02000000)
+#define EMAC_ISR_PP (0x01000000)
+#define EMAC_ISR_BP (0x00800000)
+#define EMAC_ISR_RP (0x00400000)
+#define EMAC_ISR_SE (0x00200000)
+#define EMAC_ISR_SYE (0x00100000)
+#define EMAC_ISR_BFCS (0x00080000)
+#define EMAC_ISR_PTLE (0x00040000)
+#define EMAC_ISR_ORE (0x00020000)
+#define EMAC_ISR_IRE (0x00010000)
+#define EMAC_ISR_DBDM (0x00000200)
+#define EMAC_ISR_DB0 (0x00000100)
+#define EMAC_ISR_SE0 (0x00000080)
+#define EMAC_ISR_TE0 (0x00000040)
+#define EMAC_ISR_DB1 (0x00000020)
+#define EMAC_ISR_SE1 (0x00000010)
+#define EMAC_ISR_TE1 (0x00000008)
+#define EMAC_ISR_MOS (0x00000002)
+#define EMAC_ISR_MOF (0x00000001)
+
+/* STA CONTROL REG */
+#define EMAC_STACR_OC (0x00008000)
+#define EMAC_STACR_PHYE (0x00004000)
+
+#ifdef CONFIG_IBM_EMAC4_V4 /* EMAC4 V4 changed bit setting */
+#define EMAC_STACR_INDIRECT_MODE (0x00002000)
+#define EMAC_STACR_WRITE (0x00000800) /* $BUC */
+#define EMAC_STACR_READ (0x00001000) /* $BUC */
+#define EMAC_STACR_OP_MASK (0x00001800)
+#define EMAC_STACR_MDIO_ADDR (0x00000000)
+#define EMAC_STACR_MDIO_WRITE (0x00000800)
+#define EMAC_STACR_MDIO_READ (0x00001800)
+#define EMAC_STACR_MDIO_READ_INC (0x00001000)
+#else
+#define EMAC_STACR_WRITE (0x00002000)
+#define EMAC_STACR_READ (0x00001000)
+#endif
+
+#define EMAC_STACR_CLK_83MHZ (0x00000800) /* 0's for 50Mhz */
+#define EMAC_STACR_CLK_66MHZ (0x00000400)
+#define EMAC_STACR_CLK_100MHZ (0x00000C00)
+
+/* Transmit Request Threshold Register */
+#define EMAC_TRTR_256 (0x18000000) /* 0's for 64 Bytes */
+#define EMAC_TRTR_192 (0x10000000)
+#define EMAC_TRTR_128 (0x01000000)
+
+/* the follwing defines are for the MadMAL status and control registers. */
+/* For bits 0..5 look at the mal.h file */
+#define EMAC_TX_CTRL_GFCS (0x0200)
+#define EMAC_TX_CTRL_GP (0x0100)
+#define EMAC_TX_CTRL_ISA (0x0080)
+#define EMAC_TX_CTRL_RSA (0x0040)
+#define EMAC_TX_CTRL_IVT (0x0020)
+#define EMAC_TX_CTRL_RVT (0x0010)
+
+#define EMAC_TX_CTRL_DEFAULT (EMAC_TX_CTRL_GFCS |EMAC_TX_CTRL_GP)
+
+#define EMAC_TX_ST_BFCS (0x0200)
+#define EMAC_TX_ST_BPP (0x0100)
+#define EMAC_TX_ST_LCS (0x0080)
+#define EMAC_TX_ST_ED (0x0040)
+#define EMAC_TX_ST_EC (0x0020)
+#define EMAC_TX_ST_LC (0x0010)
+#define EMAC_TX_ST_MC (0x0008)
+#define EMAC_TX_ST_SC (0x0004)
+#define EMAC_TX_ST_UR (0x0002)
+#define EMAC_TX_ST_SQE (0x0001)
+
+#define EMAC_TX_ST_DEFAULT (0x03F3)
+
+
+/* madmal receive status / Control bits */
+
+#define EMAC_RX_ST_OE (0x0200)
+#define EMAC_RX_ST_PP (0x0100)
+#define EMAC_RX_ST_BP (0x0080)
+#define EMAC_RX_ST_RP (0x0040)
+#define EMAC_RX_ST_SE (0x0020)
+#define EMAC_RX_ST_AE (0x0010)
+#define EMAC_RX_ST_BFCS (0x0008)
+#define EMAC_RX_ST_PTL (0x0004)
+#define EMAC_RX_ST_ORE (0x0002)
+#define EMAC_RX_ST_IRE (0x0001)
+/* all the errors we care about */
+#define EMAC_RX_ERRORS (0x03FF)
+
+#endif /* _PPC4XX_ENET_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-gpio.h b/arch/powerpc/include/asm/ppc4xx-gpio.h
new file mode 100644
index 0000000..23e29b1
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-gpio.h
@@ -0,0 +1,119 @@
+/*
+ * (C) Copyright 2007-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_PPC_GPIO_H
+#define __ASM_PPC_GPIO_H
+
+#include <asm/types.h>
+
+/* 4xx PPC's have 2 GPIO controllers */
+#if defined(CONFIG_405EZ) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define GPIO_GROUP_MAX 2
+#else
+#define GPIO_GROUP_MAX 1
+#endif
+
+/* GPIO controller */
+struct ppc4xx_gpio {
+ u32 or; /* Output Control */
+ u32 tcr; /* Tri-State Control */
+ u32 osl; /* Output Select 16..31 */
+ u32 osh; /* Output Select 0..15 */
+ u32 tsl; /* Tri-State Select 16..31 */
+ u32 tsh; /* Tri-State Select 0..15 */
+ u32 odr; /* Open Drain */
+ u32 ir; /* Input */
+ u32 rr1; /* Receive Register 1 */
+ u32 rr2; /* Receive Register 2 */
+ u32 rr3; /* Receive Register 3 */
+ u32 reserved;
+ u32 is1l; /* Input Select 1 16..31 */
+ u32 is1h; /* Input Select 1 0..15 */
+ u32 is2l; /* Input Select 2 16..31 */
+ u32 is2h; /* Input Select 2 0..15 */
+ u32 is3l; /* Input Select 3 16..31 */
+ u32 is3h; /* Input Select 3 0..15 */
+};
+
+/* Offsets */
+#define GPIOx_OR 0x00 /* GPIO Output Register */
+#define GPIOx_TCR 0x04 /* GPIO Three-State Control Register */
+#define GPIOx_OSL 0x08 /* GPIO Output Select Register (Bits 0-31) */
+#define GPIOx_OSH 0x0C /* GPIO Ouput Select Register (Bits 32-63) */
+#define GPIOx_TSL 0x10 /* GPIO Three-State Select Register (Bits 0-31) */
+#define GPIOx_TSH 0x14 /* GPIO Three-State Select Register (Bits 32-63) */
+#define GPIOx_ODR 0x18 /* GPIO Open drain Register */
+#define GPIOx_IR 0x1C /* GPIO Input Register */
+#define GPIOx_RR1 0x20 /* GPIO Receive Register 1 */
+#define GPIOx_RR2 0x24 /* GPIO Receive Register 2 */
+#define GPIOx_RR3 0x28 /* GPIO Receive Register 3 */
+#define GPIOx_IS1L 0x30 /* GPIO Input Select Register 1 (Bits 0-31) */
+#define GPIOx_IS1H 0x34 /* GPIO Input Select Register 1 (Bits 32-63) */
+#define GPIOx_IS2L 0x38 /* GPIO Input Select Register 2 (Bits 0-31) */
+#define GPIOx_IS2H 0x3C /* GPIO Input Select Register 2 (Bits 32-63) */
+#define GPIOx_IS3L 0x40 /* GPIO Input Select Register 3 (Bits 0-31) */
+#define GPIOx_IS3H 0x44 /* GPIO Input Select Register 3 (Bits 32-63) */
+
+#define GPIO_OR(x) (x+GPIOx_OR) /* GPIO Output Register */
+#define GPIO_TCR(x) (x+GPIOx_TCR) /* GPIO Three-State Control Register */
+#define GPIO_OS(x) (x+GPIOx_OSL) /* GPIO Output Select Register High or Low */
+#define GPIO_TS(x) (x+GPIOx_TSL) /* GPIO Three-state Control Reg High or Low */
+#define GPIO_IS1(x) (x+GPIOx_IS1L) /* GPIO Input register1 High or Low */
+#define GPIO_IS2(x) (x+GPIOx_IS2L) /* GPIO Input register2 High or Low */
+#define GPIO_IS3(x) (x+GPIOx_IS3L) /* GPIO Input register3 High or Low */
+
+#define GPIO0 0
+#define GPIO1 1
+
+#define GPIO_MAX 32
+#define GPIO_ALT1_SEL 0x40000000
+#define GPIO_ALT2_SEL 0x80000000
+#define GPIO_ALT3_SEL 0xc0000000
+#define GPIO_IN_SEL 0x40000000
+#define GPIO_MASK 0xc0000000
+
+#define GPIO_VAL(gpio) (0x80000000 >> (gpio))
+
+#ifndef __ASSEMBLY__
+typedef enum gpio_select { GPIO_SEL, GPIO_ALT1, GPIO_ALT2, GPIO_ALT3 } gpio_select_t;
+typedef enum gpio_driver { GPIO_DIS, GPIO_IN, GPIO_OUT, GPIO_BI } gpio_driver_t;
+typedef enum gpio_out { GPIO_OUT_0, GPIO_OUT_1, GPIO_OUT_NO_CHG } gpio_out_t;
+
+typedef struct {
+ unsigned long add; /* gpio core base address */
+ gpio_driver_t in_out; /* Driver Setting */
+ gpio_select_t alt_nb; /* Selected Alternate */
+ gpio_out_t out_val;/* Default Output Value */
+} gpio_param_s;
+#endif
+
+void gpio_config(int pin, int in_out, int gpio_alt, int out_val);
+void gpio_write_bit(int pin, int val);
+int gpio_read_out_bit(int pin);
+int gpio_read_in_bit(int pin);
+void gpio_set_chip_configuration(void);
+
+#endif /* __ASM_PPC_GPIO_H */
diff --git a/arch/powerpc/include/asm/ppc4xx-i2c.h b/arch/powerpc/include/asm/ppc4xx-i2c.h
new file mode 100644
index 0000000..0c6c926
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-i2c.h
@@ -0,0 +1,127 @@
+/*
+ * (C) Copyright 2007-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _4xx_i2c_h_
+#define _4xx_i2c_h_
+
+#define IIC_OK 0
+#define IIC_NOK 1
+#define IIC_NOK_LA 2 /* Lost arbitration */
+#define IIC_NOK_ICT 3 /* Incomplete transfer */
+#define IIC_NOK_XFRA 4 /* Transfer aborted */
+#define IIC_NOK_DATA 5 /* No data in buffer */
+#define IIC_NOK_TOUT 6 /* Transfer timeout */
+
+#define IIC_TIMEOUT 1 /* 1 second */
+
+#if defined(CONFIG_I2C_MULTI_BUS)
+#define I2C_BUS_OFFS (i2c_bus_num * 0x100)
+#else
+#define I2C_BUS_OFFS (0x000)
+#endif /* CONFIG_I2C_MULTI_BUS */
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define I2C_BASE_ADDR (CONFIG_SYS_PERIPHERAL_BASE + 0x00000700 + I2C_BUS_OFFS)
+#elif defined(CONFIG_440) || defined(CONFIG_405EX)
+/* all remaining 440 variants */
+#define I2C_BASE_ADDR (CONFIG_SYS_PERIPHERAL_BASE + 0x00000400 + I2C_BUS_OFFS)
+#else
+/* all 405 variants */
+#define I2C_BASE_ADDR (0xEF600500 + I2C_BUS_OFFS)
+#endif
+
+struct ppc4xx_i2c {
+ u8 mdbuf;
+ u8 res1;
+ u8 sdbuf;
+ u8 res2;
+ u8 lmadr;
+ u8 hmadr;
+ u8 cntl;
+ u8 mdcntl;
+ u8 sts;
+ u8 extsts;
+ u8 lsadr;
+ u8 hsadr;
+ u8 clkdiv;
+ u8 intrmsk;
+ u8 xfrcnt;
+ u8 xtcntlss;
+ u8 directcntl;
+ u8 intr;
+};
+
+/* MDCNTL Register Bit definition */
+#define IIC_MDCNTL_HSCL 0x01
+#define IIC_MDCNTL_EUBS 0x02
+#define IIC_MDCNTL_EINT 0x04
+#define IIC_MDCNTL_ESM 0x08
+#define IIC_MDCNTL_FSM 0x10
+#define IIC_MDCNTL_EGC 0x20
+#define IIC_MDCNTL_FMDB 0x40
+#define IIC_MDCNTL_FSDB 0x80
+
+/* CNTL Register Bit definition */
+#define IIC_CNTL_PT 0x01
+#define IIC_CNTL_READ 0x02
+#define IIC_CNTL_CHT 0x04
+#define IIC_CNTL_RPST 0x08
+/* bit 2/3 for Transfer count*/
+#define IIC_CNTL_AMD 0x40
+#define IIC_CNTL_HMT 0x80
+
+/* STS Register Bit definition */
+#define IIC_STS_PT 0x01
+#define IIC_STS_IRQA 0x02
+#define IIC_STS_ERR 0x04
+#define IIC_STS_SCMP 0x08
+#define IIC_STS_MDBF 0x10
+#define IIC_STS_MDBS 0x20
+#define IIC_STS_SLPR 0x40
+#define IIC_STS_SSS 0x80
+
+/* EXTSTS Register Bit definition */
+#define IIC_EXTSTS_XFRA 0x01
+#define IIC_EXTSTS_ICT 0x02
+#define IIC_EXTSTS_LA 0x04
+
+/* XTCNTLSS Register Bit definition */
+#define IIC_XTCNTLSS_SRST 0x01
+#define IIC_XTCNTLSS_EPI 0x02
+#define IIC_XTCNTLSS_SDBF 0x04
+#define IIC_XTCNTLSS_SBDD 0x08
+#define IIC_XTCNTLSS_SWS 0x10
+#define IIC_XTCNTLSS_SWC 0x20
+#define IIC_XTCNTLSS_SRS 0x40
+#define IIC_XTCNTLSS_SRC 0x80
+
+/* IICx_DIRECTCNTL register */
+#define IIC_DIRCNTL_SDAC 0x08
+#define IIC_DIRCNTL_SCC 0x04
+#define IIC_DIRCNTL_MSDA 0x02
+#define IIC_DIRCNTL_MSC 0x01
+
+#define DIRCTNL_FREE(v) (((v) & 0x0f) == 0x0f)
+#endif
diff --git a/arch/powerpc/include/asm/ppc4xx-isram.h b/arch/powerpc/include/asm/ppc4xx-isram.h
new file mode 100644
index 0000000..32e1297
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-isram.h
@@ -0,0 +1,83 @@
+
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_ISRAM_H_
+#define _PPC4xx_ISRAM_H_
+
+/*
+ * Internal SRAM
+ */
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_APM821XX)
+#define ISRAM0_DCR_BASE 0x380
+#else
+#define ISRAM0_DCR_BASE 0x020
+#endif
+#define ISRAM0_SB0CR (ISRAM0_DCR_BASE+0x00) /* SRAM bank config 0*/
+#define ISRAM0_SB1CR (ISRAM0_DCR_BASE+0x01) /* SRAM bank config 1*/
+#define ISRAM0_SB2CR (ISRAM0_DCR_BASE+0x02) /* SRAM bank config 2*/
+#define ISRAM0_SB3CR (ISRAM0_DCR_BASE+0x03) /* SRAM bank config 3*/
+#define ISRAM0_BEAR (ISRAM0_DCR_BASE+0x04) /* SRAM bus error addr reg */
+#define ISRAM0_BESR0 (ISRAM0_DCR_BASE+0x05) /* SRAM bus error status reg 0 */
+#define ISRAM0_BESR1 (ISRAM0_DCR_BASE+0x06) /* SRAM bus error status reg 1 */
+#define ISRAM0_PMEG (ISRAM0_DCR_BASE+0x07) /* SRAM power management */
+#define ISRAM0_CID (ISRAM0_DCR_BASE+0x08) /* SRAM bus core id reg */
+#define ISRAM0_REVID (ISRAM0_DCR_BASE+0x09) /* SRAM bus revision id reg */
+#define ISRAM0_DPC (ISRAM0_DCR_BASE+0x0a) /* SRAM data parity check reg */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_APM821XX)
+#define ISRAM1_DCR_BASE 0x0B0
+#define ISRAM1_SB0CR (ISRAM1_DCR_BASE+0x00) /* SRAM1 bank config 0*/
+#define ISRAM1_BEAR (ISRAM1_DCR_BASE+0x04) /* SRAM1 bus error addr reg */
+#define ISRAM1_BESR0 (ISRAM1_DCR_BASE+0x05) /* SRAM1 bus error status reg 0 */
+#define ISRAM1_BESR1 (ISRAM1_DCR_BASE+0x06) /* SRAM1 bus error status reg 1 */
+#define ISRAM1_PMEG (ISRAM1_DCR_BASE+0x07) /* SRAM1 power management */
+#define ISRAM1_CID (ISRAM1_DCR_BASE+0x08) /* SRAM1 bus core id reg */
+#define ISRAM1_REVID (ISRAM1_DCR_BASE+0x09) /* SRAM1 bus revision id reg */
+#define ISRAM1_DPC (ISRAM1_DCR_BASE+0x0a) /* SRAM1 data parity check reg */
+#endif /* CONFIG_460EX || CONFIG_460GT */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define ISRAM1_SIZE 0x0984 /* OCM size 64k */
+#elif defined(CONFIG_APM821XX)
+#define ISRAM1_SIZE 0x0784 /* OCM size 32k */
+#endif
+
+/*
+ * L2 Cache
+ */
+#if defined (CONFIG_440GX) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
+#define L2_CACHE_BASE 0x030
+#define L2_CACHE_CFG (L2_CACHE_BASE+0x00) /* L2 Cache Config */
+#define L2_CACHE_CMD (L2_CACHE_BASE+0x01) /* L2 Cache Command */
+#define L2_CACHE_ADDR (L2_CACHE_BASE+0x02) /* L2 Cache Address */
+#define L2_CACHE_DATA (L2_CACHE_BASE+0x03) /* L2 Cache Data */
+#define L2_CACHE_STAT (L2_CACHE_BASE+0x04) /* L2 Cache Status */
+#define L2_CACHE_CVER (L2_CACHE_BASE+0x05) /* L2 Cache Revision ID */
+#define L2_CACHE_SNP0 (L2_CACHE_BASE+0x06) /* L2 Cache Snoop reg 0 */
+#define L2_CACHE_SNP1 (L2_CACHE_BASE+0x07) /* L2 Cache Snoop reg 1 */
+#endif /* CONFIG_440GX */
+
+#endif /* _PPC4xx_ISRAM_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-mal.h b/arch/powerpc/include/asm/ppc4xx-mal.h
new file mode 100644
index 0000000..7198685
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-mal.h
@@ -0,0 +1,168 @@
+/* include/mal.h, openbios_walnut, walnut_bios 8/6/99 08:48:40 */
+/*----------------------------------------------------------------------------+
+| This source code is dual-licensed. You may use it under the terms of the
+| GNU General Public License version 2, or under the license below.
+|
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1999
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+|
+| File Name: mal.h
+|
+| Function: Header file for the MAL (MADMAL) macro on the 405GP.
+|
+| Author: Mark Wisner
+|
+| Change Activity-
+|
+| Date Description of Change BY
+| --------- --------------------- ---
+| 29-Apr-99 Created MKW
+|
++----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------+
+| 17-Nov-03 Travis B. Sawyer, Sandburst Corporation, tsawyer@sandburst.com
+| Added register bit definitions to support multiple channels
++----------------------------------------------------------------------------*/
+#ifndef _mal_h_
+#define _mal_h_
+
+#if !defined(MAL_DCR_BASE)
+#define MAL_DCR_BASE 0x180
+#endif
+#define MAL0_CFG (MAL_DCR_BASE + 0x00) /* MAL Config reg */
+#define MAL0_ESR (MAL_DCR_BASE + 0x01) /* Error Status (Read/Clear) */
+#define MAL0_IER (MAL_DCR_BASE + 0x02) /* Interrupt enable */
+#define MAL0_TXCASR (MAL_DCR_BASE + 0x04) /* TX Channel active (set) */
+#define MAL0_TXCARR (MAL_DCR_BASE + 0x05) /* TX Channel active (reset) */
+#define MAL0_TXEOBISR (MAL_DCR_BASE + 0x06) /* TX End of buffer int status*/
+#define MAL0_TXDEIR (MAL_DCR_BASE + 0x07) /* TX Descr. Error Int */
+#define MAL0_TXBADDR (MAL_DCR_BASE + 0x09) /* TX descriptor base addr*/
+#define MAL0_RXCASR (MAL_DCR_BASE + 0x10) /* RX Channel active (set) */
+#define MAL0_RXCARR (MAL_DCR_BASE + 0x11) /* RX Channel active (reset) */
+#define MAL0_RXEOBISR (MAL_DCR_BASE + 0x12) /* RX End of buffer int status*/
+#define MAL0_RXDEIR (MAL_DCR_BASE + 0x13) /* RX Descr. Error Int */
+#define MAL0_RXBADDR (MAL_DCR_BASE + 0x15) /* RX descriptor base addr */
+#define MAL0_TXCTP0R (MAL_DCR_BASE + 0x20) /* TX 0 Channel table pointer */
+#define MAL0_TXCTP1R (MAL_DCR_BASE + 0x21) /* TX 1 Channel table pointer */
+#define MAL0_TXCTP2R (MAL_DCR_BASE + 0x22) /* TX 2 Channel table pointer */
+#define MAL0_TXCTP3R (MAL_DCR_BASE + 0x23) /* TX 3 Channel table pointer */
+#define MAL0_RXCTP0R (MAL_DCR_BASE + 0x40) /* RX 0 Channel table pointer */
+#define MAL0_RXCTP1R (MAL_DCR_BASE + 0x41) /* RX 1 Channel table pointer */
+#define MAL0_RCBS0 (MAL_DCR_BASE + 0x60) /* RX 0 Channel buffer size */
+#define MAL0_RCBS1 (MAL_DCR_BASE + 0x61) /* RX 1 Channel buffer size */
+#if defined(CONFIG_440GX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#define MAL0_RXCTP2R (MAL_DCR_BASE + 0x42) /* RX 2 Channel table pointer */
+#define MAL0_RXCTP3R (MAL_DCR_BASE + 0x43) /* RX 3 Channel table pointer */
+#define MAL0_RXCTP8R (MAL_DCR_BASE + 0x48) /* RX 8 Channel table pointer */
+#define MAL0_RXCTP16R (MAL_DCR_BASE + 0x50) /* RX 16 Channel table pointer*/
+#define MAL0_RXCTP24R (MAL_DCR_BASE + 0x58) /* RX 24 Channel table pointer*/
+#define MAL0_RCBS2 (MAL_DCR_BASE + 0x62) /* RX 2 Channel buffer size */
+#define MAL0_RCBS3 (MAL_DCR_BASE + 0x63) /* RX 3 Channel buffer size */
+#define MAL0_RCBS8 (MAL_DCR_BASE + 0x68) /* RX 8 Channel buffer size */
+#define MAL0_RCBS16 (MAL_DCR_BASE + 0x70) /* RX 16 Channel buffer size */
+#define MAL0_RCBS24 (MAL_DCR_BASE + 0x78) /* RX 24 Channel buffer size */
+#endif /* CONFIG_440GX */
+
+/* MADMAL transmit and receive status/control bits */
+/* for COMMAC bits, refer to the COMMAC header file */
+
+#define MAL_TX_CTRL_READY 0x8000
+#define MAL_TX_CTRL_WRAP 0x4000
+#define MAL_TX_CTRL_CM 0x2000
+#define MAL_TX_CTRL_LAST 0x1000
+#define MAL_TX_CTRL_INTR 0x0400
+
+#define MAL_RX_CTRL_EMPTY 0x8000
+#define MAL_RX_CTRL_WRAP 0x4000
+#define MAL_RX_CTRL_CM 0x2000
+#define MAL_RX_CTRL_LAST 0x1000
+#define MAL_RX_CTRL_FIRST 0x0800
+#define MAL_RX_CTRL_INTR 0x0400
+
+ /* Configuration Reg */
+#define MAL_CR_MMSR 0x80000000
+#define MAL_CR_PLBP_1 0x00400000 /* lowsest is 00 */
+#define MAL_CR_PLBP_2 0x00800000
+#define MAL_CR_PLBP_3 0x00C00000 /* highest */
+#define MAL_CR_GA 0x00200000
+#define MAL_CR_OA 0x00100000
+#define MAL_CR_PLBLE 0x00080000
+#define MAL_CR_PLBLT_1 0x00040000
+#define MAL_CR_PLBLT_2 0x00020000
+#define MAL_CR_PLBLT_3 0x00010000
+#define MAL_CR_PLBLT_4 0x00008000
+#define MAL_CR_PLBLT_DEFAULT 0x00078000 /* ????? */
+#define MAL_CR_PLBB 0x00004000
+#define MAL_CR_OPBBL 0x00000080
+#define MAL_CR_EOPIE 0x00000004
+#define MAL_CR_LEA 0x00000002
+#define MAL_CR_MSD 0x00000001
+
+ /* Error Status Reg */
+#define MAL_ESR_EVB 0x80000000
+#define MAL_ESR_CID 0x40000000
+#define MAL_ESR_DE 0x00100000
+#define MAL_ESR_ONE 0x00080000
+#define MAL_ESR_OTE 0x00040000
+#define MAL_ESR_OSE 0x00020000
+#define MAL_ESR_PEIN 0x00010000
+ /* same bit position as the IER */
+ /* VV VV */
+#define MAL_ESR_DEI 0x00000010
+#define MAL_ESR_ONEI 0x00000008
+#define MAL_ESR_OTEI 0x00000004
+#define MAL_ESR_OSEI 0x00000002
+#define MAL_ESR_PBEI 0x00000001
+ /* ^^ ^^ */
+ /* Mal IER */
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_405EX)
+#define MAL_IER_PT 0x00000080
+#define MAL_IER_PRE 0x00000040
+#define MAL_IER_PWE 0x00000020
+#define MAL_IER_DE 0x00000010
+#define MAL_IER_OTE 0x00000004
+#define MAL_IER_OE 0x00000002
+#define MAL_IER_PE 0x00000001
+#else
+#define MAL_IER_DE 0x00000010
+#define MAL_IER_NE 0x00000008
+#define MAL_IER_TE 0x00000004
+#define MAL_IER_OPBE 0x00000002
+#define MAL_IER_PLBE 0x00000001
+#endif
+
+/* MAL Channel Active Set and Reset Registers */
+#define MAL_TXRX_CASR (0x80000000)
+
+#define MAL_TXRX_CASR_V(__x) (__x) /* Channel 0 shifts 0, channel 1 shifts 1, etc */
+
+
+/* MAL Buffer Descriptor structure */
+typedef struct {
+ short ctrl; /* MAL / Commac status control bits */
+ short data_len; /* Max length is 4K-1 (12 bits) */
+ char *data_ptr; /* pointer to actual data buffer */
+} mal_desc_t;
+
+#endif
diff --git a/arch/powerpc/include/asm/ppc4xx-sdram.h b/arch/powerpc/include/asm/ppc4xx-sdram.h
new file mode 100644
index 0000000..e35d9b6
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-sdram.h
@@ -0,0 +1,1418 @@
+/*
+ * (C) Copyright 2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_SDRAM_H_
+#define _PPC4xx_SDRAM_H_
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_SDRAM)
+
+/*
+ * SDRAM Controller
+ */
+
+#ifndef CONFIG_405EP
+#define SDRAM0_BESR0 0x00 /* bus error syndrome reg a */
+#define SDRAM0_BESRS0 0x04 /* bus error syndrome reg set a */
+#define SDRAM0_BESR1 0x08 /* bus error syndrome reg b */
+#define SDRAM0_BESRS1 0x0c /* bus error syndrome reg set b */
+#define SDRAM0_BEAR 0x10 /* bus error address reg */
+#endif
+#define SDRAM0_CFG 0x20 /* memory controller options 1 */
+#define SDRAM0_STATUS 0x24 /* memory status */
+#define SDRAM0_RTR 0x30 /* refresh timer reg */
+#define SDRAM0_PMIT 0x34 /* power management idle timer */
+#define SDRAM0_B0CR 0x40 /* memory bank 0 configuration */
+#define SDRAM0_B1CR 0x44 /* memory bank 1 configuration */
+#ifndef CONFIG_405EP
+#define SDRAM0_B2CR 0x48 /* memory bank 2 configuration */
+#define SDRAM0_B3CR 0x4c /* memory bank 3 configuration */
+#endif
+#define SDRAM0_TR 0x80 /* timing reg 1 */
+#ifndef CONFIG_405EP
+#define SDRAM0_ECCCFG 0x94 /* ECC configuration */
+#define SDRAM0_ECCESR 0x98 /* ECC error status */
+#endif
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_SDRAM */
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
+
+/*
+ * Memory controller registers
+ */
+#define SDRAM_CFG0 0x20 /* memory controller options 0 */
+#define SDRAM_CFG1 0x21 /* memory controller options 1 */
+
+#define SDRAM0_BESR0 0x0000 /* bus error status reg 0 */
+#define SDRAM0_BESR1 0x0008 /* bus error status reg 1 */
+#define SDRAM0_BEAR 0x0010 /* bus error address reg */
+#define SDRAM0_SLIO 0x0018 /* ddr sdram slave interface options */
+#define SDRAM0_CFG0 0x0020 /* ddr sdram options 0 */
+#define SDRAM0_CFG1 0x0021 /* ddr sdram options 1 */
+#define SDRAM0_DEVOPT 0x0022 /* ddr sdram device options */
+#define SDRAM0_MCSTS 0x0024 /* memory controller status */
+#define SDRAM0_RTR 0x0030 /* refresh timer register */
+#define SDRAM0_PMIT 0x0034 /* power management idle timer */
+#define SDRAM0_UABBA 0x0038 /* plb UABus base address */
+#define SDRAM0_B0CR 0x0040 /* ddr sdram bank 0 configuration */
+#define SDRAM0_B1CR 0x0044 /* ddr sdram bank 1 configuration */
+#define SDRAM0_B2CR 0x0048 /* ddr sdram bank 2 configuration */
+#define SDRAM0_B3CR 0x004c /* ddr sdram bank 3 configuration */
+#define SDRAM0_TR0 0x0080 /* sdram timing register 0 */
+#define SDRAM0_TR1 0x0081 /* sdram timing register 1 */
+#define SDRAM0_CLKTR 0x0082 /* ddr clock timing register */
+#define SDRAM0_WDDCTR 0x0083 /* write data/dm/dqs clock timing reg */
+#define SDRAM0_DLYCAL 0x0084 /* delay line calibration register */
+#define SDRAM0_ECCESR 0x0098 /* ECC error status */
+
+/*
+ * Memory Controller Options 0
+ */
+#define SDRAM_CFG0_DCEN 0x80000000 /* SDRAM Controller Enable */
+#define SDRAM_CFG0_MCHK_MASK 0x30000000 /* Memory data errchecking mask */
+#define SDRAM_CFG0_MCHK_NON 0x00000000 /* No ECC generation */
+#define SDRAM_CFG0_MCHK_GEN 0x20000000 /* ECC generation */
+#define SDRAM_CFG0_MCHK_CHK 0x30000000 /* ECC generation and checking */
+#define SDRAM_CFG0_RDEN 0x08000000 /* Registered DIMM enable */
+#define SDRAM_CFG0_PMUD 0x04000000 /* Page management unit */
+#define SDRAM_CFG0_DMWD_MASK 0x02000000 /* DRAM width mask */
+#define SDRAM_CFG0_DMWD_32 0x00000000 /* 32 bits */
+#define SDRAM_CFG0_DMWD_64 0x02000000 /* 64 bits */
+#define SDRAM_CFG0_UIOS_MASK 0x00C00000 /* Unused IO State */
+#define SDRAM_CFG0_PDP 0x00200000 /* Page deallocation policy */
+
+/*
+ * Memory Controller Options 1
+ */
+#define SDRAM_CFG1_SRE 0x80000000 /* Self-Refresh Entry */
+#define SDRAM_CFG1_PMEN 0x40000000 /* Power Management Enable */
+
+/*
+ * SDRAM DEVPOT Options
+ */
+#define SDRAM_DEVOPT_DLL 0x80000000
+#define SDRAM_DEVOPT_DS 0x40000000
+
+/*
+ * SDRAM MCSTS Options
+ */
+#define SDRAM_MCSTS_MRSC 0x80000000
+#define SDRAM_MCSTS_SRMS 0x40000000
+#define SDRAM_MCSTS_CIS 0x20000000
+#define SDRAM_MCSTS_IDLE_NOT 0x00000000 /* Mem contr not idle */
+
+/*
+ * SDRAM Refresh Timer Register
+ */
+#define SDRAM_RTR_RINT_MASK 0xFFFF0000
+#define SDRAM_RTR_RINT_ENCODE(n) (((n) << 16) & SDRAM_RTR_RINT_MASK)
+
+/*
+ * SDRAM UABus Base Address Reg
+ */
+#define SDRAM_UABBA_UBBA_MASK 0x0000000F
+
+/*
+ * Memory Bank 0-7 configuration
+ */
+#define SDRAM_BXCR_SDBA_MASK 0xff800000 /* Base address */
+#define SDRAM_BXCR_SDSZ_MASK 0x000e0000 /* Size */
+#define SDRAM_BXCR_SDSZ_8 0x00020000 /* 8M */
+#define SDRAM_BXCR_SDSZ_16 0x00040000 /* 16M */
+#define SDRAM_BXCR_SDSZ_32 0x00060000 /* 32M */
+#define SDRAM_BXCR_SDSZ_64 0x00080000 /* 64M */
+#define SDRAM_BXCR_SDSZ_128 0x000a0000 /* 128M */
+#define SDRAM_BXCR_SDSZ_256 0x000c0000 /* 256M */
+#define SDRAM_BXCR_SDSZ_512 0x000e0000 /* 512M */
+#define SDRAM_BXCR_SDAM_MASK 0x0000e000 /* Addressing mode */
+#define SDRAM_BXCR_SDAM_1 0x00000000 /* Mode 1 */
+#define SDRAM_BXCR_SDAM_2 0x00002000 /* Mode 2 */
+#define SDRAM_BXCR_SDAM_3 0x00004000 /* Mode 3 */
+#define SDRAM_BXCR_SDAM_4 0x00006000 /* Mode 4 */
+#define SDRAM_BXCR_SDBE 0x00000001 /* Memory Bank Enable */
+
+/*
+ * SDRAM TR0 Options
+ */
+#define SDRAM_TR0_SDWR_MASK 0x80000000
+#define SDRAM_TR0_SDWR_2_CLK 0x00000000
+#define SDRAM_TR0_SDWR_3_CLK 0x80000000
+#define SDRAM_TR0_SDWD_MASK 0x40000000
+#define SDRAM_TR0_SDWD_0_CLK 0x00000000
+#define SDRAM_TR0_SDWD_1_CLK 0x40000000
+#define SDRAM_TR0_SDCL_MASK 0x01800000
+#define SDRAM_TR0_SDCL_2_0_CLK 0x00800000
+#define SDRAM_TR0_SDCL_2_5_CLK 0x01000000
+#define SDRAM_TR0_SDCL_3_0_CLK 0x01800000
+#define SDRAM_TR0_SDPA_MASK 0x000C0000
+#define SDRAM_TR0_SDPA_2_CLK 0x00040000
+#define SDRAM_TR0_SDPA_3_CLK 0x00080000
+#define SDRAM_TR0_SDPA_4_CLK 0x000C0000
+#define SDRAM_TR0_SDCP_MASK 0x00030000
+#define SDRAM_TR0_SDCP_2_CLK 0x00000000
+#define SDRAM_TR0_SDCP_3_CLK 0x00010000
+#define SDRAM_TR0_SDCP_4_CLK 0x00020000
+#define SDRAM_TR0_SDCP_5_CLK 0x00030000
+#define SDRAM_TR0_SDLD_MASK 0x0000C000
+#define SDRAM_TR0_SDLD_1_CLK 0x00000000
+#define SDRAM_TR0_SDLD_2_CLK 0x00004000
+#define SDRAM_TR0_SDRA_MASK 0x0000001C
+#define SDRAM_TR0_SDRA_6_CLK 0x00000000
+#define SDRAM_TR0_SDRA_7_CLK 0x00000004
+#define SDRAM_TR0_SDRA_8_CLK 0x00000008
+#define SDRAM_TR0_SDRA_9_CLK 0x0000000C
+#define SDRAM_TR0_SDRA_10_CLK 0x00000010
+#define SDRAM_TR0_SDRA_11_CLK 0x00000014
+#define SDRAM_TR0_SDRA_12_CLK 0x00000018
+#define SDRAM_TR0_SDRA_13_CLK 0x0000001C
+#define SDRAM_TR0_SDRD_MASK 0x00000003
+#define SDRAM_TR0_SDRD_2_CLK 0x00000001
+#define SDRAM_TR0_SDRD_3_CLK 0x00000002
+#define SDRAM_TR0_SDRD_4_CLK 0x00000003
+
+/*
+ * SDRAM TR1 Options
+ */
+#define SDRAM_TR1_RDSS_MASK 0xC0000000
+#define SDRAM_TR1_RDSS_TR0 0x00000000
+#define SDRAM_TR1_RDSS_TR1 0x40000000
+#define SDRAM_TR1_RDSS_TR2 0x80000000
+#define SDRAM_TR1_RDSS_TR3 0xC0000000
+#define SDRAM_TR1_RDSL_MASK 0x00C00000
+#define SDRAM_TR1_RDSL_STAGE1 0x00000000
+#define SDRAM_TR1_RDSL_STAGE2 0x00400000
+#define SDRAM_TR1_RDSL_STAGE3 0x00800000
+#define SDRAM_TR1_RDCD_MASK 0x00000800
+#define SDRAM_TR1_RDCD_RCD_0_0 0x00000000
+#define SDRAM_TR1_RDCD_RCD_1_2 0x00000800
+#define SDRAM_TR1_RDCT_MASK 0x000001FF
+#define SDRAM_TR1_RDCT_ENCODE(x) (((x) << 0) & SDRAM_TR1_RDCT_MASK)
+#define SDRAM_TR1_RDCT_DECODE(x) (((x) & SDRAM_TR1_RDCT_MASK) >> 0)
+#define SDRAM_TR1_RDCT_MIN 0x00000000
+#define SDRAM_TR1_RDCT_MAX 0x000001FF
+
+/*
+ * SDRAM WDDCTR Options
+ */
+#define SDRAM_WDDCTR_WRCP_MASK 0xC0000000
+#define SDRAM_WDDCTR_WRCP_0DEG 0x00000000
+#define SDRAM_WDDCTR_WRCP_90DEG 0x40000000
+#define SDRAM_WDDCTR_WRCP_180DEG 0x80000000
+#define SDRAM_WDDCTR_DCD_MASK 0x000001FF
+
+/*
+ * SDRAM CLKTR Options
+ */
+#define SDRAM_CLKTR_CLKP_MASK 0xC0000000
+#define SDRAM_CLKTR_CLKP_0DEG 0x00000000
+#define SDRAM_CLKTR_CLKP_90DEG 0x40000000
+#define SDRAM_CLKTR_CLKP_180DEG 0x80000000
+#define SDRAM_CLKTR_DCDT_MASK 0x000001FF
+
+/*
+ * SDRAM DLYCAL Options
+ */
+#define SDRAM_DLYCAL_DLCV_MASK 0x000003FC
+#define SDRAM_DLYCAL_DLCV_ENCODE(x) (((x)<<2) & SDRAM_DLYCAL_DLCV_MASK)
+#define SDRAM_DLYCAL_DLCV_DECODE(x) (((x) & SDRAM_DLYCAL_DLCV_MASK)>>2)
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_DDR */
+
+#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
+
+#define SDRAM_DLYCAL_DLCV_MASK 0x000003FC
+#define SDRAM_DLYCAL_DLCV_ENCODE(x) (((x)<<2) & SDRAM_DLYCAL_DLCV_MASK)
+#define SDRAM_DLYCAL_DLCV_DECODE(x) (((x) & SDRAM_DLYCAL_DLCV_MASK)>>2)
+
+#if !defined(CONFIG_405EX)
+/*
+ * Memory queue defines
+ */
+#define SDRAMQ_DCR_BASE 0x040
+
+#define SDRAM_R0BAS (SDRAMQ_DCR_BASE+0x0) /* rank 0 base address & size */
+#define SDRAM_R1BAS (SDRAMQ_DCR_BASE+0x1) /* rank 1 base address & size */
+#define SDRAM_R2BAS (SDRAMQ_DCR_BASE+0x2) /* rank 2 base address & size */
+#define SDRAM_R3BAS (SDRAMQ_DCR_BASE+0x3) /* rank 3 base address & size */
+#define SDRAM_CONF1HB (SDRAMQ_DCR_BASE+0x5) /* configuration 1 HB */
+#define SDRAM_CONF1HB_AAFR 0x80000000 /* Address Ack on First Request - Bit 0 */
+#define SDRAM_CONF1HB_PRPD 0x00080000 /* PLB Read pipeline Disable - Bit 12 */
+#define SDRAM_CONF1HB_PWPD 0x00040000 /* PLB Write pipeline Disable - Bit 13 */
+#define SDRAM_CONF1HB_PRW 0x00020000 /* PLB Read Wait - Bit 14 */
+#define SDRAM_CONF1HB_RPLM 0x00001000 /* Read Passing Limit 1 - Bits 16..19 */
+#define SDRAM_CONF1HB_RPEN 0x00000800 /* Read Passing Enable - Bit 20 */
+#define SDRAM_CONF1HB_RFTE 0x00000400 /* Read Flow Through Enable - Bit 21 */
+#define SDRAM_CONF1HB_WRCL 0x00000080 /* MCIF Cycle Limit 1 - Bits 22..24 */
+#define SDRAM_CONF1HB_MASK 0x0000F380 /* RPLM & WRCL mask */
+
+#define SDRAM_ERRSTATHB (SDRAMQ_DCR_BASE+0x7) /* error status HB */
+#define SDRAM_ERRADDUHB (SDRAMQ_DCR_BASE+0x8) /* error address upper 32 HB */
+#define SDRAM_ERRADDLHB (SDRAMQ_DCR_BASE+0x9) /* error address lower 32 HB */
+#define SDRAM_PLBADDULL (SDRAMQ_DCR_BASE+0xA) /* PLB base address upper 32 LL */
+#define SDRAM_CONF1LL (SDRAMQ_DCR_BASE+0xB) /* configuration 1 LL */
+#define SDRAM_CONF1LL_AAFR 0x80000000 /* Address Ack on First Request - Bit 0 */
+#define SDRAM_CONF1LL_PRPD 0x00080000 /* PLB Read pipeline Disable - Bit 12 */
+#define SDRAM_CONF1LL_PWPD 0x00040000 /* PLB Write pipeline Disable - Bit 13 */
+#define SDRAM_CONF1LL_PRW 0x00020000 /* PLB Read Wait - Bit 14 */
+#define SDRAM_CONF1LL_RPLM 0x00001000 /* Read Passing Limit 1 - Bits 16..19 */
+#define SDRAM_CONF1LL_RPEN 0x00000800 /* Read Passing Enable - Bit 20 */
+#define SDRAM_CONF1LL_RFTE 0x00000400 /* Read Flow Through Enable - Bit 21 */
+#define SDRAM_CONF1LL_MASK 0x0000F000 /* RPLM mask */
+
+#define SDRAM_ERRSTATLL (SDRAMQ_DCR_BASE+0xC) /* error status LL */
+#define SDRAM_ERRADDULL (SDRAMQ_DCR_BASE+0xD) /* error address upper 32 LL */
+#define SDRAM_ERRADDLLL (SDRAMQ_DCR_BASE+0xE) /* error address lower 32 LL */
+#define SDRAM_CONFPATHB (SDRAMQ_DCR_BASE+0xF) /* configuration between paths */
+#define SDRAM_CONFPATHB_TPEN 0x08000000 /* Transaction Passing Enable - Bit 4 */
+
+#define SDRAM_PLBADDUHB (SDRAMQ_DCR_BASE+0x10) /* PLB base address upper 32 LL */
+
+/*
+ * Memory Bank 0-7 configuration
+ */
+#if defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
+#define SDRAM_RXBAS_SDBA_MASK 0xFFE00000 /* Base address */
+#define SDRAM_RXBAS_SDBA_ENCODE(n) ((u32)(((phys_size_t)(n) >> 2) & 0xFFE00000))
+#define SDRAM_RXBAS_SDBA_DECODE(n) ((((phys_size_t)(n)) & 0xFFE00000) << 2)
+#endif /* CONFIG_440SPE */
+#if defined(CONFIG_440SP)
+#define SDRAM_RXBAS_SDBA_MASK 0xFF800000 /* Base address */
+#define SDRAM_RXBAS_SDBA_ENCODE(n) ((((u32)(n))&0xFF800000))
+#define SDRAM_RXBAS_SDBA_DECODE(n) ((((u32)(n))&0xFF800000))
+#endif /* CONFIG_440SP */
+#define SDRAM_RXBAS_SDSZ_MASK 0x0000FFC0 /* Size */
+#define SDRAM_RXBAS_SDSZ_ENCODE(n) ((((u32)(n))&0x3FF)<<6)
+#define SDRAM_RXBAS_SDSZ_DECODE(n) ((((u32)(n))>>6)&0x3FF)
+#define SDRAM_RXBAS_SDSZ_0 0x00000000 /* 0M */
+#define SDRAM_RXBAS_SDSZ_8 0x0000FFC0 /* 8M */
+#define SDRAM_RXBAS_SDSZ_16 0x0000FF80 /* 16M */
+#define SDRAM_RXBAS_SDSZ_32 0x0000FF00 /* 32M */
+#define SDRAM_RXBAS_SDSZ_64 0x0000FE00 /* 64M */
+#define SDRAM_RXBAS_SDSZ_128 0x0000FC00 /* 128M */
+#define SDRAM_RXBAS_SDSZ_256 0x0000F800 /* 256M */
+#define SDRAM_RXBAS_SDSZ_512 0x0000F000 /* 512M */
+#define SDRAM_RXBAS_SDSZ_1024 0x0000E000 /* 1024M */
+#define SDRAM_RXBAS_SDSZ_2048 0x0000C000 /* 2048M */
+#define SDRAM_RXBAS_SDSZ_4096 0x00008000 /* 4096M */
+#else /* CONFIG_405EX */
+/*
+ * XXX - ToDo:
+ * Revisit this file to check if all these 405EX defines are correct and
+ * can be used in the common 44x_spd_ddr2 code as well. sr, 2008-06-02
+ */
+#define SDRAM_RXBAS_SDSZ_MASK PPC_REG_VAL(19, 0xF)
+#define SDRAM_RXBAS_SDSZ_4MB PPC_REG_VAL(19, 0x0)
+#define SDRAM_RXBAS_SDSZ_8MB PPC_REG_VAL(19, 0x1)
+#define SDRAM_RXBAS_SDSZ_16MB PPC_REG_VAL(19, 0x2)
+#define SDRAM_RXBAS_SDSZ_32MB PPC_REG_VAL(19, 0x3)
+#define SDRAM_RXBAS_SDSZ_64MB PPC_REG_VAL(19, 0x4)
+#define SDRAM_RXBAS_SDSZ_128MB PPC_REG_VAL(19, 0x5)
+#define SDRAM_RXBAS_SDSZ_256MB PPC_REG_VAL(19, 0x6)
+#define SDRAM_RXBAS_SDSZ_512MB PPC_REG_VAL(19, 0x7)
+#define SDRAM_RXBAS_SDSZ_1024MB PPC_REG_VAL(19, 0x8)
+#define SDRAM_RXBAS_SDSZ_2048MB PPC_REG_VAL(19, 0x9)
+#define SDRAM_RXBAS_SDSZ_4096MB PPC_REG_VAL(19, 0xA)
+#define SDRAM_RXBAS_SDSZ_8192MB PPC_REG_VAL(19, 0xB)
+#define SDRAM_RXBAS_SDSZ_8 SDRAM_RXBAS_SDSZ_8MB
+#define SDRAM_RXBAS_SDSZ_16 SDRAM_RXBAS_SDSZ_16MB
+#define SDRAM_RXBAS_SDSZ_32 SDRAM_RXBAS_SDSZ_32MB
+#define SDRAM_RXBAS_SDSZ_64 SDRAM_RXBAS_SDSZ_64MB
+#define SDRAM_RXBAS_SDSZ_128 SDRAM_RXBAS_SDSZ_128MB
+#define SDRAM_RXBAS_SDSZ_256 SDRAM_RXBAS_SDSZ_256MB
+#define SDRAM_RXBAS_SDSZ_512 SDRAM_RXBAS_SDSZ_512MB
+#define SDRAM_RXBAS_SDSZ_1024 SDRAM_RXBAS_SDSZ_1024MB
+#define SDRAM_RXBAS_SDSZ_2048 SDRAM_RXBAS_SDSZ_2048MB
+#define SDRAM_RXBAS_SDSZ_4096 SDRAM_RXBAS_SDSZ_4096MB
+#define SDRAM_RXBAS_SDSZ_8192 SDRAM_RXBAS_SDSZ_8192MB
+#endif /* CONFIG_405EX */
+
+/* The mode definitions are the same for all PPC4xx variants */
+#define SDRAM_RXBAS_SDAM_MODE0 PPC_REG_VAL(23, 0x0)
+#define SDRAM_RXBAS_SDAM_MODE1 PPC_REG_VAL(23, 0x1)
+#define SDRAM_RXBAS_SDAM_MODE2 PPC_REG_VAL(23, 0x2)
+#define SDRAM_RXBAS_SDAM_MODE3 PPC_REG_VAL(23, 0x3)
+#define SDRAM_RXBAS_SDAM_MODE4 PPC_REG_VAL(23, 0x4)
+#define SDRAM_RXBAS_SDAM_MODE5 PPC_REG_VAL(23, 0x5)
+#define SDRAM_RXBAS_SDAM_MODE6 PPC_REG_VAL(23, 0x6)
+#define SDRAM_RXBAS_SDAM_MODE7 PPC_REG_VAL(23, 0x7)
+#define SDRAM_RXBAS_SDAM_MODE8 PPC_REG_VAL(23, 0x8)
+#define SDRAM_RXBAS_SDAM_MODE9 PPC_REG_VAL(23, 0x9)
+#define SDRAM_RXBAS_SDBE_DISABLE PPC_REG_VAL(31, 0x0)
+#define SDRAM_RXBAS_SDBE_ENABLE PPC_REG_VAL(31, 0x1)
+
+/*
+ * Memory controller registers
+ */
+#if defined(CONFIG_405EX) || defined(CONFIG_APM821XX)
+#define SDRAM_BESR 0x00 /* PLB bus error status (read/clear) */
+#define SDRAM_BESRT 0x01 /* PLB bus error status (test/set) */
+#define SDRAM_BEARL 0x02 /* PLB bus error address low */
+#define SDRAM_BEARH 0x03 /* PLB bus error address high */
+#define SDRAM_WMIRQ 0x06 /* PLB write master interrupt (read/clear) */
+#define SDRAM_WMIRQT 0x07 /* PLB write master interrupt (test/set) */
+#define SDRAM_PLBOPT 0x08 /* PLB slave options */
+#define SDRAM_PUABA 0x09 /* PLB upper address base */
+#define SDRAM_MCSTAT 0x1F /* memory controller status */
+#else /* CONFIG_405EX || CONFIG_APM821XX */
+#define SDRAM_MCSTAT 0x14 /* memory controller status */
+#endif /* CONFIG_405EX || CONFIG_APM821XX */
+#define SDRAM_MCOPT1 0x20 /* memory controller options 1 */
+#define SDRAM_MCOPT2 0x21 /* memory controller options 2 */
+#define SDRAM_MODT0 0x22 /* on die termination for bank 0 */
+#define SDRAM_MODT1 0x23 /* on die termination for bank 1 */
+#define SDRAM_MODT2 0x24 /* on die termination for bank 2 */
+#define SDRAM_MODT3 0x25 /* on die termination for bank 3 */
+#define SDRAM_CODT 0x26 /* on die termination for controller */
+#define SDRAM_VVPR 0x27 /* variable VRef programmming */
+#define SDRAM_OPARS 0x28 /* on chip driver control setup */
+#define SDRAM_OPART 0x29 /* on chip driver control trigger */
+#define SDRAM_RTR 0x30 /* refresh timer */
+#define SDRAM_PMIT 0x34 /* power management idle timer */
+#define SDRAM_MB0CF 0x40 /* memory bank 0 configuration */
+#define SDRAM_MB1CF 0x44 /* memory bank 1 configuration */
+#define SDRAM_MB2CF 0x48
+#define SDRAM_MB3CF 0x4C
+#define SDRAM_INITPLR0 0x50 /* manual initialization control */
+#define SDRAM_INITPLR1 0x51 /* manual initialization control */
+#define SDRAM_INITPLR2 0x52 /* manual initialization control */
+#define SDRAM_INITPLR3 0x53 /* manual initialization control */
+#define SDRAM_INITPLR4 0x54 /* manual initialization control */
+#define SDRAM_INITPLR5 0x55 /* manual initialization control */
+#define SDRAM_INITPLR6 0x56 /* manual initialization control */
+#define SDRAM_INITPLR7 0x57 /* manual initialization control */
+#define SDRAM_INITPLR8 0x58 /* manual initialization control */
+#define SDRAM_INITPLR9 0x59 /* manual initialization control */
+#define SDRAM_INITPLR10 0x5a /* manual initialization control */
+#define SDRAM_INITPLR11 0x5b /* manual initialization control */
+#define SDRAM_INITPLR12 0x5c /* manual initialization control */
+#define SDRAM_INITPLR13 0x5d /* manual initialization control */
+#define SDRAM_INITPLR14 0x5e /* manual initialization control */
+#define SDRAM_INITPLR15 0x5f /* manual initialization control */
+#define SDRAM_RQDC 0x70 /* read DQS delay control */
+#define SDRAM_RFDC 0x74 /* read feedback delay control */
+#define SDRAM_RDCC 0x78 /* read data capture control */
+#define SDRAM_DLCR 0x7A /* delay line calibration */
+#define SDRAM_CLKTR 0x80 /* DDR clock timing */
+#define SDRAM_WRDTR 0x81 /* write data, DQS, DM clock, timing */
+#define SDRAM_SDTR1 0x85 /* DDR SDRAM timing 1 */
+#define SDRAM_SDTR2 0x86 /* DDR SDRAM timing 2 */
+#define SDRAM_SDTR3 0x87 /* DDR SDRAM timing 3 */
+#define SDRAM_MMODE 0x88 /* memory mode */
+#define SDRAM_MEMODE 0x89 /* memory extended mode */
+#define SDRAM_ECCES 0x98 /* ECC error status */
+#define SDRAM_CID 0xA4 /* core ID */
+#if !defined(CONFIG_405EX) && !defined(CONFIG_APM821XX)
+#define SDRAM_RID 0xA8 /* revision ID */
+#endif
+#define SDRAM_FCSR 0xB0 /* feedback calibration status */
+#define SDRAM_RTSR 0xB1 /* run time status tracking */
+#if defined(CONFIG_405EX) || defined(CONFIG_APM821XX)
+#define SDRAM_RID 0xF8 /* revision ID */
+#endif
+
+/*
+ * Memory Controller Bus Error Status
+ */
+#define SDRAM_BESR_MASK PPC_REG_VAL(7, 0xFF)
+#define SDRAM_BESR_M0ID_MASK PPC_REG_VAL(3, 0xF)
+#define SDRAM_BESR_M0ID_ICU PPC_REG_VAL(3, 0x0)
+#define SDRAM_BESR_M0ID_PCIE0 PPC_REG_VAL(3, 0x1)
+#define SDRAM_BESR_M0ID_PCIE1 PPC_REG_VAL(3, 0x2)
+#define SDRAM_BESR_M0ID_DMA PPC_REG_VAL(3, 0x3)
+#define SDRAM_BESR_M0ID_DCU PPC_REG_VAL(3, 0x4)
+#define SDRAM_BESR_M0ID_OPB PPC_REG_VAL(3, 0x5)
+#define SDRAM_BESR_M0ID_MAL PPC_REG_VAL(3, 0x6)
+#define SDRAM_BESR_M0ID_SEC PPC_REG_VAL(3, 0x7)
+#define SDRAM_BESR_M0ET_MASK PPC_REG_VAL(6, 0x7)
+#define SDRAM_BESR_M0ET_NONE PPC_REG_VAL(6, 0x0)
+#define SDRAM_BESR_M0ET_ECC PPC_REG_VAL(6, 0x1)
+#define SDRAM_BESR_M0RW_WRITE PPC_REG_VAL(7, 0)
+#define SDRAM_BESR_M0RW_READ PPC_REG_VAL(8, 1)
+
+/*
+ * Memory Controller Status
+ */
+#define SDRAM_MCSTAT_MIC_MASK 0x80000000 /* Memory init status mask */
+#define SDRAM_MCSTAT_MIC_NOTCOMP 0x00000000 /* Mem init not complete */
+#define SDRAM_MCSTAT_MIC_COMP 0x80000000 /* Mem init complete */
+#define SDRAM_MCSTAT_SRMS_MASK 0x40000000 /* Mem self refresh stat mask */
+#define SDRAM_MCSTAT_SRMS_NOT_SF 0x00000000 /* Mem not in self refresh */
+#define SDRAM_MCSTAT_SRMS_SF 0x40000000 /* Mem in self refresh */
+#define SDRAM_MCSTAT_IDLE_MASK 0x20000000 /* Mem self refresh stat mask */
+#define SDRAM_MCSTAT_IDLE_NOT 0x00000000 /* Mem contr not idle */
+#define SDRAM_MCSTAT_IDLE 0x20000000 /* Mem contr idle */
+
+/*
+ * Memory Controller Options 1
+ */
+#define SDRAM_MCOPT1_MCHK_MASK 0x30000000 /* Memory data err check mask*/
+#define SDRAM_MCOPT1_MCHK_NON 0x00000000 /* No ECC generation */
+#define SDRAM_MCOPT1_MCHK_GEN 0x20000000 /* ECC generation */
+#define SDRAM_MCOPT1_MCHK_CHK 0x10000000 /* ECC generation and check */
+#define SDRAM_MCOPT1_MCHK_CHK_REP 0x30000000 /* ECC generation, chk, report*/
+#define SDRAM_MCOPT1_MCHK_CHK_DECODE(n) ((((u32)(n))>>28)&0x3)
+#define SDRAM_MCOPT1_RDEN_MASK 0x08000000 /* Registered DIMM mask */
+#define SDRAM_MCOPT1_RDEN 0x08000000 /* Registered DIMM enable */
+#define SDRAM_MCOPT1_PMU_MASK 0x06000000 /* Page management unit mask */
+#define SDRAM_MCOPT1_PMU_CLOSE 0x00000000 /* PMU Close */
+#define SDRAM_MCOPT1_PMU_OPEN 0x04000000 /* PMU Open */
+#define SDRAM_MCOPT1_PMU_AUTOCLOSE 0x02000000 /* PMU AutoClose */
+#define SDRAM_MCOPT1_DMWD_MASK 0x01000000 /* DRAM width mask */
+#define SDRAM_MCOPT1_DMWD_32 0x00000000 /* 32 bits */
+#define SDRAM_MCOPT1_DMWD_64 0x01000000 /* 64 bits */
+#define SDRAM_MCOPT1_UIOS_MASK 0x00C00000 /* Unused IO State */
+#define SDRAM_MCOPT1_BCNT_MASK 0x00200000 /* Bank count */
+#define SDRAM_MCOPT1_4_BANKS 0x00000000 /* 4 Banks */
+#define SDRAM_MCOPT1_8_BANKS 0x00200000 /* 8 Banks */
+#define SDRAM_MCOPT1_DDR_TYPE_MASK 0x00100000 /* DDR Memory Type mask */
+#define SDRAM_MCOPT1_DDR1_TYPE 0x00000000 /* DDR1 Memory Type */
+#define SDRAM_MCOPT1_DDR2_TYPE 0x00100000 /* DDR2 Memory Type */
+#define SDRAM_MCOPT1_QDEP 0x00020000 /* 4 commands deep */
+#define SDRAM_MCOPT1_RWOO_MASK 0x00008000 /* Out of Order Read mask */
+#define SDRAM_MCOPT1_RWOO_DISABLED 0x00000000 /* disabled */
+#define SDRAM_MCOPT1_RWOO_ENABLED 0x00008000 /* enabled */
+#define SDRAM_MCOPT1_WOOO_MASK 0x00004000 /* Out of Order Write mask */
+#define SDRAM_MCOPT1_WOOO_DISABLED 0x00000000 /* disabled */
+#define SDRAM_MCOPT1_WOOO_ENABLED 0x00004000 /* enabled */
+#define SDRAM_MCOPT1_DCOO_MASK 0x00002000 /* All Out of Order mask */
+#define SDRAM_MCOPT1_DCOO_DISABLED 0x00002000 /* disabled */
+#define SDRAM_MCOPT1_DCOO_ENABLED 0x00000000 /* enabled */
+#define SDRAM_MCOPT1_DREF_MASK 0x00001000 /* Deferred refresh mask */
+#define SDRAM_MCOPT1_DREF_NORMAL 0x00000000 /* normal refresh */
+#define SDRAM_MCOPT1_DREF_DEFER_4 0x00001000 /* defer up to 4 refresh cmd */
+
+/*
+ * Memory Controller Options 2
+ */
+#define SDRAM_MCOPT2_SREN_MASK 0x80000000 /* Self Test mask */
+#define SDRAM_MCOPT2_SREN_EXIT 0x00000000 /* Self Test exit */
+#define SDRAM_MCOPT2_SREN_ENTER 0x80000000 /* Self Test enter */
+#define SDRAM_MCOPT2_PMEN_MASK 0x40000000 /* Power Management mask */
+#define SDRAM_MCOPT2_PMEN_DISABLE 0x00000000 /* disable */
+#define SDRAM_MCOPT2_PMEN_ENABLE 0x40000000 /* enable */
+#define SDRAM_MCOPT2_IPTR_MASK 0x20000000 /* Init Trigger Reg mask */
+#define SDRAM_MCOPT2_IPTR_IDLE 0x00000000 /* idle */
+#define SDRAM_MCOPT2_IPTR_EXECUTE 0x20000000 /* execute preloaded init */
+#define SDRAM_MCOPT2_XSRP_MASK 0x10000000 /* Exit Self Refresh Prevent */
+#define SDRAM_MCOPT2_XSRP_ALLOW 0x00000000 /* allow self refresh exit */
+#define SDRAM_MCOPT2_XSRP_PREVENT 0x10000000 /* prevent self refresh exit */
+#define SDRAM_MCOPT2_DCEN_MASK 0x08000000 /* SDRAM Controller Enable */
+#define SDRAM_MCOPT2_DCEN_DISABLE 0x00000000 /* SDRAM Controller Enable */
+#define SDRAM_MCOPT2_DCEN_ENABLE 0x08000000 /* SDRAM Controller Enable */
+#define SDRAM_MCOPT2_ISIE_MASK 0x04000000 /* Init Seq Interruptable mas*/
+#define SDRAM_MCOPT2_ISIE_DISABLE 0x00000000 /* disable */
+#define SDRAM_MCOPT2_ISIE_ENABLE 0x04000000 /* enable */
+
+/*
+ * SDRAM Refresh Timer Register
+ */
+#define SDRAM_RTR_RINT_MASK 0xFFF80000
+#define SDRAM_RTR_RINT_ENCODE(n) ((((u32)(n))&0xFFF8)<<16)
+#define SDRAM_RTR_RINT_DECODE(n) ((((u32)(n))>>16)&0xFFF8)
+
+/*
+ * SDRAM Read DQS Delay Control Register
+ */
+#define SDRAM_RQDC_RQDE_MASK 0x80000000
+#define SDRAM_RQDC_RQDE_DISABLE 0x00000000
+#define SDRAM_RQDC_RQDE_ENABLE 0x80000000
+#define SDRAM_RQDC_RQFD_MASK 0x000001FF
+#define SDRAM_RQDC_RQFD_ENCODE(n) ((((u32)(n))&0x1FF)<<0)
+
+#define SDRAM_RQDC_RQFD_MAX 0x1FF
+
+/*
+ * SDRAM Read Data Capture Control Register
+ */
+#define SDRAM_RDCC_RDSS_MASK 0xC0000000
+#define SDRAM_RDCC_RDSS_T1 0x00000000
+#define SDRAM_RDCC_RDSS_T2 0x40000000
+#define SDRAM_RDCC_RDSS_T3 0x80000000
+#define SDRAM_RDCC_RDSS_T4 0xC0000000
+#define SDRAM_RDCC_RSAE_MASK 0x00000001
+#define SDRAM_RDCC_RSAE_DISABLE 0x00000001
+#define SDRAM_RDCC_RSAE_ENABLE 0x00000000
+#define SDRAM_RDCC_RDSS_ENCODE(n) ((((u32)(n))&0x03)<<30)
+#define SDRAM_RDCC_RDSS_DECODE(n) ((((u32)(n))>>30)&0x03)
+
+/*
+ * SDRAM Read Feedback Delay Control Register
+ */
+#define SDRAM_RFDC_ARSE_MASK 0x80000000
+#define SDRAM_RFDC_ARSE_DISABLE 0x80000000
+#define SDRAM_RFDC_ARSE_ENABLE 0x00000000
+#define SDRAM_RFDC_RFOS_MASK 0x007F0000
+#define SDRAM_RFDC_RFOS_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define SDRAM_RFDC_RFFD_MASK 0x000007FF
+#define SDRAM_RFDC_RFFD_ENCODE(n) ((((u32)(n))&0x7FF)<<0)
+
+#define SDRAM_RFDC_RFFD_MAX 0x7FF
+
+/*
+ * SDRAM Delay Line Calibration Register
+ */
+#define SDRAM_DLCR_DCLM_MASK 0x80000000
+#define SDRAM_DLCR_DCLM_MANUAL 0x80000000
+#define SDRAM_DLCR_DCLM_AUTO 0x00000000
+#define SDRAM_DLCR_DLCR_MASK 0x08000000
+#define SDRAM_DLCR_DLCR_CALIBRATE 0x08000000
+#define SDRAM_DLCR_DLCR_IDLE 0x00000000
+#define SDRAM_DLCR_DLCS_MASK 0x07000000
+#define SDRAM_DLCR_DLCS_NOT_RUN 0x00000000
+#define SDRAM_DLCR_DLCS_IN_PROGRESS 0x01000000
+#define SDRAM_DLCR_DLCS_COMPLETE 0x02000000
+#define SDRAM_DLCR_DLCS_CONT_DONE 0x03000000
+#define SDRAM_DLCR_DLCS_ERROR 0x04000000
+#define SDRAM_DLCR_DLCV_MASK 0x000001FF
+#define SDRAM_DLCR_DLCV_ENCODE(n) ((((u32)(n))&0x1FF)<<0)
+#define SDRAM_DLCR_DLCV_DECODE(n) ((((u32)(n))>>0)&0x1FF)
+
+/*
+ * SDRAM Memory On Die Terimination Control Register
+ */
+#define SDRAM_MODT_ODTON_DISABLE PPC_REG_VAL(0, 0)
+#define SDRAM_MODT_ODTON_ENABLE PPC_REG_VAL(0, 1)
+#define SDRAM_MODT_EB1W_DISABLE PPC_REG_VAL(1, 0)
+#define SDRAM_MODT_EB1W_ENABLE PPC_REG_VAL(1, 1)
+#define SDRAM_MODT_EB1R_DISABLE PPC_REG_VAL(2, 0)
+#define SDRAM_MODT_EB1R_ENABLE PPC_REG_VAL(2, 1)
+#define SDRAM_MODT_EB0W_DISABLE PPC_REG_VAL(7, 0)
+#define SDRAM_MODT_EB0W_ENABLE PPC_REG_VAL(7, 1)
+#define SDRAM_MODT_EB0R_DISABLE PPC_REG_VAL(8, 0)
+#define SDRAM_MODT_EB0R_ENABLE PPC_REG_VAL(8, 1)
+
+/*
+ * SDRAM Controller On Die Termination Register
+ */
+#define SDRAM_CODT_ODT_ON PPC_REG_VAL(0, 1)
+#define SDRAM_CODT_ODT_OFF PPC_REG_VAL(0, 0)
+#define SDRAM_CODT_RK1W_ON PPC_REG_VAL(1, 1)
+#define SDRAM_CODT_RK1W_OFF PPC_REG_VAL(1, 0)
+#define SDRAM_CODT_RK1R_ON PPC_REG_VAL(2, 1)
+#define SDRAM_CODT_RK1R_OFF PPC_REG_VAL(2, 0)
+#define SDRAM_CODT_RK0W_ON PPC_REG_VAL(7, 1)
+#define SDRAM_CODT_RK0W_OFF PPC_REG_VAL(7, 0)
+#define SDRAM_CODT_RK0R_ON PPC_REG_VAL(8, 1)
+#define SDRAM_CODT_RK0R_OFF PPC_REG_VAL(8, 0)
+#define SDRAM_CODT_ODTSH_NORMAL PPC_REG_VAL(10, 0)
+#define SDRAM_CODT_ODTSH_REMOVE_ONE_AT_END PPC_REG_VAL(10, 1)
+#define SDRAM_CODT_ODTSH_ADD_ONE_AT_START PPC_REG_VAL(10, 2)
+#define SDRAM_CODT_ODTSH_SHIFT_ONE_EARLIER PPC_REG_VAL(10, 3)
+#define SDRAM_CODT_CODTZ_75OHM PPC_REG_VAL(11, 0)
+#define SDRAM_CODT_CKEG_ON PPC_REG_VAL(12, 1)
+#define SDRAM_CODT_CKEG_OFF PPC_REG_VAL(12, 0)
+#define SDRAM_CODT_CTLG_ON PPC_REG_VAL(13, 1)
+#define SDRAM_CODT_CTLG_OFF PPC_REG_VAL(13, 0)
+#define SDRAM_CODT_FBDG_ON PPC_REG_VAL(14, 1)
+#define SDRAM_CODT_FBDG_OFF PPC_REG_VAL(14, 0)
+#define SDRAM_CODT_FBRG_ON PPC_REG_VAL(15, 1)
+#define SDRAM_CODT_FBRG_OFF PPC_REG_VAL(15, 0)
+#define SDRAM_CODT_CKLZ_36OHM PPC_REG_VAL(18, 1)
+#define SDRAM_CODT_CKLZ_18OHM PPC_REG_VAL(18, 0)
+#define SDRAM_CODT_DQS_VOLTAGE_DDR_MASK PPC_REG_VAL(26, 1)
+#define SDRAM_CODT_DQS_2_5_V_DDR1 PPC_REG_VAL(26, 0)
+#define SDRAM_CODT_DQS_1_8_V_DDR2 PPC_REG_VAL(26, 1)
+#define SDRAM_CODT_DQS_MASK PPC_REG_VAL(27, 1)
+#define SDRAM_CODT_DQS_DIFFERENTIAL PPC_REG_VAL(27, 0)
+#define SDRAM_CODT_DQS_SINGLE_END PPC_REG_VAL(27, 1)
+#define SDRAM_CODT_CKSE_DIFFERENTIAL PPC_REG_VAL(28, 0)
+#define SDRAM_CODT_CKSE_SINGLE_END PPC_REG_VAL(28, 1)
+#define SDRAM_CODT_FEEBBACK_RCV_SINGLE_END PPC_REG_VAL(29, 1)
+#define SDRAM_CODT_FEEBBACK_DRV_SINGLE_END PPC_REG_VAL(30, 1)
+#define SDRAM_CODT_IO_HIZ PPC_REG_VAL(31, 0)
+#define SDRAM_CODT_IO_NMODE PPC_REG_VAL(31, 1)
+
+/*
+ * SDRAM Initialization Preload Register
+ */
+#define SDRAM_INITPLR_ENABLE PPC_REG_VAL(0, 1)
+#define SDRAM_INITPLR_DISABLE PPC_REG_VAL(0, 0)
+#define SDRAM_INITPLR_IMWT_MASK PPC_REG_VAL(8, 0xFF)
+#define SDRAM_INITPLR_IMWT_ENCODE(n) PPC_REG_VAL(8, \
+ (static_cast(u32, \
+ n)) \
+ & 0xFF)
+#define SDRAM_INITPLR_ICMD_MASK PPC_REG_VAL(12, 0x7)
+#define SDRAM_INITPLR_ICMD_ENCODE(n) PPC_REG_VAL(12, \
+ (static_cast(u32, \
+ n)) \
+ & 0x7)
+#define SDRAM_INITPLR_IBA_MASK PPC_REG_VAL(15, 0x7)
+#define SDRAM_INITPLR_IBA_ENCODE(n) PPC_REG_VAL(15, \
+ (static_cast(u32, \
+ n)) \
+ & 0x7)
+#define SDRAM_INITPLR_IMA_MASK PPC_REG_VAL(31, 0x7FFF)
+#define SDRAM_INITPLR_IMA_ENCODE(n) PPC_REG_VAL(31, \
+ (static_cast(u32, \
+ n)) \
+ & 0x7FFF)
+
+/*
+ * JEDEC DDR Initialization Commands
+ */
+#define JEDEC_CMD_NOP 7
+#define JEDEC_CMD_PRECHARGE 2
+#define JEDEC_CMD_REFRESH 1
+#define JEDEC_CMD_EMR 0
+#define JEDEC_CMD_READ 5
+#define JEDEC_CMD_WRITE 4
+
+/*
+ * JEDEC Precharge Command Memory Address Arguments
+ */
+#define JEDEC_MA_PRECHARGE_ONE (0 << 10)
+#define JEDEC_MA_PRECHARGE_ALL (1 << 10)
+
+/*
+ * JEDEC DDR EMR Command Bank Address Arguments
+ */
+#define JEDEC_BA_MR 0
+#define JEDEC_BA_EMR 1
+#define JEDEC_BA_EMR2 2
+#define JEDEC_BA_EMR3 3
+
+/*
+ * JEDEC DDR Mode Register
+ */
+#define JEDEC_MA_MR_PDMODE_FAST_EXIT (0 << 12)
+#define JEDEC_MA_MR_PDMODE_SLOW_EXIT (1 << 12)
+#define JEDEC_MA_MR_WR_MASK (0x7 << 9)
+#define JEDEC_MA_MR_WR_DDR1 (0x0 << 9)
+#define JEDEC_MA_MR_WR_DDR2_2_CYC (0x1 << 9)
+#define JEDEC_MA_MR_WR_DDR2_3_CYC (0x2 << 9)
+#define JEDEC_MA_MR_WR_DDR2_4_CYC (0x3 << 9)
+#define JEDEC_MA_MR_WR_DDR2_5_CYC (0x4 << 9)
+#define JEDEC_MA_MR_WR_DDR2_6_CYC (0x5 << 9)
+#define JEDEC_MA_MR_DLL_RESET (1 << 8)
+#define JEDEC_MA_MR_MODE_NORMAL (0 << 8)
+#define JEDEC_MA_MR_MODE_TEST (1 << 8)
+#define JEDEC_MA_MR_CL_MASK (0x7 << 4)
+#define JEDEC_MA_MR_CL_DDR1_2_0_CLK (0x2 << 4)
+#define JEDEC_MA_MR_CL_DDR1_2_5_CLK (0x6 << 4)
+#define JEDEC_MA_MR_CL_DDR1_3_0_CLK (0x3 << 4)
+#define JEDEC_MA_MR_CL_DDR2_2_0_CLK (0x2 << 4)
+#define JEDEC_MA_MR_CL_DDR2_3_0_CLK (0x3 << 4)
+#define JEDEC_MA_MR_CL_DDR2_4_0_CLK (0x4 << 4)
+#define JEDEC_MA_MR_CL_DDR2_5_0_CLK (0x5 << 4)
+#define JEDEC_MA_MR_CL_DDR2_6_0_CLK (0x6 << 4)
+#define JEDEC_MA_MR_CL_DDR2_7_0_CLK (0x7 << 4)
+#define JEDEC_MA_MR_BTYP_SEQUENTIAL (0 << 3)
+#define JEDEC_MA_MR_BTYP_INTERLEAVED (1 << 3)
+#define JEDEC_MA_MR_BLEN_MASK (0x7 << 0)
+#define JEDEC_MA_MR_BLEN_4 (2 << 0)
+#define JEDEC_MA_MR_BLEN_8 (3 << 0)
+
+/*
+ * JEDEC DDR Extended Mode Register
+ */
+#define JEDEC_MA_EMR_OUTPUT_MASK (1 << 12)
+#define JEDEC_MA_EMR_OUTPUT_ENABLE (0 << 12)
+#define JEDEC_MA_EMR_OUTPUT_DISABLE (1 << 12)
+#define JEDEC_MA_EMR_RQDS_MASK (1 << 11)
+#define JEDEC_MA_EMR_RDQS_DISABLE (0 << 11)
+#define JEDEC_MA_EMR_RDQS_ENABLE (1 << 11)
+#define JEDEC_MA_EMR_DQS_MASK (1 << 10)
+#define JEDEC_MA_EMR_DQS_DISABLE (1 << 10)
+#define JEDEC_MA_EMR_DQS_ENABLE (0 << 10)
+#define JEDEC_MA_EMR_OCD_MASK (0x7 << 7)
+#define JEDEC_MA_EMR_OCD_EXIT (0 << 7)
+#define JEDEC_MA_EMR_OCD_ENTER (7 << 7)
+#define JEDEC_MA_EMR_AL_DDR1_0_CYC (0 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_1_CYC (1 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_2_CYC (2 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_3_CYC (3 << 3)
+#define JEDEC_MA_EMR_AL_DDR2_4_CYC (4 << 3)
+#define JEDEC_MA_EMR_RTT_MASK (0x11 << 2)
+#define JEDEC_MA_EMR_RTT_DISABLED (0x00 << 2)
+#define JEDEC_MA_EMR_RTT_75OHM (0x01 << 2)
+#define JEDEC_MA_EMR_RTT_150OHM (0x10 << 2)
+#define JEDEC_MA_EMR_RTT_50OHM (0x11 << 2)
+#define JEDEC_MA_EMR_ODS_MASK (1 << 1)
+#define JEDEC_MA_EMR_ODS_NORMAL (0 << 1)
+#define JEDEC_MA_EMR_ODS_WEAK (1 << 1)
+#define JEDEC_MA_EMR_DLL_MASK (1 << 0)
+#define JEDEC_MA_EMR_DLL_ENABLE (0 << 0)
+#define JEDEC_MA_EMR_DLL_DISABLE (1 << 0)
+
+/*
+ * JEDEC DDR Extended Mode Register 2
+ */
+#define JEDEC_MA_EMR2_TEMP_COMMERCIAL (0 << 7)
+#define JEDEC_MA_EMR2_TEMP_INDUSTRIAL (1 << 7)
+
+/*
+ * SDRAM Mode Register (Corresponds 1:1 w/ JEDEC Mode Register)
+ */
+#define SDRAM_MMODE_WR_MASK JEDEC_MA_MR_WR_MASK
+#define SDRAM_MMODE_WR_DDR1 JEDEC_MA_MR_WR_DDR1
+#define SDRAM_MMODE_WR_DDR2_2_CYC JEDEC_MA_MR_WR_DDR2_2_CYC
+#define SDRAM_MMODE_WR_DDR2_3_CYC JEDEC_MA_MR_WR_DDR2_3_CYC
+#define SDRAM_MMODE_WR_DDR2_4_CYC JEDEC_MA_MR_WR_DDR2_4_CYC
+#define SDRAM_MMODE_WR_DDR2_5_CYC JEDEC_MA_MR_WR_DDR2_5_CYC
+#define SDRAM_MMODE_WR_DDR2_6_CYC JEDEC_MA_MR_WR_DDR2_6_CYC
+#define SDRAM_MMODE_DCL_MASK JEDEC_MA_MR_CL_MASK
+#define SDRAM_MMODE_DCL_DDR1_2_0_CLK JEDEC_MA_MR_CL_DDR1_2_0_CLK
+#define SDRAM_MMODE_DCL_DDR1_2_5_CLK JEDEC_MA_MR_CL_DDR1_2_5_CLK
+#define SDRAM_MMODE_DCL_DDR1_3_0_CLK JEDEC_MA_MR_CL_DDR1_3_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_2_0_CLK JEDEC_MA_MR_CL_DDR2_2_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_3_0_CLK JEDEC_MA_MR_CL_DDR2_3_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_4_0_CLK JEDEC_MA_MR_CL_DDR2_4_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_5_0_CLK JEDEC_MA_MR_CL_DDR2_5_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_6_0_CLK JEDEC_MA_MR_CL_DDR2_6_0_CLK
+#define SDRAM_MMODE_DCL_DDR2_7_0_CLK JEDEC_MA_MR_CL_DDR2_7_0_CLK
+#define SDRAM_MMODE_BTYP_SEQUENTIAL JEDEC_MA_MR_BTYP_SEQUENTIAL
+#define SDRAM_MMODE_BTYP_INTERLEAVED JEDEC_MA_MR_BTYP_INTERLEAVED
+#define SDRAM_MMODE_BLEN_MASK JEDEC_MA_MR_BLEN_MASK
+#define SDRAM_MMODE_BLEN_4 JEDEC_MA_MR_BLEN_4
+#define SDRAM_MMODE_BLEN_8 JEDEC_MA_MR_BLEN_8
+
+/*
+ * SDRAM Extended Mode Register (Corresponds 1:1 w/ JEDEC Extended
+ * Mode Register)
+ */
+#define SDRAM_MEMODE_QOFF_MASK JEDEC_MA_EMR_OUTPUT_MASK
+#define SDRAM_MEMODE_QOFF_DISABLE JEDEC_MA_EMR_OUTPUT_DISABLE
+#define SDRAM_MEMODE_QOFF_ENABLE JEDEC_MA_EMR_OUTPUT_ENABLE
+#define SDRAM_MEMODE_RDQS_MASK JEDEC_MA_EMR_RQDS_MASK
+#define SDRAM_MEMODE_RDQS_DISABLE JEDEC_MA_EMR_RDQS_DISABLE
+#define SDRAM_MEMODE_RDQS_ENABLE JEDEC_MA_EMR_RDQS_ENABLE
+#define SDRAM_MEMODE_DQS_MASK JEDEC_MA_EMR_DQS_MASK
+#define SDRAM_MEMODE_DQS_DISABLE JEDEC_MA_EMR_DQS_DISABLE
+#define SDRAM_MEMODE_DQS_ENABLE JEDEC_MA_EMR_DQS_ENABLE
+#define SDRAM_MEMODE_AL_DDR1_0_CYC JEDEC_MA_EMR_AL_DDR1_0_CYC
+#define SDRAM_MEMODE_AL_DDR2_1_CYC JEDEC_MA_EMR_AL_DDR2_1_CYC
+#define SDRAM_MEMODE_AL_DDR2_2_CYC JEDEC_MA_EMR_AL_DDR2_2_CYC
+#define SDRAM_MEMODE_AL_DDR2_3_CYC JEDEC_MA_EMR_AL_DDR2_3_CYC
+#define SDRAM_MEMODE_AL_DDR2_4_CYC JEDEC_MA_EMR_AL_DDR2_4_CYC
+#define SDRAM_MEMODE_RTT_MASK JEDEC_MA_EMR_RTT_MASK
+#define SDRAM_MEMODE_RTT_DISABLED JEDEC_MA_EMR_RTT_DISABLED
+#define SDRAM_MEMODE_RTT_75OHM JEDEC_MA_EMR_RTT_75OHM
+#define SDRAM_MEMODE_RTT_150OHM JEDEC_MA_EMR_RTT_150OHM
+#define SDRAM_MEMODE_RTT_50OHM JEDEC_MA_EMR_RTT_50OHM
+#define SDRAM_MEMODE_DIC_MASK JEDEC_MA_EMR_ODS_MASK
+#define SDRAM_MEMODE_DIC_NORMAL JEDEC_MA_EMR_ODS_NORMAL
+#define SDRAM_MEMODE_DIC_WEAK JEDEC_MA_EMR_ODS_WEAK
+#define SDRAM_MEMODE_DLL_MASK JEDEC_MA_EMR_DLL_MASK
+#define SDRAM_MEMODE_DLL_DISABLE JEDEC_MA_EMR_DLL_DISABLE
+#define SDRAM_MEMODE_DLL_ENABLE JEDEC_MA_EMR_DLL_ENABLE
+
+/*
+ * SDRAM Clock Timing Register
+ */
+#define SDRAM_CLKTR_CLKP_MASK 0xC0000000
+#define SDRAM_CLKTR_CLKP_0_DEG 0x00000000
+#define SDRAM_CLKTR_CLKP_180_DEG_ADV 0x80000000
+#define SDRAM_CLKTR_CLKP_90_DEG_ADV 0x40000000
+#define SDRAM_CLKTR_CLKP_270_DEG_ADV 0xC0000000
+
+/*
+ * SDRAM Write Timing Register
+ */
+#define SDRAM_WRDTR_LLWP_MASK 0x10000000
+#define SDRAM_WRDTR_LLWP_DIS 0x10000000
+#define SDRAM_WRDTR_LLWP_1_CYC 0x00000000
+#define SDRAM_WRDTR_WTR_MASK 0x0E000000
+#define SDRAM_WRDTR_WTR_0_DEG 0x06000000
+#define SDRAM_WRDTR_WTR_90_DEG_ADV 0x04000000
+#define SDRAM_WRDTR_WTR_180_DEG_ADV 0x02000000
+#define SDRAM_WRDTR_WTR_270_DEG_ADV 0x00000000
+
+/*
+ * SDRAM SDTR1 Options
+ */
+#define SDRAM_SDTR1_LDOF_MASK 0x80000000
+#define SDRAM_SDTR1_LDOF_1_CLK 0x00000000
+#define SDRAM_SDTR1_LDOF_2_CLK 0x80000000
+#define SDRAM_SDTR1_RTW_MASK 0x00F00000
+#define SDRAM_SDTR1_RTW_2_CLK 0x00200000
+#define SDRAM_SDTR1_RTW_3_CLK 0x00300000
+#define SDRAM_SDTR1_WTWO_MASK 0x000F0000
+#define SDRAM_SDTR1_WTWO_0_CLK 0x00000000
+#define SDRAM_SDTR1_WTWO_1_CLK 0x00010000
+#define SDRAM_SDTR1_RTRO_MASK 0x0000F000
+#define SDRAM_SDTR1_RTRO_1_CLK 0x00001000
+#define SDRAM_SDTR1_RTRO_2_CLK 0x00002000
+
+/*
+ * SDRAM SDTR2 Options
+ */
+#define SDRAM_SDTR2_RCD_MASK 0xF0000000
+#define SDRAM_SDTR2_RCD_1_CLK 0x10000000
+#define SDRAM_SDTR2_RCD_2_CLK 0x20000000
+#define SDRAM_SDTR2_RCD_3_CLK 0x30000000
+#define SDRAM_SDTR2_RCD_4_CLK 0x40000000
+#define SDRAM_SDTR2_RCD_5_CLK 0x50000000
+#define SDRAM_SDTR2_WTR_MASK 0x0F000000
+#define SDRAM_SDTR2_WTR_1_CLK 0x01000000
+#define SDRAM_SDTR2_WTR_2_CLK 0x02000000
+#define SDRAM_SDTR2_WTR_3_CLK 0x03000000
+#define SDRAM_SDTR2_WTR_4_CLK 0x04000000
+#define SDRAM_SDTR3_WTR_ENCODE(n) ((((u32)(n))&0xF)<<24)
+#define SDRAM_SDTR2_XSNR_MASK 0x00FF0000
+#define SDRAM_SDTR2_XSNR_8_CLK 0x00080000
+#define SDRAM_SDTR2_XSNR_16_CLK 0x00100000
+#define SDRAM_SDTR2_XSNR_32_CLK 0x00200000
+#define SDRAM_SDTR2_XSNR_64_CLK 0x00400000
+#define SDRAM_SDTR2_WPC_MASK 0x0000F000
+#define SDRAM_SDTR2_WPC_2_CLK 0x00002000
+#define SDRAM_SDTR2_WPC_3_CLK 0x00003000
+#define SDRAM_SDTR2_WPC_4_CLK 0x00004000
+#define SDRAM_SDTR2_WPC_5_CLK 0x00005000
+#define SDRAM_SDTR2_WPC_6_CLK 0x00006000
+#define SDRAM_SDTR3_WPC_ENCODE(n) ((((u32)(n))&0xF)<<12)
+#define SDRAM_SDTR2_RPC_MASK 0x00000F00
+#define SDRAM_SDTR2_RPC_2_CLK 0x00000200
+#define SDRAM_SDTR2_RPC_3_CLK 0x00000300
+#define SDRAM_SDTR2_RPC_4_CLK 0x00000400
+#define SDRAM_SDTR2_RP_MASK 0x000000F0
+#define SDRAM_SDTR2_RP_3_CLK 0x00000030
+#define SDRAM_SDTR2_RP_4_CLK 0x00000040
+#define SDRAM_SDTR2_RP_5_CLK 0x00000050
+#define SDRAM_SDTR2_RP_6_CLK 0x00000060
+#define SDRAM_SDTR2_RP_7_CLK 0x00000070
+#define SDRAM_SDTR2_RRD_MASK 0x0000000F
+#define SDRAM_SDTR2_RRD_2_CLK 0x00000002
+#define SDRAM_SDTR2_RRD_3_CLK 0x00000003
+
+/*
+ * SDRAM SDTR3 Options
+ */
+#define SDRAM_SDTR3_RAS_MASK 0x1F000000
+#define SDRAM_SDTR3_RAS_ENCODE(n) ((((u32)(n))&0x1F)<<24)
+#define SDRAM_SDTR3_RC_MASK 0x001F0000
+#define SDRAM_SDTR3_RC_ENCODE(n) ((((u32)(n))&0x1F)<<16)
+#define SDRAM_SDTR3_XCS_MASK 0x00001F00
+#define SDRAM_SDTR3_XCS 0x00000D00
+#define SDRAM_SDTR3_RFC_MASK 0x0000003F
+#define SDRAM_SDTR3_RFC_ENCODE(n) ((((u32)(n))&0x3F)<<0)
+
+/*
+ * ECC Error Status
+ */
+#define SDRAM_ECCES_MASK PPC_REG_VAL(21, 0x3FFFFF)
+#define SDRAM_ECCES_BNCE_MASK PPC_REG_VAL(15, 0xFFFF)
+#define SDRAM_ECCES_BNCE_ENCODE(lane) PPC_REG_VAL(((lane) & 0xF), 1)
+#define SDRAM_ECCES_CKBER_MASK PPC_REG_VAL(17, 0x3)
+#define SDRAM_ECCES_CKBER_NONE PPC_REG_VAL(17, 0)
+#define SDRAM_ECCES_CKBER_16_ECC_0_3 PPC_REG_VAL(17, 2)
+#define SDRAM_ECCES_CKBER_32_ECC_0_3 PPC_REG_VAL(17, 1)
+#define SDRAM_ECCES_CKBER_32_ECC_4_8 PPC_REG_VAL(17, 2)
+#define SDRAM_ECCES_CKBER_32_ECC_0_8 PPC_REG_VAL(17, 3)
+#define SDRAM_ECCES_CE PPC_REG_VAL(18, 1)
+#define SDRAM_ECCES_UE PPC_REG_VAL(19, 1)
+#define SDRAM_ECCES_BKNER_MASK PPC_REG_VAL(21, 0x3)
+#define SDRAM_ECCES_BK0ER PPC_REG_VAL(20, 1)
+#define SDRAM_ECCES_BK1ER PPC_REG_VAL(21, 1)
+
+/*
+ * Memory Bank 0-1 configuration
+ */
+#define SDRAM_BXCF_M_AM_MASK 0x00000F00 /* Addressing mode */
+#define SDRAM_BXCF_M_AM_0 0x00000000 /* Mode 0 */
+#define SDRAM_BXCF_M_AM_1 0x00000100 /* Mode 1 */
+#define SDRAM_BXCF_M_AM_2 0x00000200 /* Mode 2 */
+#define SDRAM_BXCF_M_AM_3 0x00000300 /* Mode 3 */
+#define SDRAM_BXCF_M_AM_4 0x00000400 /* Mode 4 */
+#define SDRAM_BXCF_M_AM_5 0x00000500 /* Mode 5 */
+#define SDRAM_BXCF_M_AM_6 0x00000600 /* Mode 6 */
+#define SDRAM_BXCF_M_AM_7 0x00000700 /* Mode 7 */
+#define SDRAM_BXCF_M_AM_8 0x00000800 /* Mode 8 */
+#define SDRAM_BXCF_M_AM_9 0x00000900 /* Mode 9 */
+#define SDRAM_BXCF_M_BE_MASK 0x00000001 /* Memory Bank Enable */
+#define SDRAM_BXCF_M_BE_DISABLE 0x00000000 /* Memory Bank Enable */
+#define SDRAM_BXCF_M_BE_ENABLE 0x00000001 /* Memory Bank Enable */
+
+#define SDRAM_RTSR_TRK1SM_MASK 0xC0000000 /* Tracking State Mach 1*/
+#define SDRAM_RTSR_TRK1SM_ATBASE 0x00000000 /* atbase state */
+#define SDRAM_RTSR_TRK1SM_MISSED 0x40000000 /* missed state */
+#define SDRAM_RTSR_TRK1SM_ATPLS1 0x80000000 /* atpls1 state */
+#define SDRAM_RTSR_TRK1SM_RESET 0xC0000000 /* reset state */
+
+#endif /* CONFIG_SDRAM_PPC4xx_IBM_DDR2 */
+
+#if defined(CONFIG_SDRAM_PPC4xx_DENALI_DDR2)
+/*
+ * SDRAM Controller
+ */
+#define DDR0_00 0x00
+#define DDR0_00_INT_ACK_MASK 0x7F000000 /* Write only */
+#define DDR0_00_INT_ACK_ALL 0x7F000000
+#define DDR0_00_INT_ACK_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_00_INT_ACK_DECODE(n) ((((u32)(n))>>24)&0x7F)
+/* Status */
+#define DDR0_00_INT_STATUS_MASK 0x00FF0000 /* Read only */
+/* Bit0. A single access outside the defined PHYSICAL memory space detected. */
+#define DDR0_00_INT_STATUS_BIT0 0x00010000
+/* Bit1. Multiple accesses outside the defined PHYSICAL memory space detected. */
+#define DDR0_00_INT_STATUS_BIT1 0x00020000
+/* Bit2. Single correctable ECC event detected */
+#define DDR0_00_INT_STATUS_BIT2 0x00040000
+/* Bit3. Multiple correctable ECC events detected. */
+#define DDR0_00_INT_STATUS_BIT3 0x00080000
+/* Bit4. Single uncorrectable ECC event detected. */
+#define DDR0_00_INT_STATUS_BIT4 0x00100000
+/* Bit5. Multiple uncorrectable ECC events detected. */
+#define DDR0_00_INT_STATUS_BIT5 0x00200000
+/* Bit6. DRAM initialization complete. */
+#define DDR0_00_INT_STATUS_BIT6 0x00400000
+/* Bit7. Logical OR of all lower bits. */
+#define DDR0_00_INT_STATUS_BIT7 0x00800000
+
+#define DDR0_00_INT_STATUS_ENCODE(n) ((((u32)(n))&0xFF)<<16)
+#define DDR0_00_INT_STATUS_DECODE(n) ((((u32)(n))>>16)&0xFF)
+#define DDR0_00_DLL_INCREMENT_MASK 0x00007F00
+#define DDR0_00_DLL_INCREMENT_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_00_DLL_INCREMENT_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_00_DLL_START_POINT_MASK 0x0000007F
+#define DDR0_00_DLL_START_POINT_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_00_DLL_START_POINT_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_01 0x01
+#define DDR0_01_PLB0_DB_CS_LOWER_MASK 0x1F000000
+#define DDR0_01_PLB0_DB_CS_LOWER_ENCODE(n) ((((u32)(n))&0x1F)<<24)
+#define DDR0_01_PLB0_DB_CS_LOWER_DECODE(n) ((((u32)(n))>>24)&0x1F)
+#define DDR0_01_PLB0_DB_CS_UPPER_MASK 0x001F0000
+#define DDR0_01_PLB0_DB_CS_UPPER_ENCODE(n) ((((u32)(n))&0x1F)<<16)
+#define DDR0_01_PLB0_DB_CS_UPPER_DECODE(n) ((((u32)(n))>>16)&0x1F)
+#define DDR0_01_OUT_OF_RANGE_TYPE_MASK 0x00000700 /* Read only */
+#define DDR0_01_OUT_OF_RANGE_TYPE_ENCODE(n) ((((u32)(n))&0x7)<<8)
+#define DDR0_01_OUT_OF_RANGE_TYPE_DECODE(n) ((((u32)(n))>>8)&0x7)
+#define DDR0_01_INT_MASK_MASK 0x000000FF
+#define DDR0_01_INT_MASK_ENCODE(n) ((((u32)(n))&0xFF)<<0)
+#define DDR0_01_INT_MASK_DECODE(n) ((((u32)(n))>>0)&0xFF)
+#define DDR0_01_INT_MASK_ALL_ON 0x000000FF
+#define DDR0_01_INT_MASK_ALL_OFF 0x00000000
+
+#define DDR0_02 0x02
+#define DDR0_02_MAX_CS_REG_MASK 0x02000000 /* Read only */
+#define DDR0_02_MAX_CS_REG_ENCODE(n) ((((u32)(n))&0x2)<<24)
+#define DDR0_02_MAX_CS_REG_DECODE(n) ((((u32)(n))>>24)&0x2)
+#define DDR0_02_MAX_COL_REG_MASK 0x000F0000 /* Read only */
+#define DDR0_02_MAX_COL_REG_ENCODE(n) ((((u32)(n))&0xF)<<16)
+#define DDR0_02_MAX_COL_REG_DECODE(n) ((((u32)(n))>>16)&0xF)
+#define DDR0_02_MAX_ROW_REG_MASK 0x00000F00 /* Read only */
+#define DDR0_02_MAX_ROW_REG_ENCODE(n) ((((u32)(n))&0xF)<<8)
+#define DDR0_02_MAX_ROW_REG_DECODE(n) ((((u32)(n))>>8)&0xF)
+#define DDR0_02_START_MASK 0x00000001
+#define DDR0_02_START_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_02_START_DECODE(n) ((((u32)(n))>>0)&0x1)
+#define DDR0_02_START_OFF 0x00000000
+#define DDR0_02_START_ON 0x00000001
+
+#define DDR0_03 0x03
+#define DDR0_03_BSTLEN_MASK 0x07000000
+#define DDR0_03_BSTLEN_ENCODE(n) ((((u32)(n))&0x7)<<24)
+#define DDR0_03_BSTLEN_DECODE(n) ((((u32)(n))>>24)&0x7)
+#define DDR0_03_CASLAT_MASK 0x00070000
+#define DDR0_03_CASLAT_ENCODE(n) ((((u32)(n))&0x7)<<16)
+#define DDR0_03_CASLAT_DECODE(n) ((((u32)(n))>>16)&0x7)
+#define DDR0_03_CASLAT_LIN_MASK 0x00000F00
+#define DDR0_03_CASLAT_LIN_ENCODE(n) ((((u32)(n))&0xF)<<8)
+#define DDR0_03_CASLAT_LIN_DECODE(n) ((((u32)(n))>>8)&0xF)
+#define DDR0_03_INITAREF_MASK 0x0000000F
+#define DDR0_03_INITAREF_ENCODE(n) ((((u32)(n))&0xF)<<0)
+#define DDR0_03_INITAREF_DECODE(n) ((((u32)(n))>>0)&0xF)
+
+#define DDR0_04 0x04
+#define DDR0_04_TRC_MASK 0x1F000000
+#define DDR0_04_TRC_ENCODE(n) ((((u32)(n))&0x1F)<<24)
+#define DDR0_04_TRC_DECODE(n) ((((u32)(n))>>24)&0x1F)
+#define DDR0_04_TRRD_MASK 0x00070000
+#define DDR0_04_TRRD_ENCODE(n) ((((u32)(n))&0x7)<<16)
+#define DDR0_04_TRRD_DECODE(n) ((((u32)(n))>>16)&0x7)
+#define DDR0_04_TRTP_MASK 0x00000700
+#define DDR0_04_TRTP_ENCODE(n) ((((u32)(n))&0x7)<<8)
+#define DDR0_04_TRTP_DECODE(n) ((((u32)(n))>>8)&0x7)
+
+#define DDR0_05 0x05
+#define DDR0_05_TMRD_MASK 0x1F000000
+#define DDR0_05_TMRD_ENCODE(n) ((((u32)(n))&0x1F)<<24)
+#define DDR0_05_TMRD_DECODE(n) ((((u32)(n))>>24)&0x1F)
+#define DDR0_05_TEMRS_MASK 0x00070000
+#define DDR0_05_TEMRS_ENCODE(n) ((((u32)(n))&0x7)<<16)
+#define DDR0_05_TEMRS_DECODE(n) ((((u32)(n))>>16)&0x7)
+#define DDR0_05_TRP_MASK 0x00000F00
+#define DDR0_05_TRP_ENCODE(n) ((((u32)(n))&0xF)<<8)
+#define DDR0_05_TRP_DECODE(n) ((((u32)(n))>>8)&0xF)
+#define DDR0_05_TRAS_MIN_MASK 0x000000FF
+#define DDR0_05_TRAS_MIN_ENCODE(n) ((((u32)(n))&0xFF)<<0)
+#define DDR0_05_TRAS_MIN_DECODE(n) ((((u32)(n))>>0)&0xFF)
+
+#define DDR0_06 0x06
+#define DDR0_06_WRITEINTERP_MASK 0x01000000
+#define DDR0_06_WRITEINTERP_ENCODE(n) ((((u32)(n))&0x1)<<24)
+#define DDR0_06_WRITEINTERP_DECODE(n) ((((u32)(n))>>24)&0x1)
+#define DDR0_06_TWTR_MASK 0x00070000
+#define DDR0_06_TWTR_ENCODE(n) ((((u32)(n))&0x7)<<16)
+#define DDR0_06_TWTR_DECODE(n) ((((u32)(n))>>16)&0x7)
+#define DDR0_06_TDLL_MASK 0x0000FF00
+#define DDR0_06_TDLL_ENCODE(n) ((((u32)(n))&0xFF)<<8)
+#define DDR0_06_TDLL_DECODE(n) ((((u32)(n))>>8)&0xFF)
+#define DDR0_06_TRFC_MASK 0x0000007F
+#define DDR0_06_TRFC_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_06_TRFC_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_07 0x07
+#define DDR0_07_NO_CMD_INIT_MASK 0x01000000
+#define DDR0_07_NO_CMD_INIT_ENCODE(n) ((((u32)(n))&0x1)<<24)
+#define DDR0_07_NO_CMD_INIT_DECODE(n) ((((u32)(n))>>24)&0x1)
+#define DDR0_07_TFAW_MASK 0x001F0000
+#define DDR0_07_TFAW_ENCODE(n) ((((u32)(n))&0x1F)<<16)
+#define DDR0_07_TFAW_DECODE(n) ((((u32)(n))>>16)&0x1F)
+#define DDR0_07_AUTO_REFRESH_MODE_MASK 0x00000100
+#define DDR0_07_AUTO_REFRESH_MODE_ENCODE(n) ((((u32)(n))&0x1)<<8)
+#define DDR0_07_AUTO_REFRESH_MODE_DECODE(n) ((((u32)(n))>>8)&0x1)
+#define DDR0_07_AREFRESH_MASK 0x00000001
+#define DDR0_07_AREFRESH_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_07_AREFRESH_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_08 0x08
+#define DDR0_08_WRLAT_MASK 0x07000000
+#define DDR0_08_WRLAT_ENCODE(n) ((((u32)(n))&0x7)<<24)
+#define DDR0_08_WRLAT_DECODE(n) ((((u32)(n))>>24)&0x7)
+#define DDR0_08_TCPD_MASK 0x00FF0000
+#define DDR0_08_TCPD_ENCODE(n) ((((u32)(n))&0xFF)<<16)
+#define DDR0_08_TCPD_DECODE(n) ((((u32)(n))>>16)&0xFF)
+#define DDR0_08_DQS_N_EN_MASK 0x00000100
+#define DDR0_08_DQS_N_EN_ENCODE(n) ((((u32)(n))&0x1)<<8)
+#define DDR0_08_DQS_N_EN_DECODE(n) ((((u32)(n))>>8)&0x1)
+#define DDR0_08_DDRII_SDRAM_MODE_MASK 0x00000001
+#define DDR0_08_DDRII_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_08_DDRII_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_09 0x09
+#define DDR0_09_OCD_ADJUST_PDN_CS_0_MASK 0x1F000000
+#define DDR0_09_OCD_ADJUST_PDN_CS_0_ENCODE(n) ((((u32)(n))&0x1F)<<24)
+#define DDR0_09_OCD_ADJUST_PDN_CS_0_DECODE(n) ((((u32)(n))>>24)&0x1F)
+#define DDR0_09_RTT_0_MASK 0x00030000
+#define DDR0_09_RTT_0_ENCODE(n) ((((u32)(n))&0x3)<<16)
+#define DDR0_09_RTT_0_DECODE(n) ((((u32)(n))>>16)&0x3)
+#define DDR0_09_WR_DQS_SHIFT_BYPASS_MASK 0x00007F00
+#define DDR0_09_WR_DQS_SHIFT_BYPASS_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_09_WR_DQS_SHIFT_BYPASS_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_09_WR_DQS_SHIFT_MASK 0x0000007F
+#define DDR0_09_WR_DQS_SHIFT_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_09_WR_DQS_SHIFT_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_10 0x0A
+#define DDR0_10_WRITE_MODEREG_MASK 0x00010000 /* Write only */
+#define DDR0_10_WRITE_MODEREG_ENCODE(n) ((((u32)(n))&0x1)<<16)
+#define DDR0_10_WRITE_MODEREG_DECODE(n) ((((u32)(n))>>16)&0x1)
+#define DDR0_10_CS_MAP_MASK 0x00000300
+#define DDR0_10_CS_MAP_NO_MEM 0x00000000
+#define DDR0_10_CS_MAP_RANK0_INSTALLED 0x00000100
+#define DDR0_10_CS_MAP_RANK1_INSTALLED 0x00000200
+#define DDR0_10_CS_MAP_ENCODE(n) ((((u32)(n))&0x3)<<8)
+#define DDR0_10_CS_MAP_DECODE(n) ((((u32)(n))>>8)&0x3)
+#define DDR0_10_OCD_ADJUST_PUP_CS_0_MASK 0x0000001F
+#define DDR0_10_OCD_ADJUST_PUP_CS_0_ENCODE(n) ((((u32)(n))&0x1F)<<0)
+#define DDR0_10_OCD_ADJUST_PUP_CS_0_DECODE(n) ((((u32)(n))>>0)&0x1F)
+
+#define DDR0_11 0x0B
+#define DDR0_11_SREFRESH_MASK 0x01000000
+#define DDR0_11_SREFRESH_ENCODE(n) ((((u32)(n))&0x1)<<24)
+#define DDR0_11_SREFRESH_DECODE(n) ((((u32)(n))>>24)&0x1F)
+#define DDR0_11_TXSNR_MASK 0x00FF0000
+#define DDR0_11_TXSNR_ENCODE(n) ((((u32)(n))&0xFF)<<16)
+#define DDR0_11_TXSNR_DECODE(n) ((((u32)(n))>>16)&0xFF)
+#define DDR0_11_TXSR_MASK 0x0000FF00
+#define DDR0_11_TXSR_ENCODE(n) ((((u32)(n))&0xFF)<<8)
+#define DDR0_11_TXSR_DECODE(n) ((((u32)(n))>>8)&0xFF)
+
+#define DDR0_12 0x0C
+#define DDR0_12_TCKE_MASK 0x0000007
+#define DDR0_12_TCKE_ENCODE(n) ((((u32)(n))&0x7)<<0)
+#define DDR0_12_TCKE_DECODE(n) ((((u32)(n))>>0)&0x7)
+
+#define DDR0_14 0x0E
+#define DDR0_14_DLL_BYPASS_MODE_MASK 0x01000000
+#define DDR0_14_DLL_BYPASS_MODE_ENCODE(n) ((((u32)(n))&0x1)<<24)
+#define DDR0_14_DLL_BYPASS_MODE_DECODE(n) ((((u32)(n))>>24)&0x1)
+#define DDR0_14_REDUC_MASK 0x00010000
+#define DDR0_14_REDUC_64BITS 0x00000000
+#define DDR0_14_REDUC_32BITS 0x00010000
+#define DDR0_14_REDUC_ENCODE(n) ((((u32)(n))&0x1)<<16)
+#define DDR0_14_REDUC_DECODE(n) ((((u32)(n))>>16)&0x1)
+#define DDR0_14_REG_DIMM_ENABLE_MASK 0x00000100
+#define DDR0_14_REG_DIMM_ENABLE_ENCODE(n) ((((u32)(n))&0x1)<<8)
+#define DDR0_14_REG_DIMM_ENABLE_DECODE(n) ((((u32)(n))>>8)&0x1)
+
+#define DDR0_17 0x11
+#define DDR0_17_DLL_DQS_DELAY_0_MASK 0x7F000000
+#define DDR0_17_DLL_DQS_DELAY_0_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_17_DLL_DQS_DELAY_0_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_17_DLLLOCKREG_MASK 0x00010000 /* Read only */
+#define DDR0_17_DLLLOCKREG_LOCKED 0x00010000
+#define DDR0_17_DLLLOCKREG_UNLOCKED 0x00000000
+#define DDR0_17_DLLLOCKREG_ENCODE(n) ((((u32)(n))&0x1)<<16)
+#define DDR0_17_DLLLOCKREG_DECODE(n) ((((u32)(n))>>16)&0x1)
+#define DDR0_17_DLL_LOCK_MASK 0x00007F00 /* Read only */
+#define DDR0_17_DLL_LOCK_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_17_DLL_LOCK_DECODE(n) ((((u32)(n))>>8)&0x7F)
+
+#define DDR0_18 0x12
+#define DDR0_18_DLL_DQS_DELAY_X_MASK 0x7F7F7F7F
+#define DDR0_18_DLL_DQS_DELAY_4_MASK 0x7F000000
+#define DDR0_18_DLL_DQS_DELAY_4_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_18_DLL_DQS_DELAY_4_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_18_DLL_DQS_DELAY_3_MASK 0x007F0000
+#define DDR0_18_DLL_DQS_DELAY_3_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_18_DLL_DQS_DELAY_3_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_18_DLL_DQS_DELAY_2_MASK 0x00007F00
+#define DDR0_18_DLL_DQS_DELAY_2_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_18_DLL_DQS_DELAY_2_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_18_DLL_DQS_DELAY_1_MASK 0x0000007F
+#define DDR0_18_DLL_DQS_DELAY_1_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_18_DLL_DQS_DELAY_1_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_19 0x13
+#define DDR0_19_DLL_DQS_DELAY_X_MASK 0x7F7F7F7F
+#define DDR0_19_DLL_DQS_DELAY_8_MASK 0x7F000000
+#define DDR0_19_DLL_DQS_DELAY_8_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_19_DLL_DQS_DELAY_8_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_19_DLL_DQS_DELAY_7_MASK 0x007F0000
+#define DDR0_19_DLL_DQS_DELAY_7_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_19_DLL_DQS_DELAY_7_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_19_DLL_DQS_DELAY_6_MASK 0x00007F00
+#define DDR0_19_DLL_DQS_DELAY_6_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_19_DLL_DQS_DELAY_6_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_19_DLL_DQS_DELAY_5_MASK 0x0000007F
+#define DDR0_19_DLL_DQS_DELAY_5_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_19_DLL_DQS_DELAY_5_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_20 0x14
+#define DDR0_20_DLL_DQS_BYPASS_3_MASK 0x7F000000
+#define DDR0_20_DLL_DQS_BYPASS_3_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_20_DLL_DQS_BYPASS_3_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_20_DLL_DQS_BYPASS_2_MASK 0x007F0000
+#define DDR0_20_DLL_DQS_BYPASS_2_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_20_DLL_DQS_BYPASS_2_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_20_DLL_DQS_BYPASS_1_MASK 0x00007F00
+#define DDR0_20_DLL_DQS_BYPASS_1_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_20_DLL_DQS_BYPASS_1_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_20_DLL_DQS_BYPASS_0_MASK 0x0000007F
+#define DDR0_20_DLL_DQS_BYPASS_0_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_20_DLL_DQS_BYPASS_0_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_21 0x15
+#define DDR0_21_DLL_DQS_BYPASS_7_MASK 0x7F000000
+#define DDR0_21_DLL_DQS_BYPASS_7_ENCODE(n) ((((u32)(n))&0x7F)<<24)
+#define DDR0_21_DLL_DQS_BYPASS_7_DECODE(n) ((((u32)(n))>>24)&0x7F)
+#define DDR0_21_DLL_DQS_BYPASS_6_MASK 0x007F0000
+#define DDR0_21_DLL_DQS_BYPASS_6_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_21_DLL_DQS_BYPASS_6_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_21_DLL_DQS_BYPASS_5_MASK 0x00007F00
+#define DDR0_21_DLL_DQS_BYPASS_5_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_21_DLL_DQS_BYPASS_5_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_21_DLL_DQS_BYPASS_4_MASK 0x0000007F
+#define DDR0_21_DLL_DQS_BYPASS_4_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_21_DLL_DQS_BYPASS_4_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_22 0x16
+#define DDR0_22_CTRL_RAW_MASK 0x03000000
+#define DDR0_22_CTRL_RAW_ECC_DISABLE 0x00000000
+#define DDR0_22_CTRL_RAW_ECC_CHECK_ONLY 0x01000000
+#define DDR0_22_CTRL_RAW_NO_ECC_RAM 0x02000000
+#define DDR0_22_CTRL_RAW_ECC_ENABLE 0x03000000
+#define DDR0_22_CTRL_RAW_ENCODE(n) ((((u32)(n))&0x3)<<24)
+#define DDR0_22_CTRL_RAW_DECODE(n) ((((u32)(n))>>24)&0x3)
+#define DDR0_22_DQS_OUT_SHIFT_BYPASS_MASK 0x007F0000
+#define DDR0_22_DQS_OUT_SHIFT_BYPASS_ENCODE(n) ((((u32)(n))&0x7F)<<16)
+#define DDR0_22_DQS_OUT_SHIFT_BYPASS_DECODE(n) ((((u32)(n))>>16)&0x7F)
+#define DDR0_22_DQS_OUT_SHIFT_MASK 0x00007F00
+#define DDR0_22_DQS_OUT_SHIFT_ENCODE(n) ((((u32)(n))&0x7F)<<8)
+#define DDR0_22_DQS_OUT_SHIFT_DECODE(n) ((((u32)(n))>>8)&0x7F)
+#define DDR0_22_DLL_DQS_BYPASS_8_MASK 0x0000007F
+#define DDR0_22_DLL_DQS_BYPASS_8_ENCODE(n) ((((u32)(n))&0x7F)<<0)
+#define DDR0_22_DLL_DQS_BYPASS_8_DECODE(n) ((((u32)(n))>>0)&0x7F)
+
+#define DDR0_23 0x17
+#define DDR0_23_ODT_RD_MAP_CS0_MASK 0x03000000
+#define DDR0_23_ODT_RD_MAP_CS0_ENCODE(n) ((((u32)(n))&0x3)<<24)
+#define DDR0_23_ODT_RD_MAP_CS0_DECODE(n) ((((u32)(n))>>24)&0x3)
+#define DDR0_23_ECC_C_SYND_MASK 0x00FF0000 /* Read only */
+#define DDR0_23_ECC_C_SYND_ENCODE(n) ((((u32)(n))&0xFF)<<16)
+#define DDR0_23_ECC_C_SYND_DECODE(n) ((((u32)(n))>>16)&0xFF)
+#define DDR0_23_ECC_U_SYND_MASK 0x0000FF00 /* Read only */
+#define DDR0_23_ECC_U_SYND_ENCODE(n) ((((u32)(n))&0xFF)<<8)
+#define DDR0_23_ECC_U_SYND_DECODE(n) ((((u32)(n))>>8)&0xFF)
+#define DDR0_23_FWC_MASK 0x00000001 /* Write only */
+#define DDR0_23_FWC_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_23_FWC_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_24 0x18
+#define DDR0_24_RTT_PAD_TERMINATION_MASK 0x03000000
+#define DDR0_24_RTT_PAD_TERMINATION_ENCODE(n) ((((u32)(n))&0x3)<<24)
+#define DDR0_24_RTT_PAD_TERMINATION_DECODE(n) ((((u32)(n))>>24)&0x3)
+#define DDR0_24_ODT_WR_MAP_CS1_MASK 0x00030000
+#define DDR0_24_ODT_WR_MAP_CS1_ENCODE(n) ((((u32)(n))&0x3)<<16)
+#define DDR0_24_ODT_WR_MAP_CS1_DECODE(n) ((((u32)(n))>>16)&0x3)
+#define DDR0_24_ODT_RD_MAP_CS1_MASK 0x00000300
+#define DDR0_24_ODT_RD_MAP_CS1_ENCODE(n) ((((u32)(n))&0x3)<<8)
+#define DDR0_24_ODT_RD_MAP_CS1_DECODE(n) ((((u32)(n))>>8)&0x3)
+#define DDR0_24_ODT_WR_MAP_CS0_MASK 0x00000003
+#define DDR0_24_ODT_WR_MAP_CS0_ENCODE(n) ((((u32)(n))&0x3)<<0)
+#define DDR0_24_ODT_WR_MAP_CS0_DECODE(n) ((((u32)(n))>>0)&0x3)
+
+#define DDR0_25 0x19
+#define DDR0_25_VERSION_MASK 0xFFFF0000 /* Read only */
+#define DDR0_25_VERSION_ENCODE(n) ((((u32)(n))&0xFFFF)<<16)
+#define DDR0_25_VERSION_DECODE(n) ((((u32)(n))>>16)&0xFFFF)
+#define DDR0_25_OUT_OF_RANGE_LENGTH_MASK 0x000003FF /* Read only */
+#define DDR0_25_OUT_OF_RANGE_LENGTH_ENCODE(n) ((((u32)(n))&0x3FF)<<0)
+#define DDR0_25_OUT_OF_RANGE_LENGTH_DECODE(n) ((((u32)(n))>>0)&0x3FF)
+
+#define DDR0_26 0x1A
+#define DDR0_26_TRAS_MAX_MASK 0xFFFF0000
+#define DDR0_26_TRAS_MAX_ENCODE(n) ((((u32)(n))&0xFFFF)<<16)
+#define DDR0_26_TRAS_MAX_DECODE(n) ((((u32)(n))>>16)&0xFFFF)
+#define DDR0_26_TREF_MASK 0x00003FFF
+#define DDR0_26_TREF_ENCODE(n) ((((u32)(n))&0x3FFF)<<0)
+#define DDR0_26_TREF_DECODE(n) ((((u32)(n))>>0)&0x3FFF)
+
+#define DDR0_27 0x1B
+#define DDR0_27_EMRS_DATA_MASK 0x3FFF0000
+#define DDR0_27_EMRS_DATA_ENCODE(n) ((((u32)(n))&0x3FFF)<<16)
+#define DDR0_27_EMRS_DATA_DECODE(n) ((((u32)(n))>>16)&0x3FFF)
+#define DDR0_27_TINIT_MASK 0x0000FFFF
+#define DDR0_27_TINIT_ENCODE(n) ((((u32)(n))&0xFFFF)<<0)
+#define DDR0_27_TINIT_DECODE(n) ((((u32)(n))>>0)&0xFFFF)
+
+#define DDR0_28 0x1C
+#define DDR0_28_EMRS3_DATA_MASK 0x3FFF0000
+#define DDR0_28_EMRS3_DATA_ENCODE(n) ((((u32)(n))&0x3FFF)<<16)
+#define DDR0_28_EMRS3_DATA_DECODE(n) ((((u32)(n))>>16)&0x3FFF)
+#define DDR0_28_EMRS2_DATA_MASK 0x00003FFF
+#define DDR0_28_EMRS2_DATA_ENCODE(n) ((((u32)(n))&0x3FFF)<<0)
+#define DDR0_28_EMRS2_DATA_DECODE(n) ((((u32)(n))>>0)&0x3FFF)
+
+#define DDR0_31 0x1F
+#define DDR0_31_XOR_CHECK_BITS_MASK 0x0000FFFF
+#define DDR0_31_XOR_CHECK_BITS_ENCODE(n) ((((u32)(n))&0xFFFF)<<0)
+#define DDR0_31_XOR_CHECK_BITS_DECODE(n) ((((u32)(n))>>0)&0xFFFF)
+
+#define DDR0_32 0x20
+#define DDR0_32_OUT_OF_RANGE_ADDR_MASK 0xFFFFFFFF /* Read only */
+#define DDR0_32_OUT_OF_RANGE_ADDR_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_32_OUT_OF_RANGE_ADDR_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_33 0x21
+#define DDR0_33_OUT_OF_RANGE_ADDR_MASK 0x00000001 /* Read only */
+#define DDR0_33_OUT_OF_RANGE_ADDR_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_33_OUT_OF_RANGE_ADDR_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_34 0x22
+#define DDR0_34_ECC_U_ADDR_MASK 0xFFFFFFFF /* Read only */
+#define DDR0_34_ECC_U_ADDR_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_34_ECC_U_ADDR_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_35 0x23
+#define DDR0_35_ECC_U_ADDR_MASK 0x00000001 /* Read only */
+#define DDR0_35_ECC_U_ADDR_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_35_ECC_U_ADDR_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_36 0x24
+#define DDR0_36_ECC_U_DATA_MASK 0xFFFFFFFF /* Read only */
+#define DDR0_36_ECC_U_DATA_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_36_ECC_U_DATA_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_37 0x25
+#define DDR0_37_ECC_U_DATA_MASK 0xFFFFFFFF /* Read only */
+#define DDR0_37_ECC_U_DATA_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_37_ECC_U_DATA_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_38 0x26
+#define DDR0_38_ECC_C_ADDR_MASK 0xFFFFFFFF /* Read only */
+#define DDR0_38_ECC_C_ADDR_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_38_ECC_C_ADDR_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_39 0x27
+#define DDR0_39_ECC_C_ADDR_MASK 0x00000001 /* Read only */
+#define DDR0_39_ECC_C_ADDR_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_39_ECC_C_ADDR_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_40 0x28
+#define DDR0_40_ECC_C_DATA_MASK 0xFFFFFFFF /* Read only */
+#define DDR0_40_ECC_C_DATA_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_40_ECC_C_DATA_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_41 0x29
+#define DDR0_41_ECC_C_DATA_MASK 0xFFFFFFFF /* Read only */
+#define DDR0_41_ECC_C_DATA_ENCODE(n) ((((u32)(n))&0xFFFFFFFF)<<0)
+#define DDR0_41_ECC_C_DATA_DECODE(n) ((((u32)(n))>>0)&0xFFFFFFFF)
+
+#define DDR0_42 0x2A
+#define DDR0_42_ADDR_PINS_MASK 0x07000000
+#define DDR0_42_ADDR_PINS_ENCODE(n) ((((u32)(n))&0x7)<<24)
+#define DDR0_42_ADDR_PINS_DECODE(n) ((((u32)(n))>>24)&0x7)
+#define DDR0_42_CASLAT_LIN_GATE_MASK 0x0000000F
+#define DDR0_42_CASLAT_LIN_GATE_ENCODE(n) ((((u32)(n))&0xF)<<0)
+#define DDR0_42_CASLAT_LIN_GATE_DECODE(n) ((((u32)(n))>>0)&0xF)
+
+#define DDR0_43 0x2B
+#define DDR0_43_TWR_MASK 0x07000000
+#define DDR0_43_TWR_ENCODE(n) ((((u32)(n))&0x7)<<24)
+#define DDR0_43_TWR_DECODE(n) ((((u32)(n))>>24)&0x7)
+#define DDR0_43_APREBIT_MASK 0x000F0000
+#define DDR0_43_APREBIT_ENCODE(n) ((((u32)(n))&0xF)<<16)
+#define DDR0_43_APREBIT_DECODE(n) ((((u32)(n))>>16)&0xF)
+#define DDR0_43_COLUMN_SIZE_MASK 0x00000700
+#define DDR0_43_COLUMN_SIZE_ENCODE(n) ((((u32)(n))&0x7)<<8)
+#define DDR0_43_COLUMN_SIZE_DECODE(n) ((((u32)(n))>>8)&0x7)
+#define DDR0_43_EIGHT_BANK_MODE_MASK 0x00000001
+#define DDR0_43_EIGHT_BANK_MODE_8_BANKS 0x00000001
+#define DDR0_43_EIGHT_BANK_MODE_4_BANKS 0x00000000
+#define DDR0_43_EIGHT_BANK_MODE_ENCODE(n) ((((u32)(n))&0x1)<<0)
+#define DDR0_43_EIGHT_BANK_MODE_DECODE(n) ((((u32)(n))>>0)&0x1)
+
+#define DDR0_44 0x2C
+#define DDR0_44_TRCD_MASK 0x000000FF
+#define DDR0_44_TRCD_ENCODE(n) ((((u32)(n))&0xFF)<<0)
+#define DDR0_44_TRCD_DECODE(n) ((((u32)(n))>>0)&0xFF)
+
+#endif /* CONFIG_SDRAM_PPC4xx_DENALI_DDR2 */
+
+#ifndef __ASSEMBLY__
+struct sdram_timing {
+ u32 wrdtr;
+ u32 clktr;
+};
+
+/*
+ * Prototypes
+ */
+void ppc4xx_ibm_ddr2_register_dump(void);
+u32 mfdcr_any(u32);
+void mtdcr_any(u32, u32);
+u32 ddr_wrdtr(u32);
+u32 ddr_clktr(u32);
+void spd_ddr_init_hang(void);
+u32 DQS_autocalibration(void);
+phys_size_t sdram_memsize(void);
+void dcbz_area(u32 start_address, u32 num_bytes);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PPC4xx_SDRAM_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx-uic.h b/arch/powerpc/include/asm/ppc4xx-uic.h
new file mode 100644
index 0000000..3714a0a
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx-uic.h
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com>
+ *
+ * (C) Copyright 2008-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _PPC4xx_UIC_H_
+#define _PPC4xx_UIC_H_
+
+/*
+ * Define the number of UIC's
+ */
+#if defined(CONFIG_440GX) || defined(CONFIG_440SPE) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_460SX) || defined(CONFIG_APM821XX)
+#define UIC_MAX 4
+#elif defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_405EX)
+#define UIC_MAX 3
+#elif defined(CONFIG_440GP) || defined(CONFIG_440SP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#define UIC_MAX 2
+#else
+#define UIC_MAX 1
+#endif
+
+#define IRQ_MAX (UIC_MAX * 32)
+
+/*
+ * UIC register
+ */
+#define UIC_SR 0x0 /* UIC status */
+#define UIC_ER 0x2 /* UIC enable */
+#define UIC_CR 0x3 /* UIC critical */
+#define UIC_PR 0x4 /* UIC polarity */
+#define UIC_TR 0x5 /* UIC triggering */
+#define UIC_MSR 0x6 /* UIC masked status */
+#define UIC_VR 0x7 /* UIC vector */
+#define UIC_VCR 0x8 /* UIC vector configuration */
+
+/*
+ * On 440GX we use the UICB0 as UIC0. Its the root UIC where all other UIC's
+ * are cascaded on. With this trick we can use the common UIC code for 440GX
+ * too.
+ */
+#if defined(CONFIG_440GX)
+#define UIC0_DCR_BASE 0x200
+#define UIC1_DCR_BASE 0xc0
+#define UIC2_DCR_BASE 0xd0
+#define UIC3_DCR_BASE 0x210
+#else
+#define UIC0_DCR_BASE 0xc0
+#define UIC1_DCR_BASE 0xd0
+#define UIC2_DCR_BASE 0xe0
+#define UIC3_DCR_BASE 0xf0
+#endif
+
+#define UIC0SR (UIC0_DCR_BASE+0x0) /* UIC0 status */
+#define UIC0ER (UIC0_DCR_BASE+0x2) /* UIC0 enable */
+#define UIC0CR (UIC0_DCR_BASE+0x3) /* UIC0 critical */
+#define UIC0PR (UIC0_DCR_BASE+0x4) /* UIC0 polarity */
+#define UIC0TR (UIC0_DCR_BASE+0x5) /* UIC0 triggering */
+#define UIC0MSR (UIC0_DCR_BASE+0x6) /* UIC0 masked status */
+#define UIC0VR (UIC0_DCR_BASE+0x7) /* UIC0 vector */
+#define UIC0VCR (UIC0_DCR_BASE+0x8) /* UIC0 vector configuration */
+
+#define UIC1SR (UIC1_DCR_BASE+0x0) /* UIC1 status */
+#define UIC1ER (UIC1_DCR_BASE+0x2) /* UIC1 enable */
+#define UIC1CR (UIC1_DCR_BASE+0x3) /* UIC1 critical */
+#define UIC1PR (UIC1_DCR_BASE+0x4) /* UIC1 polarity */
+#define UIC1TR (UIC1_DCR_BASE+0x5) /* UIC1 triggering */
+#define UIC1MSR (UIC1_DCR_BASE+0x6) /* UIC1 masked status */
+#define UIC1VR (UIC1_DCR_BASE+0x7) /* UIC1 vector */
+#define UIC1VCR (UIC1_DCR_BASE+0x8) /* UIC1 vector configuration */
+
+#define UIC2SR (UIC2_DCR_BASE+0x0) /* UIC2 status-Read Clear */
+#define UIC2ER (UIC2_DCR_BASE+0x2) /* UIC2 enable */
+#define UIC2CR (UIC2_DCR_BASE+0x3) /* UIC2 critical */
+#define UIC2PR (UIC2_DCR_BASE+0x4) /* UIC2 polarity */
+#define UIC2TR (UIC2_DCR_BASE+0x5) /* UIC2 triggering */
+#define UIC2MSR (UIC2_DCR_BASE+0x6) /* UIC2 masked status */
+#define UIC2VR (UIC2_DCR_BASE+0x7) /* UIC2 vector */
+#define UIC2VCR (UIC2_DCR_BASE+0x8) /* UIC2 vector configuration */
+
+#define UIC3SR (UIC3_DCR_BASE+0x0) /* UIC3 status-Read Clear */
+#define UIC3ER (UIC3_DCR_BASE+0x2) /* UIC3 enable */
+#define UIC3CR (UIC3_DCR_BASE+0x3) /* UIC3 critical */
+#define UIC3PR (UIC3_DCR_BASE+0x4) /* UIC3 polarity */
+#define UIC3TR (UIC3_DCR_BASE+0x5) /* UIC3 triggering */
+#define UIC3MSR (UIC3_DCR_BASE+0x6) /* UIC3 masked status */
+#define UIC3VR (UIC3_DCR_BASE+0x7) /* UIC3 vector */
+#define UIC3VCR (UIC3_DCR_BASE+0x8) /* UIC3 vector configuration */
+
+/*
+ * Now the interrupt vector definitions. They are different for most of
+ * the 4xx variants, so we need some more #ifdef's here. No mask
+ * definitions anymore here. For this please use the UIC_MASK macro below.
+ *
+ * Note: Please only define the interrupts really used in U-Boot here.
+ * Those are the cascading and EMAC/MAL related interrupt.
+ */
+
+#if defined(CONFIG_405EP) || defined(CONFIG_405GP)
+#define VECNUM_MAL_SERR 10
+#define VECNUM_MAL_TXEOB 11
+#define VECNUM_MAL_RXEOB 12
+#define VECNUM_MAL_TXDE 13
+#define VECNUM_MAL_RXDE 14
+#define VECNUM_ETH0 15
+#define VECNUM_ETH1_OFFS 2
+#define VECNUM_EIRQ6 29
+#endif /* defined(CONFIG_405EP) */
+
+#if defined(CONFIG_405EZ)
+#define VECNUM_USBDEV 15
+#define VECNUM_ETH0 16
+#define VECNUM_MAL_SERR 18
+#define VECNUM_MAL_TXDE 18
+#define VECNUM_MAL_RXDE 18
+#define VECNUM_MAL_TXEOB 19
+#define VECNUM_MAL_RXEOB 21
+#endif /* CONFIG_405EX */
+
+#if defined(CONFIG_405EX)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB 10
+#define VECNUM_MAL_RXEOB 11
+#define VECNUM_ETH0 24
+#define VECNUM_ETH1_OFFS 1
+#define VECNUM_UIC2NCI 28
+#define VECNUM_UIC2CI 29
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 0)
+#define VECNUM_MAL_TXDE (32 + 1)
+#define VECNUM_MAL_RXDE (32 + 2)
+#endif /* CONFIG_405EX */
+
+#if defined(CONFIG_440GP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB 10
+#define VECNUM_MAL_RXEOB 11
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 0)
+#define VECNUM_MAL_TXDE (32 + 1)
+#define VECNUM_MAL_RXDE (32 + 2)
+#define VECNUM_USBDEV (32 + 23)
+#define VECNUM_ETH0 (32 + 28)
+#define VECNUM_ETH1_OFFS 2
+#endif /* CONFIG_440GP */
+
+#if defined(CONFIG_440GX)
+/* UICB 0 (440GX only) */
+/*
+ * All those defines below are off-by-one, so that the common UIC code
+ * can be used. So VECNUM_UIC1CI refers to VECNUM_UIC0CI etc.
+ */
+#define VECNUM_UIC1CI 0
+#define VECNUM_UIC1NCI 1
+#define VECNUM_UIC2CI 2
+#define VECNUM_UIC2NCI 3
+#define VECNUM_UIC3CI 4
+#define VECNUM_UIC3NCI 5
+
+/* UIC 0, used as UIC1 on 440GX because of UICB0 */
+#define VECNUM_MAL_TXEOB (32 + 10)
+#define VECNUM_MAL_RXEOB (32 + 11)
+
+/* UIC 1, used as UIC2 on 440GX because of UICB0 */
+#define VECNUM_MAL_SERR (64 + 0)
+#define VECNUM_MAL_TXDE (64 + 1)
+#define VECNUM_MAL_RXDE (64 + 2)
+#define VECNUM_ETH0 (64 + 28)
+#define VECNUM_ETH1_OFFS 2
+#endif /* CONFIG_440GX */
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+/* UIC 0 */
+#define VECNUM_MAL_TXEOB 10
+#define VECNUM_MAL_RXEOB 11
+#define VECNUM_USBDEV 20
+#define VECNUM_ETH0 24
+#define VECNUM_ETH1_OFFS 1
+#define VECNUM_UIC2NCI 28
+#define VECNUM_UIC2CI 29
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 0)
+#define VECNUM_MAL_TXDE (32 + 1)
+#define VECNUM_MAL_RXDE (32 + 2)
+
+/* UIC 2 */
+#define VECNUM_EIRQ2 (64 + 3)
+#endif /* CONFIG_440EPX */
+
+#if defined(CONFIG_440SP)
+/* UIC 0 */
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 1)
+#define VECNUM_MAL_TXDE (32 + 2)
+#define VECNUM_MAL_RXDE (32 + 3)
+#define VECNUM_MAL_TXEOB (32 + 6)
+#define VECNUM_MAL_RXEOB (32 + 7)
+#define VECNUM_ETH0 (32 + 28)
+#endif /* CONFIG_440SP */
+
+#if defined(CONFIG_440SPE)
+/* UIC 0 */
+#define VECNUM_UIC2NCI 10
+#define VECNUM_UIC2CI 11
+#define VECNUM_UIC3NCI 16
+#define VECNUM_UIC3CI 17
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 1)
+#define VECNUM_MAL_TXDE (32 + 2)
+#define VECNUM_MAL_RXDE (32 + 3)
+#define VECNUM_MAL_TXEOB (32 + 6)
+#define VECNUM_MAL_RXEOB (32 + 7)
+#define VECNUM_ETH0 (32 + 28)
+#endif /* CONFIG_440SPE */
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \
+ defined(CONFIG_APM821XX)
+/* UIC 0 */
+#define VECNUM_UIC2NCI 10
+#define VECNUM_UIC2CI 11
+#define VECNUM_UIC3NCI 16
+#define VECNUM_UIC3CI 17
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 2 */
+#define VECNUM_MAL_SERR (64 + 3)
+#define VECNUM_MAL_TXDE (64 + 4)
+#define VECNUM_MAL_RXDE (64 + 5)
+#define VECNUM_MAL_TXEOB (64 + 6)
+#define VECNUM_MAL_RXEOB (64 + 7)
+#define VECNUM_ETH0 (64 + 16)
+#define VECNUM_ETH1_OFFS 1
+#endif /* CONFIG_460EX */
+
+#if defined(CONFIG_460SX)
+/* UIC 0 */
+#define VECNUM_UIC2NCI 10
+#define VECNUM_UIC2CI 11
+#define VECNUM_UIC3NCI 16
+#define VECNUM_UIC3CI 17
+#define VECNUM_ETH0 19
+#define VECNUM_ETH1_OFFS 1
+#define VECNUM_UIC1NCI 30
+#define VECNUM_UIC1CI 31
+
+/* UIC 1 */
+#define VECNUM_MAL_SERR (32 + 1)
+#define VECNUM_MAL_TXDE (32 + 2)
+#define VECNUM_MAL_RXDE (32 + 3)
+#define VECNUM_MAL_TXEOB (32 + 6)
+#define VECNUM_MAL_RXEOB (32 + 7)
+#endif /* CONFIG_460EX */
+
+#if !defined(VECNUM_ETH1_OFFS)
+#define VECNUM_ETH1_OFFS 1
+#endif
+
+/*
+ * Mask definitions (used for example in 4xx_enet.c)
+ */
+#define UIC_MASK(vec) (0x80000000 >> ((vec) & 0x1f))
+/* UIC_NR won't work for 440GX because of its specific UIC DCR addresses */
+#define UIC_NR(vec) ((vec) >> 5)
+
+#endif /* _PPC4xx_UIC_H_ */
diff --git a/arch/powerpc/include/asm/ppc4xx.h b/arch/powerpc/include/asm/ppc4xx.h
new file mode 100644
index 0000000..9f2a08b
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx.h
@@ -0,0 +1,324 @@
+/*----------------------------------------------------------------------------+
+| This source code is dual-licensed. You may use it under the terms of
+| the GNU General Public License version 2, or under the license below.
+|
+| This source code has been made available to you by IBM on an AS-IS
+| basis. Anyone receiving this source is licensed under IBM
+| copyrights to use it in any way he or she deems fit, including
+| copying it, modifying it, compiling it, and redistributing it either
+| with or without modifications. No license under IBM patents or
+| patent applications is to be implied by the copyright license.
+|
+| Any user of this software should understand that IBM cannot provide
+| technical support for this software and will not be responsible for
+| any consequences resulting from the use of this software.
+|
+| Any person who transfers this source code or any derivative work
+| must include the IBM copyright notice, this paragraph, and the
+| preceding two paragraphs in the transferred software.
+|
+| COPYRIGHT I B M CORPORATION 1999
+| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
++----------------------------------------------------------------------------*/
+
+#ifndef __PPC4XX_H__
+#define __PPC4XX_H__
+
+/*
+ * Include SoC specific headers
+ */
+#if defined(CONFIG_405CR)
+#include <asm/ppc405cr.h>
+#endif
+
+#if defined(CONFIG_405EP)
+#include <asm/ppc405ep.h>
+#endif
+
+#if defined(CONFIG_405EX)
+#include <asm/ppc405ex.h>
+#endif
+
+#if defined(CONFIG_405EZ)
+#include <asm/ppc405ez.h>
+#endif
+
+#if defined(CONFIG_405GP)
+#include <asm/ppc405gp.h>
+#endif
+
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR)
+#include <asm/ppc440ep_gr.h>
+#endif
+
+#if defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#include <asm/ppc440epx_grx.h>
+#endif
+
+#if defined(CONFIG_440GP)
+#include <asm/ppc440gp.h>
+#endif
+
+#if defined(CONFIG_440GX)
+#include <asm/ppc440gx.h>
+#endif
+
+#if defined(CONFIG_440SP)
+#include <asm/ppc440sp.h>
+#endif
+
+#if defined(CONFIG_440SPE)
+#include <asm/ppc440spe.h>
+#endif
+
+#if defined(CONFIG_460EX) || defined(CONFIG_460GT)
+#include <asm/ppc460ex_gt.h>
+#endif
+
+#if defined(CONFIG_460SX)
+#include <asm/ppc460sx.h>
+#endif
+
+#if defined(CONFIG_APM821XX)
+#include <asm/apm821xx.h>
+#endif
+
+/*
+ * Common registers for all SoC's
+ */
+/* DCR registers */
+#define PLB3A0_ACR 0x0077
+#define PLB4A0_ACR 0x0081
+#define PLB4A1_ACR 0x0089
+
+/* CPR register declarations */
+
+#define PLB4Ax_ACR_PPM_MASK 0xf0000000
+#define PLB4Ax_ACR_PPM_FIXED 0x00000000
+#define PLB4Ax_ACR_PPM_FAIR 0xd0000000
+#define PLB4Ax_ACR_HBU_MASK 0x08000000
+#define PLB4Ax_ACR_HBU_DISABLED 0x00000000
+#define PLB4Ax_ACR_HBU_ENABLED 0x08000000
+#define PLB4Ax_ACR_RDP_MASK 0x06000000
+#define PLB4Ax_ACR_RDP_DISABLED 0x00000000
+#define PLB4Ax_ACR_RDP_2DEEP 0x02000000
+#define PLB4Ax_ACR_RDP_3DEEP 0x04000000
+#define PLB4Ax_ACR_RDP_4DEEP 0x06000000
+#define PLB4Ax_ACR_WRP_MASK 0x01000000
+#define PLB4Ax_ACR_WRP_DISABLED 0x00000000
+#define PLB4Ax_ACR_WRP_2DEEP 0x01000000
+
+/*
+ * External Bus Controller
+ */
+/* Values for EBC0_CFGADDR register - indirect addressing of these regs */
+#define PB0CR 0x00 /* periph bank 0 config reg */
+#define PB1CR 0x01 /* periph bank 1 config reg */
+#define PB2CR 0x02 /* periph bank 2 config reg */
+#define PB3CR 0x03 /* periph bank 3 config reg */
+#define PB4CR 0x04 /* periph bank 4 config reg */
+#define PB5CR 0x05 /* periph bank 5 config reg */
+#define PB6CR 0x06 /* periph bank 6 config reg */
+#define PB7CR 0x07 /* periph bank 7 config reg */
+#define PB0AP 0x10 /* periph bank 0 access parameters */
+#define PB1AP 0x11 /* periph bank 1 access parameters */
+#define PB2AP 0x12 /* periph bank 2 access parameters */
+#define PB3AP 0x13 /* periph bank 3 access parameters */
+#define PB4AP 0x14 /* periph bank 4 access parameters */
+#define PB5AP 0x15 /* periph bank 5 access parameters */
+#define PB6AP 0x16 /* periph bank 6 access parameters */
+#define PB7AP 0x17 /* periph bank 7 access parameters */
+#define PBEAR 0x20 /* periph bus error addr reg */
+#define PBESR0 0x21 /* periph bus error status reg 0 */
+#define PBESR1 0x22 /* periph bus error status reg 1 */
+#define EBC0_CFG 0x23 /* external bus configuration reg */
+
+/*
+ * GPIO macro register defines
+ */
+/* todo: merge with gpio.h header */
+#define GPIO_BASE GPIO0_BASE
+
+#define GPIO0_OR (GPIO0_BASE + 0x0)
+#define GPIO0_TCR (GPIO0_BASE + 0x4)
+#define GPIO0_OSRL (GPIO0_BASE + 0x8)
+#define GPIO0_OSRH (GPIO0_BASE + 0xC)
+#define GPIO0_TSRL (GPIO0_BASE + 0x10)
+#define GPIO0_TSRH (GPIO0_BASE + 0x14)
+#define GPIO0_ODR (GPIO0_BASE + 0x18)
+#define GPIO0_IR (GPIO0_BASE + 0x1C)
+#define GPIO0_RR1 (GPIO0_BASE + 0x20)
+#define GPIO0_RR2 (GPIO0_BASE + 0x24)
+#define GPIO0_RR3 (GPIO0_BASE + 0x28)
+#define GPIO0_ISR1L (GPIO0_BASE + 0x30)
+#define GPIO0_ISR1H (GPIO0_BASE + 0x34)
+#define GPIO0_ISR2L (GPIO0_BASE + 0x38)
+#define GPIO0_ISR2H (GPIO0_BASE + 0x3C)
+#define GPIO0_ISR3L (GPIO0_BASE + 0x40)
+#define GPIO0_ISR3H (GPIO0_BASE + 0x44)
+
+#define GPIO1_OR (GPIO1_BASE + 0x0)
+#define GPIO1_TCR (GPIO1_BASE + 0x4)
+#define GPIO1_OSRL (GPIO1_BASE + 0x8)
+#define GPIO1_OSRH (GPIO1_BASE + 0xC)
+#define GPIO1_TSRL (GPIO1_BASE + 0x10)
+#define GPIO1_TSRH (GPIO1_BASE + 0x14)
+#define GPIO1_ODR (GPIO1_BASE + 0x18)
+#define GPIO1_IR (GPIO1_BASE + 0x1C)
+#define GPIO1_RR1 (GPIO1_BASE + 0x20)
+#define GPIO1_RR2 (GPIO1_BASE + 0x24)
+#define GPIO1_RR3 (GPIO1_BASE + 0x28)
+#define GPIO1_ISR1L (GPIO1_BASE + 0x30)
+#define GPIO1_ISR1H (GPIO1_BASE + 0x34)
+#define GPIO1_ISR2L (GPIO1_BASE + 0x38)
+#define GPIO1_ISR2H (GPIO1_BASE + 0x3C)
+#define GPIO1_ISR3L (GPIO1_BASE + 0x40)
+#define GPIO1_ISR3H (GPIO1_BASE + 0x44)
+
+/* General Purpose Timer (GPT) Register Offsets */
+#define GPT0_TBC 0x00000000
+#define GPT0_IM 0x00000018
+#define GPT0_ISS 0x0000001C
+#define GPT0_ISC 0x00000020
+#define GPT0_IE 0x00000024
+#define GPT0_COMP0 0x00000080
+#define GPT0_COMP1 0x00000084
+#define GPT0_COMP2 0x00000088
+#define GPT0_COMP3 0x0000008C
+#define GPT0_COMP4 0x00000090
+#define GPT0_COMP5 0x00000094
+#define GPT0_COMP6 0x00000098
+#define GPT0_MASK0 0x000000C0
+#define GPT0_MASK1 0x000000C4
+#define GPT0_MASK2 0x000000C8
+#define GPT0_MASK3 0x000000CC
+#define GPT0_MASK4 0x000000D0
+#define GPT0_MASK5 0x000000D4
+#define GPT0_MASK6 0x000000D8
+#define GPT0_DCT0 0x00000110
+#define GPT0_DCIS 0x0000011C
+
+#if defined(CONFIG_440)
+#include <asm/ppc440.h>
+#else
+#include <asm/ppc405.h>
+#endif
+
+#include <asm/ppc4xx-sdram.h>
+#include <asm/ppc4xx-ebc.h>
+#if !defined(CONFIG_XILINX_440)
+#include <asm/ppc4xx-uic.h>
+#endif
+
+/*
+ * Macro for generating register field mnemonics
+ */
+#define PPC_REG_BITS 32
+#define PPC_REG_VAL(bit, value) ((value) << ((PPC_REG_BITS - 1) - (bit)))
+
+/*
+ * Elide casts when assembling register mnemonics
+ */
+#ifndef __ASSEMBLY__
+#define static_cast(type, val) (type)(val)
+#else
+#define static_cast(type, val) (val)
+#endif
+
+/*
+ * Common stuff for 4xx (405 and 440)
+ */
+
+#define EXC_OFF_SYS_RESET 0x0100 /* System reset */
+#define _START_OFFSET (EXC_OFF_SYS_RESET + 0x2000)
+
+#define RESET_VECTOR 0xfffffffc
+#define CACHELINE_MASK (CONFIG_SYS_CACHELINE_SIZE - 1) /* Address mask for
+ cache line aligned data. */
+
+#define CPR0_DCR_BASE 0x0C
+#define CPR0_CFGADDR (CPR0_DCR_BASE + 0x0)
+#define CPR0_CFGDATA (CPR0_DCR_BASE + 0x1)
+
+#define SDR_DCR_BASE 0x0E
+#define SDR0_CFGADDR (SDR_DCR_BASE + 0x0)
+#define SDR0_CFGDATA (SDR_DCR_BASE + 0x1)
+
+#define SDRAM_DCR_BASE 0x10
+#define SDRAM0_CFGADDR (SDRAM_DCR_BASE + 0x0)
+#define SDRAM0_CFGDATA (SDRAM_DCR_BASE + 0x1)
+
+#define EBC_DCR_BASE 0x12
+#define EBC0_CFGADDR (EBC_DCR_BASE + 0x0)
+#define EBC0_CFGDATA (EBC_DCR_BASE + 0x1)
+
+/*
+ * Macros for indirect DCR access
+ */
+#define mtcpr(reg, d) \
+ do { mtdcr(CPR0_CFGADDR, reg); mtdcr(CPR0_CFGDATA, d); } while (0)
+#define mfcpr(reg, d) \
+ do { mtdcr(CPR0_CFGADDR, reg); d = mfdcr(CPR0_CFGDATA); } while (0)
+
+#define mtebc(reg, d) \
+ do { mtdcr(EBC0_CFGADDR, reg); mtdcr(EBC0_CFGDATA, d); } while (0)
+#define mfebc(reg, d) \
+ do { mtdcr(EBC0_CFGADDR, reg); d = mfdcr(EBC0_CFGDATA); } while (0)
+
+#define mtsdram(reg, d) \
+ do { mtdcr(SDRAM0_CFGADDR, reg); mtdcr(SDRAM0_CFGDATA, d); } while (0)
+#define mfsdram(reg, d) \
+ do { mtdcr(SDRAM0_CFGADDR, reg); d = mfdcr(SDRAM0_CFGDATA); } while (0)
+
+#define mtsdr(reg, d) \
+ do { mtdcr(SDR0_CFGADDR, reg); mtdcr(SDR0_CFGDATA, d); } while (0)
+#define mfsdr(reg, d) \
+ do { mtdcr(SDR0_CFGADDR, reg); d = mfdcr(SDR0_CFGDATA); } while (0)
+
+#ifndef __ASSEMBLY__
+
+typedef struct
+{
+ unsigned long freqDDR;
+ unsigned long freqEBC;
+ unsigned long freqOPB;
+ unsigned long freqPCI;
+ unsigned long freqPLB;
+ unsigned long freqTmrClk;
+ unsigned long freqUART;
+ unsigned long freqProcessor;
+ unsigned long freqVCOHz;
+ unsigned long freqVCOMhz; /* in MHz */
+ unsigned long pciClkSync; /* PCI clock is synchronous */
+ unsigned long pciIntArbEn; /* Internal PCI arbiter is enabled */
+ unsigned long pllExtBusDiv;
+ unsigned long pllFbkDiv;
+ unsigned long pllFwdDiv;
+ unsigned long pllFwdDivA;
+ unsigned long pllFwdDivB;
+ unsigned long pllOpbDiv;
+ unsigned long pllPciDiv;
+ unsigned long pllPlbDiv;
+} PPC4xx_SYS_INFO;
+
+static inline u32 get_mcsr(void)
+{
+ u32 val;
+
+ asm volatile("mfspr %0, 0x23c" : "=r" (val) :);
+ return val;
+}
+
+static inline void set_mcsr(u32 val)
+{
+ asm volatile("mtspr 0x23c, %0" : "=r" (val) :);
+}
+
+int ppc4xx_pci_sync_clock_config(u32 async);
+
+#endif /* __ASSEMBLY__ */
+
+/* for multi-cpu support */
+#define NA_OR_UNKNOWN_CPU -1
+
+#endif /* __PPC4XX_H__ */
diff --git a/arch/powerpc/include/asm/ppc4xx_config.h b/arch/powerpc/include/asm/ppc4xx_config.h
new file mode 100644
index 0000000..49acb60
--- /dev/null
+++ b/arch/powerpc/include/asm/ppc4xx_config.h
@@ -0,0 +1,42 @@
+/*
+ * (C) Copyright 2008-2009
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * (C) Copyright 2009
+ * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef __PPC4xx_CONFIG_H
+#define __PPC4xx_CONFIG_H
+
+#include <common.h>
+
+struct ppc4xx_config {
+ char label[16];
+ char description[64];
+ u8 val[CONFIG_4xx_CONFIG_BLOCKSIZE];
+};
+
+extern struct ppc4xx_config ppc4xx_config_val[];
+extern int ppc4xx_config_count;
+
+#endif /* __PPC4xx_CONFIG_H */
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
new file mode 100644
index 0000000..56b22d8
--- /dev/null
+++ b/arch/powerpc/include/asm/processor.h
@@ -0,0 +1,1381 @@
+#ifndef __ASM_PPC_PROCESSOR_H
+#define __ASM_PPC_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <linux/config.h>
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+/* Machine State Register (MSR) Fields */
+
+#ifdef CONFIG_PPC64BRIDGE
+#define MSR_SF (1<<63)
+#define MSR_ISF (1<<61)
+#endif /* CONFIG_PPC64BRIDGE */
+#define MSR_UCLE (1<<26) /* User-mode cache lock enable (e500) */
+#define MSR_VEC (1<<25) /* Enable AltiVec(74xx) */
+#define MSR_SPE (1<<25) /* Enable SPE(e500) */
+#define MSR_POW (1<<18) /* Enable Power Management */
+#define MSR_WE (1<<18) /* Wait State Enable */
+#define MSR_TGPR (1<<17) /* TLB Update registers in use */
+#define MSR_CE (1<<17) /* Critical Interrupt Enable */
+#define MSR_ILE (1<<16) /* Interrupt Little Endian */
+#define MSR_EE (1<<15) /* External Interrupt Enable */
+#define MSR_PR (1<<14) /* Problem State / Privilege Level */
+#define MSR_FP (1<<13) /* Floating Point enable */
+#define MSR_ME (1<<12) /* Machine Check Enable */
+#define MSR_FE0 (1<<11) /* Floating Exception mode 0 */
+#define MSR_SE (1<<10) /* Single Step */
+#define MSR_DWE (1<<10) /* Debug Wait Enable (4xx) */
+#define MSR_UBLE (1<<10) /* BTB lock enable (e500) */
+#define MSR_BE (1<<9) /* Branch Trace */
+#define MSR_DE (1<<9) /* Debug Exception Enable */
+#define MSR_FE1 (1<<8) /* Floating Exception mode 1 */
+#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR (1<<5) /* Instruction Relocate */
+#define MSR_IS (1<<5) /* Book E Instruction space */
+#define MSR_DR (1<<4) /* Data Relocate */
+#define MSR_DS (1<<4) /* Book E Data space */
+#define MSR_PE (1<<3) /* Protection Enable */
+#define MSR_PX (1<<2) /* Protection Exclusive Mode */
+#define MSR_PMM (1<<2) /* Performance monitor mark bit (e500) */
+#define MSR_RI (1<<1) /* Recoverable Exception */
+#define MSR_LE (1<<0) /* Little Endian */
+
+#ifdef CONFIG_APUS_FAST_EXCEPT
+#define MSR_ MSR_ME|MSR_IP|MSR_RI
+#else
+#define MSR_ MSR_ME|MSR_RI
+#endif
+#ifndef CONFIG_E500
+#define MSR_KERNEL MSR_|MSR_IR|MSR_DR
+#else
+#define MSR_KERNEL MSR_ME
+#endif
+
+/* Floating Point Status and Control Register (FPSCR) Fields */
+
+#define FPSCR_FX 0x80000000 /* FPU exception summary */
+#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */
+#define FPSCR_VX 0x20000000 /* Invalid operation summary */
+#define FPSCR_OX 0x10000000 /* Overflow exception summary */
+#define FPSCR_UX 0x08000000 /* Underflow exception summary */
+#define FPSCR_ZX 0x04000000 /* Zero-devide exception summary */
+#define FPSCR_XX 0x02000000 /* Inexact exception summary */
+#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */
+#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */
+#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */
+#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */
+#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */
+#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */
+#define FPSCR_FR 0x00040000 /* Fraction rounded */
+#define FPSCR_FI 0x00020000 /* Fraction inexact */
+#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */
+#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */
+#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */
+#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */
+#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */
+#define FPSCR_VE 0x00000080 /* Invalid op exception enable */
+#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */
+#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */
+#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */
+#define FPSCR_XE 0x00000008 /* FP inexact exception enable */
+#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */
+#define FPSCR_RN 0x00000003 /* FPU rounding control */
+
+/* Special Purpose Registers (SPRNs)*/
+
+/* PPC440 Architecture is BOOK-E */
+#ifdef CONFIG_440
+#define CONFIG_BOOKE
+#endif
+
+#define SPRN_CCR0 0x3B3 /* Core Configuration Register 0 */
+#ifdef CONFIG_BOOKE
+#define SPRN_CCR1 0x378 /* Core Configuration Register for 440 only */
+#endif
+#define SPRN_CDBCR 0x3D7 /* Cache Debug Control Register */
+#define SPRN_CTR 0x009 /* Count Register */
+#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_DAC1 0x3F6 /* Data Address Compare 1 */
+#define SPRN_DAC2 0x3F7 /* Data Address Compare 2 */
+#else
+#define SPRN_DAC1 0x13C /* Book E Data Address Compare 1 */
+#define SPRN_DAC2 0x13D /* Book E Data Address Compare 2 */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DAR 0x013 /* Data Address Register */
+#define SPRN_DBAT0L 0x219 /* Data BAT 0 Lower Register */
+#define SPRN_DBAT0U 0x218 /* Data BAT 0 Upper Register */
+#define SPRN_DBAT1L 0x21B /* Data BAT 1 Lower Register */
+#define SPRN_DBAT1U 0x21A /* Data BAT 1 Upper Register */
+#define SPRN_DBAT2L 0x21D /* Data BAT 2 Lower Register */
+#define SPRN_DBAT2U 0x21C /* Data BAT 2 Upper Register */
+#define SPRN_DBAT3L 0x21F /* Data BAT 3 Lower Register */
+#define SPRN_DBAT3U 0x21E /* Data BAT 3 Upper Register */
+#define SPRN_DBAT4L 0x239 /* Data BAT 4 Lower Register */
+#define SPRN_DBAT4U 0x238 /* Data BAT 4 Upper Register */
+#define SPRN_DBAT5L 0x23B /* Data BAT 5 Lower Register */
+#define SPRN_DBAT5U 0x23A /* Data BAT 5 Upper Register */
+#define SPRN_DBAT6L 0x23D /* Data BAT 6 Lower Register */
+#define SPRN_DBAT6U 0x23C /* Data BAT 6 Upper Register */
+#define SPRN_DBAT7L 0x23F /* Data BAT 7 Lower Register */
+#define SPRN_DBAT7U 0x23E /* Data BAT 7 Lower Register */
+#define SPRN_DBCR 0x3F2 /* Debug Control Regsiter */
+#define DBCR_EDM 0x80000000
+#define DBCR_IDM 0x40000000
+#define DBCR_RST(x) (((x) & 0x3) << 28)
+#define DBCR_RST_NONE 0
+#define DBCR_RST_CORE 1
+#define DBCR_RST_CHIP 2
+#define DBCR_RST_SYSTEM 3
+#define DBCR_IC 0x08000000 /* Instruction Completion Debug Evnt */
+#define DBCR_BT 0x04000000 /* Branch Taken Debug Event */
+#define DBCR_EDE 0x02000000 /* Exception Debug Event */
+#define DBCR_TDE 0x01000000 /* TRAP Debug Event */
+#define DBCR_FER 0x00F80000 /* First Events Remaining Mask */
+#define DBCR_FT 0x00040000 /* Freeze Timers on Debug Event */
+#define DBCR_IA1 0x00020000 /* Instr. Addr. Compare 1 Enable */
+#define DBCR_IA2 0x00010000 /* Instr. Addr. Compare 2 Enable */
+#define DBCR_D1R 0x00008000 /* Data Addr. Compare 1 Read Enable */
+#define DBCR_D1W 0x00004000 /* Data Addr. Compare 1 Write Enable */
+#define DBCR_D1S(x) (((x) & 0x3) << 12) /* Data Adrr. Compare 1 Size */
+#define DAC_BYTE 0
+#define DAC_HALF 1
+#define DAC_WORD 2
+#define DAC_QUAD 3
+#define DBCR_D2R 0x00000800 /* Data Addr. Compare 2 Read Enable */
+#define DBCR_D2W 0x00000400 /* Data Addr. Compare 2 Write Enable */
+#define DBCR_D2S(x) (((x) & 0x3) << 8) /* Data Addr. Compare 2 Size */
+#define DBCR_SBT 0x00000040 /* Second Branch Taken Debug Event */
+#define DBCR_SED 0x00000020 /* Second Exception Debug Event */
+#define DBCR_STD 0x00000010 /* Second Trap Debug Event */
+#define DBCR_SIA 0x00000008 /* Second IAC Enable */
+#define DBCR_SDA 0x00000004 /* Second DAC Enable */
+#define DBCR_JOI 0x00000002 /* JTAG Serial Outbound Int. Enable */
+#define DBCR_JII 0x00000001 /* JTAG Serial Inbound Int. Enable */
+#ifndef CONFIG_BOOKE
+#define SPRN_DBCR0 0x3F2 /* Debug Control Register 0 */
+#else
+#define SPRN_DBCR0 0x134 /* Book E Debug Control Register 0 */
+#endif /* CONFIG_BOOKE */
+#ifndef CONFIG_BOOKE
+#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */
+#define SPRN_DBSR 0x3F0 /* Debug Status Register */
+#else
+#define SPRN_DBCR1 0x135 /* Book E Debug Control Register 1 */
+#ifdef CONFIG_BOOKE
+#define SPRN_DBDR 0x3f3 /* Debug Data Register */
+#endif
+#define SPRN_DBSR 0x130 /* Book E Debug Status Register */
+#define DBSR_IC 0x08000000 /* Book E Instruction Completion */
+#define DBSR_TIE 0x01000000 /* Book E Trap Instruction Event */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */
+#define DCCR_NOCACHE 0 /* Noncacheable */
+#define DCCR_CACHE 1 /* Cacheable */
+#ifndef CONFIG_BOOKE
+#define SPRN_DCDBTRL 0x39c /* Data Cache Debug Tag Register Low */
+#define SPRN_DCDBTRH 0x39d /* Data Cache Debug Tag Register High */
+#endif
+#define SPRN_DCMP 0x3D1 /* Data TLB Compare Register */
+#define SPRN_DCWR 0x3BA /* Data Cache Write-thru Register */
+#define DCWR_COPY 0 /* Copy-back */
+#define DCWR_WRITE 1 /* Write-through */
+#ifndef CONFIG_BOOKE
+#define SPRN_DEAR 0x3D5 /* Data Error Address Register */
+#else
+#define SPRN_DEAR 0x03D /* Book E Data Error Address Register */
+#endif /* CONFIG_BOOKE */
+#define SPRN_DEC 0x016 /* Decrement Register */
+#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
+#ifdef CONFIG_BOOKE
+#define SPRN_DNV0 0x390 /* Data Cache Normal Victim 0 */
+#define SPRN_DNV1 0x391 /* Data Cache Normal Victim 1 */
+#define SPRN_DNV2 0x392 /* Data Cache Normal Victim 2 */
+#define SPRN_DNV3 0x393 /* Data Cache Normal Victim 3 */
+#endif
+#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
+#ifdef CONFIG_BOOKE
+#define SPRN_DTV0 0x394 /* Data Cache Transient Victim 0 */
+#define SPRN_DTV1 0x395 /* Data Cache Transient Victim 1 */
+#define SPRN_DTV2 0x396 /* Data Cache Transient Victim 2 */
+#define SPRN_DTV3 0x397 /* Data Cache Transient Victim 3 */
+#define SPRN_DVLIM 0x398 /* Data Cache Victim Limit */
+#endif
+#define SPRN_EAR 0x11A /* External Address Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */
+#else
+#define SPRN_ESR 0x03E /* Book E Exception Syndrome Register */
+#endif /* CONFIG_BOOKE */
+#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */
+#define ESR_IMCN 0x40000000 /* Instr. Machine Check - Non-config */
+#define ESR_IMCB 0x20000000 /* Instr. Machine Check - Bus error */
+#define ESR_IMCT 0x10000000 /* Instr. Machine Check - Timeout */
+#define ESR_PIL 0x08000000 /* Program Exception - Illegal */
+#define ESR_PPR 0x04000000 /* Program Exception - Priveleged */
+#define ESR_PTR 0x02000000 /* Program Exception - Trap */
+#define ESR_DST 0x00800000 /* Storage Exception - Data miss */
+#define ESR_DIZ 0x00400000 /* Storage Exception - Zone fault */
+#define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */
+#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
+#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
+#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
+
+#define HID0_ICE_SHIFT 15
+#define HID0_DCE_SHIFT 14
+#define HID0_DLOCK_SHIFT 12
+
+#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
+#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
+#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
+#define HID0_SBCLK (1<<27)
+#define HID0_EICE (1<<26)
+#define HID0_ECLK (1<<25)
+#define HID0_PAR (1<<24)
+#define HID0_DOZE (1<<23)
+#define HID0_NAP (1<<22)
+#define HID0_SLEEP (1<<21)
+#define HID0_DPM (1<<20)
+#define HID0_ICE (1<<HID0_ICE_SHIFT) /* Instruction Cache Enable */
+#define HID0_DCE (1<<HID0_DCE_SHIFT) /* Data Cache Enable */
+#define HID0_TBEN (1<<14) /* Time Base Enable */
+#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
+#define HID0_DLOCK (1<<HID0_DLOCK_SHIFT) /* Data Cache Lock */
+#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
+#define HID0_DCFI (1<<10) /* Data Cache Flash Invalidate */
+#define HID0_DCI HID0_DCFI
+#define HID0_SPD (1<<9) /* Speculative disable */
+#define HID0_ENMAS7 (1<<7) /* Enable MAS7 Update for 36-bit phys */
+#define HID0_SGE (1<<7) /* Store Gathering Enable */
+#define HID0_SIED HID_SGE /* Serial Instr. Execution [Disable] */
+#define HID0_DCFA (1<<6) /* Data Cache Flush Assist */
+#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */
+#define HID0_ABE (1<<3) /* Address Broadcast Enable */
+#define HID0_BHTE (1<<2) /* Branch History Table Enable */
+#define HID0_BTCD (1<<1) /* Branch target cache disable */
+#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
+#define HID1_RFXE (1<<17) /* Read Fault Exception Enable */
+#define HID1_ASTME (1<<13) /* Address bus streaming mode */
+#define HID1_ABE (1<<12) /* Address broadcast enable */
+#define HID1_MBDD (1<<6) /* optimized sync instruction */
+#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
+#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
+#else
+#define SPRN_IAC1 0x138 /* Book E Instruction Address Compare 1 */
+#define SPRN_IAC2 0x139 /* Book E Instruction Address Compare 2 */
+#endif /* CONFIG_BOOKE */
+#define SPRN_IBAT0L 0x211 /* Instruction BAT 0 Lower Register */
+#define SPRN_IBAT0U 0x210 /* Instruction BAT 0 Upper Register */
+#define SPRN_IBAT1L 0x213 /* Instruction BAT 1 Lower Register */
+#define SPRN_IBAT1U 0x212 /* Instruction BAT 1 Upper Register */
+#define SPRN_IBAT2L 0x215 /* Instruction BAT 2 Lower Register */
+#define SPRN_IBAT2U 0x214 /* Instruction BAT 2 Upper Register */
+#define SPRN_IBAT3L 0x217 /* Instruction BAT 3 Lower Register */
+#define SPRN_IBAT3U 0x216 /* Instruction BAT 3 Upper Register */
+#define SPRN_IBAT4L 0x231 /* Instruction BAT 4 Lower Register */
+#define SPRN_IBAT4U 0x230 /* Instruction BAT 4 Upper Register */
+#define SPRN_IBAT5L 0x233 /* Instruction BAT 5 Lower Register */
+#define SPRN_IBAT5U 0x232 /* Instruction BAT 5 Upper Register */
+#define SPRN_IBAT6L 0x235 /* Instruction BAT 6 Lower Register */
+#define SPRN_IBAT6U 0x234 /* Instruction BAT 6 Upper Register */
+#define SPRN_IBAT7L 0x237 /* Instruction BAT 7 Lower Register */
+#define SPRN_IBAT7U 0x236 /* Instruction BAT 7 Upper Register */
+#define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */
+#define ICCR_NOCACHE 0 /* Noncacheable */
+#define ICCR_CACHE 1 /* Cacheable */
+#define SPRN_ICDBDR 0x3D3 /* Instruction Cache Debug Data Register */
+#ifdef CONFIG_BOOKE
+#define SPRN_ICDBTRL 0x39e /* instruction cache debug tag register low */
+#define SPRN_ICDBTRH 0x39f /* instruction cache debug tag register high */
+#endif
+#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
+#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
+#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
+#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
+#ifdef CONFIG_BOOKE
+#define SPRN_INV0 0x370 /* Instruction Cache Normal Victim 0 */
+#define SPRN_INV1 0x371 /* Instruction Cache Normal Victim 1 */
+#define SPRN_INV2 0x372 /* Instruction Cache Normal Victim 2 */
+#define SPRN_INV3 0x373 /* Instruction Cache Normal Victim 3 */
+#define SPRN_ITV0 0x374 /* Instruction Cache Transient Victim 0 */
+#define SPRN_ITV1 0x375 /* Instruction Cache Transient Victim 1 */
+#define SPRN_ITV2 0x376 /* Instruction Cache Transient Victim 2 */
+#define SPRN_ITV3 0x377 /* Instruction Cache Transient Victim 3 */
+#define SPRN_IVLIM 0x399 /* Instruction Cache Victim Limit */
+#endif
+#define SPRN_LDSTCR 0x3F8 /* Load/Store Control Register */
+#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
+#define SPRN_LR 0x008 /* Link Register */
+#define SPRN_MBAR 0x137 /* System memory base address */
+#define SPRN_MMCR0 0x3B8 /* Monitor Mode Control Register 0 */
+#define SPRN_MMCR1 0x3BC /* Monitor Mode Control Register 1 */
+#ifdef CONFIG_BOOKE
+#define SPRN_MMUCR 0x3b2 /* MMU Control Register */
+#endif
+#define SPRN_PBL1 0x3FC /* Protection Bound Lower 1 */
+#define SPRN_PBL2 0x3FE /* Protection Bound Lower 2 */
+#define SPRN_PBU1 0x3FD /* Protection Bound Upper 1 */
+#define SPRN_PBU2 0x3FF /* Protection Bound Upper 2 */
+#ifndef CONFIG_BOOKE
+#define SPRN_PID 0x3B1 /* Process ID */
+#define SPRN_PIR 0x3FF /* Processor Identification Register */
+#else
+#define SPRN_PID 0x030 /* Book E Process ID */
+#define SPRN_PIR 0x11E /* Book E Processor Identification Register */
+#endif /* CONFIG_BOOKE */
+#define SPRN_PIT 0x3DB /* Programmable Interval Timer */
+#define SPRN_PMC1 0x3B9 /* Performance Counter Register 1 */
+#define SPRN_PMC2 0x3BA /* Performance Counter Register 2 */
+#define SPRN_PMC3 0x3BD /* Performance Counter Register 3 */
+#define SPRN_PMC4 0x3BE /* Performance Counter Register 4 */
+#define SPRN_PVR 0x11F /* Processor Version Register */
+#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
+#ifdef CONFIG_BOOKE
+#define SPRN_RSTCFG 0x39b /* Reset Configuration */
+#endif
+#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
+#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
+#define SPRN_SGR 0x3B9 /* Storage Guarded Register */
+#define SGR_NORMAL 0
+#define SGR_GUARDED 1
+#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
+#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
+#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
+#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
+#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
+#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
+#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
+#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
+#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
+#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
+#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
+#define SPRN_SRR2 0x3DE /* Save/Restore Register 2 */
+#define SPRN_SRR3 0x3DF /* Save/Restore Register 3 */
+
+#ifdef CONFIG_BOOKE
+#define SPRN_SVR 0x3FF /* System Version Register */
+#else
+#define SPRN_SVR 0x11E /* System Version Register */
+#endif
+#define SPRN_TBHI 0x3DC /* Time Base High */
+#define SPRN_TBHU 0x3CC /* Time Base High User-mode */
+#define SPRN_TBLO 0x3DD /* Time Base Low */
+#define SPRN_TBLU 0x3CD /* Time Base Low User-mode */
+#define SPRN_TBRL 0x10C /* Time Base Read Lower Register */
+#define SPRN_TBRU 0x10D /* Time Base Read Upper Register */
+#define SPRN_TBWL 0x11C /* Time Base Write Lower Register */
+#define SPRN_TBWU 0x11D /* Time Base Write Upper Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_TCR 0x3DA /* Timer Control Register */
+#else
+#define SPRN_TCR 0x154 /* Book E Timer Control Register */
+#endif /* CONFIG_BOOKE */
+#define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */
+#define WP_2_17 0 /* 2^17 clocks */
+#define WP_2_21 1 /* 2^21 clocks */
+#define WP_2_25 2 /* 2^25 clocks */
+#define WP_2_29 3 /* 2^29 clocks */
+#define TCR_WRC(x) (((x)&0x3)<<28) /* WDT Reset Control */
+#define WRC_NONE 0 /* No reset will occur */
+#define WRC_CORE 1 /* Core reset will occur */
+#define WRC_CHIP 2 /* Chip reset will occur */
+#define WRC_SYSTEM 3 /* System reset will occur */
+#define TCR_WIE 0x08000000 /* WDT Interrupt Enable */
+#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */
+#define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */
+#define FP_2_9 0 /* 2^9 clocks */
+#define FP_2_13 1 /* 2^13 clocks */
+#define FP_2_17 2 /* 2^17 clocks */
+#define FP_2_21 3 /* 2^21 clocks */
+#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */
+#define TCR_ARE 0x00400000 /* Auto Reload Enable */
+#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
+#define THRM1_TIN (1<<0)
+#define THRM1_TIV (1<<1)
+#define THRM1_THRES (0x7f<<2)
+#define THRM1_TID (1<<29)
+#define THRM1_TIE (1<<30)
+#define THRM1_V (1<<31)
+#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
+#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
+#define THRM3_E (1<<31)
+#define SPRN_TLBMISS 0x3D4 /* 980 7450 TLB Miss Register */
+#ifndef CONFIG_BOOKE
+#define SPRN_TSR 0x3D8 /* Timer Status Register */
+#else
+#define SPRN_TSR 0x150 /* Book E Timer Status Register */
+#endif /* CONFIG_BOOKE */
+#define TSR_ENW 0x80000000 /* Enable Next Watchdog */
+#define TSR_WIS 0x40000000 /* WDT Interrupt Status */
+#define TSR_WRS(x) (((x)&0x3)<<28) /* WDT Reset Status */
+#define WRS_NONE 0 /* No WDT reset occurred */
+#define WRS_CORE 1 /* WDT forced core reset */
+#define WRS_CHIP 2 /* WDT forced chip reset */
+#define WRS_SYSTEM 3 /* WDT forced system reset */
+#define TSR_PIS 0x08000000 /* PIT Interrupt Status */
+#define TSR_FIS 0x04000000 /* FIT Interrupt Status */
+#define SPRN_UMMCR0 0x3A8 /* User Monitor Mode Control Register 0 */
+#define SPRN_UMMCR1 0x3AC /* User Monitor Mode Control Register 0 */
+#define SPRN_UPMC1 0x3A9 /* User Performance Counter Register 1 */
+#define SPRN_UPMC2 0x3AA /* User Performance Counter Register 2 */
+#define SPRN_UPMC3 0x3AD /* User Performance Counter Register 3 */
+#define SPRN_UPMC4 0x3AE /* User Performance Counter Register 4 */
+#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
+#define SPRN_XER 0x001 /* Fixed Point Exception Register */
+#define SPRN_ZPR 0x3B0 /* Zone Protection Register */
+
+/* Book E definitions */
+#define SPRN_DECAR 0x036 /* Decrementer Auto Reload Register */
+#define SPRN_CSRR0 0x03A /* Critical SRR0 */
+#define SPRN_CSRR1 0x03B /* Critical SRR0 */
+#define SPRN_IVPR 0x03F /* Interrupt Vector Prefix Register */
+#define SPRN_USPRG0 0x100 /* User Special Purpose Register General 0 */
+#define SPRN_SPRG4R 0x104 /* Special Purpose Register General 4 Read */
+#define SPRN_SPRG5R 0x105 /* Special Purpose Register General 5 Read */
+#define SPRN_SPRG6R 0x106 /* Special Purpose Register General 6 Read */
+#define SPRN_SPRG7R 0x107 /* Special Purpose Register General 7 Read */
+#define SPRN_SPRG4W 0x114 /* Special Purpose Register General 4 Write */
+#define SPRN_SPRG5W 0x115 /* Special Purpose Register General 5 Write */
+#define SPRN_SPRG6W 0x116 /* Special Purpose Register General 6 Write */
+#define SPRN_SPRG7W 0x117 /* Special Purpose Register General 7 Write */
+#define SPRN_DBCR2 0x136 /* Debug Control Register 2 */
+#define SPRN_IAC3 0x13A /* Instruction Address Compare 3 */
+#define SPRN_IAC4 0x13B /* Instruction Address Compare 4 */
+#define SPRN_DVC1 0x13E /* Data Value Compare Register 1 */
+#define SPRN_DVC2 0x13F /* Data Value Compare Register 2 */
+#define SPRN_IVOR0 0x190 /* Interrupt Vector Offset Register 0 */
+#define SPRN_IVOR1 0x191 /* Interrupt Vector Offset Register 1 */
+#define SPRN_IVOR2 0x192 /* Interrupt Vector Offset Register 2 */
+#define SPRN_IVOR3 0x193 /* Interrupt Vector Offset Register 3 */
+#define SPRN_IVOR4 0x194 /* Interrupt Vector Offset Register 4 */
+#define SPRN_IVOR5 0x195 /* Interrupt Vector Offset Register 5 */
+#define SPRN_IVOR6 0x196 /* Interrupt Vector Offset Register 6 */
+#define SPRN_IVOR7 0x197 /* Interrupt Vector Offset Register 7 */
+#define SPRN_IVOR8 0x198 /* Interrupt Vector Offset Register 8 */
+#define SPRN_IVOR9 0x199 /* Interrupt Vector Offset Register 9 */
+#define SPRN_IVOR10 0x19a /* Interrupt Vector Offset Register 10 */
+#define SPRN_IVOR11 0x19b /* Interrupt Vector Offset Register 11 */
+#define SPRN_IVOR12 0x19c /* Interrupt Vector Offset Register 12 */
+#define SPRN_IVOR13 0x19d /* Interrupt Vector Offset Register 13 */
+#define SPRN_IVOR14 0x19e /* Interrupt Vector Offset Register 14 */
+#define SPRN_IVOR15 0x19f /* Interrupt Vector Offset Register 15 */
+#define SPRN_IVOR38 0x1b0 /* Interrupt Vector Offset Register 38 */
+#define SPRN_IVOR39 0x1b1 /* Interrupt Vector Offset Register 39 */
+#define SPRN_IVOR40 0x1b2 /* Interrupt Vector Offset Register 40 */
+#define SPRN_IVOR41 0x1b3 /* Interrupt Vector Offset Register 41 */
+#define SPRN_GIVOR2 0x1b8 /* Guest Interrupt Vector Offset Register 2 */
+#define SPRN_GIVOR3 0x1b9 /* Guest Interrupt Vector Offset Register 3 */
+#define SPRN_GIVOR4 0x1ba /* Guest Interrupt Vector Offset Register 4 */
+#define SPRN_GIVOR8 0x1bb /* Guest Interrupt Vector Offset Register 8 */
+#define SPRN_GIVOR13 0x1bc /* Guest Interrupt Vector Offset Register 13 */
+#define SPRN_GIVOR14 0x1bd /* Guest Interrupt Vector Offset Register 14 */
+
+/* e500 definitions */
+#define SPRN_L1CFG0 0x203 /* L1 Cache Configuration Register 0 */
+#define SPRN_L1CFG1 0x204 /* L1 Cache Configuration Register 1 */
+#define SPRN_L2CFG0 0x207 /* L2 Cache Configuration Register 0 */
+#define SPRN_L1CSR0 0x3f2 /* L1 Data Cache Control and Status Register 0 */
+#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */
+#define L1CSR0_CUL 0x00000400 /* (D-)Cache Unable to Lock */
+#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */
+#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
+#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */
+#define SPRN_L1CSR1 0x3f3 /* L1 Instruction Cache Control and Status Register 1 */
+#define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */
+#define L1CSR1_ICUL 0x00000400 /* I-Cache Unable to Lock */
+#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */
+#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */
+#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */
+#define SPRN_L1CSR2 0x25e /* L1 Data Cache Control and Status Register 2 */
+#define L1CSR2_DCWS 0x40000000 /* Data Cache Write Shadow */
+#define SPRN_L2CSR0 0x3f9 /* L2 Data Cache Control and Status Register 0 */
+#define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */
+#define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */
+#define L2CSR0_L2WP 0x1c000000 /* L2 I/D Way Partioning */
+#define L2CSR0_L2CM 0x03000000 /* L2 Cache Coherency Mode */
+#define L2CSR0_L2FI 0x00200000 /* L2 Cache Flash Invalidate */
+#define L2CSR0_L2IO 0x00100000 /* L2 Cache Instruction Only */
+#define L2CSR0_L2DO 0x00010000 /* L2 Cache Data Only */
+#define L2CSR0_L2REP 0x00003000 /* L2 Line Replacement Algo */
+
+/* e6500 */
+#define L2CSR0_L2REP_SPLRUAGE 0x00000000 /* L2REP Streaming PLRU with Aging */
+#define L2CSR0_L2REP_FIFO 0x00001000 /* L2REP FIFO */
+#define L2CSR0_L2REP_SPLRU 0x00002000 /* L2REP Streaming PLRU */
+#define L2CSR0_L2REP_PLRU 0x00003000 /* L2REP PLRU */
+
+#define L2CSR0_L2REP_MODE L2CSR0_L2REP_SPLRUAGE
+
+#define L2CSR0_L2FL 0x00000800 /* L2 Cache Flush */
+#define L2CSR0_L2LFC 0x00000400 /* L2 Cache Lock Flash Clear */
+#define L2CSR0_L2LOA 0x00000080 /* L2 Cache Lock Overflow Allocate */
+#define L2CSR0_L2LO 0x00000020 /* L2 Cache Lock Overflow */
+#define SPRN_L2CSR1 0x3fa /* L2 Data Cache Control and Status Register 1 */
+
+#define SPRN_TLB0CFG 0x2B0 /* TLB 0 Config Register */
+#define SPRN_TLB1CFG 0x2B1 /* TLB 1 Config Register */
+#define TLBnCFG_NENTRY_MASK 0x00000fff
+#define SPRN_TLB0PS 0x158 /* TLB 0 Page Size Register */
+#define SPRN_TLB1PS 0x159 /* TLB 1 Page Size Register */
+#define SPRN_MMUCSR0 0x3f4 /* MMU control and status register 0 */
+#define SPRN_MMUCFG 0x3F7 /* MMU Configuration Register */
+#define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */
+#define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */
+#define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */
+#define SPRN_MAS0 0x270 /* MMU Assist Register 0 */
+#define SPRN_MAS1 0x271 /* MMU Assist Register 1 */
+#define SPRN_MAS2 0x272 /* MMU Assist Register 2 */
+#define SPRN_MAS3 0x273 /* MMU Assist Register 3 */
+#define SPRN_MAS4 0x274 /* MMU Assist Register 4 */
+#define SPRN_MAS5 0x275 /* MMU Assist Register 5 */
+#define SPRN_MAS6 0x276 /* MMU Assist Register 6 */
+#define SPRN_MAS7 0x3B0 /* MMU Assist Register 7 */
+#define SPRN_MAS8 0x155 /* MMU Assist Register 8 */
+
+#define SPRN_IVOR32 0x210 /* Interrupt Vector Offset Register 32 */
+#define SPRN_IVOR33 0x211 /* Interrupt Vector Offset Register 33 */
+#define SPRN_IVOR34 0x212 /* Interrupt Vector Offset Register 34 */
+#define SPRN_IVOR35 0x213 /* Interrupt Vector Offset Register 35 */
+#define SPRN_IVOR36 0x214 /* Interrupt Vector Offset Register 36 */
+#define SPRN_IVOR37 0x215 /* Interrupt Vector Offset Register 37 */
+#define SPRN_SPEFSCR 0x200 /* SPE & Embedded FP Status & Control */
+
+#define SPRN_MCSRR0 0x23a /* Machine Check Save and Restore Register 0 */
+#define SPRN_MCSRR1 0x23b /* Machine Check Save and Restore Register 1 */
+#define SPRN_BUCSR 0x3f5 /* Branch Control and Status Register */
+#define BUCSR_STAC_EN 0x01000000 /* Segment target addr cache enable */
+#define BUCSR_LS_EN 0x00400000 /* Link stack enable */
+#define BUCSR_BBFI 0x00000200 /* Branch buffer flash invalidate */
+#define BUCSR_BPEN 0x00000001 /* Branch prediction enable */
+#define BUCSR_ENABLE (BUCSR_STAC_EN|BUCSR_LS_EN|BUCSR_BBFI|BUCSR_BPEN)
+#define SPRN_BBEAR 0x201 /* Branch Buffer Entry Address Register */
+#define SPRN_BBTAR 0x202 /* Branch Buffer Target Address Register */
+#define SPRN_PID1 0x279 /* Process ID Register 1 */
+#define SPRN_PID2 0x27a /* Process ID Register 2 */
+#define SPRN_MCSR 0x23c /* Machine Check Syndrome register */
+#define SPRN_MCAR 0x23d /* Machine Check Address register */
+#define MCSR_MCS 0x80000000 /* Machine Check Summary */
+#define MCSR_IB 0x40000000 /* Instruction PLB Error */
+#if defined(CONFIG_440)
+#define MCSR_DRB 0x20000000 /* Data Read PLB Error */
+#define MCSR_DWB 0x10000000 /* Data Write PLB Error */
+#else
+#define MCSR_DB 0x20000000 /* Data PLB Error */
+#endif /* defined(CONFIG_440) */
+#define MCSR_TLBP 0x08000000 /* TLB Parity Error */
+#define MCSR_ICP 0x04000000 /* I-Cache Parity Error */
+#define MCSR_DCSP 0x02000000 /* D-Cache Search Parity Error */
+#define MCSR_DCFP 0x01000000 /* D-Cache Flush Parity Error */
+#define MCSR_IMPE 0x00800000 /* Imprecise Machine Check Exception */
+#define ESR_ST 0x00800000 /* Store Operation */
+
+#if defined(CONFIG_MPC86xx)
+#define SPRN_MSSCR0 0x3f6
+#define SPRN_MSSSR0 0x3f7
+#endif
+
+#define SPRN_HDBCR0 0x3d0
+#define SPRN_HDBCR1 0x3d1
+#define SPRN_HDBCR2 0x3d2
+#define SPRN_HDBCR3 0x3d3
+#define SPRN_HDBCR4 0x3d4
+#define SPRN_HDBCR5 0x3d5
+#define SPRN_HDBCR6 0x3d6
+#define SPRN_HDBCR7 0x277
+#define SPRN_HDBCR8 0x278
+
+/* Short-hand versions for a number of the above SPRNs */
+
+#define CTR SPRN_CTR /* Counter Register */
+#define DAR SPRN_DAR /* Data Address Register */
+#define DABR SPRN_DABR /* Data Address Breakpoint Register */
+#define DAC1 SPRN_DAC1 /* Data Address Register 1 */
+#define DAC2 SPRN_DAC2 /* Data Address Register 2 */
+#define DBAT0L SPRN_DBAT0L /* Data BAT 0 Lower Register */
+#define DBAT0U SPRN_DBAT0U /* Data BAT 0 Upper Register */
+#define DBAT1L SPRN_DBAT1L /* Data BAT 1 Lower Register */
+#define DBAT1U SPRN_DBAT1U /* Data BAT 1 Upper Register */
+#define DBAT2L SPRN_DBAT2L /* Data BAT 2 Lower Register */
+#define DBAT2U SPRN_DBAT2U /* Data BAT 2 Upper Register */
+#define DBAT3L SPRN_DBAT3L /* Data BAT 3 Lower Register */
+#define DBAT3U SPRN_DBAT3U /* Data BAT 3 Upper Register */
+#define DBAT4L SPRN_DBAT4L /* Data BAT 4 Lower Register */
+#define DBAT4U SPRN_DBAT4U /* Data BAT 4 Upper Register */
+#define DBAT5L SPRN_DBAT5L /* Data BAT 5 Lower Register */
+#define DBAT5U SPRN_DBAT5U /* Data BAT 5 Upper Register */
+#define DBAT6L SPRN_DBAT6L /* Data BAT 6 Lower Register */
+#define DBAT6U SPRN_DBAT6U /* Data BAT 6 Upper Register */
+#define DBAT7L SPRN_DBAT7L /* Data BAT 7 Lower Register */
+#define DBAT7U SPRN_DBAT7U /* Data BAT 7 Upper Register */
+#define DBCR0 SPRN_DBCR0 /* Debug Control Register 0 */
+#define DBCR1 SPRN_DBCR1 /* Debug Control Register 1 */
+#define DBSR SPRN_DBSR /* Debug Status Register */
+#define DCMP SPRN_DCMP /* Data TLB Compare Register */
+#define DEC SPRN_DEC /* Decrement Register */
+#define DMISS SPRN_DMISS /* Data TLB Miss Register */
+#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
+#define EAR SPRN_EAR /* External Address Register */
+#define ESR SPRN_ESR /* Exception Syndrome Register */
+#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */
+#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */
+#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
+#define HID1 SPRN_HID1 /* Hardware Implementation Register 1 */
+#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
+#define IAC1 SPRN_IAC1 /* Instruction Address Register 1 */
+#define IAC2 SPRN_IAC2 /* Instruction Address Register 2 */
+#define IBAT0L SPRN_IBAT0L /* Instruction BAT 0 Lower Register */
+#define IBAT0U SPRN_IBAT0U /* Instruction BAT 0 Upper Register */
+#define IBAT1L SPRN_IBAT1L /* Instruction BAT 1 Lower Register */
+#define IBAT1U SPRN_IBAT1U /* Instruction BAT 1 Upper Register */
+#define IBAT2L SPRN_IBAT2L /* Instruction BAT 2 Lower Register */
+#define IBAT2U SPRN_IBAT2U /* Instruction BAT 2 Upper Register */
+#define IBAT3L SPRN_IBAT3L /* Instruction BAT 3 Lower Register */
+#define IBAT3U SPRN_IBAT3U /* Instruction BAT 3 Upper Register */
+#define IBAT4L SPRN_IBAT4L /* Instruction BAT 4 Lower Register */
+#define IBAT4U SPRN_IBAT4U /* Instruction BAT 4 Upper Register */
+#define IBAT5L SPRN_IBAT5L /* Instruction BAT 5 Lower Register */
+#define IBAT5U SPRN_IBAT5U /* Instruction BAT 5 Upper Register */
+#define IBAT6L SPRN_IBAT6L /* Instruction BAT 6 Lower Register */
+#define IBAT6U SPRN_IBAT6U /* Instruction BAT 6 Upper Register */
+#define IBAT7L SPRN_IBAT7L /* Instruction BAT 7 Lower Register */
+#define IBAT7U SPRN_IBAT7U /* Instruction BAT 7 Lower Register */
+#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */
+#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */
+#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */
+#define LDSTCR SPRN_LDSTCR /* Load/Store Control Register */
+#define L2CR SPRN_L2CR /* PPC 750 L2 control register */
+#define LR SPRN_LR
+#define MBAR SPRN_MBAR /* System memory base address */
+#if defined(CONFIG_MPC86xx)
+#define MSSCR0 SPRN_MSSCR0
+#endif
+#if defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+#define PIR SPRN_PIR
+#endif
+#define SVR SPRN_SVR /* System-On-Chip Version Register */
+#define PVR SPRN_PVR /* Processor Version */
+#define RPA SPRN_RPA /* Required Physical Address Register */
+#define SDR1 SPRN_SDR1 /* MMU hash base register */
+#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
+#define SPR1 SPRN_SPRG1
+#define SPR2 SPRN_SPRG2
+#define SPR3 SPRN_SPRG3
+#define SPRG0 SPRN_SPRG0
+#define SPRG1 SPRN_SPRG1
+#define SPRG2 SPRN_SPRG2
+#define SPRG3 SPRN_SPRG3
+#define SPRG4 SPRN_SPRG4
+#define SPRG5 SPRN_SPRG5
+#define SPRG6 SPRN_SPRG6
+#define SPRG7 SPRN_SPRG7
+#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */
+#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */
+#define SRR2 SPRN_SRR2 /* Save and Restore Register 2 */
+#define SRR3 SPRN_SRR3 /* Save and Restore Register 3 */
+#define SVR SPRN_SVR /* System Version Register */
+#define TBRL SPRN_TBRL /* Time Base Read Lower Register */
+#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
+#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
+#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
+#define TCR SPRN_TCR /* Timer Control Register */
+#define TSR SPRN_TSR /* Timer Status Register */
+#define ICTC 1019
+#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */
+#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
+#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
+#define XER SPRN_XER
+
+#define DECAR SPRN_DECAR
+#define CSRR0 SPRN_CSRR0
+#define CSRR1 SPRN_CSRR1
+#define IVPR SPRN_IVPR
+#define USPRG0 SPRN_USPRG
+#define SPRG4R SPRN_SPRG4R
+#define SPRG5R SPRN_SPRG5R
+#define SPRG6R SPRN_SPRG6R
+#define SPRG7R SPRN_SPRG7R
+#define SPRG4W SPRN_SPRG4W
+#define SPRG5W SPRN_SPRG5W
+#define SPRG6W SPRN_SPRG6W
+#define SPRG7W SPRN_SPRG7W
+#define DEAR SPRN_DEAR
+#define DBCR2 SPRN_DBCR2
+#define IAC3 SPRN_IAC3
+#define IAC4 SPRN_IAC4
+#define DVC1 SPRN_DVC1
+#define DVC2 SPRN_DVC2
+#define IVOR0 SPRN_IVOR0
+#define IVOR1 SPRN_IVOR1
+#define IVOR2 SPRN_IVOR2
+#define IVOR3 SPRN_IVOR3
+#define IVOR4 SPRN_IVOR4
+#define IVOR5 SPRN_IVOR5
+#define IVOR6 SPRN_IVOR6
+#define IVOR7 SPRN_IVOR7
+#define IVOR8 SPRN_IVOR8
+#define IVOR9 SPRN_IVOR9
+#define IVOR10 SPRN_IVOR10
+#define IVOR11 SPRN_IVOR11
+#define IVOR12 SPRN_IVOR12
+#define IVOR13 SPRN_IVOR13
+#define IVOR14 SPRN_IVOR14
+#define IVOR15 SPRN_IVOR15
+#define IVOR32 SPRN_IVOR32
+#define IVOR33 SPRN_IVOR33
+#define IVOR34 SPRN_IVOR34
+#define IVOR35 SPRN_IVOR35
+#define MCSRR0 SPRN_MCSRR0
+#define MCSRR1 SPRN_MCSRR1
+#define L1CSR0 SPRN_L1CSR0
+#define L1CSR1 SPRN_L1CSR1
+#define L1CSR2 SPRN_L1CSR2
+#define L1CFG0 SPRN_L1CFG0
+#define L1CFG1 SPRN_L1CFG1
+#define L2CFG0 SPRN_L2CFG0
+#define L2CSR0 SPRN_L2CSR0
+#define L2CSR1 SPRN_L2CSR1
+#define MCSR SPRN_MCSR
+#define MMUCSR0 SPRN_MMUCSR0
+#define BUCSR SPRN_BUCSR
+#define PID0 SPRN_PID
+#define PID1 SPRN_PID1
+#define PID2 SPRN_PID2
+#define MAS0 SPRN_MAS0
+#define MAS1 SPRN_MAS1
+#define MAS2 SPRN_MAS2
+#define MAS3 SPRN_MAS3
+#define MAS4 SPRN_MAS4
+#define MAS5 SPRN_MAS5
+#define MAS6 SPRN_MAS6
+#define MAS7 SPRN_MAS7
+#define MAS8 SPRN_MAS8
+
+#if defined(CONFIG_4xx) || defined(CONFIG_44x) || defined(CONFIG_MPC85xx)
+#define DAR_DEAR DEAR
+#else
+#define DAR_DEAR DAR
+#endif
+
+/* Device Control Registers */
+
+#define DCRN_BEAR 0x090 /* Bus Error Address Register */
+#define DCRN_BESR 0x091 /* Bus Error Syndrome Register */
+#define BESR_DSES 0x80000000 /* Data-Side Error Status */
+#define BESR_DMES 0x40000000 /* DMA Error Status */
+#define BESR_RWS 0x20000000 /* Read/Write Status */
+#define BESR_ETMASK 0x1C000000 /* Error Type */
+#define ET_PROT 0
+#define ET_PARITY 1
+#define ET_NCFG 2
+#define ET_BUSERR 4
+#define ET_BUSTO 6
+#define DCRN_DMACC0 0x0C4 /* DMA Chained Count Register 0 */
+#define DCRN_DMACC1 0x0CC /* DMA Chained Count Register 1 */
+#define DCRN_DMACC2 0x0D4 /* DMA Chained Count Register 2 */
+#define DCRN_DMACC3 0x0DC /* DMA Chained Count Register 3 */
+#define DCRN_DMACR0 0x0C0 /* DMA Channel Control Register 0 */
+#define DCRN_DMACR1 0x0C8 /* DMA Channel Control Register 1 */
+#define DCRN_DMACR2 0x0D0 /* DMA Channel Control Register 2 */
+#define DCRN_DMACR3 0x0D8 /* DMA Channel Control Register 3 */
+#define DCRN_DMACT0 0x0C1 /* DMA Count Register 0 */
+#define DCRN_DMACT1 0x0C9 /* DMA Count Register 1 */
+#define DCRN_DMACT2 0x0D1 /* DMA Count Register 2 */
+#define DCRN_DMACT3 0x0D9 /* DMA Count Register 3 */
+#define DCRN_DMADA0 0x0C2 /* DMA Destination Address Register 0 */
+#define DCRN_DMADA1 0x0CA /* DMA Destination Address Register 1 */
+#define DCRN_DMADA2 0x0D2 /* DMA Destination Address Register 2 */
+#define DCRN_DMADA3 0x0DA /* DMA Destination Address Register 3 */
+#define DCRN_DMASA0 0x0C3 /* DMA Source Address Register 0 */
+#define DCRN_DMASA1 0x0CB /* DMA Source Address Register 1 */
+#define DCRN_DMASA2 0x0D3 /* DMA Source Address Register 2 */
+#define DCRN_DMASA3 0x0DB /* DMA Source Address Register 3 */
+#define DCRN_DMASR 0x0E0 /* DMA Status Register */
+#define DCRN_EXIER 0x042 /* External Interrupt Enable Register */
+#define EXIER_CIE 0x80000000 /* Critical Interrupt Enable */
+#define EXIER_SRIE 0x08000000 /* Serial Port Rx Int. Enable */
+#define EXIER_STIE 0x04000000 /* Serial Port Tx Int. Enable */
+#define EXIER_JRIE 0x02000000 /* JTAG Serial Port Rx Int. Enable */
+#define EXIER_JTIE 0x01000000 /* JTAG Serial Port Tx Int. Enable */
+#define EXIER_D0IE 0x00800000 /* DMA Channel 0 Interrupt Enable */
+#define EXIER_D1IE 0x00400000 /* DMA Channel 1 Interrupt Enable */
+#define EXIER_D2IE 0x00200000 /* DMA Channel 2 Interrupt Enable */
+#define EXIER_D3IE 0x00100000 /* DMA Channel 3 Interrupt Enable */
+#define EXIER_E0IE 0x00000010 /* External Interrupt 0 Enable */
+#define EXIER_E1IE 0x00000008 /* External Interrupt 1 Enable */
+#define EXIER_E2IE 0x00000004 /* External Interrupt 2 Enable */
+#define EXIER_E3IE 0x00000002 /* External Interrupt 3 Enable */
+#define EXIER_E4IE 0x00000001 /* External Interrupt 4 Enable */
+#define DCRN_EXISR 0x040 /* External Interrupt Status Register */
+#define DCRN_IOCR 0x0A0 /* Input/Output Configuration Register */
+#define IOCR_E0TE 0x80000000
+#define IOCR_E0LP 0x40000000
+#define IOCR_E1TE 0x20000000
+#define IOCR_E1LP 0x10000000
+#define IOCR_E2TE 0x08000000
+#define IOCR_E2LP 0x04000000
+#define IOCR_E3TE 0x02000000
+#define IOCR_E3LP 0x01000000
+#define IOCR_E4TE 0x00800000
+#define IOCR_E4LP 0x00400000
+#define IOCR_EDT 0x00080000
+#define IOCR_SOR 0x00040000
+#define IOCR_EDO 0x00008000
+#define IOCR_2XC 0x00004000
+#define IOCR_ATC 0x00002000
+#define IOCR_SPD 0x00001000
+#define IOCR_BEM 0x00000800
+#define IOCR_PTD 0x00000400
+#define IOCR_ARE 0x00000080
+#define IOCR_DRC 0x00000020
+#define IOCR_RDM(x) (((x) & 0x3) << 3)
+#define IOCR_TCS 0x00000004
+#define IOCR_SCS 0x00000002
+#define IOCR_SPC 0x00000001
+
+/* System-On-Chip Version Register */
+
+/* System-On-Chip Version Register (SVR) field extraction */
+
+#define SVR_VER(svr) (((svr) >> 16) & 0xFFFF) /* Version field */
+#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revision field */
+
+#define SVR_CID(svr) (((svr) >> 28) & 0x0F) /* Company or manufacturer ID */
+#define SVR_SOCOP(svr) (((svr) >> 22) & 0x3F) /* SOC integration options */
+#define SVR_SID(svr) (((svr) >> 16) & 0x3F) /* SOC ID */
+#define SVR_PROC(svr) (((svr) >> 12) & 0x0F) /* Process revision field */
+#define SVR_MFG(svr) (((svr) >> 8) & 0x0F) /* Manufacturing revision */
+#define SVR_MJREV(svr) (((svr) >> 4) & 0x0F) /* Major SOC design revision indicator */
+#define SVR_MNREV(svr) (((svr) >> 0) & 0x0F) /* Minor SOC design revision indicator */
+
+/* Processor Version Register */
+
+/* Processor Version Register (PVR) field extraction */
+
+#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+
+/*
+ * AMCC has further subdivided the standard PowerPC 16-bit version and
+ * revision subfields of the PVR for the PowerPC 403s into the following:
+ */
+
+#define PVR_FAM(pvr) (((pvr) >> 20) & 0xFFF) /* Family field */
+#define PVR_MEM(pvr) (((pvr) >> 16) & 0xF) /* Member field */
+#define PVR_CORE(pvr) (((pvr) >> 12) & 0xF) /* Core field */
+#define PVR_CFG(pvr) (((pvr) >> 8) & 0xF) /* Configuration field */
+#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
+#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
+
+/* e600 core PVR fields */
+
+#define PVR_E600_VER(pvr) (((pvr) >> 15) & 0xFFFF) /* Version/type */
+#define PVR_E600_TECH(pvr) (((pvr) >> 12) & 0xF) /* Technology */
+#define PVR_E600_MAJ(pvr) (((pvr) >> 8) & 0xF) /* Major revision */
+#define PVR_E600_MIN(pvr) (((pvr) >> 0) & 0xFF) /* Minor revision */
+
+/* Processor Version Numbers */
+
+#define PVR_403GA 0x00200000
+#define PVR_403GB 0x00200100
+#define PVR_403GC 0x00200200
+#define PVR_403GCX 0x00201400
+#define PVR_405GP 0x40110000
+#define PVR_405GP_RB 0x40110040
+#define PVR_405GP_RC 0x40110082
+#define PVR_405GP_RD 0x401100C4
+#define PVR_405GP_RE 0x40110145 /* same as pc405cr rev c */
+#define PVR_405CR_RA 0x40110041
+#define PVR_405CR_RB 0x401100C5
+#define PVR_405CR_RC 0x40110145 /* same as pc405gp rev e */
+#define PVR_405EP_RA 0x51210950
+#define PVR_405GPR_RB 0x50910951
+#define PVR_405EZ_RA 0x41511460
+#define PVR_405EXR2_RA 0x12911471 /* 405EXr rev A/B without Security */
+#define PVR_405EX1_RA 0x12911477 /* 405EX rev A/B with Security */
+#define PVR_405EXR1_RC 0x1291147B /* 405EXr rev C with Security */
+#define PVR_405EXR2_RC 0x12911479 /* 405EXr rev C without Security */
+#define PVR_405EX1_RC 0x1291147F /* 405EX rev C with Security */
+#define PVR_405EX2_RC 0x1291147D /* 405EX rev C without Security */
+#define PVR_405EXR1_RD 0x12911472 /* 405EXr rev D with Security */
+#define PVR_405EXR2_RD 0x12911470 /* 405EXr rev D without Security */
+#define PVR_405EX1_RD 0x12911475 /* 405EX rev D with Security */
+#define PVR_405EX2_RD 0x12911473 /* 405EX rev D without Security */
+#define PVR_440GP_RB 0x40120440
+#define PVR_440GP_RC 0x40120481
+#define PVR_440EP_RA 0x42221850
+#define PVR_440EP_RB 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */
+#define PVR_440EP_RC 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */
+#define PVR_440GR_RA 0x422218D3 /* 440EP rev B and 440GR rev A have same PVR */
+#define PVR_440GR_RB 0x422218D4 /* 440EP rev C and 440GR rev B have same PVR */
+#define PVR_440EPX1_RA 0x216218D0 /* 440EPX rev A with Security / Kasumi */
+#define PVR_440EPX2_RA 0x216218D4 /* 440EPX rev A without Security / Kasumi */
+#define PVR_440GRX1_RA 0x216218D0 /* 440GRX rev A with Security / Kasumi */
+#define PVR_440GRX2_RA 0x216218D4 /* 440GRX rev A without Security / Kasumi */
+#define PVR_440GX_RA 0x51B21850
+#define PVR_440GX_RB 0x51B21851
+#define PVR_440GX_RC 0x51B21892
+#define PVR_440GX_RF 0x51B21894
+#define PVR_405EP_RB 0x51210950
+#define PVR_440SP_6_RAB 0x53221850 /* 440SP rev A&B with RAID 6 support enabled */
+#define PVR_440SP_RAB 0x53321850 /* 440SP rev A&B without RAID 6 support */
+#define PVR_440SP_6_RC 0x53221891 /* 440SP rev C with RAID 6 support enabled */
+#define PVR_440SP_RC 0x53321891 /* 440SP rev C without RAID 6 support */
+#define PVR_440SPe_6_RA 0x53421890 /* 440SPe rev A with RAID 6 support enabled */
+#define PVR_440SPe_RA 0x53521890 /* 440SPe rev A without RAID 6 support */
+#define PVR_440SPe_6_RB 0x53421891 /* 440SPe rev B with RAID 6 support enabled */
+#define PVR_440SPe_RB 0x53521891 /* 440SPe rev B without RAID 6 support */
+#define PVR_460EX_SE_RA 0x130218A2 /* 460EX rev A with Security Engine */
+#define PVR_460EX_RA 0x130218A3 /* 460EX rev A without Security Engine */
+#define PVR_460EX_RB 0x130218A4 /* 460EX rev B with and without Sec Eng*/
+#define PVR_460GT_SE_RA 0x130218A0 /* 460GT rev A with Security Engine */
+#define PVR_460GT_RA 0x130218A1 /* 460GT rev A without Security Engine */
+#define PVR_460GT_RB 0x130218A5 /* 460GT rev B with and without Sec Eng*/
+#define PVR_460SX_RA 0x13541800 /* 460SX rev A */
+#define PVR_460SX_RA_V1 0x13541801 /* 460SX rev A Variant 1 Security disabled */
+#define PVR_460GX_RA 0x13541802 /* 460GX rev A */
+#define PVR_460GX_RA_V1 0x13541803 /* 460GX rev A Variant 1 Security disabled */
+#define PVR_APM821XX_RA 0x12C41C80 /* APM821XX rev A */
+#define PVR_601 0x00010000
+#define PVR_602 0x00050000
+#define PVR_603 0x00030000
+#define PVR_603e 0x00060000
+#define PVR_603ev 0x00070000
+#define PVR_603r 0x00071000
+#define PVR_604 0x00040000
+#define PVR_604e 0x00090000
+#define PVR_604r 0x000A0000
+#define PVR_620 0x00140000
+#define PVR_740 0x00080000
+#define PVR_750 PVR_740
+#define PVR_740P 0x10080000
+#define PVR_750P PVR_740P
+#define PVR_7400 0x000C0000
+#define PVR_7410 0x800C0000
+#define PVR_7450 0x80000000
+
+#define PVR_85xx 0x80200000
+#define PVR_85xx_REV1 (PVR_85xx | 0x0010)
+#define PVR_85xx_REV2 (PVR_85xx | 0x0020)
+#define PVR_VER_E500_V1 0x8020
+#define PVR_VER_E500_V2 0x8021
+#define PVR_VER_E500MC 0x8023
+#define PVR_VER_E5500 0x8024
+#define PVR_VER_E6500 0x8040
+
+#define PVR_86xx 0x80040000
+
+#define PVR_VIRTEX5 0x7ff21912
+
+/*
+ * For the 8xx processors, all of them report the same PVR family for
+ * the PowerPC core. The various versions of these processors must be
+ * differentiated by the version number in the Communication Processor
+ * Module (CPM).
+ */
+#define PVR_821 0x00500000
+#define PVR_823 PVR_821
+#define PVR_850 PVR_821
+#define PVR_860 PVR_821
+#define PVR_7400 0x000C0000
+#define PVR_8240 0x00810100
+
+/*
+ * PowerQUICC II family processors report different PVR values depending
+ * on silicon process (HiP3, HiP4, HiP7, etc.)
+ */
+#define PVR_8260 PVR_8240
+#define PVR_8260_HIP3 0x00810101
+#define PVR_8260_HIP4 0x80811014
+#define PVR_8260_HIP7 0x80822011
+#define PVR_8260_HIP7R1 0x80822013
+#define PVR_8260_HIP7RA 0x80822014
+
+/*
+ * MPC 52xx
+ */
+#define PVR_5200 0x80822011
+#define PVR_5200B 0x80822014
+
+/*
+ * 405EX/EXr CHIP_21 Errata
+ */
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX1_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX1_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x0
+#endif
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX2_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX2_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x1
+#endif
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR1_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR1_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x2
+#endif
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR2_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR2_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x3
+#endif
+
+/*
+ * System Version Register
+ */
+
+/* System Version Register (SVR) field extraction */
+
+#define SVR_VER(svr) (((svr) >> 16) & 0xFFFF) /* Version field */
+#define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revison field */
+
+#define SVR_SUBVER(svr) (((svr) >> 8) & 0xFF) /* Process/MFG sub-version */
+
+#define SVR_FAM(svr) (((svr) >> 20) & 0xFFF) /* Family field */
+#define SVR_MEM(svr) (((svr) >> 16) & 0xF) /* Member field */
+
+#ifdef CONFIG_MPC8536
+#define SVR_MAJ(svr) (((svr) >> 4) & 0x7) /* Major revision field*/
+#else
+#define SVR_MAJ(svr) (((svr) >> 4) & 0xF) /* Major revision field*/
+#endif
+#define SVR_MIN(svr) (((svr) >> 0) & 0xF) /* Minor revision field*/
+
+/* Some parts define SVR[0:23] as the SOC version */
+#define SVR_SOC_VER(svr) (((svr) >> 8) & 0xFFF7FF) /* SOC w/o E bit*/
+
+/* whether MPC8xxxE (i.e. has SEC) */
+#if defined(CONFIG_MPC85xx)
+#define IS_E_PROCESSOR(svr) (svr & 0x80000)
+#else
+#if defined(CONFIG_MPC83xx)
+#define IS_E_PROCESSOR(spridr) (!(spridr & 0x00010000))
+#endif
+#endif
+
+#define IS_SVR_REV(svr, maj, min) \
+ ((SVR_MAJ(svr) == maj) && (SVR_MIN(svr) == min))
+
+/*
+ * SVR_SOC_VER() Version Values
+ */
+
+#define SVR_8533 0x803400
+#define SVR_8535 0x803701
+#define SVR_8536 0x803700
+#define SVR_8540 0x803000
+#define SVR_8541 0x807200
+#define SVR_8543 0x803200
+#define SVR_8544 0x803401
+#define SVR_8545 0x803102
+#define SVR_8547 0x803101
+#define SVR_8548 0x803100
+#define SVR_8555 0x807100
+#define SVR_8560 0x807000
+#define SVR_8567 0x807501
+#define SVR_8568 0x807500
+#define SVR_8569 0x808000
+#define SVR_8572 0x80E000
+#define SVR_P1010 0x80F100
+#define SVR_P1011 0x80E500
+#define SVR_P1012 0x80E501
+#define SVR_P1013 0x80E700
+#define SVR_P1014 0x80F101
+#define SVR_P1017 0x80F700
+#define SVR_P1020 0x80E400
+#define SVR_P1021 0x80E401
+#define SVR_P1022 0x80E600
+#define SVR_P1023 0x80F600
+#define SVR_P1024 0x80E402
+#define SVR_P1025 0x80E403
+#define SVR_P2010 0x80E300
+#define SVR_P2020 0x80E200
+#define SVR_P2040 0x821000
+#define SVR_P2041 0x821001
+#define SVR_P3041 0x821103
+#define SVR_P4040 0x820100
+#define SVR_P4080 0x820000
+#define SVR_P5010 0x822100
+#define SVR_P5020 0x822000
+#define SVR_P5021 0X820500
+#define SVR_P5040 0x820400
+#define SVR_T4240 0x824000
+#define SVR_T4120 0x824001
+#define SVR_T4160 0x824100
+#define SVR_B4860 0X868000
+#define SVR_G4860 0x868001
+#define SVR_G4060 0x868003
+#define SVR_B4440 0x868100
+#define SVR_G4440 0x868101
+#define SVR_B4420 0x868102
+#define SVR_B4220 0x868103
+#define SVR_T1040 0x852000
+#define SVR_T1041 0x852001
+#define SVR_T1042 0x852002
+#define SVR_T1020 0x852100
+#define SVR_T1021 0x852101
+#define SVR_T1022 0x852102
+
+#define SVR_8610 0x80A000
+#define SVR_8641 0x809000
+#define SVR_8641D 0x809001
+
+#define SVR_9130 0x860001
+#define SVR_9131 0x860000
+#define SVR_9132 0x861000
+#define SVR_9232 0x861400
+
+#define SVR_Unknown 0xFFFFFF
+
+#define _GLOBAL(n)\
+ .globl n;\
+n:
+
+/* Macros for setting and retrieving special purpose registers */
+
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+
+#define mfdcr(rn) ({unsigned int rval; \
+ asm volatile("mfdcr %0," stringify(rn) \
+ : "=r" (rval)); rval;})
+#define mtdcr(rn, v) asm volatile("mtdcr " stringify(rn) ",%0" : : "r" (v))
+
+#define mfmsr() ({unsigned int rval; \
+ asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
+
+#define mfspr(rn) ({unsigned int rval; \
+ asm volatile("mfspr %0," stringify(rn) \
+ : "=r" (rval)); rval;})
+#define mtspr(rn, v) asm volatile("mtspr " stringify(rn) ",%0" : : "r" (v))
+
+#define tlbie(v) asm volatile("tlbie %0 \n sync" : : "r" (v))
+
+/* Segment Registers */
+
+#define SR0 0
+#define SR1 1
+#define SR2 2
+#define SR3 3
+#define SR4 4
+#define SR5 5
+#define SR6 6
+#define SR7 7
+#define SR8 8
+#define SR9 9
+#define SR10 10
+#define SR11 11
+#define SR12 12
+#define SR13 13
+#define SR14 14
+#define SR15 15
+
+#ifndef __ASSEMBLY__
+
+struct cpu_type {
+ char name[15];
+ u32 soc_ver;
+ u32 num_cores;
+ u32 mask; /* which cpu(s) actually exist */
+};
+
+struct cpu_type *identify_cpu(u32 ver);
+int fixup_cpu(void);
+
+int fsl_qoriq_core_to_cluster(unsigned int core);
+
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+#define CPU_TYPE_ENTRY(n, v, nc) \
+ { .name = #n, .soc_ver = SVR_##v, .num_cores = (nc), \
+ .mask = (1 << (nc)) - 1 }
+#define CPU_TYPE_ENTRY_MASK(n, v, nc, m) \
+ { .name = #n, .soc_ver = SVR_##v, .num_cores = (nc), .mask = (m) }
+#else
+#if defined(CONFIG_MPC83xx)
+#define CPU_TYPE_ENTRY(x) {#x, SPR_##x}
+#endif
+#endif
+
+
+#ifndef CONFIG_MACH_SPECIFIC
+extern int _machine;
+extern int have_of;
+#endif /* CONFIG_MACH_SPECIFIC */
+
+/* what kind of prep workstation we are */
+extern int _prep_type;
+/*
+ * This is used to identify the board type from a given PReP board
+ * vendor. Board revision is also made available.
+ */
+extern unsigned char ucSystemType;
+extern unsigned char ucBoardRev;
+extern unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+struct task_struct;
+void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
+void release_thread(struct task_struct *);
+
+/*
+ * Create a new kernel thread.
+ */
+extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/* Lazy FPU handling on uni-processor */
+extern struct task_struct *last_task_used_math;
+extern struct task_struct *last_task_used_altivec;
+
+/*
+ * this is the minimum allowable io space due to the location
+ * of the io areas on prep (first one at 0x80000000) but
+ * as soon as I get around to remapping the io areas with the BATs
+ * to match the mac we can raise this. -- Cort
+ */
+#define TASK_SIZE (0x80000000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
+
+typedef struct {
+ unsigned long seg;
+} mm_segment_t;
+
+struct thread_struct {
+ unsigned long ksp; /* Kernel stack pointer */
+ unsigned long wchan; /* Event task is sleeping on */
+ struct pt_regs *regs; /* Pointer to saved register state */
+ mm_segment_t fs; /* for get_fs() validation */
+ void *pgdir; /* root of page-table tree */
+ signed long last_syscall;
+ double fpr[32]; /* Complete floating point set */
+ unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */
+ unsigned long fpscr; /* Floating point status */
+#ifdef CONFIG_ALTIVEC
+ vector128 vr[32]; /* Complete AltiVec set */
+ vector128 vscr; /* AltiVec status */
+ unsigned long vrsave;
+#endif /* CONFIG_ALTIVEC */
+};
+
+#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
+
+#define INIT_THREAD { \
+ INIT_SP, /* ksp */ \
+ 0, /* wchan */ \
+ (struct pt_regs *)INIT_SP - 1, /* regs */ \
+ KERNEL_DS, /*fs*/ \
+ swapper_pg_dir, /* pgdir */ \
+ 0, /* last_syscall */ \
+ {0}, 0, 0 \
+}
+
+/*
+ * Note: the vm_start and vm_end fields here should *not*
+ * be in kernel space. (Could vm_end == vm_start perhaps?)
+ */
+#define INIT_MMAP { &init_mm, 0, 0x1000, NULL, \
+ PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \
+ 1, NULL, NULL }
+
+/*
+ * Return saved PC of a blocked thread. For now, this is the "user" PC
+ */
+static inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+ return (t->regs) ? t->regs->nip : 0;
+}
+
+#define copy_segments(tsk, mm) do { } while (0)
+#define release_segments(mm) do { } while (0)
+#define forget_segments() do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip)
+#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1])
+
+/*
+ * NOTE! The task struct and the stack go together
+ */
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define alloc_task_struct() \
+ ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
+#define free_task_struct(p) free_pages((unsigned long)(p),1)
+#define get_task_struct(tsk) atomic_inc(&mem_map[MAP_NR(tsk)].count)
+
+/* in process.c - for early bootup debug -- Cort */
+int ll_printk(const char *, ...);
+void ll_puts(const char *);
+
+#define init_task (init_task_union.task)
+#define init_stack (init_task_union.stack)
+
+/* In misc.c */
+void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+
+#endif /* ndef ASSEMBLY*/
+
+#ifdef CONFIG_MACH_SPECIFIC
+#if defined(CONFIG_8xx)
+#define _machine _MACH_8xx
+#define have_of 0
+#elif defined(CONFIG_OAK)
+#define _machine _MACH_oak
+#define have_of 0
+#elif defined(CONFIG_WALNUT)
+#define _machine _MACH_walnut
+#define have_of 0
+#elif defined(CONFIG_APUS)
+#define _machine _MACH_apus
+#define have_of 0
+#elif defined(CONFIG_GEMINI)
+#define _machine _MACH_gemini
+#define have_of 0
+#elif defined(CONFIG_8260)
+#define _machine _MACH_8260
+#define have_of 0
+#elif defined(CONFIG_SANDPOINT)
+#define _machine _MACH_sandpoint
+#elif defined(CONFIG_HIDDEN_DRAGON)
+#define _machine _MACH_hidden_dragon
+#define have_of 0
+#else
+#error "Machine not defined correctly"
+#endif
+#endif /* CONFIG_MACH_SPECIFIC */
+
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_440)
+ #define EPAPR_MAGIC (0x45504150)
+#else
+ #define EPAPR_MAGIC (0x65504150)
+#endif
+
+#endif /* __ASM_PPC_PROCESSOR_H */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
new file mode 100644
index 0000000..cf09edf
--- /dev/null
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -0,0 +1,107 @@
+#ifndef _PPC_PTRACE_H
+#define _PPC_PTRACE_H
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ *
+ * this should only contain volatile regs
+ * since we can keep non-volatile in the thread_struct
+ * should set this up when only volatiles are saved
+ * by intr code.
+ *
+ * Since this is going on the stack, *CARE MUST BE TAKEN* to insure
+ * that the overall structure is a multiple of 16 bytes in length.
+ *
+ * Note that the offsets of the fields in this struct correspond with
+ * the PT_* values below. This simplifies arch/powerpc/kernel/ptrace.c.
+ */
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_PPC64BRIDGE
+#define PPC_REG unsigned long /*long*/
+#else
+#define PPC_REG unsigned long
+#endif
+struct pt_regs {
+ PPC_REG gpr[32];
+ PPC_REG nip;
+ PPC_REG msr;
+ PPC_REG orig_gpr3; /* Used for restarting system calls */
+ PPC_REG ctr;
+ PPC_REG link;
+ PPC_REG xer;
+ PPC_REG ccr;
+ PPC_REG mq; /* 601 only (not used at present) */
+ /* Used on APUS to hold IPL value. */
+ PPC_REG trap; /* Reason for being here */
+ PPC_REG dar; /* Fault registers */
+ PPC_REG dsisr;
+ PPC_REG result; /* Result of a system call */
+};
+#endif
+
+#define STACK_FRAME_OVERHEAD 16 /* size of minimum stack frame */
+
+/* Size of stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE 64
+
+#define instruction_pointer(regs) ((regs)->nip)
+#define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ * These can't be changed without breaking binary compatibility
+ * with MkLinux, etc.
+ */
+#define PT_R0 0
+#define PT_R1 1
+#define PT_R2 2
+#define PT_R3 3
+#define PT_R4 4
+#define PT_R5 5
+#define PT_R6 6
+#define PT_R7 7
+#define PT_R8 8
+#define PT_R9 9
+#define PT_R10 10
+#define PT_R11 11
+#define PT_R12 12
+#define PT_R13 13
+#define PT_R14 14
+#define PT_R15 15
+#define PT_R16 16
+#define PT_R17 17
+#define PT_R18 18
+#define PT_R19 19
+#define PT_R20 20
+#define PT_R21 21
+#define PT_R22 22
+#define PT_R23 23
+#define PT_R24 24
+#define PT_R25 25
+#define PT_R26 26
+#define PT_R27 27
+#define PT_R28 28
+#define PT_R29 29
+#define PT_R30 30
+#define PT_R31 31
+
+#define PT_NIP 32
+#define PT_MSR 33
+#ifdef __KERNEL__
+#define PT_ORIG_R3 34
+#endif
+#define PT_CTR 35
+#define PT_LNK 36
+#define PT_XER 37
+#define PT_CCR 38
+#define PT_MQ 39
+
+#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */
+#define PT_FPR31 (PT_FPR0 + 2*31)
+#define PT_FPSCR (PT_FPR0 + 2*32 + 1)
+
+#endif
diff --git a/arch/powerpc/include/asm/residual.h b/arch/powerpc/include/asm/residual.h
new file mode 100644
index 0000000..dc85edb
--- /dev/null
+++ b/arch/powerpc/include/asm/residual.h
@@ -0,0 +1,331 @@
+/* 7/18/95 */
+/*----------------------------------------------------------------------------*/
+/* Residual Data header definitions and prototypes */
+/*----------------------------------------------------------------------------*/
+
+/* Structure map for RESIDUAL on PowerPC Reference Platform */
+/* residual.h - Residual data structure passed in r3. */
+/* Load point passed in r4 to boot image. */
+/* For enum's: if given in hex then they are bit significant, */
+/* i.e. only one bit is on for each enum */
+/* Reserved fields must be filled with zeros. */
+
+#ifndef _RESIDUAL_
+#define _RESIDUAL_
+
+#ifndef __ASSEMBLY__
+
+#define MAX_CPUS 32 /* These should be set to the maximum */
+#define MAX_MEMS 64 /* number possible for this system. */
+#define MAX_DEVICES 256 /* Changing these will change the */
+#define AVE_PNP_SIZE 32 /* structure, hence the version of */
+#define MAX_MEM_SEGS 64 /* this header file. */
+
+/*----------------------------------------------------------------------------*/
+/* Public structures... */
+/*----------------------------------------------------------------------------*/
+
+#include "pnp.h"
+
+typedef enum _L1CACHE_TYPE {
+ NoneCAC = 0,
+ SplitCAC = 1,
+ CombinedCAC = 2
+ } L1CACHE_TYPE;
+
+typedef enum _TLB_TYPE {
+ NoneTLB = 0,
+ SplitTLB = 1,
+ CombinedTLB = 2
+ } TLB_TYPE;
+
+typedef enum _FIRMWARE_SUPPORT {
+ Conventional = 0x01,
+ OpenFirmware = 0x02,
+ Diagnostics = 0x04,
+ LowDebug = 0x08,
+ Multiboot = 0x10,
+ LowClient = 0x20,
+ Hex41 = 0x40,
+ FAT = 0x80,
+ ISO9660 = 0x0100,
+ SCSI_InitiatorID_Override = 0x0200,
+ Tape_Boot = 0x0400,
+ FW_Boot_Path = 0x0800
+ } FIRMWARE_SUPPORT;
+
+typedef enum _FIRMWARE_SUPPLIERS {
+ IBMFirmware = 0x00,
+ MotoFirmware = 0x01, /* 7/18/95 */
+ FirmWorks = 0x02, /* 10/5/95 */
+ Bull = 0x03, /* 04/03/96 */
+ } FIRMWARE_SUPPLIERS;
+
+typedef enum _ENDIAN_SWITCH_METHODS {
+ UsePort92 = 0x01,
+ UsePCIConfigA8 = 0x02,
+ UseFF001030 = 0x03,
+ } ENDIAN_SWITCH_METHODS;
+
+typedef enum _SPREAD_IO_METHODS {
+ UsePort850 = 0x00,
+/*UsePCIConfigA8 = 0x02,*/
+ } SPREAD_IO_METHODS;
+
+typedef struct _VPD {
+
+ /* Box dependent stuff */
+ unsigned char PrintableModel[32]; /* Null terminated string.
+ Must be of the form:
+ vvv,<20h>,<model designation>,<0x0>
+ where vvv is the vendor ID
+ e.g. IBM PPS MODEL 6015<0x0> */
+ unsigned char Serial[16]; /* 12/94:
+ Serial Number; must be of the form:
+ vvv<serial number> where vvv is the
+ vendor ID.
+ e.g. IBM60151234567<20h><20h> */
+ unsigned char Reserved[48];
+ unsigned long FirmwareSupplier; /* See FirmwareSuppliers enum */
+ unsigned long FirmwareSupports; /* See FirmwareSupport enum */
+ unsigned long NvramSize; /* Size of nvram in bytes */
+ unsigned long NumSIMMSlots;
+ unsigned short EndianSwitchMethod; /* See EndianSwitchMethods enum */
+ unsigned short SpreadIOMethod; /* See SpreadIOMethods enum */
+ unsigned long SmpIar;
+ unsigned long RAMErrLogOffset; /* Heap offset to error log */
+ unsigned long Reserved5;
+ unsigned long Reserved6;
+ unsigned long ProcessorHz; /* Processor clock frequency in Hertz */
+ unsigned long ProcessorBusHz; /* Processor bus clock frequency */
+ unsigned long Reserved7;
+ unsigned long TimeBaseDivisor; /* (Bus clocks per timebase tic)*1000 */
+ unsigned long WordWidth; /* Word width in bits */
+ unsigned long PageSize; /* Page size in bytes */
+ unsigned long CoherenceBlockSize; /* Unit of transfer in/out of cache
+ for which coherency is maintained;
+ normally <= CacheLineSize. */
+ unsigned long GranuleSize; /* Unit of lock allocation to avoid */
+ /* false sharing of locks. */
+
+ /* L1 Cache variables */
+ unsigned long CacheSize; /* L1 Cache size in KB. This is the */
+ /* total size of the L1, whether */
+ /* combined or split */
+ unsigned long CacheAttrib; /* L1CACHE_TYPE */
+ unsigned long CacheAssoc; /* L1 Cache associativity. Use this
+ for combined cache. If split, put
+ zeros here. */
+ unsigned long CacheLineSize; /* L1 Cache line size in bytes. Use
+ for combined cache. If split, put
+ zeros here. */
+ /* For split L1 Cache: (= combined if combined cache) */
+ unsigned long I_CacheSize;
+ unsigned long I_CacheAssoc;
+ unsigned long I_CacheLineSize;
+ unsigned long D_CacheSize;
+ unsigned long D_CacheAssoc;
+ unsigned long D_CacheLineSize;
+
+ /* Translation Lookaside Buffer variables */
+ unsigned long TLBSize; /* Total number of TLBs on the system */
+ unsigned long TLBAttrib; /* Combined I+D or split TLB */
+ unsigned long TLBAssoc; /* TLB Associativity. Use this for
+ combined TLB. If split, put zeros
+ here. */
+ /* For split TLB: (= combined if combined TLB) */
+ unsigned long I_TLBSize;
+ unsigned long I_TLBAssoc;
+ unsigned long D_TLBSize;
+ unsigned long D_TLBAssoc;
+
+ unsigned long ExtendedVPD; /* Offset to extended VPD area;
+ null if unused */
+ } VPD;
+
+typedef enum _DEVICE_FLAGS {
+ Enabled = 0x4000, /* 1 - PCI device is enabled */
+ Integrated = 0x2000,
+ Failed = 0x1000, /* 1 - device failed POST code tests */
+ Static = 0x0800, /* 0 - dynamically configurable
+ 1 - static */
+ Dock = 0x0400, /* 0 - not a docking station device
+ 1 - is a docking station device */
+ Boot = 0x0200, /* 0 - device cannot be used for BOOT
+ 1 - can be a BOOT device */
+ Configurable = 0x0100, /* 1 - device is configurable */
+ Disableable = 0x80, /* 1 - device can be disabled */
+ PowerManaged = 0x40, /* 0 - not managed; 1 - managed */
+ ReadOnly = 0x20, /* 1 - device is read only */
+ Removable = 0x10, /* 1 - device is removable */
+ ConsoleIn = 0x08,
+ ConsoleOut = 0x04,
+ Input = 0x02,
+ Output = 0x01
+ } DEVICE_FLAGS;
+
+typedef enum _BUS_ID {
+ ISADEVICE = 0x01,
+ EISADEVICE = 0x02,
+ PCIDEVICE = 0x04,
+ PCMCIADEVICE = 0x08,
+ PNPISADEVICE = 0x10,
+ MCADEVICE = 0x20,
+ MXDEVICE = 0x40, /* Devices on mezzanine bus */
+ PROCESSORDEVICE = 0x80, /* Devices on processor bus */
+ VMEDEVICE = 0x100,
+ } BUS_ID;
+
+typedef struct _DEVICE_ID {
+ unsigned long BusId; /* See BUS_ID enum above */
+ unsigned long DevId; /* Big Endian format */
+ unsigned long SerialNum; /* For multiple usage of a single
+ DevId */
+ unsigned long Flags; /* See DEVICE_FLAGS enum above */
+ unsigned char BaseType; /* See pnp.h for bit definitions */
+ unsigned char SubType; /* See pnp.h for bit definitions */
+ unsigned char Interface; /* See pnp.h for bit definitions */
+ unsigned char Spare;
+ } DEVICE_ID;
+
+typedef union _BUS_ACCESS {
+ struct _PnPAccess{
+ unsigned char CSN;
+ unsigned char LogicalDevNumber;
+ unsigned short ReadDataPort;
+ } PnPAccess;
+ struct _ISAAccess{
+ unsigned char SlotNumber; /* ISA Slot Number generally not
+ available; 0 if unknown */
+ unsigned char LogicalDevNumber;
+ unsigned short ISAReserved;
+ } ISAAccess;
+ struct _MCAAccess{
+ unsigned char SlotNumber;
+ unsigned char LogicalDevNumber;
+ unsigned short MCAReserved;
+ } MCAAccess;
+ struct _PCMCIAAccess{
+ unsigned char SlotNumber;
+ unsigned char LogicalDevNumber;
+ unsigned short PCMCIAReserved;
+ } PCMCIAAccess;
+ struct _EISAAccess{
+ unsigned char SlotNumber;
+ unsigned char FunctionNumber;
+ unsigned short EISAReserved;
+ } EISAAccess;
+ struct _PCIAccess{
+ unsigned char BusNumber;
+ unsigned char DevFuncNumber;
+ unsigned short PCIReserved;
+ } PCIAccess;
+ struct _ProcBusAccess{
+ unsigned char BusNumber;
+ unsigned char BUID;
+ unsigned short ProcBusReserved;
+ } ProcBusAccess;
+ } BUS_ACCESS;
+
+/* Per logical device information */
+typedef struct _PPC_DEVICE {
+ DEVICE_ID DeviceId;
+ BUS_ACCESS BusAccess;
+
+ /* The following three are offsets into the DevicePnPHeap */
+ /* All are in PnP compressed format */
+ unsigned long AllocatedOffset; /* Allocated resource description */
+ unsigned long PossibleOffset; /* Possible resource description */
+ unsigned long CompatibleOffset; /* Compatible device identifiers */
+ } PPC_DEVICE;
+
+typedef enum _CPU_STATE {
+ CPU_GOOD = 0, /* CPU is present, and active */
+ CPU_GOOD_FW = 1, /* CPU is present, and in firmware */
+ CPU_OFF = 2, /* CPU is present, but inactive */
+ CPU_FAILED = 3, /* CPU is present, but failed POST */
+ CPU_NOT_PRESENT = 255 /* CPU not present */
+ } CPU_STATE;
+
+typedef struct _PPC_CPU {
+ unsigned long CpuType; /* Result of mfspr from Processor
+ Version Register (PVR).
+ PVR(0-15) = Version (e.g. 601)
+ PVR(16-31 = EC Level */
+ unsigned char CpuNumber; /* CPU Number for this processor */
+ unsigned char CpuState; /* CPU State, see CPU_STATE enum */
+ unsigned short Reserved;
+ } PPC_CPU;
+
+typedef struct _PPC_MEM {
+ unsigned long SIMMSize; /* 0 - absent or bad
+ 8M, 32M (in MB) */
+ } PPC_MEM;
+
+typedef enum _MEM_USAGE {
+ Other = 0x8000,
+ ResumeBlock = 0x4000, /* for use by power management */
+ SystemROM = 0x2000, /* Flash memory (populated) */
+ UnPopSystemROM = 0x1000, /* Unpopulated part of SystemROM area */
+ IOMemory = 0x0800,
+ SystemIO = 0x0400,
+ SystemRegs = 0x0200,
+ PCIAddr = 0x0100,
+ PCIConfig = 0x80,
+ ISAAddr = 0x40,
+ Unpopulated = 0x20, /* Unpopulated part of System Memory */
+ Free = 0x10, /* Free part of System Memory */
+ BootImage = 0x08, /* BootImage part of System Memory */
+ FirmwareCode = 0x04, /* FirmwareCode part of System Memory */
+ FirmwareHeap = 0x02, /* FirmwareHeap part of System Memory */
+ FirmwareStack = 0x01 /* FirmwareStack part of System Memory*/
+ } MEM_USAGE;
+
+typedef struct _MEM_MAP {
+ unsigned long Usage; /* See MEM_USAGE above */
+ unsigned long BasePage; /* Page number measured in 4KB pages */
+ unsigned long PageCount; /* Page count measured in 4KB pages */
+ } MEM_MAP;
+
+typedef struct _RESIDUAL {
+ unsigned long ResidualLength; /* Length of Residual */
+ unsigned char Version; /* of this data structure */
+ unsigned char Revision; /* of this data structure */
+ unsigned short EC; /* of this data structure */
+ /* VPD */
+ VPD VitalProductData;
+ /* CPU */
+ unsigned short MaxNumCpus; /* Max CPUs in this system */
+ unsigned short ActualNumCpus; /* ActualNumCpus < MaxNumCpus means */
+ /* that there are unpopulated or */
+ /* otherwise unusable cpu locations */
+ PPC_CPU Cpus[MAX_CPUS];
+ /* Memory */
+ unsigned long TotalMemory; /* Total amount of memory installed */
+ unsigned long GoodMemory; /* Total amount of good memory */
+ unsigned long ActualNumMemSegs;
+ MEM_MAP Segs[MAX_MEM_SEGS];
+ unsigned long ActualNumMemories;
+ PPC_MEM Memories[MAX_MEMS];
+ /* Devices */
+ unsigned long ActualNumDevices;
+ PPC_DEVICE Devices[MAX_DEVICES];
+ unsigned char DevicePnPHeap[2*MAX_DEVICES*AVE_PNP_SIZE];
+ } RESIDUAL;
+
+
+extern RESIDUAL *res;
+extern void print_residual_device_info(void);
+extern PPC_DEVICE *residual_find_device(unsigned long BusMask,
+ unsigned char * DevID, int BaseType,
+ int SubType, int Interface, int n);
+extern PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag,
+ int n);
+extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
+ unsigned packet_type,
+ int n);
+extern PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
+ unsigned packet_type,
+ int n);
+#endif /* __ASSEMBLY__ */
+#endif /* ndef _RESIDUAL_ */
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
new file mode 100644
index 0000000..0a94102
--- /dev/null
+++ b/arch/powerpc/include/asm/sections.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __ASM_POWERPC_SECTIONS_H
+#define __ASM_POWERPC_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+#endif
diff --git a/arch/powerpc/include/asm/sigcontext.h b/arch/powerpc/include/asm/sigcontext.h
new file mode 100644
index 0000000..715c868
--- /dev/null
+++ b/arch/powerpc/include/asm/sigcontext.h
@@ -0,0 +1,15 @@
+#ifndef _ASM_PPC_SIGCONTEXT_H
+#define _ASM_PPC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+
+struct sigcontext_struct {
+ unsigned long _unused[4];
+ int signal;
+ unsigned long handler;
+ unsigned long oldmask;
+ struct pt_regs *regs;
+};
+
+#endif
diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h
new file mode 100644
index 0000000..b11a28e
--- /dev/null
+++ b/arch/powerpc/include/asm/signal.h
@@ -0,0 +1,154 @@
+#ifndef _ASMPPC_SIGNAL_H
+#define _ASMPPC_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems. */
+struct siginfo;
+
+/* Most things should be clean enough to redefine this at will, if care
+ is taken to make libc match. */
+
+#define _NSIG 64
+#define _NSIG_BPW 32
+#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t; /* at least 32 bits */
+
+typedef struct {
+ unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+/*
+#define SIGLOST 29
+*/
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED 31
+
+/* These should not be considered constants from userland. */
+#define SIGRTMIN 32
+#define SIGRTMAX (_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP 0x00000001
+#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
+#define SA_SIGINFO 0x00000004
+#define SA_ONSTACK 0x08000000
+#define SA_RESTART 0x10000000
+#define SA_NODEFER 0x40000000
+#define SA_RESETHAND 0x80000000
+
+#define SA_NOMASK SA_NODEFER
+#define SA_ONESHOT SA_RESETHAND
+#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER 0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE SA_ONESHOT
+#define SA_SAMPLE_RANDOM SA_RESTART
+#define SA_SHIRQ 0x04000000
+#endif
+
+#define SIG_BLOCK 0 /* for blocking signals */
+#define SIG_UNBLOCK 1 /* for unblocking signals */
+#define SIG_SETMASK 2 /* for setting the signal mask */
+
+/* Type of a signal handler. */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
+#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
+#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
+
+struct old_sigaction {
+ __sighandler_t sa_handler;
+ old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct k_sigaction {
+ struct sigaction sa;
+};
+
+typedef struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#endif
+
+#endif
diff --git a/arch/powerpc/include/asm/spl.h b/arch/powerpc/include/asm/spl.h
new file mode 100644
index 0000000..7d5f9a0
--- /dev/null
+++ b/arch/powerpc/include/asm/spl.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2012
+ * Texas Instruments, <www.ti.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _ASM_SPL_H_
+#define _ASM_SPL_H_
+
+#define BOOT_DEVICE_NOR 1
+
+/* Linker symbols */
+extern char __bss_start[], __bss_end[];
+
+#endif
diff --git a/arch/powerpc/include/asm/status_led.h b/arch/powerpc/include/asm/status_led.h
new file mode 100644
index 0000000..0375709
--- /dev/null
+++ b/arch/powerpc/include/asm/status_led.h
@@ -0,0 +1,77 @@
+/*
+ * asm/status_led.h
+ *
+ * MPC8xx/MPC8260/MPC5xx based status led support functions
+ */
+
+#ifndef __ASM_STATUS_LED_H__
+#define __ASM_STATUS_LED_H__
+
+/* if not overriden */
+#ifndef CONFIG_BOARD_SPECIFIC_LED
+# if defined(CONFIG_8xx)
+# include <mpc8xx.h>
+# elif defined(CONFIG_8260)
+# include <mpc8260.h>
+# elif defined(CONFIG_5xx)
+# include <mpc5xx.h>
+# else
+# error CPU specific Status LED header file missing.
+#endif
+
+/* led_id_t is unsigned long mask */
+typedef unsigned long led_id_t;
+
+static inline void __led_init (led_id_t mask, int state)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#ifdef STATUS_LED_PAR
+ immr->STATUS_LED_PAR &= ~mask;
+#endif
+#ifdef STATUS_LED_ODR
+ immr->STATUS_LED_ODR &= ~mask;
+#endif
+
+#if (STATUS_LED_ACTIVE == 0)
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT &= ~mask;
+ else
+ immr->STATUS_LED_DAT |= mask;
+#else
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT |= mask;
+ else
+ immr->STATUS_LED_DAT &= ~mask;
+#endif
+#ifdef STATUS_LED_DIR
+ immr->STATUS_LED_DIR |= mask;
+#endif
+}
+
+static inline void __led_toggle (led_id_t mask)
+{
+ ((immap_t *) CONFIG_SYS_IMMR)->STATUS_LED_DAT ^= mask;
+}
+
+static inline void __led_set (led_id_t mask, int state)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+
+#if (STATUS_LED_ACTIVE == 0)
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT &= ~mask;
+ else
+ immr->STATUS_LED_DAT |= mask;
+#else
+ if (state == STATUS_LED_ON)
+ immr->STATUS_LED_DAT |= mask;
+ else
+ immr->STATUS_LED_DAT &= ~mask;
+#endif
+
+}
+
+#endif
+
+#endif /* __ASM_STATUS_LED_H__ */
diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h
new file mode 100644
index 0000000..036805e
--- /dev/null
+++ b/arch/powerpc/include/asm/string.h
@@ -0,0 +1,29 @@
+#ifndef _PPC_STRING_H_
+#define _PPC_STRING_H_
+
+#define __HAVE_ARCH_STRCPY
+#define __HAVE_ARCH_STRNCPY
+#define __HAVE_ARCH_STRLEN
+#define __HAVE_ARCH_STRCMP
+#define __HAVE_ARCH_STRCAT
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_BCOPY
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
+#define __HAVE_ARCH_MEMCMP
+#define __HAVE_ARCH_MEMCHR
+
+extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, __kernel_size_t);
+extern char * strcpy(char *,const char *);
+extern char * strncpy(char *,const char *, __kernel_size_t);
+extern __kernel_size_t strlen(const char *);
+extern int strcmp(const char *,const char *);
+extern char * strcat(char *, const char *);
+extern void * memset(void *,int,__kernel_size_t);
+extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void * memmove(void *,const void *,__kernel_size_t);
+extern int memcmp(const void *,const void *,__kernel_size_t);
+extern void * memchr(const void *,int,__kernel_size_t);
+
+#endif
diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h
new file mode 100644
index 0000000..b27a6b7
--- /dev/null
+++ b/arch/powerpc/include/asm/types.h
@@ -0,0 +1,58 @@
+#ifndef _PPC_TYPES_H
+#define _PPC_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#endif
+
+typedef struct {
+ __u32 u[4];
+} __attribute__((aligned(16))) vector128;
+
+#ifdef __KERNEL__
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* DMA addresses are 32-bits wide */
+typedef u32 dma_addr_t;
+
+#ifdef CONFIG_PHYS_64BIT
+typedef unsigned long long phys_addr_t;
+typedef unsigned long long phys_size_t;
+#else
+typedef unsigned long phys_addr_t;
+typedef unsigned long phys_size_t;
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/powerpc/include/asm/u-boot.h b/arch/powerpc/include/asm/u-boot.h
new file mode 100644
index 0000000..93496a0
--- /dev/null
+++ b/arch/powerpc/include/asm/u-boot.h
@@ -0,0 +1,149 @@
+/*
+ * (C) Copyright 2000 - 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef __U_BOOT_H__
+#define __U_BOOT_H__
+
+/*
+ * Board information passed to Linux kernel from U-Boot
+ *
+ * include/asm-ppc/u-boot.h
+ */
+
+#ifdef CONFIG_SYS_GENERIC_BOARD
+/* Use the generic board which requires a unified bd_info */
+#include <asm-generic/u-boot.h>
+#else
+
+#ifndef __ASSEMBLY__
+
+typedef struct bd_info {
+ unsigned long bi_memstart; /* start of DRAM memory */
+ phys_size_t bi_memsize; /* size of DRAM memory in bytes */
+ unsigned long bi_flashstart; /* start of FLASH memory */
+ unsigned long bi_flashsize; /* size of FLASH memory */
+ unsigned long bi_flashoffset; /* reserved area for startup monitor */
+ unsigned long bi_sramstart; /* start of SRAM memory */
+ unsigned long bi_sramsize; /* size of SRAM memory */
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
+ || defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+ unsigned long bi_immr_base; /* base of IMMR register */
+#endif
+#if defined(CONFIG_MPC5xxx)
+ unsigned long bi_mbar_base; /* base of internal registers */
+#endif
+#if defined(CONFIG_MPC83xx)
+ unsigned long bi_immrbar;
+#endif
+ unsigned long bi_bootflags; /* boot / reboot flag (Unused) */
+ unsigned long bi_ip_addr; /* IP Address */
+ unsigned char bi_enetaddr[6]; /* OLD: see README.enetaddr */
+ unsigned short bi_ethspeed; /* Ethernet speed in Mbps */
+ unsigned long bi_intfreq; /* Internal Freq, in MHz */
+ unsigned long bi_busfreq; /* Bus Freq, in MHz */
+#if defined(CONFIG_CPM2)
+ unsigned long bi_cpmfreq; /* CPM_CLK Freq, in MHz */
+ unsigned long bi_brgfreq; /* BRG_CLK Freq, in MHz */
+ unsigned long bi_sccfreq; /* SCC_CLK Freq, in MHz */
+ unsigned long bi_vco; /* VCO Out from PLL, in MHz */
+#endif
+#if defined(CONFIG_MPC512X)
+ unsigned long bi_ipsfreq; /* IPS Bus Freq, in MHz */
+#endif /* CONFIG_MPC512X */
+#if defined(CONFIG_MPC5xxx)
+ unsigned long bi_ipbfreq; /* IPB Bus Freq, in MHz */
+ unsigned long bi_pcifreq; /* PCI Bus Freq, in MHz */
+#endif
+ unsigned int bi_baudrate; /* Console Baudrate */
+#if defined(CONFIG_405) || \
+ defined(CONFIG_405GP) || \
+ defined(CONFIG_405CR) || \
+ defined(CONFIG_405EP) || \
+ defined(CONFIG_405EZ) || \
+ defined(CONFIG_405EX) || \
+ defined(CONFIG_440)
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[32]; /* Version of the ROM (AMCC) */
+ unsigned int bi_procfreq; /* CPU (Internal) Freq, in Hz */
+ unsigned int bi_plb_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
+ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
+#endif
+#if defined(CONFIG_HYMOD)
+ hymod_conf_t bi_hymod_conf; /* hymod configuration information */
+#endif
+
+#ifdef CONFIG_HAS_ETH1
+ unsigned char bi_enet1addr[6]; /* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH2
+ unsigned char bi_enet2addr[6]; /* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH3
+ unsigned char bi_enet3addr[6]; /* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH4
+ unsigned char bi_enet4addr[6]; /* OLD: see README.enetaddr */
+#endif
+#ifdef CONFIG_HAS_ETH5
+ unsigned char bi_enet5addr[6]; /* OLD: see README.enetaddr */
+#endif
+
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || \
+ defined(CONFIG_405EZ) || defined(CONFIG_440GX) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ unsigned int bi_opbfreq; /* OPB clock in Hz */
+ int bi_iic_fast[2]; /* Use fast i2c mode */
+#endif
+#if defined(CONFIG_NX823)
+ unsigned char bi_sernum[8];
+#endif
+#if defined(CONFIG_4xx)
+#if defined(CONFIG_440GX) || \
+ defined(CONFIG_460EX) || defined(CONFIG_460GT)
+ int bi_phynum[4]; /* Determines phy mapping */
+ int bi_phymode[4]; /* Determines phy mode */
+#elif defined(CONFIG_405EP) || defined(CONFIG_405EX) || defined(CONFIG_440)
+ int bi_phynum[2]; /* Determines phy mapping */
+ int bi_phymode[2]; /* Determines phy mode */
+#else
+ int bi_phynum[1]; /* Determines phy mapping */
+ int bi_phymode[1]; /* Determines phy mode */
+#endif
+#endif /* defined(CONFIG_4xx) */
+} bd_t;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* !CONFIG_SYS_GENERIC_BOARD */
+
+/* For image.h:image_check_target_arch() */
+#define IH_ARCH_DEFAULT IH_ARCH_PPC
+
+#endif /* __U_BOOT_H__ */
diff --git a/arch/powerpc/include/asm/unaligned.h b/arch/powerpc/include/asm/unaligned.h
new file mode 100644
index 0000000..5f1b1e3
--- /dev/null
+++ b/arch/powerpc/include/asm/unaligned.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_POWERPC_UNALIGNED_H
+#define _ASM_POWERPC_UNALIGNED_H
+
+#ifdef __KERNEL__
+
+/*
+ * The PowerPC can do unaligned accesses itself in big endian mode.
+ */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
+
+#define get_unaligned __get_unaligned_be
+#define put_unaligned __put_unaligned_be
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_UNALIGNED_H */
diff --git a/arch/powerpc/include/asm/xilinx_irq.h b/arch/powerpc/include/asm/xilinx_irq.h
new file mode 100644
index 0000000..61171c2
--- /dev/null
+++ b/arch/powerpc/include/asm/xilinx_irq.h
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2008
+ * Ricado Ribalda-Universidad Autonoma de Madrid-ricardo.ribalda@uam.es
+ * This work has been supported by: QTechnology http://qtec.com/
+ * Based on interrupts.c Wolfgang Denk-DENX Software Engineering-wd@denx.de
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef XILINX_IRQ_H
+#define XILINX_IRQ_H
+
+#define intc XPAR_INTC_0_BASEADDR
+#define ISR (intc + (0 * 4)) /* Interrupt Status Register */
+#define IPR (intc + (1 * 4)) /* Interrupt Pending Register */
+#define IER (intc + (2 * 4)) /* Interrupt Enable Register */
+#define IAR (intc + (3 * 4)) /* Interrupt Acknowledge Register */
+#define SIE (intc + (4 * 4)) /* Set Interrupt Enable bits */
+#define CIE (intc + (5 * 4)) /* Clear Interrupt Enable bits */
+#define IVR (intc + (6 * 4)) /* Interrupt Vector Register */
+#define MER (intc + (7 * 4)) /* Master Enable Register */
+
+#define IRQ_MASK(irq) (1 << (irq & 0x1f))
+
+#define IRQ_MAX XPAR_INTC_MAX_NUM_INTR_INPUTS
+
+#endif
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
new file mode 100644
index 0000000..8c4920b
--- /dev/null
+++ b/arch/powerpc/lib/Makefile
@@ -0,0 +1,120 @@
+#
+# (C) Copyright 2000-2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+## Build a couple of necessary functions into a private libgcc
+LIBGCC = $(obj)libgcc.o
+GLSOBJS += _ashldi3.o
+GLSOBJS += _ashrdi3.o
+GLSOBJS += _lshrdi3.o
+LGOBJS := $(addprefix $(obj),$(GLSOBJS)) \
+ $(addprefix $(obj),$(GLCOBJS))
+
+## But only build it if the user asked for it
+ifdef USE_PRIVATE_LIBGCC
+TARGETS += $(LIBGCC)
+endif
+
+LIB = $(obj)lib$(ARCH).o
+
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+COBJS-y += cache.o time.o
+SOBJS-y += ticks.o
+else
+
+SOBJS-y += ppcstring.o
+
+SOBJS-y += ppccache.o
+SOBJS-y += ticks.o
+SOBJS-y += reloc.o
+
+COBJS-$(CONFIG_BAT_RW) += bat_rw.o
+ifndef CONFIG_SPL_BUILD
+ifndef CONFIG_SYS_GENERIC_BOARD
+COBJS-y += board.o
+endif
+endif
+COBJS-$(CONFIG_CMD_BOOTM) += bootm.o
+COBJS-y += cache.o
+COBJS-y += extable.o
+COBJS-y += interrupts.o
+COBJS-$(CONFIG_CMD_KGDB) += kgdb.o
+COBJS-${CONFIG_CMD_IDE} += ide.o
+COBJS-y += time.o
+
+# Don't include the MPC5xxx special memcpy into the
+# SPL U-Boot image. memcpy is used in the SPL NOR
+# flash driver. And we need the real, fast memcpy
+# here. We have no problems with unaligned access.
+ifndef CONFIG_SPL_BUILD
+# Workaround for local bus unaligned access problems
+# on MPC512x and MPC5200
+ifdef CONFIG_MPC512X
+$(obj)ppcstring.o: AFLAGS += -Dmemcpy=__memcpy
+COBJS-y += memcpy_mpc5200.o
+endif
+ifdef CONFIG_MPC5200
+$(obj)ppcstring.o: AFLAGS += -Dmemcpy=__memcpy
+COBJS-y += memcpy_mpc5200.o
+endif
+endif
+
+endif # not minimal
+
+ifdef CONFIG_SPL_BUILD
+COBJS-$(CONFIG_SPL_FRAMEWORK) += spl.o
+endif
+
+COBJS += $(sort $(COBJS-y))
+
+SRCS := $(GLSOBJS:.o=.S) $(GLCOBJS:.o=.c) \
+ $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+TARGETS += $(LIB)
+
+all: $(TARGETS)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+$(LIBGCC): $(obj).depend $(LGOBJS)
+ $(call cmd_link_o_target, $(LGOBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/powerpc/lib/_ashldi3.S b/arch/powerpc/lib/_ashldi3.S
new file mode 100644
index 0000000..e452f56
--- /dev/null
+++ b/arch/powerpc/lib/_ashldi3.S
@@ -0,0 +1,45 @@
+/*
+ * This code was copied from arch/powerpc/kernel/misc_32.S in the Linux
+ * kernel sources (commit 85e2efbb1db9a18d218006706d6e4fbeb0216213, also
+ * known as 2.6.38-rc5). The source file copyrights are as follows:
+ *
+ * (C) Copyright 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <config.h>
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+ .globl __ashldi3
+__ashldi3:
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
+ blr
diff --git a/arch/powerpc/lib/_ashrdi3.S b/arch/powerpc/lib/_ashrdi3.S
new file mode 100644
index 0000000..f28ab49
--- /dev/null
+++ b/arch/powerpc/lib/_ashrdi3.S
@@ -0,0 +1,47 @@
+/*
+ * This code was copied from arch/powerpc/kernel/misc_32.S in the Linux
+ * kernel sources (commit 85e2efbb1db9a18d218006706d6e4fbeb0216213, also
+ * known as 2.6.38-rc5). The source file copyrights are as follows:
+ *
+ * (C) Copyright 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <config.h>
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+ .globl __ashrdi3
+__ashrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
diff --git a/arch/powerpc/lib/_lshrdi3.S b/arch/powerpc/lib/_lshrdi3.S
new file mode 100644
index 0000000..c1bbe7b
--- /dev/null
+++ b/arch/powerpc/lib/_lshrdi3.S
@@ -0,0 +1,45 @@
+/*
+ * This code was copied from arch/powerpc/kernel/misc_32.S in the Linux
+ * kernel sources (commit 85e2efbb1db9a18d218006706d6e4fbeb0216213, also
+ * known as 2.6.38-rc5). The source file copyrights are as follows:
+ *
+ * (C) Copyright 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <config.h>
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+ .globl __lshrdi3
+__lshrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
diff --git a/arch/powerpc/lib/bat_rw.c b/arch/powerpc/lib/bat_rw.c
new file mode 100644
index 0000000..113c293
--- /dev/null
+++ b/arch/powerpc/lib/bat_rw.c
@@ -0,0 +1,261 @@
+/*
+ * (C) Copyright 2002
+ * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+#include <linux/compiler.h>
+
+#ifdef CONFIG_ADDR_MAP
+#include <addr_map.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int write_bat (ppc_bat_t bat, unsigned long upper, unsigned long lower)
+{
+ __maybe_unused int batn = -1;
+
+ sync();
+
+ switch (bat) {
+ case DBAT0:
+ mtspr (DBAT0L, lower);
+ mtspr (DBAT0U, upper);
+ batn = 0;
+ break;
+ case IBAT0:
+ mtspr (IBAT0L, lower);
+ mtspr (IBAT0U, upper);
+ break;
+ case DBAT1:
+ mtspr (DBAT1L, lower);
+ mtspr (DBAT1U, upper);
+ batn = 1;
+ break;
+ case IBAT1:
+ mtspr (IBAT1L, lower);
+ mtspr (IBAT1U, upper);
+ break;
+ case DBAT2:
+ mtspr (DBAT2L, lower);
+ mtspr (DBAT2U, upper);
+ batn = 2;
+ break;
+ case IBAT2:
+ mtspr (IBAT2L, lower);
+ mtspr (IBAT2U, upper);
+ break;
+ case DBAT3:
+ mtspr (DBAT3L, lower);
+ mtspr (DBAT3U, upper);
+ batn = 3;
+ break;
+ case IBAT3:
+ mtspr (IBAT3L, lower);
+ mtspr (IBAT3U, upper);
+ break;
+#ifdef CONFIG_HIGH_BATS
+ case DBAT4:
+ mtspr (DBAT4L, lower);
+ mtspr (DBAT4U, upper);
+ batn = 4;
+ break;
+ case IBAT4:
+ mtspr (IBAT4L, lower);
+ mtspr (IBAT4U, upper);
+ break;
+ case DBAT5:
+ mtspr (DBAT5L, lower);
+ mtspr (DBAT5U, upper);
+ batn = 5;
+ break;
+ case IBAT5:
+ mtspr (IBAT5L, lower);
+ mtspr (IBAT5U, upper);
+ break;
+ case DBAT6:
+ mtspr (DBAT6L, lower);
+ mtspr (DBAT6U, upper);
+ batn = 6;
+ break;
+ case IBAT6:
+ mtspr (IBAT6L, lower);
+ mtspr (IBAT6U, upper);
+ break;
+ case DBAT7:
+ mtspr (DBAT7L, lower);
+ mtspr (DBAT7U, upper);
+ batn = 7;
+ break;
+ case IBAT7:
+ mtspr (IBAT7L, lower);
+ mtspr (IBAT7U, upper);
+ break;
+#endif
+ default:
+ return (-1);
+ }
+
+#ifdef CONFIG_ADDR_MAP
+ if ((gd->flags & GD_FLG_RELOC) && (batn >= 0)) {
+ phys_size_t size;
+ if (!BATU_VALID(upper))
+ size = 0;
+ else
+ size = BATU_SIZE(upper);
+ addrmap_set_entry(BATU_VADDR(upper), BATL_PADDR(lower),
+ size, batn);
+ }
+#endif
+
+ sync();
+ isync();
+
+ return (0);
+}
+
+int read_bat (ppc_bat_t bat, unsigned long *upper, unsigned long *lower)
+{
+ unsigned long register u;
+ unsigned long register l;
+
+ switch (bat) {
+ case DBAT0:
+ l = mfspr (DBAT0L);
+ u = mfspr (DBAT0U);
+ break;
+ case IBAT0:
+ l = mfspr (IBAT0L);
+ u = mfspr (IBAT0U);
+ break;
+ case DBAT1:
+ l = mfspr (DBAT1L);
+ u = mfspr (DBAT1U);
+ break;
+ case IBAT1:
+ l = mfspr (IBAT1L);
+ u = mfspr (IBAT1U);
+ break;
+ case DBAT2:
+ l = mfspr (DBAT2L);
+ u = mfspr (DBAT2U);
+ break;
+ case IBAT2:
+ l = mfspr (IBAT2L);
+ u = mfspr (IBAT2U);
+ break;
+ case DBAT3:
+ l = mfspr (DBAT3L);
+ u = mfspr (DBAT3U);
+ break;
+ case IBAT3:
+ l = mfspr (IBAT3L);
+ u = mfspr (IBAT3U);
+ break;
+#ifdef CONFIG_HIGH_BATS
+ case DBAT4:
+ l = mfspr (DBAT4L);
+ u = mfspr (DBAT4U);
+ break;
+ case IBAT4:
+ l = mfspr (IBAT4L);
+ u = mfspr (IBAT4U);
+ break;
+ case DBAT5:
+ l = mfspr (DBAT5L);
+ u = mfspr (DBAT5U);
+ break;
+ case IBAT5:
+ l = mfspr (IBAT5L);
+ u = mfspr (IBAT5U);
+ break;
+ case DBAT6:
+ l = mfspr (DBAT6L);
+ u = mfspr (DBAT6U);
+ break;
+ case IBAT6:
+ l = mfspr (IBAT6L);
+ u = mfspr (IBAT6U);
+ break;
+ case DBAT7:
+ l = mfspr (DBAT7L);
+ u = mfspr (DBAT7U);
+ break;
+ case IBAT7:
+ l = mfspr (IBAT7L);
+ u = mfspr (IBAT7U);
+ break;
+#endif
+ default:
+ return (-1);
+ }
+
+ *upper = u;
+ *lower = l;
+
+ return (0);
+}
+
+void print_bats(void)
+{
+ printf("BAT registers:\n");
+
+ printf ("\tIBAT0L = 0x%08X ", mfspr (IBAT0L));
+ printf ("\tIBAT0U = 0x%08X\n", mfspr (IBAT0U));
+ printf ("\tDBAT0L = 0x%08X ", mfspr (DBAT0L));
+ printf ("\tDBAT0U = 0x%08X\n", mfspr (DBAT0U));
+ printf ("\tIBAT1L = 0x%08X ", mfspr (IBAT1L));
+ printf ("\tIBAT1U = 0x%08X\n", mfspr (IBAT1U));
+ printf ("\tDBAT1L = 0x%08X ", mfspr (DBAT1L));
+ printf ("\tDBAT1U = 0x%08X\n", mfspr (DBAT1U));
+ printf ("\tIBAT2L = 0x%08X ", mfspr (IBAT2L));
+ printf ("\tIBAT2U = 0x%08X\n", mfspr (IBAT2U));
+ printf ("\tDBAT2L = 0x%08X ", mfspr (DBAT2L));
+ printf ("\tDBAT2U = 0x%08X\n", mfspr (DBAT2U));
+ printf ("\tIBAT3L = 0x%08X ", mfspr (IBAT3L));
+ printf ("\tIBAT3U = 0x%08X\n", mfspr (IBAT3U));
+ printf ("\tDBAT3L = 0x%08X ", mfspr (DBAT3L));
+ printf ("\tDBAT3U = 0x%08X\n", mfspr (DBAT3U));
+
+#ifdef CONFIG_HIGH_BATS
+ printf ("\tIBAT4L = 0x%08X ", mfspr (IBAT4L));
+ printf ("\tIBAT4U = 0x%08X\n", mfspr (IBAT4U));
+ printf ("\tDBAT4L = 0x%08X ", mfspr (DBAT4L));
+ printf ("\tDBAT4U = 0x%08X\n", mfspr (DBAT4U));
+ printf ("\tIBAT5L = 0x%08X ", mfspr (IBAT5L));
+ printf ("\tIBAT5U = 0x%08X\n", mfspr (IBAT5U));
+ printf ("\tDBAT5L = 0x%08X ", mfspr (DBAT5L));
+ printf ("\tDBAT5U = 0x%08X\n", mfspr (DBAT5U));
+ printf ("\tIBAT6L = 0x%08X ", mfspr (IBAT6L));
+ printf ("\tIBAT6U = 0x%08X\n", mfspr (IBAT6U));
+ printf ("\tDBAT6L = 0x%08X ", mfspr (DBAT6L));
+ printf ("\tDBAT6U = 0x%08X\n", mfspr (DBAT6U));
+ printf ("\tIBAT7L = 0x%08X ", mfspr (IBAT7L));
+ printf ("\tIBAT7U = 0x%08X\n", mfspr (IBAT7U));
+ printf ("\tDBAT7L = 0x%08X ", mfspr (DBAT7L));
+ printf ("\tDBAT7U = 0x%08X\n", mfspr (DBAT7U));
+#endif
+}
diff --git a/arch/powerpc/lib/board.c b/arch/powerpc/lib/board.c
new file mode 100644
index 0000000..fc4c1d5
--- /dev/null
+++ b/arch/powerpc/lib/board.c
@@ -0,0 +1,1041 @@
+/*
+ * (C) Copyright 2000-2011
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <malloc.h>
+#include <stdio_dev.h>
+#ifdef CONFIG_8xx
+#include <mpc8xx.h>
+#endif
+#ifdef CONFIG_5xx
+#include <mpc5xx.h>
+#endif
+#ifdef CONFIG_MPC5xxx
+#include <mpc5xxx.h>
+#endif
+#if defined(CONFIG_CMD_IDE)
+#include <ide.h>
+#endif
+#if defined(CONFIG_CMD_SCSI)
+#include <scsi.h>
+#endif
+#if defined(CONFIG_CMD_KGDB)
+#include <kgdb.h>
+#endif
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+#include <net.h>
+#ifdef CONFIG_GENERIC_MMC
+#include <mmc.h>
+#endif
+#include <serial.h>
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+#if !defined(CONFIG_CPM2)
+#include <commproc.h>
+#endif
+#endif
+#include <version.h>
+#if defined(CONFIG_BAB7xx)
+#include <w83c553f.h>
+#endif
+#include <dtt.h>
+#if defined(CONFIG_POST)
+#include <post.h>
+#endif
+#if defined(CONFIG_LOGBUFFER)
+#include <logbuff.h>
+#endif
+#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
+#include <asm/cache.h>
+#endif
+#ifdef CONFIG_PS2KBD
+#include <keyboard.h>
+#endif
+
+#ifdef CONFIG_ADDR_MAP
+#include <asm/mmu.h>
+#endif
+
+#ifdef CONFIG_MP
+#include <asm/mp.h>
+#endif
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+#ifdef CONFIG_SYS_UPDATE_FLASH_SIZE
+extern int update_flash_size(int flash_size);
+#endif
+
+#if defined(CONFIG_SC3)
+extern void sc3_read_eeprom(void);
+#endif
+
+#if defined(CONFIG_CMD_DOC)
+void doc_init(void);
+#endif
+#if defined(CONFIG_HARD_I2C) || \
+ defined(CONFIG_SOFT_I2C)
+#include <i2c.h>
+#endif
+#include <spi.h>
+#include <nand.h>
+
+static char *failed = "*** failed ***\n";
+
+#if defined(CONFIG_OXC) || defined(CONFIG_RMU)
+extern flash_info_t flash_info[];
+#endif
+
+#if defined(CONFIG_START_IDE)
+extern int board_start_ide(void);
+#endif
+#include <environment.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_SYS_MEM_TOP_HIDE)
+#define CONFIG_SYS_MEM_TOP_HIDE 0
+#endif
+
+extern ulong __init_end;
+extern ulong __bss_end;
+ulong monitor_flash_len;
+
+#if defined(CONFIG_CMD_BEDBUG)
+#include <bedbug/type.h>
+#endif
+
+/*
+ * Utilities
+ */
+
+/*
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependend #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+typedef int (init_fnc_t)(void);
+
+/*
+ * Init Utilities
+ *
+ * Some of this code should be moved into the core functions,
+ * but let's get it working (again) first...
+ */
+
+static int init_baudrate(void)
+{
+ gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
+ return 0;
+}
+
+/***********************************************************************/
+
+static void __board_add_ram_info(int use_default)
+{
+ /* please define platform specific board_add_ram_info() */
+}
+
+void board_add_ram_info(int)
+ __attribute__ ((weak, alias("__board_add_ram_info")));
+
+static int __board_flash_wp_on(void)
+{
+ /*
+ * Most flashes can't be detected when write protection is enabled,
+ * so provide a way to let U-Boot gracefully ignore write protected
+ * devices.
+ */
+ return 0;
+}
+
+int board_flash_wp_on(void)
+ __attribute__ ((weak, alias("__board_flash_wp_on")));
+
+static void __cpu_secondary_init_r(void)
+{
+}
+
+void cpu_secondary_init_r(void)
+ __attribute__ ((weak, alias("__cpu_secondary_init_r")));
+
+static int init_func_ram(void)
+{
+#ifdef CONFIG_BOARD_TYPES
+ int board_type = gd->board_type;
+#else
+ int board_type = 0; /* use dummy arg */
+#endif
+ puts("DRAM: ");
+
+ gd->ram_size = initdram(board_type);
+
+ if (gd->ram_size > 0) {
+ print_size(gd->ram_size, "");
+ board_add_ram_info(0);
+ putc('\n');
+ return 0;
+ }
+ puts(failed);
+ return 1;
+}
+
+/***********************************************************************/
+
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+static int init_func_i2c(void)
+{
+ puts("I2C: ");
+ i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ puts("ready\n");
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_HARD_SPI)
+static int init_func_spi(void)
+{
+ puts("SPI: ");
+ spi_init();
+ puts("ready\n");
+ return 0;
+}
+#endif
+
+/***********************************************************************/
+
+#if defined(CONFIG_WATCHDOG)
+int init_func_watchdog_init(void)
+{
+ puts(" Watchdog enabled\n");
+ WATCHDOG_RESET();
+ return 0;
+}
+
+int init_func_watchdog_reset(void)
+{
+ WATCHDOG_RESET();
+ return 0;
+}
+#endif /* CONFIG_WATCHDOG */
+
+/*
+ * Initialization sequence
+ */
+
+static init_fnc_t *init_sequence[] = {
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+ probecpu,
+#endif
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+ board_early_init_f,
+#endif
+#if !defined(CONFIG_8xx_CPUCLK_DEFAULT)
+ get_clocks, /* get CPU and bus clocks (etc.) */
+#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \
+ && !defined(CONFIG_TQM885D)
+ adjust_sdram_tbs_8xx,
+#endif
+ init_timebase,
+#endif
+#ifdef CONFIG_SYS_ALLOC_DPRAM
+#if !defined(CONFIG_CPM2)
+ dpram_init,
+#endif
+#endif
+#if defined(CONFIG_BOARD_POSTCLK_INIT)
+ board_postclk_init,
+#endif
+ env_init,
+#if defined(CONFIG_8xx_CPUCLK_DEFAULT)
+ /* get CPU and bus clocks according to the environment variable */
+ get_clocks_866,
+ /* adjust sdram refresh rate according to the new clock */
+ sdram_adjust_866,
+ init_timebase,
+#endif
+ init_baudrate,
+ serial_init,
+ console_init_f,
+ display_options,
+#if defined(CONFIG_8260)
+ prt_8260_rsr,
+ prt_8260_clks,
+#endif /* CONFIG_8260 */
+#if defined(CONFIG_MPC83xx)
+ prt_83xx_rsr,
+#endif
+ checkcpu,
+#if defined(CONFIG_MPC5xxx)
+ prt_mpc5xxx_clks,
+#endif /* CONFIG_MPC5xxx */
+ checkboard,
+ INIT_FUNC_WATCHDOG_INIT
+#if defined(CONFIG_MISC_INIT_F)
+ misc_init_f,
+#endif
+ INIT_FUNC_WATCHDOG_RESET
+#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
+ init_func_i2c,
+#endif
+#if defined(CONFIG_HARD_SPI)
+ init_func_spi,
+#endif
+#ifdef CONFIG_POST
+ post_init_f,
+#endif
+ INIT_FUNC_WATCHDOG_RESET
+ init_func_ram,
+#if defined(CONFIG_SYS_DRAM_TEST)
+ testdram,
+#endif /* CONFIG_SYS_DRAM_TEST */
+ INIT_FUNC_WATCHDOG_RESET
+ NULL, /* Terminate this list */
+};
+
+ulong get_effective_memsize(void)
+{
+#ifndef CONFIG_VERY_BIG_RAM
+ return gd->ram_size;
+#else
+ /* limit stack to what we can reasonable map */
+ return ((gd->ram_size > CONFIG_MAX_MEM_MAPPED) ?
+ CONFIG_MAX_MEM_MAPPED : gd->ram_size);
+#endif
+}
+
+static int __fixup_cpu(void)
+{
+ return 0;
+}
+
+int fixup_cpu(void) __attribute__((weak, alias("__fixup_cpu")));
+
+/*
+ * This is the first part of the initialization sequence that is
+ * implemented in C, but still running from ROM.
+ *
+ * The main purpose is to provide a (serial) console interface as
+ * soon as possible (so we can see any error messages), and to
+ * initialize the RAM so that we can relocate the monitor code to
+ * RAM.
+ *
+ * Be aware of the restrictions: global data is read-only, BSS is not
+ * initialized, and stack space is limited to a few kB.
+ */
+
+#ifdef CONFIG_LOGBUFFER
+unsigned long logbuffer_base(void)
+{
+ return CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - LOGBUFF_LEN;
+}
+#endif
+
+void board_init_f(ulong bootflag)
+{
+ bd_t *bd;
+ ulong len, addr, addr_sp;
+ ulong *s;
+ gd_t *id;
+ init_fnc_t **init_fnc_ptr;
+
+#ifdef CONFIG_PRAM
+ ulong reg;
+#endif
+
+ /* Pointer is writable since we allocated a register for it */
+ gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+ /* compiler optimization barrier needed for GCC >= 3.4 */
+ __asm__ __volatile__("":::"memory");
+
+#if !defined(CONFIG_CPM2) && !defined(CONFIG_MPC512X) && \
+ !defined(CONFIG_MPC83xx) && !defined(CONFIG_MPC85xx) && \
+ !defined(CONFIG_MPC86xx)
+ /* Clear initial global data */
+ memset((void *) gd, 0, sizeof(gd_t));
+#endif
+
+ for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
+ if ((*init_fnc_ptr) () != 0)
+ hang();
+
+#ifdef CONFIG_POST
+ post_bootmode_init();
+ post_run(NULL, POST_ROM | post_bootmode_get(NULL));
+#endif
+
+ WATCHDOG_RESET();
+
+ /*
+ * Now that we have DRAM mapped and working, we can
+ * relocate the code and continue running from DRAM.
+ *
+ * Reserve memory at end of RAM for (top down in that order):
+ * - area that won't get touched by U-Boot and Linux (optional)
+ * - kernel log buffer
+ * - protected RAM
+ * - LCD framebuffer
+ * - monitor code
+ * - board info struct
+ */
+ len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
+
+ /*
+ * Subtract specified amount of memory to hide so that it won't
+ * get "touched" at all by U-Boot. By fixing up gd->ram_size
+ * the Linux kernel should now get passed the now "corrected"
+ * memory size and won't touch it either. This should work
+ * for arch/ppc and arch/powerpc. Only Linux board ports in
+ * arch/powerpc with bootwrapper support, that recalculate the
+ * memory size from the SDRAM controller setup will have to
+ * get fixed.
+ */
+ gd->ram_size -= CONFIG_SYS_MEM_TOP_HIDE;
+
+ addr = CONFIG_SYS_SDRAM_BASE + get_effective_memsize();
+
+#if defined(CONFIG_MP) && (defined(CONFIG_MPC86xx) || defined(CONFIG_E500))
+ /*
+ * We need to make sure the location we intend to put secondary core
+ * boot code is reserved and not used by any part of u-boot
+ */
+ if (addr > determine_mp_bootpg(NULL)) {
+ addr = determine_mp_bootpg(NULL);
+ debug("Reserving MP boot page to %08lx\n", addr);
+ }
+#endif
+
+#ifdef CONFIG_LOGBUFFER
+#ifndef CONFIG_ALT_LB_ADDR
+ /* reserve kernel log buffer */
+ addr -= (LOGBUFF_RESERVE);
+ debug("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN,
+ addr);
+#endif
+#endif
+
+#ifdef CONFIG_PRAM
+ /*
+ * reserve protected RAM
+ */
+ reg = getenv_ulong("pram", 10, CONFIG_PRAM);
+ addr -= (reg << 10); /* size is in kB */
+ debug("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
+#endif /* CONFIG_PRAM */
+
+ /* round down to next 4 kB limit */
+ addr &= ~(4096 - 1);
+ debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
+
+#ifdef CONFIG_LCD
+#ifdef CONFIG_FB_ADDR
+ gd->fb_base = CONFIG_FB_ADDR;
+#else
+ /* reserve memory for LCD display (always full pages) */
+ addr = lcd_setmem(addr);
+ gd->fb_base = addr;
+#endif /* CONFIG_FB_ADDR */
+#endif /* CONFIG_LCD */
+
+#if defined(CONFIG_VIDEO) && defined(CONFIG_8xx)
+ /* reserve memory for video display (always full pages) */
+ addr = video_setmem(addr);
+ gd->fb_base = addr;
+#endif /* CONFIG_VIDEO */
+
+ /*
+ * reserve memory for U-Boot code, data & bss
+ * round down to next 4 kB limit
+ */
+ addr -= len;
+ addr &= ~(4096 - 1);
+#ifdef CONFIG_E500
+ /* round down to next 64 kB limit so that IVPR stays aligned */
+ addr &= ~(65536 - 1);
+#endif
+
+ debug("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
+
+ /*
+ * reserve memory for malloc() arena
+ */
+ addr_sp = addr - TOTAL_MALLOC_LEN;
+ debug("Reserving %dk for malloc() at: %08lx\n",
+ TOTAL_MALLOC_LEN >> 10, addr_sp);
+
+ /*
+ * (permanently) allocate a Board Info struct
+ * and a permanent copy of the "global" data
+ */
+ addr_sp -= sizeof(bd_t);
+ bd = (bd_t *) addr_sp;
+ memset(bd, 0, sizeof(bd_t));
+ gd->bd = bd;
+ debug("Reserving %zu Bytes for Board Info at: %08lx\n",
+ sizeof(bd_t), addr_sp);
+ addr_sp -= sizeof(gd_t);
+ id = (gd_t *) addr_sp;
+ debug("Reserving %zu Bytes for Global Data at: %08lx\n",
+ sizeof(gd_t), addr_sp);
+
+ /*
+ * Finally, we set up a new (bigger) stack.
+ *
+ * Leave some safety gap for SP, force alignment on 16 byte boundary
+ * Clear initial stack frame
+ */
+ addr_sp -= 16;
+ addr_sp &= ~0xF;
+ s = (ulong *) addr_sp;
+ *s = 0; /* Terminate back chain */
+ *++s = 0; /* NULL return address */
+ debug("Stack Pointer at: %08lx\n", addr_sp);
+
+ /*
+ * Save local variables to board info struct
+ */
+
+ bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of memory */
+ bd->bi_memsize = gd->ram_size; /* size in bytes */
+
+#ifdef CONFIG_SYS_SRAM_BASE
+ bd->bi_sramstart = CONFIG_SYS_SRAM_BASE; /* start of SRAM */
+ bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE; /* size of SRAM */
+#endif
+
+#if defined(CONFIG_8xx) || defined(CONFIG_8260) || defined(CONFIG_5xx) || \
+ defined(CONFIG_E500) || defined(CONFIG_MPC86xx)
+ bd->bi_immr_base = CONFIG_SYS_IMMR; /* base of IMMR register */
+#endif
+#if defined(CONFIG_MPC5xxx)
+ bd->bi_mbar_base = CONFIG_SYS_MBAR; /* base of internal registers */
+#endif
+#if defined(CONFIG_MPC83xx)
+ bd->bi_immrbar = CONFIG_SYS_IMMR;
+#endif
+
+ WATCHDOG_RESET();
+ bd->bi_intfreq = gd->cpu_clk; /* Internal Freq, in Hz */
+ bd->bi_busfreq = gd->bus_clk; /* Bus Freq, in Hz */
+#if defined(CONFIG_CPM2)
+ bd->bi_cpmfreq = gd->arch.cpm_clk;
+ bd->bi_brgfreq = gd->arch.brg_clk;
+ bd->bi_sccfreq = gd->arch.scc_clk;
+ bd->bi_vco = gd->arch.vco_out;
+#endif /* CONFIG_CPM2 */
+#if defined(CONFIG_MPC512X)
+ bd->bi_ipsfreq = gd->arch.ips_clk;
+#endif /* CONFIG_MPC512X */
+#if defined(CONFIG_MPC5xxx)
+ bd->bi_ipbfreq = gd->arch.ipb_clk;
+ bd->bi_pcifreq = gd->pci_clk;
+#endif /* CONFIG_MPC5xxx */
+ bd->bi_baudrate = gd->baudrate; /* Console Baudrate */
+
+#ifdef CONFIG_SYS_EXTBDINFO
+ strncpy((char *) bd->bi_s_version, "1.2", sizeof(bd->bi_s_version));
+ strncpy((char *) bd->bi_r_version, U_BOOT_VERSION,
+ sizeof(bd->bi_r_version));
+
+ bd->bi_procfreq = gd->cpu_clk; /* Processor Speed, In Hz */
+ bd->bi_plb_busfreq = gd->bus_clk;
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || \
+ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+ bd->bi_pci_busfreq = get_PCI_freq();
+ bd->bi_opbfreq = get_OPB_freq();
+#elif defined(CONFIG_XILINX_405)
+ bd->bi_pci_busfreq = get_PCI_freq();
+#endif
+#endif
+
+ debug("New Stack Pointer is: %08lx\n", addr_sp);
+
+ WATCHDOG_RESET();
+
+ gd->relocaddr = addr; /* Store relocation addr, useful for debug */
+
+ memcpy(id, (void *) gd, sizeof(gd_t));
+
+ relocate_code(addr_sp, id, addr);
+
+ /* NOTREACHED - relocate_code() does not return */
+}
+
+/*
+ * This is the next part if the initialization sequence: we are now
+ * running from RAM and have a "normal" C environment, i. e. global
+ * data can be written, BSS has been cleared, the stack size in not
+ * that critical any more, etc.
+ */
+void board_init_r(gd_t *id, ulong dest_addr)
+{
+ bd_t *bd;
+ ulong malloc_start;
+
+#ifndef CONFIG_SYS_NO_FLASH
+ ulong flash_size;
+#endif
+
+ gd = id; /* initialize RAM version of global data */
+ bd = gd->bd;
+
+ gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
+
+ /* The Malloc area is immediately below the monitor copy in DRAM */
+ malloc_start = dest_addr - TOTAL_MALLOC_LEN;
+
+#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
+ /*
+ * The gd->arch.cpu pointer is set to an address in flash before
+ * relocation. We need to update it to point to the same CPU entry
+ * in RAM.
+ */
+ gd->arch.cpu += dest_addr - CONFIG_SYS_MONITOR_BASE;
+
+ /*
+ * If we didn't know the cpu mask & # cores, we can save them of
+ * now rather than 'computing' them constantly
+ */
+ fixup_cpu();
+#endif
+
+#ifdef CONFIG_SYS_EXTRA_ENV_RELOC
+ /*
+ * Some systems need to relocate the env_addr pointer early because the
+ * location it points to will get invalidated before env_relocate is
+ * called. One example is on systems that might use a L2 or L3 cache
+ * in SRAM mode and initialize that cache from SRAM mode back to being
+ * a cache in cpu_init_r.
+ */
+ gd->env_addr += dest_addr - CONFIG_SYS_MONITOR_BASE;
+#endif
+
+ serial_initialize();
+
+ debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
+
+ WATCHDOG_RESET();
+
+ /*
+ * Setup trap handlers
+ */
+ trap_init(dest_addr);
+
+#ifdef CONFIG_ADDR_MAP
+ init_addr_map();
+#endif
+
+#if defined(CONFIG_BOARD_EARLY_INIT_R)
+ board_early_init_r();
+#endif
+
+ monitor_flash_len = (ulong)&__init_end - dest_addr;
+
+ WATCHDOG_RESET();
+
+#ifdef CONFIG_LOGBUFFER
+ logbuff_init_ptrs();
+#endif
+#ifdef CONFIG_POST
+ post_output_backlog();
+#endif
+
+ WATCHDOG_RESET();
+
+#if defined(CONFIG_SYS_DELAYED_ICACHE)
+ icache_enable(); /* it's time to enable the instruction cache */
+#endif
+
+#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
+ unlock_ram_in_cache(); /* it's time to unlock D-cache in e500 */
+#endif
+
+#if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT)
+ /*
+ * Do early PCI configuration _before_ the flash gets initialised,
+ * because PCU ressources are crucial for flash access on some boards.
+ */
+ pci_init();
+#endif
+#if defined(CONFIG_WINBOND_83C553)
+ /*
+ * Initialise the ISA bridge
+ */
+ initialise_w83c553f();
+#endif
+
+ asm("sync ; isync");
+
+ mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN);
+
+#if !defined(CONFIG_SYS_NO_FLASH)
+ puts("Flash: ");
+
+ if (board_flash_wp_on()) {
+ printf("Uninitialized - Write Protect On\n");
+ /* Since WP is on, we can't find real size. Set to 0 */
+ flash_size = 0;
+ } else if ((flash_size = flash_init()) > 0) {
+#ifdef CONFIG_SYS_FLASH_CHECKSUM
+ print_size(flash_size, "");
+ /*
+ * Compute and print flash CRC if flashchecksum is set to 'y'
+ *
+ * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
+ */
+ if (getenv_yesno("flashchecksum") == 1) {
+ printf(" CRC: %08X",
+ crc32(0,
+ (const unsigned char *)
+ CONFIG_SYS_FLASH_BASE, flash_size)
+ );
+ }
+ putc('\n');
+#else /* !CONFIG_SYS_FLASH_CHECKSUM */
+ print_size(flash_size, "\n");
+#endif /* CONFIG_SYS_FLASH_CHECKSUM */
+ } else {
+ puts(failed);
+ hang();
+ }
+
+ /* update start of FLASH memory */
+ bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
+ /* size of FLASH memory (final value) */
+ bd->bi_flashsize = flash_size;
+
+#if defined(CONFIG_SYS_UPDATE_FLASH_SIZE)
+ /* Make a update of the Memctrl. */
+ update_flash_size(flash_size);
+#endif
+
+
+#if defined(CONFIG_OXC) || defined(CONFIG_RMU)
+ /* flash mapped at end of memory map */
+ bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size;
+#elif CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
+ bd->bi_flashoffset = monitor_flash_len; /* reserved area for monitor */
+#endif
+#endif /* !CONFIG_SYS_NO_FLASH */
+
+ WATCHDOG_RESET();
+
+ /* initialize higher level parts of CPU like time base and timers */
+ cpu_init_r();
+
+ WATCHDOG_RESET();
+
+#ifdef CONFIG_SPI
+#if !defined(CONFIG_ENV_IS_IN_EEPROM)
+ spi_init_f();
+#endif
+ spi_init_r();
+#endif
+
+#if defined(CONFIG_CMD_NAND)
+ WATCHDOG_RESET();
+ puts("NAND: ");
+ nand_init(); /* go init the NAND */
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+/*
+ * MMC initialization is called before relocating env.
+ * Thus It is required that operations like pin multiplexer
+ * be put in board_init.
+ */
+ WATCHDOG_RESET();
+ puts("MMC: ");
+ mmc_initialize(bd);
+#endif
+
+ /* relocate environment function pointers etc. */
+ env_relocate();
+
+ /*
+ * after non-volatile devices & environment is setup and cpu code have
+ * another round to deal with any initialization that might require
+ * full access to the environment or loading of some image (firmware)
+ * from a non-volatile device
+ */
+ cpu_secondary_init_r();
+
+ /*
+ * Fill in missing fields of bd_info.
+ * We do this here, where we have "normal" access to the
+ * environment; we used to do this still running from ROM,
+ * where had to use getenv_f(), which can be pretty slow when
+ * the environment is in EEPROM.
+ */
+
+#if defined(CONFIG_SYS_EXTBDINFO)
+#if defined(CONFIG_405GP) || defined(CONFIG_405EP)
+#if defined(CONFIG_I2CFAST)
+ /*
+ * set bi_iic_fast for linux taking environment variable
+ * "i2cfast" into account
+ */
+ {
+ if (getenv_yesno("i2cfast") == 1) {
+ bd->bi_iic_fast[0] = 1;
+ bd->bi_iic_fast[1] = 1;
+ }
+ }
+#endif /* CONFIG_I2CFAST */
+#endif /* CONFIG_405GP, CONFIG_405EP */
+#endif /* CONFIG_SYS_EXTBDINFO */
+
+#if defined(CONFIG_SC3)
+ sc3_read_eeprom();
+#endif
+
+#if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET)
+ mac_read_from_eeprom();
+#endif
+
+#ifdef CONFIG_HERMES
+ if ((gd->board_type >> 16) == 2)
+ bd->bi_ethspeed = gd->board_type & 0xFFFF;
+ else
+ bd->bi_ethspeed = 0xFFFF;
+#endif
+
+#ifdef CONFIG_CMD_NET
+ /* kept around for legacy kernels only ... ignore the next section */
+ eth_getenv_enetaddr("ethaddr", bd->bi_enetaddr);
+#ifdef CONFIG_HAS_ETH1
+ eth_getenv_enetaddr("eth1addr", bd->bi_enet1addr);
+#endif
+#ifdef CONFIG_HAS_ETH2
+ eth_getenv_enetaddr("eth2addr", bd->bi_enet2addr);
+#endif
+#ifdef CONFIG_HAS_ETH3
+ eth_getenv_enetaddr("eth3addr", bd->bi_enet3addr);
+#endif
+#ifdef CONFIG_HAS_ETH4
+ eth_getenv_enetaddr("eth4addr", bd->bi_enet4addr);
+#endif
+#ifdef CONFIG_HAS_ETH5
+ eth_getenv_enetaddr("eth5addr", bd->bi_enet5addr);
+#endif
+#endif /* CONFIG_CMD_NET */
+
+ WATCHDOG_RESET();
+
+#if defined(CONFIG_PCI) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
+ /*
+ * Do pci configuration
+ */
+ pci_init();
+#endif
+
+/** leave this here (after malloc(), environment and PCI are working) **/
+ /* Initialize stdio devices */
+ stdio_init();
+
+ /* Initialize the jump table for applications */
+ jumptable_init();
+
+#if defined(CONFIG_API)
+ /* Initialize API */
+ api_init();
+#endif
+
+ /* Initialize the console (after the relocation and devices init) */
+ console_init_r();
+
+#if defined(CONFIG_MISC_INIT_R)
+ /* miscellaneous platform dependent initialisations */
+ misc_init_r();
+#endif
+
+#ifdef CONFIG_HERMES
+ if (bd->bi_ethspeed != 0xFFFF)
+ hermes_start_lxt980((int) bd->bi_ethspeed);
+#endif
+
+#if defined(CONFIG_CMD_KGDB)
+ WATCHDOG_RESET();
+ puts("KGDB: ");
+ kgdb_init();
+#endif
+
+ debug("U-Boot relocated to %08lx\n", dest_addr);
+
+ /*
+ * Enable Interrupts
+ */
+ interrupt_init();
+
+#if defined(CONFIG_STATUS_LED) && defined(STATUS_LED_BOOT)
+ status_led_set(STATUS_LED_BOOT, STATUS_LED_BLINKING);
+#endif
+
+ udelay(20);
+
+ /* Initialize from environment */
+ load_addr = getenv_ulong("loadaddr", 16, load_addr);
+
+ WATCHDOG_RESET();
+
+#if defined(CONFIG_CMD_SCSI)
+ WATCHDOG_RESET();
+ puts("SCSI: ");
+ scsi_init();
+#endif
+
+#if defined(CONFIG_CMD_DOC)
+ WATCHDOG_RESET();
+ puts("DOC: ");
+ doc_init();
+#endif
+
+#ifdef CONFIG_BITBANGMII
+ bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+ WATCHDOG_RESET();
+ puts("Net: ");
+ eth_initialize(bd);
+#endif
+
+#if defined(CONFIG_CMD_NET) && defined(CONFIG_RESET_PHY_R)
+ WATCHDOG_RESET();
+ debug("Reset Ethernet PHY\n");
+ reset_phy();
+#endif
+
+#ifdef CONFIG_POST
+ post_run(NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+#if defined(CONFIG_CMD_PCMCIA) \
+ && !defined(CONFIG_CMD_IDE)
+ WATCHDOG_RESET();
+ puts("PCMCIA:");
+ pcmcia_init();
+#endif
+
+#if defined(CONFIG_CMD_IDE)
+ WATCHDOG_RESET();
+#ifdef CONFIG_IDE_8xx_PCCARD
+ puts("PCMCIA:");
+#else
+ puts("IDE: ");
+#endif
+#if defined(CONFIG_START_IDE)
+ if (board_start_ide())
+ ide_init();
+#else
+ ide_init();
+#endif
+#endif
+
+#ifdef CONFIG_LAST_STAGE_INIT
+ WATCHDOG_RESET();
+ /*
+ * Some parts can be only initialized if all others (like
+ * Interrupts) are up and running (i.e. the PC-style ISA
+ * keyboard).
+ */
+ last_stage_init();
+#endif
+
+#if defined(CONFIG_CMD_BEDBUG)
+ WATCHDOG_RESET();
+ bedbug_init();
+#endif
+
+#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
+ /*
+ * Export available size of memory for Linux,
+ * taking into account the protected RAM at top of memory
+ */
+ {
+ ulong pram = 0;
+ char memsz[32];
+
+#ifdef CONFIG_PRAM
+ pram = getenv_ulong("pram", 10, CONFIG_PRAM);
+#endif
+#ifdef CONFIG_LOGBUFFER
+#ifndef CONFIG_ALT_LB_ADDR
+ /* Also take the logbuffer into account (pram is in kB) */
+ pram += (LOGBUFF_LEN + LOGBUFF_OVERHEAD) / 1024;
+#endif
+#endif
+ sprintf(memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
+ setenv("mem", memsz);
+ }
+#endif
+
+#ifdef CONFIG_PS2KBD
+ puts("PS/2: ");
+ kbd_init();
+#endif
+
+#ifdef CONFIG_MODEM_SUPPORT
+ {
+ extern int do_mdm_init;
+
+ do_mdm_init = gd->do_mdm_init;
+ }
+#endif
+
+ /* Initialization complete - start the monitor */
+
+ /* main_loop() can return to retry autoboot, if so just run it again. */
+ for (;;) {
+ WATCHDOG_RESET();
+ main_loop();
+ }
+
+ /* NOTREACHED - no way out of command loop except booting */
+}
+
+#if 0 /* We could use plain global data, but the resulting code is bigger */
+/*
+ * Pointer to initial global data area
+ *
+ * Here we initialize it.
+ */
+#undef XTRN_DECLARE_GLOBAL_DATA_PTR
+#define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */
+DECLARE_GLOBAL_DATA_PTR =
+ (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
+#endif /* 0 */
+
+/************************************************************************/
diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c
new file mode 100644
index 0000000..d4ad323
--- /dev/null
+++ b/arch/powerpc/lib/bootm.c
@@ -0,0 +1,295 @@
+/*
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <image.h>
+#include <malloc.h>
+#include <u-boot/zlib.h>
+#include <bzlib.h>
+#include <environment.h>
+#include <asm/byteorder.h>
+#include <asm/mp.h>
+
+#if defined(CONFIG_OF_LIBFDT)
+#include <libfdt.h>
+#include <fdt_support.h>
+#endif
+
+#ifdef CONFIG_SYS_INIT_RAM_LOCK
+#include <asm/cache.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern ulong get_effective_memsize(void);
+static ulong get_sp (void);
+static void set_clocks_in_mhz (bd_t *kbd);
+
+#ifndef CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE
+#define CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE (768*1024*1024)
+#endif
+
+static void boot_jump_linux(bootm_headers_t *images)
+{
+ void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6,
+ ulong r7, ulong r8, ulong r9);
+#ifdef CONFIG_OF_LIBFDT
+ char *of_flat_tree = images->ft_addr;
+#endif
+
+ kernel = (void (*)(bd_t *, ulong, ulong, ulong,
+ ulong, ulong, ulong))images->ep;
+ debug ("## Transferring control to Linux (at address %08lx) ...\n",
+ (ulong)kernel);
+
+ bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+#if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
+ unlock_ram_in_cache();
+#endif
+
+#if defined(CONFIG_OF_LIBFDT)
+ if (of_flat_tree) { /* device tree; boot new style */
+ /*
+ * Linux Kernel Parameters (passing device tree):
+ * r3: pointer to the fdt
+ * r4: 0
+ * r5: 0
+ * r6: epapr magic
+ * r7: size of IMA in bytes
+ * r8: 0
+ * r9: 0
+ */
+ debug (" Booting using OF flat tree...\n");
+ WATCHDOG_RESET ();
+ (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
+ getenv_bootm_mapsize(), 0, 0);
+ /* does not return */
+ } else
+#endif
+ {
+ /*
+ * Linux Kernel Parameters (passing board info data):
+ * r3: ptr to board info data
+ * r4: initrd_start or 0 if no initrd
+ * r5: initrd_end - unused if r4 is 0
+ * r6: Start of command line string
+ * r7: End of command line string
+ * r8: 0
+ * r9: 0
+ */
+ ulong cmd_start = images->cmdline_start;
+ ulong cmd_end = images->cmdline_end;
+ ulong initrd_start = images->initrd_start;
+ ulong initrd_end = images->initrd_end;
+ bd_t *kbd = images->kbd;
+
+ debug (" Booting using board info...\n");
+ WATCHDOG_RESET ();
+ (*kernel) (kbd, initrd_start, initrd_end,
+ cmd_start, cmd_end, 0, 0);
+ /* does not return */
+ }
+ return ;
+}
+
+void arch_lmb_reserve(struct lmb *lmb)
+{
+ phys_size_t bootm_size;
+ ulong size, sp, bootmap_base;
+
+ bootmap_base = getenv_bootm_low();
+ bootm_size = getenv_bootm_size();
+
+#ifdef DEBUG
+ if (((u64)bootmap_base + bootm_size) >
+ (CONFIG_SYS_SDRAM_BASE + (u64)gd->ram_size))
+ puts("WARNING: bootm_low + bootm_size exceed total memory\n");
+ if ((bootmap_base + bootm_size) > get_effective_memsize())
+ puts("WARNING: bootm_low + bootm_size exceed eff. memory\n");
+#endif
+
+ size = min(bootm_size, get_effective_memsize());
+ size = min(size, CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE);
+
+ if (size < bootm_size) {
+ ulong base = bootmap_base + size;
+ printf("WARNING: adjusting available memory to %lx\n", size);
+ lmb_reserve(lmb, base, bootm_size - size);
+ }
+
+ /*
+ * Booting a (Linux) kernel image
+ *
+ * Allocate space for command line and board info - the
+ * address should be as high as possible within the reach of
+ * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
+ * memory, which means far enough below the current stack
+ * pointer.
+ */
+ sp = get_sp();
+ debug ("## Current stack ends at 0x%08lx\n", sp);
+
+ /* adjust sp by 4K to be safe */
+ sp -= 4096;
+ lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - sp));
+
+#ifdef CONFIG_MP
+ cpu_mp_lmb_reserve(lmb);
+#endif
+
+ return ;
+}
+
+static void boot_prep_linux(bootm_headers_t *images)
+{
+#ifdef CONFIG_MP
+ /*
+ * if we are MP make sure to flush the device tree so any changes are
+ * made visibile to all other cores. In AMP boot scenarios the cores
+ * might not be HW cache coherent with each other.
+ */
+ flush_cache((unsigned long)images->ft_addr, images->ft_len);
+#endif
+}
+
+static int boot_cmdline_linux(bootm_headers_t *images)
+{
+ ulong of_size = images->ft_len;
+ struct lmb *lmb = &images->lmb;
+ ulong *cmd_start = &images->cmdline_start;
+ ulong *cmd_end = &images->cmdline_end;
+
+ int ret = 0;
+
+ if (!of_size) {
+ /* allocate space and init command line */
+ ret = boot_get_cmdline (lmb, cmd_start, cmd_end);
+ if (ret) {
+ puts("ERROR with allocation of cmdline\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int boot_bd_t_linux(bootm_headers_t *images)
+{
+ ulong of_size = images->ft_len;
+ struct lmb *lmb = &images->lmb;
+ bd_t **kbd = &images->kbd;
+
+ int ret = 0;
+
+ if (!of_size) {
+ /* allocate space for kernel copy of board info */
+ ret = boot_get_kbd (lmb, kbd);
+ if (ret) {
+ puts("ERROR with allocation of kernel bd\n");
+ return ret;
+ }
+ set_clocks_in_mhz(*kbd);
+ }
+
+ return ret;
+}
+
+static int boot_body_linux(bootm_headers_t *images)
+{
+ int ret;
+
+ /* allocate space for kernel copy of board info */
+ ret = boot_bd_t_linux(images);
+ if (ret)
+ return ret;
+
+ ret = image_setup_linux(images);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+noinline
+int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
+{
+ int ret;
+
+ if (flag & BOOTM_STATE_OS_CMDLINE) {
+ boot_cmdline_linux(images);
+ return 0;
+ }
+
+ if (flag & BOOTM_STATE_OS_BD_T) {
+ boot_bd_t_linux(images);
+ return 0;
+ }
+
+ if (flag & BOOTM_STATE_OS_PREP) {
+ boot_prep_linux(images);
+ return 0;
+ }
+
+ boot_prep_linux(images);
+ ret = boot_body_linux(images);
+ if (ret)
+ return ret;
+ boot_jump_linux(images);
+
+ return 0;
+}
+
+static ulong get_sp (void)
+{
+ ulong sp;
+
+ asm( "mr %0,1": "=r"(sp) : );
+ return sp;
+}
+
+static void set_clocks_in_mhz (bd_t *kbd)
+{
+ char *s;
+
+ if ((s = getenv ("clocks_in_mhz")) != NULL) {
+ /* convert all clock information to MHz */
+ kbd->bi_intfreq /= 1000000L;
+ kbd->bi_busfreq /= 1000000L;
+#if defined(CONFIG_CPM2)
+ kbd->bi_cpmfreq /= 1000000L;
+ kbd->bi_brgfreq /= 1000000L;
+ kbd->bi_sccfreq /= 1000000L;
+ kbd->bi_vco /= 1000000L;
+#endif
+#if defined(CONFIG_MPC5xxx)
+ kbd->bi_ipbfreq /= 1000000L;
+ kbd->bi_pcifreq /= 1000000L;
+#endif /* CONFIG_MPC5xxx */
+ }
+}
diff --git a/arch/powerpc/lib/cache.c b/arch/powerpc/lib/cache.c
new file mode 100644
index 0000000..338b08b
--- /dev/null
+++ b/arch/powerpc/lib/cache.c
@@ -0,0 +1,53 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/cache.h>
+#include <watchdog.h>
+
+void flush_cache(ulong start_addr, ulong size)
+{
+#ifndef CONFIG_5xx
+ ulong addr, start, end;
+
+ start = start_addr & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
+ end = start_addr + size - 1;
+
+ for (addr = start; (addr <= end) && (addr >= start);
+ addr += CONFIG_SYS_CACHELINE_SIZE) {
+ asm volatile("dcbst 0,%0" : : "r" (addr) : "memory");
+ WATCHDOG_RESET();
+ }
+ /* wait for all dcbst to complete on bus */
+ asm volatile("sync" : : : "memory");
+
+ for (addr = start; (addr <= end) && (addr >= start);
+ addr += CONFIG_SYS_CACHELINE_SIZE) {
+ asm volatile("icbi 0,%0" : : "r" (addr) : "memory");
+ WATCHDOG_RESET();
+ }
+ asm volatile("sync" : : : "memory");
+ /* flush prefetch queue */
+ asm volatile("isync" : : : "memory");
+#endif
+}
diff --git a/arch/powerpc/lib/extable.c b/arch/powerpc/lib/extable.c
new file mode 100644
index 0000000..60983ae
--- /dev/null
+++ b/arch/powerpc/lib/extable.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <common.h>
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue. No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path. This means when everything is well,
+ * we don't even have to jump over them. Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct exception_table_entry
+{
+ unsigned long insn, fixup;
+};
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
+{
+ long diff;
+ while (first <= last) {
+ diff = first->insn - value;
+ if (diff == 0)
+ return first->fixup;
+ first++;
+ }
+
+ return 0;
+}
+
+unsigned long
+search_exception_table(unsigned long addr)
+{
+ unsigned long ret;
+
+ /* There is only the kernel to search. */
+ ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
+ /* if the serial port does not hang in exception, printf can be used */
+#if !defined(CONFIG_SYS_SERIAL_HANG_IN_EXCEPTION)
+ debug("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret);
+#endif
+ if (ret) return ret;
+
+ return 0;
+}
diff --git a/arch/powerpc/lib/ide.c b/arch/powerpc/lib/ide.c
new file mode 100644
index 0000000..139a94a
--- /dev/null
+++ b/arch/powerpc/lib/ide.c
@@ -0,0 +1,201 @@
+/*
+ * (C) Copyright 2000-2011
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* Code taken from cmd_ide.c */
+#include <common.h>
+#include <ata.h>
+#include "ide.h"
+
+#ifdef CONFIG_IDE_8xx_DIRECT
+#include <mpc8xx.h>
+#include <pcmcia.h>
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Timings for IDE Interface
+ *
+ * SETUP / LENGTH / HOLD - cycles valid for 50 MHz clk
+ * 70 165 30 PIO-Mode 0, [ns]
+ * 4 9 2 [Cycles]
+ * 50 125 20 PIO-Mode 1, [ns]
+ * 3 7 2 [Cycles]
+ * 30 100 15 PIO-Mode 2, [ns]
+ * 2 6 1 [Cycles]
+ * 30 80 10 PIO-Mode 3, [ns]
+ * 2 5 1 [Cycles]
+ * 25 70 10 PIO-Mode 4, [ns]
+ * 2 4 1 [Cycles]
+ */
+
+static const pio_config_t pio_config_ns[IDE_MAX_PIO_MODE+1] = {
+ /* Setup Length Hold */
+ { 70, 165, 30 }, /* PIO-Mode 0, [ns] */
+ { 50, 125, 20 }, /* PIO-Mode 1, [ns] */
+ { 30, 101, 15 }, /* PIO-Mode 2, [ns] */
+ { 30, 80, 10 }, /* PIO-Mode 3, [ns] */
+ { 25, 70, 10 }, /* PIO-Mode 4, [ns] */
+};
+
+static pio_config_t pio_config_clk[IDE_MAX_PIO_MODE+1];
+
+#ifndef CONFIG_SYS_PIO_MODE
+#define CONFIG_SYS_PIO_MODE 0 /* use a relaxed default */
+#endif
+static int pio_mode = CONFIG_SYS_PIO_MODE;
+
+/* Make clock cycles and always round up */
+
+#define PCMCIA_MK_CLKS(t, T) (((t) * (T) + 999U) / 1000U)
+
+static void set_pcmcia_timing(int pmode)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
+ ulong timings;
+
+ debug("Set timing for PIO Mode %d\n", pmode);
+
+ timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold)
+ | PCMCIA_SST(pio_config_clk[pmode].t_setup)
+ | PCMCIA_SL(pio_config_clk[pmode].t_length);
+
+ /*
+ * IDE 0
+ */
+ pcmp->pcmc_pbr0 = CONFIG_SYS_PCMCIA_PBR0;
+#if (CONFIG_SYS_PCMCIA_POR0 != 0)
+ pcmp->pcmc_por0 = CONFIG_SYS_PCMCIA_POR0 | timings;
+#else
+ pcmp->pcmc_por0 = CONFIG_SYS_PCMCIA_POR0;
+#endif
+ debug("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0);
+
+ pcmp->pcmc_pbr1 = CONFIG_SYS_PCMCIA_PBR1;
+#if (CONFIG_SYS_PCMCIA_POR1 != 0)
+ pcmp->pcmc_por1 = CONFIG_SYS_PCMCIA_POR1 | timings;
+#else
+ pcmp->pcmc_por1 = CONFIG_SYS_PCMCIA_POR1;
+#endif
+ debug("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1);
+
+ pcmp->pcmc_pbr2 = CONFIG_SYS_PCMCIA_PBR2;
+#if (CONFIG_SYS_PCMCIA_POR2 != 0)
+ pcmp->pcmc_por2 = CONFIG_SYS_PCMCIA_POR2 | timings;
+#else
+ pcmp->pcmc_por2 = CONFIG_SYS_PCMCIA_POR2;
+#endif
+ debug("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2);
+
+ pcmp->pcmc_pbr3 = CONFIG_SYS_PCMCIA_PBR3;
+#if (CONFIG_SYS_PCMCIA_POR3 != 0)
+ pcmp->pcmc_por3 = CONFIG_SYS_PCMCIA_POR3 | timings;
+#else
+ pcmp->pcmc_por3 = CONFIG_SYS_PCMCIA_POR3;
+#endif
+ debug("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3);
+
+ /*
+ * IDE 1
+ */
+ pcmp->pcmc_pbr4 = CONFIG_SYS_PCMCIA_PBR4;
+#if (CONFIG_SYS_PCMCIA_POR4 != 0)
+ pcmp->pcmc_por4 = CONFIG_SYS_PCMCIA_POR4 | timings;
+#else
+ pcmp->pcmc_por4 = CONFIG_SYS_PCMCIA_POR4;
+#endif
+ debug("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4);
+
+ pcmp->pcmc_pbr5 = CONFIG_SYS_PCMCIA_PBR5;
+#if (CONFIG_SYS_PCMCIA_POR5 != 0)
+ pcmp->pcmc_por5 = CONFIG_SYS_PCMCIA_POR5 | timings;
+#else
+ pcmp->pcmc_por5 = CONFIG_SYS_PCMCIA_POR5;
+#endif
+ debug("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5);
+
+ pcmp->pcmc_pbr6 = CONFIG_SYS_PCMCIA_PBR6;
+#if (CONFIG_SYS_PCMCIA_POR6 != 0)
+ pcmp->pcmc_por6 = CONFIG_SYS_PCMCIA_POR6 | timings;
+#else
+ pcmp->pcmc_por6 = CONFIG_SYS_PCMCIA_POR6;
+#endif
+ debug("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6);
+
+ pcmp->pcmc_pbr7 = CONFIG_SYS_PCMCIA_PBR7;
+#if (CONFIG_SYS_PCMCIA_POR7 != 0)
+ pcmp->pcmc_por7 = CONFIG_SYS_PCMCIA_POR7 | timings;
+#else
+ pcmp->pcmc_por7 = CONFIG_SYS_PCMCIA_POR7;
+#endif
+ debug("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7);
+
+}
+
+int ide_preinit(void)
+{
+ int i;
+ /* Initialize PIO timing tables */
+ for (i = 0; i <= IDE_MAX_PIO_MODE; ++i) {
+ pio_config_clk[i].t_setup =
+ PCMCIA_MK_CLKS(pio_config_ns[i].t_setup, gd->bus_clk);
+ pio_config_clk[i].t_length =
+ PCMCIA_MK_CLKS(pio_config_ns[i].t_length, gd->bus_clk);
+ pio_config_clk[i].t_hold =
+ PCMCIA_MK_CLKS(pio_config_ns[i].t_hold, gd->bus_clk);
+ debug("PIO Mode %d: setup=%2d ns/%d clk" " len=%3d ns/%d clk"
+ " hold=%2d ns/%d clk\n", i, pio_config_ns[i].t_setup,
+ pio_config_clk[i].t_setup, pio_config_ns[i].t_length,
+ pio_config_clk[i].t_length, pio_config_ns[i].t_hold,
+ pio_config_clk[i].t_hold);
+ }
+
+ return 0;
+}
+
+int ide_init_postreset(void)
+{
+ volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
+ volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia);
+
+ /* PCMCIA / IDE initialization for common mem space */
+ pcmp->pcmc_pgcrb = 0;
+
+ /* start in PIO mode 0 - most relaxed timings */
+ pio_mode = 0;
+ set_pcmcia_timing(pio_mode);
+ return 0;
+}
+#endif /* CONFIG_IDE_8xx_DIRECT */
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+int ide_preinit(void)
+{
+ ide_devices_found = 0;
+ /* initialize the PCMCIA IDE adapter card */
+ pcmcia_on();
+ if (!ide_devices_found)
+ return 1;
+ udelay(1000000);/* 1 s */
+ return 0;
+}
+#endif
diff --git a/arch/powerpc/lib/ide.h b/arch/powerpc/lib/ide.h
new file mode 100644
index 0000000..9e80702
--- /dev/null
+++ b/arch/powerpc/lib/ide.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _MPC8XX_IDE_H_
+#define _MPC8XX_IDE_H_ 1
+
+#ifdef CONFIG_IDE_8xx_PCCARD
+int pcmcia_on(void);
+extern int ide_devices_found;
+#endif
+#endif
diff --git a/arch/powerpc/lib/interrupts.c b/arch/powerpc/lib/interrupts.c
new file mode 100644
index 0000000..aeae413
--- /dev/null
+++ b/arch/powerpc/lib/interrupts.c
@@ -0,0 +1,143 @@
+/*
+ * (C) Copyright 2000-2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2003
+ * Gleb Natapov <gnatapov@mrv.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/processor.h>
+#include <watchdog.h>
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
+
+#ifdef CONFIG_SHOW_ACTIVITY
+void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity")));
+
+void __board_show_activity (ulong dummy)
+{
+ return;
+}
+#endif /* CONFIG_SHOW_ACTIVITY */
+
+#ifndef CONFIG_SYS_WATCHDOG_FREQ
+#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
+#endif
+
+extern int interrupt_init_cpu (unsigned *);
+extern void timer_interrupt_cpu (struct pt_regs *);
+
+static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
+
+static __inline__ unsigned long get_msr (void)
+{
+ unsigned long msr;
+
+ asm volatile ("mfmsr %0":"=r" (msr):);
+
+ return msr;
+}
+
+static __inline__ void set_msr (unsigned long msr)
+{
+ asm volatile ("mtmsr %0"::"r" (msr));
+}
+
+static __inline__ unsigned long get_dec (void)
+{
+ unsigned long val;
+
+ asm volatile ("mfdec %0":"=r" (val):);
+
+ return val;
+}
+
+
+static __inline__ void set_dec (unsigned long val)
+{
+ if (val)
+ asm volatile ("mtdec %0"::"r" (val));
+}
+
+
+void enable_interrupts (void)
+{
+ set_msr (get_msr () | MSR_EE);
+}
+
+/* returns flag if MSR_EE was set before */
+int disable_interrupts (void)
+{
+ ulong msr = get_msr ();
+
+ set_msr (msr & ~MSR_EE);
+ return ((msr & MSR_EE) != 0);
+}
+
+int interrupt_init (void)
+{
+ int ret;
+
+ /* call cpu specific function from $(CPU)/interrupts.c */
+ ret = interrupt_init_cpu (&decrementer_count);
+
+ if (ret)
+ return ret;
+
+ set_dec (decrementer_count);
+
+ set_msr (get_msr () | MSR_EE);
+
+ return (0);
+}
+
+static volatile ulong timestamp = 0;
+
+void timer_interrupt (struct pt_regs *regs)
+{
+ /* call cpu specific function from $(CPU)/interrupts.c */
+ timer_interrupt_cpu (regs);
+
+ /* Restore Decrementer Count */
+ set_dec (decrementer_count);
+
+ timestamp++;
+
+#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
+ if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
+ WATCHDOG_RESET ();
+#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
+
+#ifdef CONFIG_STATUS_LED
+ status_led_tick (timestamp);
+#endif /* CONFIG_STATUS_LED */
+
+#ifdef CONFIG_SHOW_ACTIVITY
+ board_show_activity (timestamp);
+#endif /* CONFIG_SHOW_ACTIVITY */
+}
+
+ulong get_timer (ulong base)
+{
+ return (timestamp - base);
+}
diff --git a/arch/powerpc/lib/kgdb.c b/arch/powerpc/lib/kgdb.c
new file mode 100644
index 0000000..19a56db
--- /dev/null
+++ b/arch/powerpc/lib/kgdb.c
@@ -0,0 +1,326 @@
+#include <common.h>
+#include <command.h>
+#include <kgdb.h>
+#include <asm/signal.h>
+#include <asm/processor.h>
+
+#define PC_REGNUM 64
+#define SP_REGNUM 1
+
+void breakinst(void);
+
+int
+kgdb_setjmp(long *buf)
+{
+ unsigned long temp;
+
+ asm volatile("mflr %0; stw %0,0(%1);"
+ "stw %%r1,4(%1); stw %%r2,8(%1);"
+ "mfcr %0; stw %0,12(%1);"
+ "stmw %%r13,16(%1)"
+ : "=&r"(temp) : "r" (buf));
+ /* XXX should save fp regs as well */
+ return 0;
+}
+
+void
+kgdb_longjmp(long *buf, int val)
+{
+ unsigned long temp;
+
+ if (val == 0)
+ val = 1;
+
+ asm volatile("lmw %%r13,16(%1);"
+ "lwz %0,12(%1); mtcrf 0x38,%0;"
+ "lwz %0,0(%1); lwz %%r1,4(%1); lwz %%r2,8(%1);"
+ "mtlr %0; mr %%r3,%2"
+ : "=&r"(temp) : "r" (buf), "r" (val));
+}
+
+static inline unsigned long
+get_msr(void)
+{
+ unsigned long msr;
+ asm volatile("mfmsr %0" : "=r" (msr):);
+ return msr;
+}
+
+static inline void
+set_msr(unsigned long msr)
+{
+ asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
+/*
+ * This table contains the mapping between PowerPC hardware trap types, and
+ * signals, which are primarily what GDB understands.
+ */
+static struct hard_trap_info
+{
+ unsigned int tt; /* Trap type code for powerpc */
+ unsigned char signo; /* Signal that we map this trap into */
+} hard_trap_info[] = {
+ { 0x200, SIGSEGV }, /* machine check */
+ { 0x300, SIGSEGV }, /* address error (store) */
+ { 0x400, SIGBUS }, /* instruction bus error */
+ { 0x500, SIGINT }, /* interrupt */
+ { 0x600, SIGBUS }, /* alingment */
+ { 0x700, SIGTRAP }, /* breakpoint trap */
+ { 0x800, SIGFPE }, /* fpu unavail */
+ { 0x900, SIGALRM }, /* decrementer */
+ { 0xa00, SIGILL }, /* reserved */
+ { 0xb00, SIGILL }, /* reserved */
+ { 0xc00, SIGCHLD }, /* syscall */
+ { 0xd00, SIGTRAP }, /* single-step/watch */
+ { 0xe00, SIGFPE }, /* fp assist */
+ { 0, 0} /* Must be last */
+};
+
+static int
+computeSignal(unsigned int tt)
+{
+ struct hard_trap_info *ht;
+
+ for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+ if (ht->tt == tt)
+ return ht->signo;
+
+ return SIGHUP; /* default for things we don't know about */
+}
+
+void
+kgdb_enter(struct pt_regs *regs, kgdb_data *kdp)
+{
+ unsigned long msr;
+
+ kdp->private[0] = msr = get_msr();
+ set_msr(msr & ~MSR_EE); /* disable interrupts */
+
+ if (regs->nip == (unsigned long)breakinst) {
+ /* Skip over breakpoint trap insn */
+ regs->nip += 4;
+ }
+ regs->msr &= ~MSR_SE;
+
+ /* reply to host that an exception has occurred */
+ kdp->sigval = computeSignal(regs->trap);
+
+ kdp->nregs = 2;
+
+ kdp->regs[0].num = PC_REGNUM;
+ kdp->regs[0].val = regs->nip;
+
+ kdp->regs[1].num = SP_REGNUM;
+ kdp->regs[1].val = regs->gpr[SP_REGNUM];
+}
+
+void
+kgdb_exit(struct pt_regs *regs, kgdb_data *kdp)
+{
+ unsigned long msr = kdp->private[0];
+
+ if (kdp->extype & KGDBEXIT_WITHADDR)
+ regs->nip = kdp->exaddr;
+
+ switch (kdp->extype & KGDBEXIT_TYPEMASK) {
+
+ case KGDBEXIT_KILL:
+ case KGDBEXIT_CONTINUE:
+ set_msr(msr);
+ break;
+
+ case KGDBEXIT_SINGLE:
+ regs->msr |= MSR_SE;
+#if 0
+ set_msr(msr | MSR_SE);
+#endif
+ break;
+ }
+}
+
+int
+kgdb_trap(struct pt_regs *regs)
+{
+ return (regs->trap);
+}
+
+/* return the value of the CPU registers.
+ * some of them are non-PowerPC names :(
+ * they are stored in gdb like:
+ * struct {
+ * u32 gpr[32];
+ * f64 fpr[32];
+ * u32 pc, ps, cnd, lr; (ps=msr)
+ * u32 cnt, xer, mq;
+ * }
+ */
+
+#define SPACE_REQUIRED ((32*4)+(32*8)+(6*4))
+
+#ifdef CONFIG_8260
+/* store floating double indexed */
+#define STFDI(n,p) __asm__ __volatile__ ("stfd " #n ",%0" : "=o"(p[2*n]))
+/* store floating double multiple */
+#define STFDM(p) { STFDI( 0,p); STFDI( 1,p); STFDI( 2,p); STFDI( 3,p); \
+ STFDI( 4,p); STFDI( 5,p); STFDI( 6,p); STFDI( 7,p); \
+ STFDI( 8,p); STFDI( 9,p); STFDI(10,p); STFDI(11,p); \
+ STFDI(12,p); STFDI(13,p); STFDI(14,p); STFDI(15,p); \
+ STFDI(16,p); STFDI(17,p); STFDI(18,p); STFDI(19,p); \
+ STFDI(20,p); STFDI(21,p); STFDI(22,p); STFDI(23,p); \
+ STFDI(24,p); STFDI(25,p); STFDI(26,p); STFDI(27,p); \
+ STFDI(28,p); STFDI(29,p); STFDI(30,p); STFDI(31,p); }
+#endif
+
+int
+kgdb_getregs(struct pt_regs *regs, char *buf, int max)
+{
+ int i;
+ unsigned long *ptr = (unsigned long *)buf;
+
+ if (max < SPACE_REQUIRED)
+ kgdb_error(KGDBERR_NOSPACE);
+
+ if ((unsigned long)ptr & 3)
+ kgdb_error(KGDBERR_ALIGNFAULT);
+
+ /* General Purpose Regs */
+ for (i = 0; i < 32; i++)
+ *ptr++ = regs->gpr[i];
+
+ /* Floating Point Regs */
+#ifdef CONFIG_8260
+ STFDM(ptr);
+ ptr += 32*2;
+#else
+ for (i = 0; i < 32; i++) {
+ *ptr++ = 0;
+ *ptr++ = 0;
+ }
+#endif
+
+ /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+ *ptr++ = regs->nip;
+ *ptr++ = regs->msr;
+ *ptr++ = regs->ccr;
+ *ptr++ = regs->link;
+ *ptr++ = regs->ctr;
+ *ptr++ = regs->xer;
+
+ return (SPACE_REQUIRED);
+}
+
+/* set the value of the CPU registers */
+
+#ifdef CONFIG_8260
+/* load floating double */
+#define LFD(n,v) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"(v))
+/* load floating double indexed */
+#define LFDI(n,p) __asm__ __volatile__ ("lfd " #n ",%0" :: "o"((p)[2*n]))
+/* load floating double multiple */
+#define LFDM(p) { LFDI( 0,p); LFDI( 1,p); LFDI( 2,p); LFDI( 3,p); \
+ LFDI( 4,p); LFDI( 5,p); LFDI( 6,p); LFDI( 7,p); \
+ LFDI( 8,p); LFDI( 9,p); LFDI(10,p); LFDI(11,p); \
+ LFDI(12,p); LFDI(13,p); LFDI(14,p); LFDI(15,p); \
+ LFDI(16,p); LFDI(17,p); LFDI(18,p); LFDI(19,p); \
+ LFDI(20,p); LFDI(21,p); LFDI(22,p); LFDI(23,p); \
+ LFDI(24,p); LFDI(25,p); LFDI(26,p); LFDI(27,p); \
+ LFDI(28,p); LFDI(29,p); LFDI(30,p); LFDI(31,p); }
+#endif
+
+void
+kgdb_putreg(struct pt_regs *regs, int regno, char *buf, int length)
+{
+ unsigned long *ptr = (unsigned long *)buf;
+
+ if (regno < 0 || regno >= 70)
+ kgdb_error(KGDBERR_BADPARAMS);
+ else if (regno >= 32 && regno < 64) {
+ if (length < 8)
+ kgdb_error(KGDBERR_NOSPACE);
+ }
+ else {
+ if (length < 4)
+ kgdb_error(KGDBERR_NOSPACE);
+ }
+
+ if ((unsigned long)ptr & 3)
+ kgdb_error(KGDBERR_ALIGNFAULT);
+
+ if (regno >= 0 && regno < 32)
+ regs->gpr[regno] = *ptr;
+ else switch (regno) {
+
+#ifdef CONFIG_8260
+#define caseF(n) \
+ case (n) + 32: LFD(n, *ptr); break;
+
+caseF( 0) caseF( 1) caseF( 2) caseF( 3) caseF( 4) caseF( 5) caseF( 6) caseF( 7)
+caseF( 8) caseF( 9) caseF(10) caseF(11) caseF(12) caseF(13) caseF(14) caseF(15)
+caseF(16) caseF(17) caseF(18) caseF(19) caseF(20) caseF(21) caseF(22) caseF(23)
+caseF(24) caseF(25) caseF(26) caseF(27) caseF(28) caseF(29) caseF(30) caseF(31)
+
+#undef caseF
+#endif
+
+ case 64: regs->nip = *ptr; break;
+ case 65: regs->msr = *ptr; break;
+ case 66: regs->ccr = *ptr; break;
+ case 67: regs->link = *ptr; break;
+ case 68: regs->ctr = *ptr; break;
+ case 69: regs->ctr = *ptr; break;
+
+ default:
+ kgdb_error(KGDBERR_BADPARAMS);
+ }
+}
+
+void
+kgdb_putregs(struct pt_regs *regs, char *buf, int length)
+{
+ int i;
+ unsigned long *ptr = (unsigned long *)buf;
+
+ if (length < SPACE_REQUIRED)
+ kgdb_error(KGDBERR_NOSPACE);
+
+ if ((unsigned long)ptr & 3)
+ kgdb_error(KGDBERR_ALIGNFAULT);
+
+ /*
+ * If the stack pointer has moved, you should pray.
+ * (cause only god can help you).
+ */
+
+ /* General Purpose Regs */
+ for (i = 0; i < 32; i++)
+ regs->gpr[i] = *ptr++;
+
+ /* Floating Point Regs */
+#ifdef CONFIG_8260
+ LFDM(ptr);
+#endif
+ ptr += 32*2;
+
+ /* pc, msr, cr, lr, ctr, xer, (mq is unused) */
+ regs->nip = *ptr++;
+ regs->msr = *ptr++;
+ regs->ccr = *ptr++;
+ regs->link = *ptr++;
+ regs->ctr = *ptr++;
+ regs->xer = *ptr++;
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void
+kgdb_breakpoint(int argc, char * const argv[])
+{
+ asm(" .globl breakinst\n\
+ breakinst: .long 0x7d821008\n\
+ ");
+}
diff --git a/arch/powerpc/lib/memcpy_mpc5200.c b/arch/powerpc/lib/memcpy_mpc5200.c
new file mode 100644
index 0000000..0950354
--- /dev/null
+++ b/arch/powerpc/lib/memcpy_mpc5200.c
@@ -0,0 +1,71 @@
+/*
+ * (C) Copyright 2010
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This is a workaround for issues on the MPC5200, where unaligned
+ * 32-bit-accesses to the local bus will deliver corrupted data. This
+ * happens for example when trying to use memcpy() from an odd NOR
+ * flash address; the behaviour can be also seen when using "md" on an
+ * odd NOR flash address (but there it is not a bug in U-Boot, which
+ * only shows the behaviour of this processor).
+ *
+ * For memcpy(), we test if either the source or the target address
+ * are not 32 bit aligned, and - if so - if the source address is in
+ * NOR flash: in this case we perform a byte-wise (slow) then; for
+ * aligned operations of non-flash areas we use the optimized (fast)
+ * real __memcpy(). This way we minimize the performance impact of
+ * this workaround.
+ *
+ */
+
+#include <common.h>
+#include <flash.h>
+#include <linux/types.h>
+
+void *memcpy(void *trg, const void *src, size_t len)
+{
+ extern void* __memcpy(void *, const void *, size_t);
+ char *s = (char *)src;
+ char *t = (char *)trg;
+ void *dest = (void *)src;
+
+ /*
+ * Check is source address is in flash:
+ * If not, we use the fast assembler code
+ */
+ if (((((unsigned long)s & 3) == 0) /* source aligned */
+ && /* AND */
+ (((unsigned long)t & 3) == 0)) /* target aligned, */
+ || /* or */
+ (addr2info((ulong)s) == NULL)) { /* source not in flash */
+ return __memcpy(trg, src, len);
+ }
+
+ /*
+ * Copying from flash, perform byte by byte copy.
+ */
+ while (len-- > 0)
+ *t++ = *s++;
+
+ return dest;
+}
diff --git a/arch/powerpc/lib/ppccache.S b/arch/powerpc/lib/ppccache.S
new file mode 100644
index 0000000..278a804
--- /dev/null
+++ b/arch/powerpc/lib/ppccache.S
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 2000, 2001,2002 Wolfgang Denk <wd@denx.de>
+ * Copyright Freescale Semiconductor, Inc. 2004, 2006.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <ppc_asm.tmpl>
+
+/*------------------------------------------------------------------------------- */
+/* Function: ppcDcbf */
+/* Description: Data Cache block flush */
+/* Input: r3 = effective address */
+/* Output: none. */
+/*------------------------------------------------------------------------------- */
+ .globl ppcDcbf
+ppcDcbf:
+ dcbf r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: ppcDcbi */
+/* Description: Data Cache block Invalidate */
+/* Input: r3 = effective address */
+/* Output: none. */
+/*------------------------------------------------------------------------------- */
+ .globl ppcDcbi
+ppcDcbi:
+ dcbi r0,r3
+ blr
+
+/*--------------------------------------------------------------------------
+ * Function: ppcDcbz
+ * Description: Data Cache block zero.
+ * Input: r3 = effective address
+ * Output: none.
+ *-------------------------------------------------------------------------- */
+
+ .globl ppcDcbz
+ppcDcbz:
+ dcbz r0,r3
+ blr
+
+/*------------------------------------------------------------------------------- */
+/* Function: ppcSync */
+/* Description: Processor Synchronize */
+/* Input: none. */
+/* Output: none. */
+/*------------------------------------------------------------------------------- */
+ .globl ppcSync
+ppcSync:
+ sync
+ blr
diff --git a/arch/powerpc/lib/ppcstring.S b/arch/powerpc/lib/ppcstring.S
new file mode 100644
index 0000000..97023a0
--- /dev/null
+++ b/arch/powerpc/lib/ppcstring.S
@@ -0,0 +1,216 @@
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <ppc_asm.tmpl>
+#include <asm/errno.h>
+
+ .globl strcpy
+strcpy:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strncpy
+strncpy:
+ cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r6)
+ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
+ blr
+
+ .globl strcat
+strcat:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r5)
+ cmpwi 0,r0,0
+ bne 1b
+ addi r5,r5,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strcmp
+strcmp:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r5)
+ cmpwi 1,r3,0
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ beqlr 1
+ beq 1b
+ blr
+
+ .globl strlen
+strlen:
+ addi r4,r3,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ bne 1b
+ subf r3,r3,r4
+ blr
+
+ .globl memset
+memset:
+ rlwimi r4,r4,8,16,23
+ rlwimi r4,r4,16,0,15
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ rlwinm r0,r5,32-2,2,31
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
+ .globl bcopy
+bcopy:
+ mr r6,r3
+ mr r3,r4
+ mr r4,r6
+ b memcpy
+
+ .globl memmove
+memmove:
+ cmplw 0,r3,r4
+ bgt backwards_memcpy
+ /* fall through */
+
+ .globl memcpy
+memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+ lwzu r8,8(r4)
+ stw r7,4(r6)
+ stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,4(r4)
+ addi r5,r5,-4
+ stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+ stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+ stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl backwards_memcpy
+backwards_memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ add r6,r3,r5
+ add r4,r4,r5
+ beq 2f
+ andi. r0,r6,3
+ mtctr r7
+ bne 5f
+1: lwz r7,-4(r4)
+ lwzu r8,-8(r4)
+ stw r7,-4(r6)
+ stwu r8,-8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,-4(r4)
+ subi r5,r5,4
+ stwu r0,-4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+4: lbzu r0,-1(r4)
+ stbu r0,-1(r6)
+ bdnz 4b
+ blr
+5: mtctr r0
+6: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl memcmp
+memcmp:
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r6)
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ bdnzt 2,1b
+ blr
+2: li r3,0
+ blr
+
+ .global memchr
+memchr:
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r3,r3,-1
+1: lbzu r0,1(r3)
+ cmpw 0,r0,r4
+ bdnzf 2,1b
+ beqlr
+2: li r3,0
+ blr
diff --git a/arch/powerpc/lib/reloc.S b/arch/powerpc/lib/reloc.S
new file mode 100644
index 0000000..50f9a83
--- /dev/null
+++ b/arch/powerpc/lib/reloc.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppc_asm.tmpl>
+
+ .file "reloc.S"
+
+ .text
+#ifndef CONFIG_NAND_SPL
+ /*
+ * Function: relocate entries for one exception vector
+ */
+ .globl trap_reloc
+ .type trap_reloc, @function
+trap_reloc:
+ lwz r0, 0(r7) /* hdlr ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 0(r7)
+
+ lwz r0, 4(r7) /* int_return ... */
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 4(r7)
+
+ lwz r0, 8(r7) /* transfer_to_handler ...*/
+ add r0, r0, r3 /* ... += dest_addr */
+ stw r0, 8(r7)
+
+ blr
+ .size trap_reloc, .-trap_reloc
+#endif
diff --git a/arch/powerpc/lib/spl.c b/arch/powerpc/lib/spl.c
new file mode 100644
index 0000000..502c93b
--- /dev/null
+++ b/arch/powerpc/lib/spl.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Stefan Roese <sr@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <common.h>
+#include <config.h>
+#include <spl.h>
+#include <image.h>
+#include <linux/compiler.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This function jumps to an image with argument. Normally an FDT or ATAGS
+ * image.
+ * arg: Pointer to paramter image in RAM
+ */
+#ifdef CONFIG_SPL_OS_BOOT
+void __noreturn jump_to_image_linux(void *arg)
+{
+ debug("Entering kernel arg pointer: 0x%p\n", arg);
+ typedef void (*image_entry_arg_t)(void *, ulong r4, ulong r5, ulong r6,
+ ulong r7, ulong r8, ulong r9)
+ __attribute__ ((noreturn));
+ image_entry_arg_t image_entry =
+ (image_entry_arg_t)spl_image.entry_point;
+
+ image_entry(arg, 0, 0, EPAPR_MAGIC, CONFIG_SYS_BOOTMAPSZ, 0, 0);
+}
+#endif /* CONFIG_SPL_OS_BOOT */
diff --git a/arch/powerpc/lib/ticks.S b/arch/powerpc/lib/ticks.S
new file mode 100644
index 0000000..63114bb
--- /dev/null
+++ b/arch/powerpc/lib/ticks.S
@@ -0,0 +1,73 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
+ * base on code by
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <config.h>
+#include <watchdog.h>
+
+/*
+ * unsigned long long get_ticks(void);
+ *
+ * read timebase as "long long"
+ */
+ .globl get_ticks
+get_ticks:
+1: mftbu r3
+ mftb r4
+ mftbu r5
+ cmp 0,r3,r5
+ bne 1b
+ blr
+
+/*
+ * Delay for a number of ticks
+ */
+ .globl wait_ticks
+wait_ticks:
+ stwu r1, -16(r1)
+ mflr r0 /* save link register */
+ stw r0, 20(r1) /* Use r0 or GDB will be unhappy */
+ stw r14, 12(r1) /* save used registers */
+ stw r15, 8(r1)
+ mr r14, r3 /* save tick count */
+ bl get_ticks /* Get start time */
+
+ /* Calculate end time */
+ addc r14, r4, r14 /* Compute end time lower */
+ addze r15, r3 /* and end time upper */
+
+ WATCHDOG_RESET /* Trigger watchdog, if needed */
+1: bl get_ticks /* Get current time */
+ subfc r4, r4, r14 /* Subtract current time from end time */
+ subfe. r3, r3, r15
+ bge 1b /* Loop until time expired */
+
+ lwz r15, 8(r1) /* restore saved registers */
+ lwz r14, 12(r1)
+ lwz r0, 20(r1)
+ addi r1,r1,16
+ mtlr r0
+ blr
diff --git a/arch/powerpc/lib/time.c b/arch/powerpc/lib/time.c
new file mode 100644
index 0000000..34633c3
--- /dev/null
+++ b/arch/powerpc/lib/time.c
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2000, 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * This function is intended for SHORT delays only.
+ * It will overflow at around 10 seconds @ 400MHz,
+ * or 20 seconds @ 200MHz.
+ */
+unsigned long usec2ticks(unsigned long usec)
+{
+ ulong ticks;
+
+ if (usec < 1000) {
+ ticks = ((usec * (get_tbclk()/1000)) + 500) / 1000;
+ } else {
+ ticks = ((usec / 10) * (get_tbclk() / 100000));
+ }
+
+ return (ticks);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * We implement the delay by converting the delay (the number of
+ * microseconds to wait) into a number of time base ticks; then we
+ * watch the time base until it has incremented by that amount.
+ */
+void __udelay(unsigned long usec)
+{
+ ulong ticks = usec2ticks (usec);
+ wait_ticks (ticks);
+}
+
+/* ------------------------------------------------------------------------- */
+#ifndef CONFIG_NAND_SPL
+unsigned long ticks2usec(unsigned long ticks)
+{
+ ulong tbclk = get_tbclk();
+
+ /* usec = ticks * 1000000 / tbclk
+ * Multiplication would overflow at ~4.2e3 ticks,
+ * so we break it up into
+ * usec = ( ( ticks * 1000) / tbclk ) * 1000;
+ */
+ ticks *= 1000L;
+ ticks /= tbclk;
+ ticks *= 1000L;
+
+ return ((ulong)ticks);
+}
+#endif
+/* ------------------------------------------------------------------------- */
+
+int init_timebase (void)
+{
+ unsigned long temp;
+
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx)
+ volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
+
+ /* unlock */
+ immap->im_sitk.sitk_tbk = KAPWR_KEY;
+#endif
+
+ /* reset */
+ asm volatile("li %0,0 ; mttbu %0 ; mttbl %0;"
+ : "=&r"(temp) );
+
+#if defined(CONFIG_5xx) || defined(CONFIG_8xx)
+ /* enable */
+ immap->im_sit.sit_tbscr |= TBSCR_TBE;
+#endif
+ return (0);
+}
+/* ------------------------------------------------------------------------- */
OpenPOWER on IntegriCloud