summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--MAINTAINERS8
-rwxr-xr-xMAKEALL69
-rw-r--r--Makefile60
-rw-r--r--README101
-rw-r--r--arch/arm/cpu/armv7/am33xx/board.c85
-rw-r--r--arch/arm/cpu/armv7/am33xx/clock.c8
-rw-r--r--arch/arm/cpu/armv7/omap3/Makefile1
-rw-r--r--arch/arm/cpu/armv7/omap3/am35x_musb.c75
-rw-r--r--arch/arm/include/asm/arch-am33xx/cpu.h11
-rw-r--r--arch/arm/include/asm/arch-am33xx/hardware.h4
-rw-r--r--arch/arm/include/asm/arch-exynos/dwmmc.h36
-rw-r--r--arch/arm/include/asm/arch-omap3/am35x_def.h27
-rw-r--r--arch/arm/include/asm/arch-omap3/musb.h (renamed from board/chromebook-x86/coreboot/coreboot_start16.S)36
-rw-r--r--arch/arm/include/asm/imx-common/mx5_video.h21
-rw-r--r--arch/arm/include/asm/omap_musb.h32
-rw-r--r--arch/arm/lib/board.c8
-rw-r--r--arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c2
-rw-r--r--arch/mips/cpu/mips32/time.c1
-rw-r--r--arch/mips/cpu/mips64/time.c1
-rw-r--r--arch/powerpc/config.mk5
-rw-r--r--arch/powerpc/cpu/mpc5xxx/Makefile4
-rw-r--r--arch/powerpc/cpu/mpc5xxx/spl_boot.c79
-rw-r--r--arch/powerpc/cpu/mpc5xxx/start.S22
-rw-r--r--arch/powerpc/cpu/mpc5xxx/u-boot-spl.lds57
-rw-r--r--arch/powerpc/cpu/mpc5xxx/usb_ohci.c2
-rw-r--r--arch/powerpc/cpu/mpc85xx/Makefile38
-rw-r--r--arch/powerpc/cpu/mpc85xx/cmd_errata.c114
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu.c17
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu_init.c14
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen1.c4
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen2.c9
-rw-r--r--arch/powerpc/cpu/mpc85xx/ddr-gen3.c14
-rw-r--r--arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c20
-rw-r--r--arch/powerpc/cpu/mpc85xx/release.S36
-rw-r--r--arch/powerpc/cpu/mpc85xx/spl_minimal.c (renamed from arch/powerpc/cpu/mpc85xx/cpu_init_nand.c)19
-rw-r--r--arch/powerpc/cpu/mpc85xx/start.S123
-rw-r--r--arch/powerpc/cpu/mpc85xx/tlb.c4
-rw-r--r--arch/powerpc/cpu/mpc85xx/u-boot-spl.lds87
-rw-r--r--arch/powerpc/cpu/mpc86xx/ddr-8641.c4
-rw-r--r--arch/powerpc/cpu/mpc8xxx/Makefile17
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c10
-rw-r--r--arch/powerpc/cpu/mpc8xxx/ddr/util.c14
-rw-r--r--arch/powerpc/cpu/mpc8xxx/fdt.c6
-rw-r--r--arch/powerpc/cpu/mpc8xxx/law.c (renamed from drivers/misc/fsl_law.c)11
-rw-r--r--arch/powerpc/cpu/ppc4xx/usb_ohci.c2
-rw-r--r--arch/powerpc/include/asm/config_mpc85xx.h20
-rw-r--r--arch/powerpc/include/asm/immap_83xx.h6
-rw-r--r--arch/powerpc/include/asm/immap_85xx.h27
-rw-r--r--arch/powerpc/include/asm/immap_86xx.h8
-rw-r--r--arch/powerpc/include/asm/processor.h6
-rw-r--r--arch/powerpc/include/asm/spl.h (renamed from board/chromebook-x86/coreboot/coreboot_pci.c)21
-rw-r--r--arch/powerpc/lib/Makefile35
-rw-r--r--arch/powerpc/lib/bootm.c6
-rw-r--r--arch/powerpc/lib/spl.c42
-rw-r--r--arch/sh/include/asm/system.h2
-rw-r--r--arch/x86/cpu/Makefile7
-rw-r--r--arch/x86/cpu/coreboot/Makefile7
-rw-r--r--arch/x86/cpu/coreboot/car.S (renamed from arch/x86/cpu/coreboot/coreboot_car.S)0
-rw-r--r--arch/x86/cpu/coreboot/config.mk (renamed from board/BuS/eb_cpu5282/config.mk)8
-rw-r--r--arch/x86/cpu/coreboot/coreboot.c (renamed from board/chromebook-x86/coreboot/coreboot.c)61
-rw-r--r--arch/x86/cpu/coreboot/pci.c65
-rw-r--r--arch/x86/cpu/coreboot/sdram.c72
-rw-r--r--arch/x86/cpu/coreboot/sysinfo.c39
-rw-r--r--arch/x86/cpu/coreboot/tables.c117
-rw-r--r--arch/x86/cpu/coreboot/timestamp.c61
-rw-r--r--arch/x86/cpu/cpu.c49
-rw-r--r--arch/x86/cpu/interrupts.c99
-rw-r--r--arch/x86/cpu/start.S77
-rw-r--r--arch/x86/cpu/start16.S3
-rw-r--r--arch/x86/cpu/timer.c17
-rw-r--r--arch/x86/cpu/u-boot.lds3
-rw-r--r--arch/x86/dts/coreboot.dtsi16
-rw-r--r--arch/x86/dts/skeleton.dtsi13
-rw-r--r--arch/x86/include/asm/arch-coreboot/sysinfo.h34
-rw-r--r--arch/x86/include/asm/arch-coreboot/tables.h74
-rw-r--r--arch/x86/include/asm/arch-coreboot/timestamp.h52
-rw-r--r--arch/x86/include/asm/bitops.h5
-rw-r--r--arch/x86/include/asm/cache.h16
-rw-r--r--arch/x86/include/asm/control_regs.h105
-rw-r--r--arch/x86/include/asm/global_data.h18
-rw-r--r--arch/x86/include/asm/gpio.h (renamed from arch/nios2/include/asm/status_led.h)16
-rw-r--r--arch/x86/include/asm/init_helpers.h2
-rw-r--r--arch/x86/include/asm/io.h18
-rw-r--r--arch/x86/include/asm/msr-index.h469
-rw-r--r--arch/x86/include/asm/msr.h238
-rw-r--r--arch/x86/include/asm/mtrr.h206
-rw-r--r--arch/x86/include/asm/pci.h2
-rw-r--r--arch/x86/include/asm/processor.h1
-rw-r--r--arch/x86/include/asm/types.h4
-rw-r--r--arch/x86/include/asm/u-boot-x86.h14
-rw-r--r--arch/x86/include/asm/u-boot.h3
-rw-r--r--arch/x86/lib/Makefile12
-rw-r--r--arch/x86/lib/board.c15
-rw-r--r--arch/x86/lib/init_helpers.c83
-rw-r--r--arch/x86/lib/init_wrappers.c28
-rw-r--r--arch/x86/lib/pcat_timer.c2
-rw-r--r--arch/x86/lib/physmem.c228
-rw-r--r--arch/x86/lib/relocate.c4
-rw-r--r--arch/x86/lib/timer.c17
-rw-r--r--arch/x86/lib/video.c2
-rw-r--r--arch/x86/lib/zimage.c27
-rw-r--r--board/BuS/eb_cpu5282/Makefile2
-rw-r--r--board/BuS/eb_cpu5282/cfm_flash.c212
-rw-r--r--board/BuS/eb_cpu5282/cfm_flash.h40
-rw-r--r--board/BuS/eb_cpu5282/eb_cpu5282.c110
-rw-r--r--board/BuS/eb_cpu5282/flash.c415
-rw-r--r--board/a3m071/Makefile36
-rw-r--r--board/a3m071/README80
-rw-r--r--board/a3m071/a3m071.c335
-rw-r--r--board/a3m071/mt46v16m16-75.h32
-rw-r--r--board/chromebook-x86/coreboot/Makefile3
-rw-r--r--board/chromebook-x86/coreboot/config.mk37
-rw-r--r--board/chromebook-x86/dts/alex.dts24
-rw-r--r--board/chromebook-x86/dts/link.dts24
-rw-r--r--board/davedenx/qong/qong.c12
-rw-r--r--board/exmeritus/hww1u1a/hww1u1a.c2
-rw-r--r--board/freescale/common/Makefile2
-rw-r--r--board/freescale/common/ngpixis.h2
-rw-r--r--board/freescale/corenet_ds/Makefile2
-rw-r--r--board/freescale/corenet_ds/corenet_ds.c22
-rw-r--r--board/freescale/corenet_ds/ddr.c4
-rw-r--r--board/freescale/corenet_ds/eth_superhydra.c722
-rw-r--r--board/freescale/corenet_ds/p5040ds_ddr.c18
-rw-r--r--board/freescale/mpc8540ads/mpc8540ads.c2
-rw-r--r--board/freescale/mpc8560ads/mpc8560ads.c2
-rw-r--r--board/freescale/mpc8569mds/mpc8569mds.c2
-rw-r--r--board/freescale/mx31pdk/mx31pdk.c12
-rw-r--r--board/freescale/mx35pdk/mx35pdk.c14
-rw-r--r--board/freescale/mx51evk/Makefile4
-rw-r--r--board/freescale/mx51evk/mx51evk.c69
-rw-r--r--board/freescale/mx51evk/mx51evk_video.c81
-rw-r--r--board/freescale/mx53evk/mx53evk.c12
-rw-r--r--board/freescale/mx53loco/Makefile4
-rw-r--r--board/freescale/mx53loco/mx53loco.c87
-rw-r--r--board/freescale/mx53loco/mx53loco_video.c94
-rw-r--r--board/freescale/p1023rds/p1023rds.c2
-rw-r--r--board/freescale/p1_p2_rdb_pc/Makefile16
-rw-r--r--board/freescale/p1_p2_rdb_pc/ddr.c2
-rw-r--r--board/freescale/p1_p2_rdb_pc/law.c2
-rw-r--r--board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c2
-rw-r--r--board/freescale/p1_p2_rdb_pc/spl_minimal.c (renamed from nand_spl/board/freescale/p1_p2_rdb_pc/nand_boot.c)12
-rw-r--r--board/freescale/p1_p2_rdb_pc/tlb.c22
-rw-r--r--board/freescale/p2020ds/p2020ds.c2
-rw-r--r--board/genesi/mx51_efikamx/efikamx.c12
-rw-r--r--board/hale/tt01/tt01.c14
-rw-r--r--board/iomega/iconnect/iconnect.c2
-rw-r--r--board/iomega/iconnect/iconnect.h2
-rw-r--r--board/iomega/iconnect/kwbimage.cfg2
-rw-r--r--board/logicpd/am3517evm/am3517evm.c74
-rw-r--r--board/raidsonic/ib62x0/ib62x0.c2
-rw-r--r--board/raidsonic/ib62x0/ib62x0.h2
-rw-r--r--board/raidsonic/ib62x0/kwbimage.cfg2
-rw-r--r--board/samsung/goni/goni.c22
-rw-r--r--board/samsung/trats/trats.c292
-rw-r--r--board/samsung/universal_c210/universal.c31
-rw-r--r--board/sbc8548/ddr.c2
-rw-r--r--board/socrates/sdram.c2
-rw-r--r--board/ti/am335x/board.c23
-rw-r--r--board/ti/beagle/beagle.c43
-rw-r--r--board/ttcontrol/vision2/vision2.c12
-rw-r--r--boards.cfg7
-rw-r--r--common/Makefile3
-rw-r--r--common/bouncebuf.c75
-rw-r--r--common/cmd_bmp.c5
-rw-r--r--common/cmd_bootm.c11
-rw-r--r--common/cmd_led.c6
-rw-r--r--common/cmd_mmc.c11
-rw-r--r--common/cmd_nand.c22
-rw-r--r--common/cmd_usb.c2
-rw-r--r--common/image.c127
-rw-r--r--common/lcd.c178
-rw-r--r--common/main.c104
-rw-r--r--common/spl/spl.c16
-rw-r--r--common/stdio.c4
-rw-r--r--common/usb.c4
-rw-r--r--common/usb_kbd.c18
-rw-r--r--disk/part.c2
-rw-r--r--doc/DocBook/Makefile2
-rw-r--r--doc/README.mpc85xx2
-rw-r--r--doc/README.nand21
-rw-r--r--doc/kwboot.12
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/intel_ich6_gpio.c290
-rw-r--r--drivers/misc/Makefile10
-rw-r--r--drivers/misc/cbmem_console.c67
-rw-r--r--drivers/misc/pmic_core.c147
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/exynos_dw_mmc.c57
-rw-r--r--drivers/mmc/mmc.c63
-rw-r--r--drivers/mmc/mxsmmc.c30
-rw-r--r--drivers/mmc/sdhci.c3
-rw-r--r--drivers/mmc/tegra_mmc.c64
-rw-r--r--drivers/mtd/nand/Makefile34
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c2
-rw-r--r--drivers/mtd/nand/fsl_elbc_spl.c168
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c64
-rw-r--r--drivers/mtd/nand/nand_base.c9
-rw-r--r--drivers/mtd/nand/nand_util.c188
-rw-r--r--drivers/net/fm/Makefile1
-rw-r--r--drivers/net/fm/p5040.c113
-rw-r--r--drivers/pci/fsl_pci_init.c22
-rw-r--r--drivers/power/Makefile12
-rw-r--r--drivers/power/battery/Makefile47
-rw-r--r--drivers/power/battery/bat_trats.c100
-rw-r--r--drivers/power/fuel_gauge/Makefile47
-rw-r--r--drivers/power/fuel_gauge/fg_max17042.c250
-rw-r--r--drivers/power/pmic/Makefile49
-rw-r--r--drivers/power/pmic/muic_max8997.c90
-rw-r--r--drivers/power/pmic/pmic_max8997.c123
-rw-r--r--drivers/power/pmic/pmic_max8998.c (renamed from drivers/misc/pmic_max8998.c)16
-rw-r--r--drivers/power/power_core.c232
-rw-r--r--drivers/power/power_dialog.c (renamed from drivers/misc/pmic_dialog.c)14
-rw-r--r--drivers/power/power_fsl.c (renamed from drivers/misc/pmic_fsl.c)22
-rw-r--r--drivers/power/power_i2c.c (renamed from drivers/misc/pmic_i2c.c)47
-rw-r--r--drivers/power/power_spi.c (renamed from drivers/misc/pmic_spi.c)4
-rw-r--r--drivers/rtc/mc13xxx-rtc.c10
-rw-r--r--drivers/serial/ns16550.c3
-rw-r--r--drivers/serial/serial_ns16550.c4
-rw-r--r--drivers/serial/serial_pl01x.c4
-rw-r--r--drivers/serial/serial_sh.c20
-rw-r--r--drivers/usb/gadget/config.c1
-rw-r--r--drivers/usb/gadget/epautoconf.c1
-rw-r--r--drivers/usb/gadget/ether.c1
-rw-r--r--drivers/usb/gadget/f_dfu.c1
-rw-r--r--drivers/usb/gadget/gadget_chips.h4
-rw-r--r--drivers/usb/gadget/s3c_udc_otg.c1
-rw-r--r--drivers/usb/gadget/usbstring.c1
-rw-r--r--drivers/usb/host/ehci-hcd.c16
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-s3c24xx.c2
-rw-r--r--drivers/usb/host/r8a66597-hcd.c17
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/musb-new/Makefile39
-rw-r--r--drivers/usb/musb-new/am35x.c709
-rw-r--r--drivers/usb/musb-new/linux-compat.h116
-rw-r--r--drivers/usb/musb-new/musb_core.c2497
-rw-r--r--drivers/usb/musb-new/musb_core.h623
-rw-r--r--drivers/usb/musb-new/musb_debug.h58
-rw-r--r--drivers/usb/musb-new/musb_dma.h186
-rw-r--r--drivers/usb/musb-new/musb_dsps.c771
-rw-r--r--drivers/usb/musb-new/musb_gadget.c2333
-rw-r--r--drivers/usb/musb-new/musb_gadget.h130
-rw-r--r--drivers/usb/musb-new/musb_gadget_ep0.c1089
-rw-r--r--drivers/usb/musb-new/musb_host.c2400
-rw-r--r--drivers/usb/musb-new/musb_host.h114
-rw-r--r--drivers/usb/musb-new/musb_io.h146
-rw-r--r--drivers/usb/musb-new/musb_regs.h645
-rw-r--r--drivers/usb/musb-new/musb_uboot.c237
-rw-r--r--drivers/usb/musb-new/omap2430.c626
-rw-r--r--drivers/usb/musb-new/omap2430.h56
-rw-r--r--drivers/usb/musb-new/usb-compat.h88
-rw-r--r--drivers/usb/musb/musb_core.h3
-rw-r--r--drivers/usb/musb/musb_hcd.c5
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/atmel_hlcdfb.c12
-rw-r--r--drivers/video/bus_vcxk.c2
-rw-r--r--drivers/video/cfb_console.c51
-rw-r--r--drivers/video/coreboot_fb.c101
-rw-r--r--drivers/video/ipu_common.c10
-rw-r--r--fs/cbfs/Makefile4
-rw-r--r--fs/cbfs/cbfs.c3
-rw-r--r--fs/ext4/dev.c1
-rw-r--r--fs/ext4/ext4_common.c14
-rw-r--r--fs/ext4/ext4_journal.c3
-rw-r--r--fs/ext4/ext4fs.c13
-rw-r--r--fs/fs.c11
-rw-r--r--fs/zfs/zfs.c4
-rw-r--r--include/atmel_hlcdc.h7
-rw-r--r--include/bouncebuf.h47
-rw-r--r--include/cbfs.h72
-rw-r--r--include/configs/CPCI405.h2
-rw-r--r--include/configs/CPCI4052.h2
-rw-r--r--include/configs/CPCI405AB.h2
-rw-r--r--include/configs/CPCI405DT.h2
-rw-r--r--include/configs/P1010RDB.h1
-rw-r--r--include/configs/P1022DS.h1
-rw-r--r--include/configs/P1023RDS.h2
-rw-r--r--include/configs/P2041RDB.h20
-rw-r--r--include/configs/P3041DS.h1
-rw-r--r--include/configs/P5020DS.h1
-rw-r--r--include/configs/P5040DS.h40
-rw-r--r--include/configs/PK1C20.h1
-rw-r--r--include/configs/a3m071.h380
-rw-r--r--include/configs/am335x_evm.h27
-rw-r--r--include/configs/am3517_crane.h3
-rw-r--r--include/configs/am3517_evm.h36
-rw-r--r--include/configs/at91sam9x5ek.h19
-rw-r--r--include/configs/cam_enc_4xx.h3
-rw-r--r--include/configs/coreboot.h68
-rw-r--r--include/configs/corenet_ds.h2
-rw-r--r--include/configs/da850evm.h3
-rw-r--r--include/configs/devkit8000.h3
-rw-r--r--include/configs/eNET.h6
-rw-r--r--include/configs/eb_cpu5282.h102
-rw-r--r--include/configs/hawkboard.h3
-rw-r--r--include/configs/ib62x0.h2
-rw-r--r--include/configs/iconnect.h2
-rw-r--r--include/configs/igep00x0.h3
-rw-r--r--include/configs/imx31_litekit.h6
-rw-r--r--include/configs/lwmon5.h1
-rw-r--r--include/configs/mcx.h4
-rw-r--r--include/configs/mx31ads.h6
-rw-r--r--include/configs/mx31pdk.h6
-rw-r--r--include/configs/mx35pdk.h6
-rw-r--r--include/configs/mx51_efikamx.h6
-rw-r--r--include/configs/mx51evk.h6
-rw-r--r--include/configs/mx53evk.h6
-rw-r--r--include/configs/mx53loco.h8
-rw-r--r--include/configs/mx6qarm2.h2
-rw-r--r--include/configs/mx6qsabre_common.h2
-rw-r--r--include/configs/mx6qsabrelite.h2
-rw-r--r--include/configs/nios2-generic.h1
-rw-r--r--include/configs/omap3_beagle.h17
-rw-r--r--include/configs/omap3_evm.h3
-rw-r--r--include/configs/omap3_evm_quick_nand.h3
-rw-r--r--include/configs/omap3_overo.h3
-rw-r--r--include/configs/p1_p2_rdb_pc.h137
-rw-r--r--include/configs/qong.h6
-rw-r--r--include/configs/s5p_goni.h6
-rw-r--r--include/configs/s5pc210_universal.h6
-rw-r--r--include/configs/sc_sps_1.h2
-rw-r--r--include/configs/seaboard.h3
-rw-r--r--include/configs/sequoia.h3
-rw-r--r--include/configs/tam3517-common.h5
-rw-r--r--include/configs/tegra-common-post.h19
-rw-r--r--include/configs/tegra20-common.h8
-rw-r--r--include/configs/trats.h14
-rw-r--r--include/configs/tricorder.h3
-rw-r--r--include/configs/tt01.h6
-rw-r--r--include/configs/vct.h1
-rw-r--r--include/configs/ventana.h3
-rw-r--r--include/configs/vision2.h6
-rw-r--r--include/fdtdec.h112
-rw-r--r--include/g_dnl.h1
-rw-r--r--include/image.h1
-rw-r--r--include/lcd.h36
-rw-r--r--include/linux/byteorder/swab.h2
-rw-r--r--include/linux/mtd/nand.h7
-rw-r--r--include/linux/usb/ch9.h514
-rw-r--r--include/linux/usb/musb.h162
-rw-r--r--include/nand.h1
-rw-r--r--include/nios2.h12
-rw-r--r--include/pci.h123
-rw-r--r--include/physmem.h21
-rw-r--r--include/power/battery.h (renamed from drivers/misc/pmic_max8997.c)29
-rw-r--r--include/power/fg_battery_cell_params.h90
-rw-r--r--include/power/max17042_fg.h74
-rw-r--r--include/power/max8997_muic.h61
-rw-r--r--include/power/max8997_pmic.h (renamed from include/max8997_pmic.h)26
-rw-r--r--include/power/max8998_pmic.h (renamed from include/max8998_pmic.h)0
-rw-r--r--include/power/pmic.h (renamed from include/pmic.h)51
-rw-r--r--include/power/power_chrg.h (renamed from nand_spl/board/freescale/common.c)41
-rw-r--r--include/sdhci.h1
-rw-r--r--include/status_led.h3
-rw-r--r--include/stdio_dev.h3
-rw-r--r--include/usb.h19
-rw-r--r--include/usb/s3c_udc.h1
-rw-r--r--include/usb_defs.h6
-rw-r--r--include/video.h48
-rw-r--r--lib/Makefile1
-rw-r--r--lib/fdtdec.c125
-rw-r--r--lib/lzma/LzmaDec.c14
-rw-r--r--lib/lzma/LzmaDec.h6
-rw-r--r--lib/lzma/Types.h36
-rw-r--r--lib/lzma/history.txt35
-rw-r--r--lib/lzma/lzma.txt34
-rw-r--r--lib/physmem.c24
-rw-r--r--nand_spl/board/freescale/mpc8536ds/Makefile13
-rw-r--r--nand_spl/board/freescale/mpc8569mds/Makefile13
-rw-r--r--nand_spl/board/freescale/mpc8572ds/Makefile13
-rw-r--r--nand_spl/board/freescale/mx31pdk/Makefile3
-rw-r--r--nand_spl/board/freescale/p1010rdb/Makefile19
-rw-r--r--nand_spl/board/freescale/p1010rdb/nand_boot.c2
-rw-r--r--nand_spl/board/freescale/p1023rds/Makefile19
-rw-r--r--nand_spl/board/freescale/p1023rds/nand_boot.c2
-rw-r--r--nand_spl/board/freescale/p1_p2_rdb/Makefile13
-rw-r--r--nand_spl/board/freescale/p1_p2_rdb_pc/Makefile146
-rw-r--r--nand_spl/board/karo/tx25/Makefile3
-rw-r--r--spl/Makefile21
-rw-r--r--tools/patman/series.py21
382 files changed, 23891 insertions, 2518 deletions
diff --git a/.gitignore b/.gitignore
index 1ac43f2825..a163728832 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,12 +38,12 @@
/u-boot.sha1
/u-boot.dis
/u-boot.lds
-/u-boot.lst
/u-boot.ubl
/u-boot.ais
/u-boot.dtb
/u-boot.sb
/u-boot.geany
+/include/u-boot.lst
#
# Generated files
diff --git a/MAINTAINERS b/MAINTAINERS
index e34d9f3ec3..36b47b741a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7,6 +7,10 @@
# and Cc: the <u-boot@lists.denx.de> mailing list. #
# #
# Note: lists sorted by Maintainer Name #
+# Note: These are the maintainers for specific *boards*. The #
+# custodians for general architectures and subsystems can #
+# be found here -- http://www.denx.de/wiki/U-Boot/Custodians #
+# #
#########################################################################
@@ -388,6 +392,8 @@ Ricardo Ribalda <ricardo.ribalda@uam.es>
Stefan Roese <sr@denx.de>
+ a3m071 MPC5200
+
P3M7448 MPC7448
uc100 MPC857
@@ -800,7 +806,7 @@ Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
apx4devkit i.MX28
-Luka Perkov <uboot@lukaperkov.net>
+Luka Perkov <luka@openwrt.org>
ib62x0 ARM926EJS
iconnect ARM926EJS
diff --git a/MAKEALL b/MAKEALL
index 84a5c92cf3..5b06c5477d 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -20,6 +20,8 @@ usage()
-m, --maintainers List all targets and maintainer email
-M, --mails List all targets and all affilated emails
-C, --check Enable build checking
+ -n, --continue Continue (skip boards already built)
+ -r, --rebuild-errors Rebuild any boards that errored
-h, --help This help output
Selections by these options are logically ANDed; if the same option
@@ -52,8 +54,8 @@ usage()
exit ${ret}
}
-SHORT_OPTS="ha:c:v:s:lmMC"
-LONG_OPTS="help,arch:,cpu:,vendor:,soc:,list,maintainers,mails,check"
+SHORT_OPTS="ha:c:v:s:lmMCnr"
+LONG_OPTS="help,arch:,cpu:,vendor:,soc:,list,maintainers,mails,check,continue,rebuild-errors"
# Option processing based on util-linux-2.13/getopt-parse.bash
@@ -73,6 +75,8 @@ SELECTED=''
ONLY_LIST=''
PRINT_MAINTS=''
MAINTAINERS_ONLY=''
+CONTINUE=''
+REBUILD_ERRORS=''
while true ; do
case "$1" in
@@ -115,6 +119,12 @@ while true ; do
-C|--check)
CHECK='C=1'
shift ;;
+ -n|--continue)
+ CONTINUE='y'
+ shift ;;
+ -r|--rebuild-errors)
+ REBUILD_ERRORS='y'
+ shift ;;
-l|--list)
ONLY_LIST='y'
shift ;;
@@ -198,7 +208,9 @@ fi
OUTPUT_PREFIX="${BUILD_DIR}"
[ -d ${LOG_DIR} ] || mkdir "${LOG_DIR}" || exit 1
-find "${LOG_DIR}/" -type f -exec rm -f {} +
+if [ "$CONTINUE" != 'y' -a "$REBUILD_ERRORS" != 'y' ] ; then
+ find "${LOG_DIR}/" -type f -exec rm -f {} +
+fi
LIST=""
@@ -208,6 +220,7 @@ ERR_LIST=""
WRN_CNT=0
WRN_LIST=""
TOTAL_CNT=0
+SKIP_CNT=0
CURRENT_CNT=0
OLDEST_IDX=1
RC=0
@@ -381,6 +394,12 @@ LIST_pxa="$(boards_by_cpu pxa)"
LIST_ixp="$(boards_by_cpu ixp)"
#########################################################################
+## SPEAr Systems
+#########################################################################
+
+LIST_spear="$(boards_by_soc spear)"
+
+#########################################################################
## ARM groups
#########################################################################
@@ -610,6 +629,13 @@ list_target() {
donep="${LOG_DIR}/._done_"
skipp="${LOG_DIR}/._skip_"
+build_target_killed() {
+ echo "Aborted $target build."
+ # Remove the logs for this board since it was aborted
+ rm -f ${LOG_DIR}/$target.MAKELOG ${LOG_DIR}/$target.ERR
+ exit
+}
+
build_target() {
target=$1
build_idx=$2
@@ -622,6 +648,7 @@ build_target() {
if [ $BUILD_MANY == 1 ] ; then
output_dir="${OUTPUT_PREFIX}/${target}"
mkdir -p "${output_dir}"
+ trap build_target_killed TERM
else
output_dir="${OUTPUT_PREFIX}"
fi
@@ -640,6 +667,8 @@ build_target() {
fi
if [ $BUILD_MANY == 1 ] ; then
+ trap - TERM
+
${MAKE} -s tidy
if [ -s ${LOG_DIR}/${target}.ERR ] ; then
@@ -718,10 +747,20 @@ build_targets() {
: $((CURRENT_CNT += 1))
rm -f "${donep}${TOTAL_CNT}"
rm -f "${skipp}${TOTAL_CNT}"
- if [ $BUILD_MANY == 1 ] ; then
- build_target ${t} ${TOTAL_CNT} &
+ if [ "$CONTINUE" = 'y' -a -e ${LOG_DIR}/$t.MAKELOG ] ; then
+ : $((SKIP_CNT += 1))
+ touch "${donep}${TOTAL_CNT}"
+ elif [ "$REBUILD_ERRORS" = 'y' -a ! -e ${LOG_DIR}/$t.ERR ] ; then
+ : $((SKIP_CNT += 1))
+ touch "${donep}${TOTAL_CNT}"
else
- build_target ${t} ${TOTAL_CNT}
+ if [ $BUILD_MANY == 1 ] ; then
+ build_target ${t} ${TOTAL_CNT} &
+ else
+ CUR_TGT="${t}"
+ build_target ${t} ${TOTAL_CNT}
+ CUR_TGT=''
+ fi
fi
fi
@@ -745,7 +784,11 @@ build_targets() {
#-----------------------------------------------------------------------
kill_children() {
- kill -- "-$1"
+ local pgid=`ps -p $$ --no-headers -o "%r" | tr -d ' '`
+ local children=`pgrep -g $pgid | grep -v $$ | grep -v $pgid`
+
+ kill $children 2> /dev/null
+ wait $children 2> /dev/null
exit
}
@@ -753,6 +796,9 @@ kill_children() {
print_stats() {
if [ "$ONLY_LIST" == 'y' ] ; then return ; fi
+ # Only count boards that completed
+ : $((TOTAL_CNT = `find ${skipp}* 2> /dev/null | wc -l`))
+
rm -f ${donep}* ${skipp}*
if [ $BUILD_MANY == 1 ] && [ -e "${OUTPUT_PREFIX}/ERR" ] ; then
@@ -762,10 +808,17 @@ print_stats() {
WRN_LIST=`grep -riwL error ${OUTPUT_PREFIX}/ERR/`
WRN_LIST=`for f in $WRN_LIST ; do echo -n " $(basename $f)" ; done`
WRN_CNT=`echo $WRN_LIST | wc -w | awk '{print $1}'`
+ else
+ # Remove the logs for any board that was interrupted
+ rm -f ${LOG_DIR}/${CUR_TGT}.MAKELOG ${LOG_DIR}/${CUR_TGT}.ERR
fi
+ : $((TOTAL_CNT -= ${SKIP_CNT}))
echo ""
echo "--------------------- SUMMARY ----------------------------"
+ if [ "$CONTINUE" = 'y' -o "$REBUILD_ERRORS" = 'y' ] ; then
+ echo "Boards skipped: ${SKIP_CNT}"
+ fi
echo "Boards compiled: ${TOTAL_CNT}"
if [ ${ERR_CNT} -gt 0 ] ; then
echo "Boards with errors: ${ERR_CNT} (${ERR_LIST} )"
@@ -776,7 +829,7 @@ print_stats() {
echo "----------------------------------------------------------"
if [ $BUILD_MANY == 1 ] ; then
- kill_children $$ &
+ kill_children
fi
exit $RC
diff --git a/Makefile b/Makefile
index 8a04727f62..44db8891f3 100644
--- a/Makefile
+++ b/Makefile
@@ -231,8 +231,8 @@ endif
OBJS = $(CPUDIR)/start.o
ifeq ($(CPU),x86)
-OBJS += $(CPUDIR)/start16.o
-OBJS += $(CPUDIR)/resetvec.o
+RESET_OBJS-$(CONFIG_X86_NO_RESET_VECTOR) += $(CPUDIR)/start16.o
+RESET_OBJS-$(CONFIG_X86_NO_RESET_VECTOR) += $(CPUDIR)/resetvec.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += $(CPUDIR)/resetvec.o
@@ -241,7 +241,7 @@ ifeq ($(CPU),mpc85xx)
OBJS += $(CPUDIR)/resetvec.o
endif
-OBJS := $(addprefix $(obj),$(OBJS))
+OBJS := $(addprefix $(obj),$(OBJS) $(RESET_OBJS-))
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard board/$(VENDOR)/common/Makefile),y,n)
@@ -293,7 +293,10 @@ LIBS-y += drivers/net/libnet.o
LIBS-y += drivers/net/phy/libphy.o
LIBS-y += drivers/pci/libpci.o
LIBS-y += drivers/pcmcia/libpcmcia.o
-LIBS-y += drivers/power/libpower.o
+LIBS-y += drivers/power/libpower.o \
+ drivers/power/fuel_gauge/libfuel_gauge.o \
+ drivers/power/pmic/libpmic.o \
+ drivers/power/battery/libbattery.o
LIBS-y += drivers/spi/libspi.o
LIBS-y += drivers/dfu/libdfu.o
ifeq ($(CPU),mpc83xx)
@@ -320,6 +323,7 @@ LIBS-y += drivers/usb/eth/libusb_eth.o
LIBS-y += drivers/usb/gadget/libusb_gadget.o
LIBS-y += drivers/usb/host/libusb_host.o
LIBS-y += drivers/usb/musb/libusb_musb.o
+LIBS-y += drivers/usb/musb-new/libusb_musb-new.o
LIBS-y += drivers/usb/phy/libusb_phy.o
LIBS-y += drivers/usb/ulpi/libusb_ulpi.o
LIBS-y += drivers/video/libvideo.o
@@ -387,12 +391,12 @@ __LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
ifneq ($(CONFIG_BOARD_SIZE_LIMIT),)
BOARD_SIZE_CHECK = \
@actual=`wc -c $@ | awk '{print $$1}'`; \
- limit=$(CONFIG_BOARD_SIZE_LIMIT); \
+ limit=`printf "%d" $(CONFIG_BOARD_SIZE_LIMIT)`; \
if test $$actual -gt $$limit; then \
- echo "$@ exceeds file size limit:"; \
- echo " limit: $$limit bytes"; \
- echo " actual: $$actual bytes"; \
- echo " excess: $$((actual - limit)) bytes"; \
+ echo "$@ exceeds file size limit:" >&2 ; \
+ echo " limit: $$limit bytes" >&2 ; \
+ echo " actual: $$actual bytes" >&2 ; \
+ echo " excess: $$((actual - limit)) bytes" >&2; \
exit 1; \
fi
else
@@ -405,6 +409,7 @@ ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin
ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin
ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin
+ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET))
ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin
# enable combined SPL/u-boot/dtb rules for tegra
@@ -446,9 +451,18 @@ $(obj)u-boot.ldr.hex: $(obj)u-boot.ldr
$(obj)u-boot.ldr.srec: $(obj)u-boot.ldr
$(OBJCOPY) ${OBJCFLAGS} -O srec $< $@ -I binary
+#
+# U-Boot entry point, needed for booting of full-blown U-Boot
+# from the SPL U-Boot version.
+#
+ifndef CONFIG_SYS_UBOOT_START
+CONFIG_SYS_UBOOT_START := 0
+endif
+
$(obj)u-boot.img: $(obj)u-boot.bin
$(obj)tools/mkimage -A $(ARCH) -T firmware -C none \
- -O u-boot -a $(CONFIG_SYS_TEXT_BASE) -e 0 \
+ -O u-boot -a $(CONFIG_SYS_TEXT_BASE) \
+ -e $(CONFIG_SYS_UBOOT_START) \
-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \
sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \
-d $< $@
@@ -472,14 +486,15 @@ $(obj)u-boot.sha1: $(obj)u-boot.bin
$(obj)u-boot.dis: $(obj)u-boot
$(OBJDUMP) -d $< > $@
-$(obj)u-boot.ubl: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
+$(obj)u-boot-with-spl.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin
$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $(obj)spl/u-boot-spl $(obj)spl/u-boot-spl-pad.bin
- cat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin > $(obj)u-boot-ubl.bin
- $(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \
- -e $(CONFIG_SYS_TEXT_BASE) -d $(obj)u-boot-ubl.bin $(obj)u-boot.ubl
- rm $(obj)u-boot-ubl.bin
+ cat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin > $@
rm $(obj)spl/u-boot-spl-pad.bin
+$(obj)u-boot.ubl: $(obj)u-boot-with-spl.bin
+ $(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \
+ -e $(CONFIG_SYS_TEXT_BASE) -d $< $(obj)u-boot.ubl
+
$(obj)u-boot.ais: $(obj)spl/u-boot-spl.bin $(obj)u-boot.img
$(obj)tools/mkimage -s -n $(if $(CONFIG_AIS_CONFIG_FILE),$(CONFIG_AIS_CONFIG_FILE),"/dev/null") \
-T aisimage \
@@ -530,6 +545,9 @@ $(obj)u-boot-$(nodtb)-tegra.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin $(dtb
rm $(obj)spl/u-boot-spl-pad.bin
endif
+$(obj)u-boot-img.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.img
+ cat $(obj)spl/u-boot-spl.bin $(obj)u-boot.img > $@
+
ifeq ($(CONFIG_SANDBOX),y)
GEN_UBOOT = \
cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \
@@ -639,6 +657,16 @@ checkthumb:
echo '*** Your board is configured for THUMB mode.'; \
false; \
fi
+
+# GCC 3.x is reported to have problems generating the type of relocation
+# that U-Boot wants.
+# See http://lists.denx.de/pipermail/u-boot/2012-September/135156.html
+checkgcc4:
+ @if test $(call cc-version) -lt 0400; then \
+ echo -n '*** Your GCC is too old, please upgrade to GCC 4.x or newer'; \
+ false; \
+ fi
+
#
# Auto-generate the autoconf.mk file (which is included by all makefiles)
#
@@ -812,7 +840,7 @@ clean:
@rm -f $(obj)include/generated/asm-offsets.h
@rm -f $(obj)$(CPUDIR)/$(SOC)/asm-offsets.s
@rm -f $(TIMESTAMP_FILE) $(VERSION_FILE)
- @$(MAKE) -C doc/DocBook/ cleandocs
+ @$(MAKE) -s -C doc/DocBook/ cleandocs
@find $(OBJTREE) -type f \
\( -name 'core' -o -name '*.bak' -o -name '*~' -o -name '*.su' \
-o -name '*.o' -o -name '*.a' -o -name '*.exe' \) -print \
diff --git a/README b/README
index 037513a134..5a86ae9c5f 100644
--- a/README
+++ b/README
@@ -54,6 +54,11 @@ In case of problems see the CHANGELOG and CREDITS files to find out
who contributed the specific port. The MAINTAINERS file lists board
maintainers.
+Note: There is no CHANGELOG file in the actual U-Boot source tree;
+it can be created dynamically from the Git log using:
+
+ make CHANGELOG
+
Where to get help:
==================
@@ -1409,6 +1414,13 @@ CBFS (Coreboot Filesystem) support
boot. See the documentation file README.video for a
description of this variable.
+ CONFIG_VIDEO_VGA
+
+ Enable the VGA video / BIOS for x86. The alternative if you
+ are using coreboot is to use the coreboot frame buffer
+ driver.
+
+
- Keyboard Support:
CONFIG_KEYBOARD
@@ -1469,21 +1481,10 @@ CBFS (Coreboot Filesystem) support
Normally display is black on white background; define
CONFIG_SYS_WHITE_ON_BLACK to get it inverted.
+ CONFIG_LCD_BMP_RLE8
- CONFIG_LCD_ALIGNMENT
-
- Normally the LCD is page-aligned (tyically 4KB). If this is
- defined then the LCD will be aligned to this value instead.
- For ARM it is sometimes useful to use MMU_SECTION_SIZE
- here, since it is cheaper to change data cache settings on
- a per-section basis.
+ Support drawing of RLE8-compressed bitmaps on the LCD.
- CONFIG_CONSOLE_SCROLL_LINES
-
- When the console need to be scrolled, this is the number of
- lines to scroll by. It defaults to 1. Increasing this makes
- the console jump but can help speed up operation when scrolling
- is slow.
- Splash Screen Support: CONFIG_SPLASH_SCREEN
@@ -2211,6 +2212,14 @@ CBFS (Coreboot Filesystem) support
HERMES, IP860, RPXlite, LWMON,
FLAGADM, TQM8260
+- Access to physical memory region (> 4GB)
+ Some basic support is provided for operations on memory not
+ normally accessible to U-Boot - e.g. some architectures
+ support access to more than 4GB of memory on 32-bit
+ machines using physical address extension or similar.
+ Define CONFIG_PHYSMEM to access this basic support, which
+ currently only supports clearing the memory.
+
- Error Recovery:
CONFIG_PANIC_HANG
@@ -2613,6 +2622,17 @@ FIT uImage format:
-150 common/cmd_nand.c Incorrect FIT image format
151 common/cmd_nand.c FIT image format OK
+- FIT image support:
+ CONFIG_FIT
+ Enable support for the FIT uImage format.
+
+ CONFIG_FIT_BEST_MATCH
+ When no configuration is explicitly selected, default to the
+ one whose fdt's compatibility field best matches that of
+ U-Boot itself. A match is considered "best" if it matches the
+ most specific compatibility entry of U-Boot's fdt's root node.
+ The order of entries in the configuration's fdt is ignored.
+
- Standalone program support:
CONFIG_STANDALONE_LOAD_ADDR
@@ -2664,6 +2684,10 @@ FIT uImage format:
CONFIG_SPL_TEXT_BASE
TEXT_BASE for linking the SPL binary.
+ CONFIG_SPL_RELOC_TEXT_BASE
+ Address to relocate to. If unspecified, this is equal to
+ CONFIG_SPL_TEXT_BASE (i.e. no relocation is done).
+
CONFIG_SPL_BSS_START_ADDR
Link address for the BSS within the SPL binary.
@@ -2673,6 +2697,11 @@ FIT uImage format:
CONFIG_SPL_STACK
Adress of the start of the stack SPL will use
+ CONFIG_SPL_RELOC_STACK
+ Adress of the start of the stack SPL will use after
+ relocation. If unspecified, this is equal to
+ CONFIG_SPL_STACK.
+
CONFIG_SYS_SPL_MALLOC_START
Starting address of the malloc pool used in SPL.
@@ -2688,6 +2717,9 @@ FIT uImage format:
For ARM, enable an optional function to print more information
about the running system.
+ CONFIG_SPL_INIT_MINIMAL
+ Arch init code should be built for a very small image
+
CONFIG_SPL_LIBCOMMON_SUPPORT
Support for common/libcommon.o in SPL binary
@@ -2715,8 +2747,19 @@ FIT uImage format:
CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME
Filename to read to load U-Boot when reading from FAT
+ CONFIG_SPL_NAND_BASE
+ Include nand_base.c in the SPL. Requires
+ CONFIG_SPL_NAND_DRIVERS.
+
+ CONFIG_SPL_NAND_DRIVERS
+ SPL uses normal NAND drivers, not minimal drivers.
+
+ CONFIG_SPL_NAND_ECC
+ Include standard software ECC in the SPL
+
CONFIG_SPL_NAND_SIMPLE
- Support for drivers/mtd/nand/libnand.o in SPL binary
+ Support for NAND boot using simple NAND drivers that
+ expose the cmd_ctrl() interface.
CONFIG_SYS_NAND_5_ADDR_CYCLE, CONFIG_SYS_NAND_PAGE_COUNT,
CONFIG_SYS_NAND_PAGE_SIZE, CONFIG_SYS_NAND_OOBSIZE,
@@ -2724,15 +2767,19 @@ FIT uImage format:
CONFIG_SYS_NAND_ECCPOS, CONFIG_SYS_NAND_ECCSIZE,
CONFIG_SYS_NAND_ECCBYTES
Defines the size and behavior of the NAND that SPL uses
- to read U-Boot with CONFIG_SPL_NAND_SIMPLE
+ to read U-Boot
CONFIG_SYS_NAND_U_BOOT_OFFS
- Location in NAND for CONFIG_SPL_NAND_SIMPLE to read U-Boot
- from.
+ Location in NAND to read U-Boot from
+
+ CONFIG_SYS_NAND_U_BOOT_DST
+ Location in memory to load U-Boot to
+
+ CONFIG_SYS_NAND_U_BOOT_SIZE
+ Size of image to load
CONFIG_SYS_NAND_U_BOOT_START
- Location in memory for CONFIG_SPL_NAND_SIMPLE to load U-Boot
- to.
+ Entry point in loaded image to jump to
CONFIG_SYS_NAND_HW_ECC_OOBFIRST
Define this if you need to first read the OOB and then the
@@ -2757,6 +2804,11 @@ FIT uImage format:
CONFIG_SPL_LIBGENERIC_SUPPORT
Support for lib/libgeneric.o in SPL binary
+ CONFIG_SPL_TARGET
+ Final target image containing SPL and payload. Some SPLs
+ use an arch-specific makefile fragment instead, for
+ example if more than one image needs to be produced.
+
Modem Support:
--------------
@@ -3632,6 +3684,16 @@ Low Level (hardware related) configuration options:
be used if available. These functions may be faster under some
conditions but may increase the binary size.
+- CONFIG_X86_NO_RESET_VECTOR
+ If defined, the x86 reset vector code is excluded. You will need
+ to do this when U-Boot is running from Coreboot.
+
+- CONFIG_X86_NO_REAL_MODE
+ If defined, x86 real mode code is omitted. This assumes a
+ 32-bit environment where such code is not needed. You will
+ need to do this when U-Boot is running from Coreboot.
+
+
Freescale QE/FMAN Firmware Support:
-----------------------------------
@@ -3859,6 +3921,7 @@ saveenv - save environment variables to persistent storage
protect - enable or disable FLASH write protection
erase - erase FLASH memory
flinfo - print FLASH memory information
+nand - NAND memory operations (see doc/README.nand)
bdinfo - print Board Info structure
iminfo - print header information for application image
coninfo - print console devices and informations
diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c
index e4c123cd21..da5bc73185 100644
--- a/arch/arm/cpu/armv7/am33xx/board.c
+++ b/arch/arm/cpu/armv7/am33xx/board.c
@@ -33,6 +33,11 @@
#include <i2c.h>
#include <miiphy.h>
#include <cpsw.h>
+#include <asm/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/musb.h>
+#include <asm/omap_musb.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -63,3 +68,83 @@ void setup_clocks_for_console(void)
/* Not yet implemented */
return;
}
+
+/* AM33XX has two MUSB controllers which can be host or gadget */
+#if (defined(CONFIG_MUSB_GADGET) || defined(CONFIG_MUSB_HOST)) && \
+ (defined(CONFIG_AM335X_USB0) || defined(CONFIG_AM335X_USB1))
+static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
+
+/* USB 2.0 PHY Control */
+#define CM_PHY_PWRDN (1 << 0)
+#define CM_PHY_OTG_PWRDN (1 << 1)
+#define OTGVDET_EN (1 << 19)
+#define OTGSESSENDEN (1 << 20)
+
+static void am33xx_usb_set_phy_power(u8 on, u32 *reg_addr)
+{
+ if (on) {
+ clrsetbits_le32(reg_addr, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN,
+ OTGVDET_EN | OTGSESSENDEN);
+ } else {
+ clrsetbits_le32(reg_addr, 0, CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
+ }
+}
+
+static struct musb_hdrc_config musb_config = {
+ .multipoint = 1,
+ .dyn_fifo = 1,
+ .num_eps = 16,
+ .ram_bits = 12,
+};
+
+#ifdef CONFIG_AM335X_USB0
+static void am33xx_otg0_set_phy_power(u8 on)
+{
+ am33xx_usb_set_phy_power(on, &cdev->usb_ctrl0);
+}
+
+struct omap_musb_board_data otg0_board_data = {
+ .set_phy_power = am33xx_otg0_set_phy_power,
+};
+
+static struct musb_hdrc_platform_data otg0_plat = {
+ .mode = CONFIG_AM335X_USB0_MODE,
+ .config = &musb_config,
+ .power = 50,
+ .platform_ops = &musb_dsps_ops,
+ .board_data = &otg0_board_data,
+};
+#endif
+
+#ifdef CONFIG_AM335X_USB1
+static void am33xx_otg1_set_phy_power(u8 on)
+{
+ am33xx_usb_set_phy_power(on, &cdev->usb_ctrl1);
+}
+
+struct omap_musb_board_data otg1_board_data = {
+ .set_phy_power = am33xx_otg1_set_phy_power,
+};
+
+static struct musb_hdrc_platform_data otg1_plat = {
+ .mode = CONFIG_AM335X_USB1_MODE,
+ .config = &musb_config,
+ .power = 50,
+ .platform_ops = &musb_dsps_ops,
+ .board_data = &otg1_board_data,
+};
+#endif
+#endif
+
+int arch_misc_init(void)
+{
+#ifdef CONFIG_AM335X_USB0
+ musb_register(&otg0_plat, &otg0_board_data,
+ (void *)AM335X_USB0_OTG_BASE);
+#endif
+#ifdef CONFIG_AM335X_USB1
+ musb_register(&otg1_plat, &otg1_board_data,
+ (void *)AM335X_USB1_OTG_BASE);
+#endif
+ return 0;
+}
diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c
index bc2abb657c..0b4cb4e529 100644
--- a/arch/arm/cpu/armv7/am33xx/clock.c
+++ b/arch/arm/cpu/armv7/am33xx/clock.c
@@ -40,6 +40,7 @@
#define CLK_MODE_MASK 0xfffffff8
#define CLK_DIV_SEL 0xFFFFFFE0
#define CPGMAC0_IDLE 0x30000
+#define DPLL_CLKDCOLDO_GATE_CTRL 0x300
const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER;
const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP;
@@ -194,6 +195,11 @@ static void enable_per_clocks(void)
writel(PRCM_MOD_EN, &cmrtc->rtcclkctrl);
while (readl(&cmrtc->rtcclkctrl) != PRCM_MOD_EN)
;
+
+ /* MUSB */
+ writel(PRCM_MOD_EN, &cmper->usb0clkctrl);
+ while (readl(&cmper->usb0clkctrl) != PRCM_MOD_EN)
+ ;
}
static void mpu_pll_config(void)
@@ -290,6 +296,8 @@ static void per_pll_config(void)
while (readl(&cmwkup->idlestdpllper) != ST_DPLL_CLK)
;
+
+ writel(DPLL_CLKDCOLDO_GATE_CTRL, &cmwkup->clkdcoldodpllper);
}
void ddr_pll_config(unsigned int ddrpll_m)
diff --git a/arch/arm/cpu/armv7/omap3/Makefile b/arch/arm/cpu/armv7/omap3/Makefile
index ac597be25a..de167eea56 100644
--- a/arch/arm/cpu/armv7/omap3/Makefile
+++ b/arch/arm/cpu/armv7/omap3/Makefile
@@ -38,6 +38,7 @@ endif
COBJS-$(CONFIG_DRIVER_TI_EMAC) += emac.o
COBJS-$(CONFIG_EMIF4) += emif4.o
COBJS-$(CONFIG_SDRC) += sdrc.o
+COBJS-$(CONFIG_USB_MUSB_AM35X) += am35x_musb.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS))
diff --git a/arch/arm/cpu/armv7/omap3/am35x_musb.c b/arch/arm/cpu/armv7/omap3/am35x_musb.c
new file mode 100644
index 0000000000..7183c4f248
--- /dev/null
+++ b/arch/arm/cpu/armv7/omap3/am35x_musb.c
@@ -0,0 +1,75 @@
+/*
+ * This file configures the internal USB PHY in AM35X.
+ *
+ * Copyright (C) 2012 Ilya Yanok <ilya.yanok@gmail.com>
+ *
+ * Based on omap_phy_internal.c code from Linux by
+ * Hema HK <hemahk@ti.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.
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/am35x_def.h>
+
+void am35x_musb_reset(void)
+{
+ /* Reset the musb interface */
+ clrsetbits_le32(&am35x_scm_general_regs->ip_sw_reset,
+ 0, USBOTGSS_SW_RST);
+ clrsetbits_le32(&am35x_scm_general_regs->ip_sw_reset,
+ USBOTGSS_SW_RST, 0);
+}
+
+void am35x_musb_phy_power(u8 on)
+{
+ unsigned long start = get_timer(0);
+
+ if (on) {
+ /*
+ * Start the on-chip PHY and its PLL.
+ */
+ clrsetbits_le32(&am35x_scm_general_regs->devconf2,
+ CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN,
+ CONF2_PHY_PLLON);
+
+ debug("Waiting for PHY clock good...\n");
+ while (!(readl(&am35x_scm_general_regs->devconf2)
+ & CONF2_PHYCLKGD)) {
+
+ if (get_timer(start) > CONFIG_SYS_HZ / 10) {
+ printf("musb PHY clock good timed out\n");
+ break;
+ }
+ }
+ } else {
+ /*
+ * Power down the on-chip PHY.
+ */
+ clrsetbits_le32(&am35x_scm_general_regs->devconf2,
+ CONF2_PHY_PLLON,
+ CONF2_PHYPWRDN | CONF2_OTGPWRDN);
+ }
+}
+
+void am35x_musb_clear_irq(void)
+{
+ clrsetbits_le32(&am35x_scm_general_regs->lvl_intr_clr,
+ 0, USBOTGSS_INT_CLR);
+ readl(&am35x_scm_general_regs->lvl_intr_clr);
+}
+
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index 819fd2f026..d6c038e3ae 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -82,7 +82,8 @@ struct cm_wkuppll {
unsigned int clkseldpllcore; /* offset 0x68 */
unsigned int resv9[1];
unsigned int idlestdpllper; /* offset 0x70 */
- unsigned int resv10[3];
+ unsigned int resv10[2];
+ unsigned int clkdcoldodpllper; /* offset 0x7c */
unsigned int divm4dpllcore; /* offset 0x80 */
unsigned int divm5dpllcore; /* offset 0x84 */
unsigned int clkmoddpllmpu; /* offset 0x88 */
@@ -275,12 +276,16 @@ struct ctrl_stat {
/* Control Device Register */
struct ctrl_dev {
unsigned int deviceid; /* offset 0x00 */
- unsigned int resv1[11];
+ unsigned int resv1[7];
+ unsigned int usb_ctrl0; /* offset 0x20 */
+ unsigned int resv2;
+ unsigned int usb_ctrl1; /* offset 0x28 */
+ unsigned int resv3;
unsigned int macid0l; /* offset 0x30 */
unsigned int macid0h; /* offset 0x34 */
unsigned int macid1l; /* offset 0x38 */
unsigned int macid1h; /* offset 0x3c */
- unsigned int resv2[4];
+ unsigned int resv4[4];
unsigned int miisel; /* offset 0x50 */
};
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/arch-am33xx/hardware.h b/arch/arm/include/asm/arch-am33xx/hardware.h
index 5bd4bc8722..24ab365ea3 100644
--- a/arch/arm/include/asm/arch-am33xx/hardware.h
+++ b/arch/arm/include/asm/arch-am33xx/hardware.h
@@ -87,4 +87,8 @@
/* RTC base address */
#define AM335X_RTC_BASE 0x44E3E000
+/* OTG */
+#define AM335X_USB0_OTG_BASE 0x47401000
+#define AM335X_USB1_OTG_BASE 0x47401800
+
#endif /* __AM33XX_HARDWARE_H */
diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h b/arch/arm/include/asm/arch-exynos/dwmmc.h
new file mode 100644
index 0000000000..8acdf9b725
--- /dev/null
+++ b/arch/arm/include/asm/arch-exynos/dwmmc.h
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung@samsung.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
+ *
+ */
+
+#define DWMCI_CLKSEL 0x09C
+#define DWMCI_SHIFT_0 0x0
+#define DWMCI_SHIFT_1 0x1
+#define DWMCI_SHIFT_2 0x2
+#define DWMCI_SHIFT_3 0x3
+#define DWMCI_SET_SAMPLE_CLK(x) (x)
+#define DWMCI_SET_DRV_CLK(x) ((x) << 16)
+#define DWMCI_SET_DIV_RATIO(x) ((x) << 24)
+
+int exynos_dwmci_init(u32 regbase, int bus_width, int index);
+
+static inline unsigned int exynos_dwmmc_init(int index, int bus_width)
+{
+ unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
+ return exynos_dwmci_init(base, bus_width, index);
+}
diff --git a/arch/arm/include/asm/arch-omap3/am35x_def.h b/arch/arm/include/asm/arch-omap3/am35x_def.h
index bbaf1bc97b..67698bc7ef 100644
--- a/arch/arm/include/asm/arch-omap3/am35x_def.h
+++ b/arch/arm/include/asm/arch-omap3/am35x_def.h
@@ -32,9 +32,34 @@
#ifndef __KERNEL_STRICT_NAMES
#ifndef __ASSEMBLY__
+/* LVL_INTR_CLEAR bits */
+#define USBOTGSS_INT_CLR (1 << 4)
+
/* IP_SW_RESET bits */
+#define USBOTGSS_SW_RST (1 << 0) /* reset USBOTG */
#define CPGMACSS_SW_RST (1 << 1) /* reset CPGMAC */
+/* DEVCONF2 bits */
+#define CONF2_PHY_GPIOMODE (1 << 23)
+#define CONF2_OTGMODE (3 << 14)
+#define CONF2_NO_OVERRIDE (0 << 14)
+#define CONF2_FORCE_HOST (1 << 14)
+#define CONF2_FORCE_DEVICE (2 << 14)
+#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
+#define CONF2_SESENDEN (1 << 13)
+#define CONF2_VBDTCTEN (1 << 12)
+#define CONF2_REFFREQ_24MHZ (2 << 8)
+#define CONF2_REFFREQ_26MHZ (7 << 8)
+#define CONF2_REFFREQ_13MHZ (6 << 8)
+#define CONF2_REFFREQ (0xf << 8)
+#define CONF2_PHYCLKGD (1 << 7)
+#define CONF2_VBUSSENSE (1 << 6)
+#define CONF2_PHY_PLLON (1 << 5)
+#define CONF2_RESET (1 << 4)
+#define CONF2_PHYPWRDN (1 << 3)
+#define CONF2_OTGPWRDN (1 << 2)
+#define CONF2_DATPOL (1 << 1)
+
/* General register mappings of system control module */
#define AM35X_SCM_GEN_BASE 0x48002270
struct am35x_scm_general {
@@ -49,6 +74,8 @@ struct am35x_scm_general {
};
#define am35x_scm_general_regs ((struct am35x_scm_general *)AM35X_SCM_GEN_BASE)
+#define AM35XX_IPSS_USBOTGSS_BASE 0x5C040000
+
#endif /*__ASSEMBLY__ */
#endif /* __KERNEL_STRICT_NAMES */
diff --git a/board/chromebook-x86/coreboot/coreboot_start16.S b/arch/arm/include/asm/arch-omap3/musb.h
index 9ad06df8bc..423ac500f4 100644
--- a/board/chromebook-x86/coreboot/coreboot_start16.S
+++ b/arch/arm/include/asm/arch-omap3/musb.h
@@ -1,7 +1,6 @@
/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (C) Copyright 2008
- * Graeme Russ, graeme.russ@gmail.com.
+ * (C) Copyright 2012
+ * Ilya Yanok, <ilya.yanok@gmail.com>
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -18,29 +17,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * Foundation, Inc.
*/
-/*
- * 16bit initialization code.
- * This code have to map the area of the boot flash
- * that is used by U-boot to its final destination.
- */
-
-.text
-.section .start16, "ax"
-.code16
-.globl board_init16
-board_init16:
- jmp board_init16_ret
-
-.section .bios, "ax"
-.code16
-.globl realmode_reset
-.hidden realmode_reset
-.type realmode_reset, @function
-realmode_reset:
-
-1: hlt
- jmp 1
+#ifndef __ASM_ARCH_OMAP3_MUSB_H
+#define __ASM_ARCH_OMAP3_MUSB_H
+extern void am35x_musb_reset(void);
+extern void am35x_musb_phy_power(u8 on);
+extern void am35x_musb_clear_irq(void);
+#endif
diff --git a/arch/arm/include/asm/imx-common/mx5_video.h b/arch/arm/include/asm/imx-common/mx5_video.h
new file mode 100644
index 0000000000..e54c25a560
--- /dev/null
+++ b/arch/arm/include/asm/imx-common/mx5_video.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012
+ * Anatolij Gustschin, DENX Software Engineering, <agust@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.
+ */
+#ifndef __MX5_VIDEO_H
+#define __MX5_VIDEO_H
+
+#ifdef CONFIG_VIDEO
+void lcd_enable(void);
+void setup_iomux_lcd(void);
+#else
+static inline void lcd_enable(void) { }
+static inline void setup_iomux_lcd(void) { }
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/omap_musb.h b/arch/arm/include/asm/omap_musb.h
new file mode 100644
index 0000000000..b04d8650ef
--- /dev/null
+++ b/arch/arm/include/asm/omap_musb.h
@@ -0,0 +1,32 @@
+/*
+ * Board data structure for musb gadget on OMAPs
+ *
+ * Copyright (C) 2012, Ilya Yanok <ilya.yanok@gmail.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.
+ */
+
+#ifndef __ASM_ARM_OMAP_MUSB_H
+#define __ASM_ARM_OMAP_MUSB_H
+
+extern struct musb_platform_ops musb_dsps_ops;
+extern const struct musb_platform_ops am35x_ops;
+extern const struct musb_platform_ops omap2430_ops;
+
+struct omap_musb_board_data {
+ u8 interface_type;
+ void (*set_phy_power)(u8 on);
+ void (*clear_irq)(void);
+ void (*reset)(void);
+};
+
+enum musb_interface {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
+#endif /* __ASM_ARM_OMAP_MUSB_H */
diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
index 92cad9a6eb..22a4d9cc0e 100644
--- a/arch/arm/lib/board.c
+++ b/arch/arm/lib/board.c
@@ -224,6 +224,13 @@ int __arch_cpu_init(void)
int arch_cpu_init(void)
__attribute__((weak, alias("__arch_cpu_init")));
+int __power_init_board(void)
+{
+ return 0;
+}
+int power_init_board(void)
+ __attribute__((weak, alias("__power_init_board")));
+
init_fnc_t *init_sequence[] = {
arch_cpu_init, /* basic arch cpu dependent setup */
@@ -525,6 +532,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
#ifdef CONFIG_ARCH_EARLY_INIT_R
arch_early_init_r();
#endif
+ power_init_board();
#if !defined(CONFIG_SYS_NO_FLASH)
puts("Flash: ");
diff --git a/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c b/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c
index c747767e1e..b9b0998d48 100644
--- a/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c
+++ b/arch/mips/cpu/mips32/au1x00/au1x00_usb_ohci.c
@@ -615,7 +615,7 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
| usb_pipeendpoint (pipe) << 7
| (usb_pipeisoc (pipe)? 0x8000: 0)
| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
- | usb_pipeslow (pipe) << 13
+ | (usb_dev->speed == USB_SPEED_LOW) << 13
| usb_maxpacket (usb_dev, pipe) << 16);
return ed_ret;
diff --git a/arch/mips/cpu/mips32/time.c b/arch/mips/cpu/mips32/time.c
index 350896a2a5..09fc842b50 100644
--- a/arch/mips/cpu/mips32/time.c
+++ b/arch/mips/cpu/mips32/time.c
@@ -36,7 +36,6 @@ static unsigned long timestamp;
int timer_init(void)
{
/* Set up the timer for the first expiration. */
- timestamp = 0;
write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
return 0;
diff --git a/arch/mips/cpu/mips64/time.c b/arch/mips/cpu/mips64/time.c
index 51542808dd..720f7b7f8c 100644
--- a/arch/mips/cpu/mips64/time.c
+++ b/arch/mips/cpu/mips64/time.c
@@ -37,7 +37,6 @@ static unsigned long timestamp;
int timer_init(void)
{
/* Set up the timer for the first expiration. */
- timestamp = 0;
write_c0_compare(read_c0_count() + CYCLES_PER_JIFFY);
return 0;
diff --git a/arch/powerpc/config.mk b/arch/powerpc/config.mk
index a30715459d..b7062818bb 100644
--- a/arch/powerpc/config.mk
+++ b/arch/powerpc/config.mk
@@ -42,3 +42,8 @@ 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/mpc5xxx/Makefile b/arch/powerpc/cpu/mpc5xxx/Makefile
index 1a088b77bc..8de2c13598 100644
--- a/arch/powerpc/cpu/mpc5xxx/Makefile
+++ b/arch/powerpc/cpu/mpc5xxx/Makefile
@@ -41,6 +41,10 @@ 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))
diff --git a/arch/powerpc/cpu/mpc5xxx/spl_boot.c b/arch/powerpc/cpu/mpc5xxx/spl_boot.c
new file mode 100644
index 0000000000..9f14127dca
--- /dev/null
+++ b/arch/powerpc/cpu/mpc5xxx/spl_boot.c
@@ -0,0 +1,79 @@
+/*
+ * 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;
+
+ /*
+ * 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/mpc5xxx/start.S b/arch/powerpc/cpu/mpc5xxx/start.S
index 51cc4e2a10..ad5bc0a179 100644
--- a/arch/powerpc/cpu/mpc5xxx/start.S
+++ b/arch/powerpc/cpu/mpc5xxx/start.S
@@ -50,6 +50,7 @@
#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
#endif
+#ifndef CONFIG_SPL_BUILD
/*
* Set up GOT: Global Offset Table
*
@@ -68,6 +69,7 @@
GOT_ENTRY(__bss_end__)
GOT_ENTRY(__bss_start)
END_GOT
+#endif
/*
* Version string
@@ -84,6 +86,18 @@ version_string:
. = 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 */
@@ -152,7 +166,9 @@ lowboot_reentry:
/* 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)*/
@@ -160,7 +176,9 @@ lowboot_reentry:
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
*/
@@ -333,6 +351,7 @@ int_return:
lwz r1,GPR1(r1)
SYNC
rfi
+#endif /* CONFIG_SPL_BUILD */
/*
* This code initialises the MPC5xxx processor core
@@ -522,6 +541,7 @@ get_pvr:
mfspr r3, PVR
blr
+#ifndef CONFIG_SPL_BUILD
/*------------------------------------------------------------------------------*/
/*
@@ -759,3 +779,5 @@ trap_init:
mtlr r4 /* restore link register */
blr
+
+#endif /* CONFIG_SPL_BUILD */
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 0000000000..cab9b9265c
--- /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/usb_ohci.c b/arch/powerpc/cpu/mpc5xxx/usb_ohci.c
index 607034b7c6..de07343d93 100644
--- a/arch/powerpc/cpu/mpc5xxx/usb_ohci.c
+++ b/arch/powerpc/cpu/mpc5xxx/usb_ohci.c
@@ -618,7 +618,7 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
| usb_pipeendpoint (pipe) << 7
| (usb_pipeisoc (pipe)? 0x8000: 0)
| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
- | usb_pipeslow (pipe) << 13
+ | (usb_dev->speed == USB_SPEED_LOW) << 13
| usb_maxpacket (usb_dev, pipe) << 16);
return ed_ret;
diff --git a/arch/powerpc/cpu/mpc85xx/Makefile b/arch/powerpc/cpu/mpc85xx/Makefile
index 78c412d9f3..4c2b1040d4 100644
--- a/arch/powerpc/cpu/mpc85xx/Makefile
+++ b/arch/powerpc/cpu/mpc85xx/Makefile
@@ -28,7 +28,22 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(CPU).o
-START = start.o resetvec.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)
@@ -121,17 +136,20 @@ COBJS-$(CONFIG_PPC_P5040) += p5040_serdes.o
COBJS-$(CONFIG_PPC_T4240) += t4240_serdes.o
COBJS-$(CONFIG_PPC_B4860) += b4860_serdes.o
-COBJS = $(COBJS-y)
-COBJS += cpu.o
-COBJS += cpu_init.o
-COBJS += cpu_init_early.o
-COBJS += interrupts.o
-COBJS += speed.o
-COBJS += tlb.o
-COBJS += traps.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 += cache.o
+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))
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index 2be192d578..e5ecf5dae5 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -24,6 +24,109 @@
#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[])
{
@@ -137,6 +240,17 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#ifdef CONFIG_SYS_FSL_ERRATUM_A_004934
puts("Work-around for Erratum A004934 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
return 0;
}
diff --git a/arch/powerpc/cpu/mpc85xx/cpu.c b/arch/powerpc/cpu/mpc85xx/cpu.c
index db232e64f8..9b9832cfc3 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu.c
@@ -332,7 +332,8 @@ void mpc85xx_reginfo(void)
/* Common ddr init for non-corenet fsl 85xx platforms */
#ifndef CONFIG_FSL_CORENET
-#if defined(CONFIG_SYS_RAMBOOT) && !defined(CONFIG_SYS_INIT_L2_ADDR)
+#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)
@@ -450,21 +451,21 @@ static void dump_spd_ddr_reg(void)
for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
switch (i) {
case 0:
- ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
break;
-#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
+#if defined(CONFIG_SYS_MPC8xxx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
case 1:
- ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR;
break;
#endif
-#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+#if defined(CONFIG_SYS_MPC8xxx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
case 2:
- ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR3_ADDR;
break;
#endif
-#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+#if defined(CONFIG_SYS_MPC8xxx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
case 3:
- ddr[i] = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR;
+ ddr[i] = (void *)CONFIG_SYS_MPC8xxx_DDR4_ADDR;
break;
#endif
default:
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index f01804bbb9..d1155e8126 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -350,6 +350,10 @@ int cpu_init_r(void)
#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)
@@ -395,6 +399,14 @@ int cpu_init_r(void)
}
#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)
@@ -470,7 +482,7 @@ int cpu_init_r(void)
&& l2srbar >= CONFIG_SYS_FLASH_BASE) {
l2srbar = CONFIG_SYS_INIT_L2_ADDR;
l2cache->l2srbar0 = l2srbar;
- printf("moving to 0x%08x", CONFIG_SYS_INIT_L2_ADDR);
+ printf(", moving to 0x%08x", CONFIG_SYS_INIT_L2_ADDR);
}
#endif /* CONFIG_SYS_INIT_L2_ADDR */
puts("\n");
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
index 54437dd0cb..8a86819fb5 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen1.c
@@ -18,7 +18,7 @@ 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_MPC85xx_DDR_ADDR;
+ 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);
@@ -73,7 +73,7 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
void
ddr_enable_ecc(unsigned int dram_size)
{
- volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+ volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR);
dma_meminit(CONFIG_MEM_INIT_VALUE, dram_size);
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
index 49000a19e8..a705862522 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen2.c
@@ -19,15 +19,12 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
unsigned int ctrl_num)
{
unsigned int i;
-#ifdef CONFIG_MPC83xx
- ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC83xx_DDR_ADDR;
-#else
- ccsr_ddr_t *ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
-#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_DDR120
+ 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
-#endif
if (ctrl_num) {
printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index f118dd5daf..ef0dd1da64 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -32,21 +32,21 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
switch (ctrl_num) {
case 0:
- ddr = (void *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
break;
-#if defined(CONFIG_SYS_MPC85xx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
+#if defined(CONFIG_SYS_MPC8xxx_DDR2_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 1)
case 1:
- ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR;
break;
#endif
-#if defined(CONFIG_SYS_MPC85xx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
+#if defined(CONFIG_SYS_MPC8xxx_DDR3_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 2)
case 2:
- ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR3_ADDR;
break;
#endif
-#if defined(CONFIG_SYS_MPC85xx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
+#if defined(CONFIG_SYS_MPC8xxx_DDR4_ADDR) && (CONFIG_NUM_DDR_CONTROLLERS > 3)
case 3:
- ddr = (void *)CONFIG_SYS_MPC85xx_DDR4_ADDR;
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR4_ADDR;
break;
#endif
default:
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
index 7f466ac6a9..5495dc59ee 100644
--- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
@@ -714,9 +714,13 @@ void fsl_serdes_init(void)
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9
/*
- * Set BnTTLCRy0[FLT_SEL] = 000011 and set BnTTLCRy0[17] = 1 for
- * each of the SerDes lanes selected as SGMII, XAUI, SRIO, or
- * AURORA before the device is initialized.
+ * 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:
@@ -733,10 +737,12 @@ void fsl_serdes_init(void)
case SRIO1:
case SRIO2:
case AURORA:
- clrsetbits_be32(&srds_regs->lane[idx].ttlcr0,
- SRDS_TTLCR0_FLT_SEL_MASK,
- SRDS_TTLCR0_FLT_SEL_750PPM |
- SRDS_TTLCR0_PM_DIS);
+ 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;
}
diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S
index 4ba44a9028..5c4b1e3b75 100644
--- a/arch/powerpc/cpu/mpc85xx/release.S
+++ b/arch/powerpc/cpu/mpc85xx/release.S
@@ -351,7 +351,13 @@ __secondary_reset_vector:
.align L1_CACHE_SHIFT
.global __second_half_boot_page
__second_half_boot_page:
-#define EPAPR_MAGIC 0x45504150
+#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
@@ -383,7 +389,24 @@ __second_half_boot_page:
stw r8,ENTRY_ADDR_LOWER(r10)
/* spin waiting for addr */
-3: lwz r4,ENTRY_ADDR_LOWER(r10)
+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
@@ -460,5 +483,14 @@ __second_half_boot_page:
.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/cpu_init_nand.c b/arch/powerpc/cpu/mpc85xx/spl_minimal.c
index bf7a6f6be6..c6b9cd0acc 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c
+++ b/arch/powerpc/cpu/mpc85xx/spl_minimal.c
@@ -21,12 +21,16 @@
*/
#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)
{
-#if defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SYS_INIT_L2_ADDR)
+#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);
@@ -40,3 +44,16 @@ void cpu_init_f(void)
(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
index ac17f9d3ca..bb0dc1a653 100644
--- a/arch/powerpc/cpu/mpc85xx/start.S
+++ b/arch/powerpc/cpu/mpc85xx/start.S
@@ -44,6 +44,15 @@
#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
*
@@ -53,7 +62,7 @@
GOT_ENTRY(_GOT2_TABLE_)
GOT_ENTRY(_FIXUP_TABLE_)
-#ifndef CONFIG_NAND_SPL
+#ifndef MINIMAL_SPL
GOT_ENTRY(_start)
GOT_ENTRY(_start_of_vectors)
GOT_ENTRY(_end_of_vectors)
@@ -282,51 +291,8 @@ l2_disabled:
isync
.endm
-#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(CONFIG_NAND_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.
- */
-
-#if !defined(CONFIG_SYS_RAMBOOT) && !defined(CONFIG_SECURE_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, MAS2_I, \
- CONFIG_SYS_MONITOR_BASE, MAS3_SX|MAS3_SW|MAS3_SR, \
- 0, r6
-#endif
-#endif
-
-/*
- * Ne need to setup interrupt vector for NAND SPL
- * because NAND SPL never compiles it.
- */
-#if !defined(CONFIG_NAND_SPL)
+/* 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
@@ -534,10 +500,6 @@ nexti: mflr r1 /* R1 = our PC */
li r3, 0
mtspr MAS1, r3
1: cmpw r3, r14
-#if defined(CONFIG_SYS_PPC_E500_DEBUG_TLB) && !defined(CONFIG_NAND_SPL)
- cmpwi cr1, r3, CONFIG_SYS_PPC_E500_DEBUG_TLB
- cror cr0*4+eq, cr0*4+eq, cr1*4+eq
-#endif
rlwinm r5, r3, 16, MAS0_ESEL_MSK
addi r3, r3, 1
beq 2f /* skip the entry we're executing from */
@@ -553,6 +515,46 @@ nexti: mflr r1 /* R1 = our PC */
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
@@ -1036,7 +1038,7 @@ create_init_ram_area:
lis r6,FSL_BOOKE_MAS0(1, 15, 0)@h
ori r6,r6,FSL_BOOKE_MAS0(1, 15, 0)@l
-#if !defined(CONFIG_SYS_RAMBOOT) && !defined(CONFIG_SECURE_BOOT)
+#ifdef NOR_BOOT
/* create a temp mapping in AS=1 to the 4M boot window */
create_tlb1_entry 15, \
1, BOOKE_PAGESZ_4M, \
@@ -1050,8 +1052,8 @@ create_init_ram_area:
*/
create_tlb1_entry 15, \
1, BOOKE_PAGESZ_1M, \
- CONFIG_SYS_MONITOR_BASE, MAS2_I|MAS2_G, \
- CONFIG_SYS_PBI_FLASH_WINDOW, MAS3_SX|MAS3_SW|MAS3_SR, \
+ CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
+ CONFIG_SYS_PBI_FLASH_WINDOW & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
0, r6
#else
/*
@@ -1060,8 +1062,8 @@ create_init_ram_area:
*/
create_tlb1_entry 15, \
1, BOOKE_PAGESZ_1M, \
- CONFIG_SYS_MONITOR_BASE, MAS2_I|MAS2_G, \
- CONFIG_SYS_MONITOR_BASE, MAS3_SX|MAS3_SW|MAS3_SR, \
+ CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS2_I|MAS2_G, \
+ CONFIG_SYS_MONITOR_BASE & 0xfff00000, MAS3_SX|MAS3_SW|MAS3_SR, \
0, r6
#endif
@@ -1111,7 +1113,8 @@ switch_as:
bdnz 1b
/* Jump out the last 4K page and continue to 'normal' start */
-#ifdef CONFIG_SYS_RAMBOOT
+#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 */
@@ -1157,7 +1160,7 @@ _start_cont:
/* NOTREACHED - board_init_f() does not return */
-#ifndef CONFIG_NAND_SPL
+#ifndef MINIMAL_SPL
. = EXC_OFF_SYS_RESET
.globl _start_of_vectors
_start_of_vectors:
@@ -1601,7 +1604,7 @@ in32:
in32r:
lwbrx r3,r0,r3
blr
-#endif /* !CONFIG_NAND_SPL */
+#endif /* !MINIMAL_SPL */
/*------------------------------------------------------------------------------*/
@@ -1798,7 +1801,7 @@ clear_bss:
mr r4,r10 /* Destination Address */
bl board_init_r
-#ifndef CONFIG_NAND_SPL
+#ifndef MINIMAL_SPL
/*
* Copy exception vector code to low memory
*
@@ -1971,4 +1974,4 @@ setup_ivors:
#include "fixed_ivor.S"
blr
-#endif /* !CONFIG_NAND_SPL */
+#endif /* !MINIMAL_SPL */
diff --git a/arch/powerpc/cpu/mpc85xx/tlb.c b/arch/powerpc/cpu/mpc85xx/tlb.c
index a548dec9a7..f44fadcffd 100644
--- a/arch/powerpc/cpu/mpc85xx/tlb.c
+++ b/arch/powerpc/cpu/mpc85xx/tlb.c
@@ -55,7 +55,7 @@ void init_tlbs(void)
return ;
}
-#ifndef CONFIG_NAND_SPL
+#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)
{
@@ -332,4 +332,4 @@ void clear_ddr_tlbs(unsigned int memsize_in_meg)
}
-#endif /* !CONFIG_NAND_SPL */
+#endif /* not SPL */
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 0000000000..1c408e29f5
--- /dev/null
+++ b/arch/powerpc/cpu/mpc85xx/u-boot-spl.lds
@@ -0,0 +1,87 @@
+/*
+ * (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
+{
+ . = 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 :
+ {
+ 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
+
+ /*
+ * Make sure that the bss segment isn't linked at 0x0, otherwise its
+ * address won't be updated during relocation fixups.
+ */
+ . |= 0x10;
+
+ __bss_start = .;
+ .bss : {
+ *(.sbss*)
+ *(.bss*)
+ }
+ __bss_end__ = .;
+}
diff --git a/arch/powerpc/cpu/mpc86xx/ddr-8641.c b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
index b8f2c9387f..92ba26dc8e 100644
--- a/arch/powerpc/cpu/mpc86xx/ddr-8641.c
+++ b/arch/powerpc/cpu/mpc86xx/ddr-8641.c
@@ -22,10 +22,10 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
switch (ctrl_num) {
case 0:
- ddr = (void *)CONFIG_SYS_MPC86xx_DDR_ADDR;
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
break;
case 1:
- ddr = (void *)CONFIG_SYS_MPC86xx_DDR2_ADDR;
+ ddr = (void *)CONFIG_SYS_MPC8xxx_DDR2_ADDR;
break;
default:
printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num);
diff --git a/arch/powerpc/cpu/mpc8xxx/Makefile b/arch/powerpc/cpu/mpc8xxx/Makefile
index 4ae26e4210..3dc8e055b6 100644
--- a/arch/powerpc/cpu/mpc8xxx/Makefile
+++ b/arch/powerpc/cpu/mpc8xxx/Makefile
@@ -10,6 +10,20 @@ 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
@@ -18,6 +32,9 @@ 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))
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
index 088cc0e855..8016bcdc22 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/ctrl_regs.c
@@ -18,15 +18,7 @@
#include "ddr.h"
-#ifdef CONFIG_MPC83xx
- #define _DDR_ADDR CONFIG_SYS_MPC83xx_DDR_ADDR
-#elif defined(CONFIG_MPC85xx)
- #define _DDR_ADDR CONFIG_SYS_MPC85xx_DDR_ADDR
-#elif defined(CONFIG_MPC86xx)
- #define _DDR_ADDR CONFIG_SYS_MPC86xx_DDR_ADDR
-#else
- #error "Undefined _DDR_ADDR"
-#endif
+#define _DDR_ADDR CONFIG_SYS_MPC8xxx_DDR_ADDR
static u32 fsl_ddr_get_version(void)
{
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
index 940ffff773..acfe1f095f 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/util.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
@@ -133,14 +133,8 @@ u32 fsl_ddr_get_intl3r(void)
void board_add_ram_info(int use_default)
{
-#if defined(CONFIG_MPC83xx)
- immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
- ccsr_ddr_t *ddr = (void *)&immap->ddr;
-#elif defined(CONFIG_MPC85xx)
- ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
-#elif defined(CONFIG_MPC86xx)
- ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC86xx_DDR_ADDR);
-#endif
+ 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
@@ -152,13 +146,13 @@ void board_add_ram_info(int use_default)
#if CONFIG_NUM_DDR_CONTROLLERS >= 2
if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
- ddr = (void __iomem *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+ 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_MPC85xx_DDR3_ADDR;
+ ddr = (void __iomem *)CONFIG_SYS_MPC8xxx_DDR3_ADDR;
sdram_cfg = in_be32(&ddr->sdram_cfg);
}
#endif
diff --git a/arch/powerpc/cpu/mpc8xxx/fdt.c b/arch/powerpc/cpu/mpc8xxx/fdt.c
index 68db8e2448..1986fea030 100644
--- a/arch/powerpc/cpu/mpc8xxx/fdt.c
+++ b/arch/powerpc/cpu/mpc8xxx/fdt.c
@@ -217,7 +217,7 @@ void fdt_fixup_dr_usb(void *blob, bd_t *bd)
#if CONFIG_SYS_FSL_SEC_COMPAT == 2 /* SEC 2.x/3.x */
void fdt_fixup_crypto_node(void *blob, int sec_rev)
{
- const struct sec_rev_prop {
+ static const struct sec_rev_prop {
u32 sec_rev;
u32 num_channels;
u32 channel_fifo_len;
@@ -232,8 +232,8 @@ void fdt_fixup_crypto_node(void *blob, int sec_rev)
{ 0x0301, 4, 24, 0xbfe, 0x03ab0ebf }, /* SEC 3.1 */
{ 0x0303, 4, 24, 0x97c, 0x03a30abf }, /* SEC 3.3 */
};
- char compat_strlist[ARRAY_SIZE(sec_rev_prop_list) *
- sizeof("fsl,secX.Y")];
+ static char compat_strlist[ARRAY_SIZE(sec_rev_prop_list) *
+ sizeof("fsl,secX.Y")];
int crypto_node, sec_idx, err;
char *p;
u32 val;
diff --git a/drivers/misc/fsl_law.c b/arch/powerpc/cpu/mpc8xxx/law.c
index 223cd5d65c..ce1d71e307 100644
--- a/drivers/misc/fsl_law.c
+++ b/arch/powerpc/cpu/mpc8xxx/law.c
@@ -92,7 +92,7 @@ void disable_law(u8 idx)
return;
}
-#ifndef CONFIG_NAND_SPL
+#if !defined(CONFIG_NAND_SPL) && !defined(CONFIG_SPL_BUILD)
static int get_law_entry(u8 i, struct law_entry *e)
{
u32 lawar;
@@ -122,7 +122,7 @@ int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id)
return idx;
}
-#ifndef CONFIG_NAND_SPL
+#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;
@@ -233,7 +233,7 @@ int set_ddr_laws(u64 start, u64 sz, enum law_trgt_if id)
return 0;
}
-#endif
+#endif /* not SPL */
void init_laws(void)
{
@@ -258,9 +258,10 @@ void init_laws(void)
gd->used_laws |= (1 << i);
}
-#if defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)
+#if (defined(CONFIG_NAND_U_BOOT) && !defined(CONFIG_NAND_SPL)) || \
+ (defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
/*
- * in NAND boot we've already parsed the law_table and setup those LAWs
+ * in SPL boot we've already parsed the law_table and setup those LAWs
* so don't do it again.
*/
return;
diff --git a/arch/powerpc/cpu/ppc4xx/usb_ohci.c b/arch/powerpc/cpu/ppc4xx/usb_ohci.c
index 4ce2726297..f820c37a8f 100644
--- a/arch/powerpc/cpu/ppc4xx/usb_ohci.c
+++ b/arch/powerpc/cpu/ppc4xx/usb_ohci.c
@@ -621,7 +621,7 @@ static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe)
| usb_pipeendpoint (pipe) << 7
| (usb_pipeisoc (pipe)? 0x8000: 0)
| (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000))
- | usb_pipeslow (pipe) << 13
+ | (usb_dev->speed == USB_SPEED_LOW) << 13
| usb_maxpacket (usb_dev, pipe) << 16);
return ed_ret;
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index 03baaee1b7..0b9638bcee 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -27,6 +27,12 @@
#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 */
@@ -131,7 +137,6 @@
#define CONFIG_SYS_PPC_E500_DEBUG_TLB 3
#define CONFIG_TSECV2
#define CONFIG_SYS_FSL_SEC_COMPAT 4
-#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
#define CONFIG_NUM_DDR_CONTROLLERS 1
#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
@@ -175,7 +180,6 @@
#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
#define CONFIG_TSECV2
#define CONFIG_SYS_FSL_SEC_COMPAT 2
-#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -188,7 +192,6 @@
#define CONFIG_SYS_PPC_E500_DEBUG_TLB 3
#define CONFIG_TSECV2
#define CONFIG_SYS_FSL_SEC_COMPAT 4
-#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
#define CONFIG_NUM_DDR_CONTROLLERS 1
#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
@@ -242,7 +245,6 @@
#define CONFIG_SYS_PPC_E500_DEBUG_TLB 2
#define CONFIG_TSECV2
#define CONFIG_SYS_FSL_SEC_COMPAT 2
-#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_CCSRBAR_DEFAULT 0xff700000
#define CONFIG_SYS_FSL_ERRATUM_ELBC_A001
#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -318,7 +320,6 @@
#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
#define CONFIG_SYS_FSL_NUM_LAWS 32
#define CONFIG_SYS_FSL_SEC_COMPAT 4
-#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_NUM_FMAN 1
#define CONFIG_SYS_NUM_FM1_DTSEC 5
#define CONFIG_SYS_NUM_FM1_10GEC 1
@@ -343,6 +344,7 @@
#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
@@ -350,7 +352,6 @@
#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
#define CONFIG_SYS_FSL_NUM_LAWS 32
#define CONFIG_SYS_FSL_SEC_COMPAT 4
-#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_NUM_FMAN 1
#define CONFIG_SYS_NUM_FM1_DTSEC 5
#define CONFIG_SYS_NUM_FM1_10GEC 1
@@ -375,6 +376,7 @@
#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
@@ -417,6 +419,9 @@
#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 */
@@ -425,7 +430,6 @@
#define CONFIG_SYS_FSL_NUM_CC_PLLS 2
#define CONFIG_SYS_FSL_NUM_LAWS 32
#define CONFIG_SYS_FSL_SEC_COMPAT 4
-#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_NUM_FMAN 1
#define CONFIG_SYS_NUM_FM1_DTSEC 5
#define CONFIG_SYS_NUM_FM1_10GEC 1
@@ -449,6 +453,7 @@
#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
@@ -472,7 +477,6 @@
#define CONFIG_SYS_FSL_ERRATUM_DDR_A003
#define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
#define CONFIG_SYS_FSL_ERRATUM_A004699
-#define CONFIG_SYS_FSL_ELBC_MULTIBIT_ECC
#define CONFIG_SYS_FSL_ERRATUM_A004510
#define CONFIG_SYS_FSL_ERRATUM_A004510_SVR_REV 0x10
#define CONFIG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
diff --git a/arch/powerpc/include/asm/immap_83xx.h b/arch/powerpc/include/asm/immap_83xx.h
index 679832cd6c..8ac13fc05c 100644
--- a/arch/powerpc/include/asm/immap_83xx.h
+++ b/arch/powerpc/include/asm/immap_83xx.h
@@ -1035,9 +1035,9 @@ typedef struct immap {
} immap_t;
#endif
-#define CONFIG_SYS_MPC83xx_DDR_OFFSET (0x2000)
-#define CONFIG_SYS_MPC83xx_DDR_ADDR \
- (CONFIG_SYS_IMMR + CONFIG_SYS_MPC83xx_DDR_OFFSET)
+#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)
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
index 969f726c36..296b549779 100644
--- a/arch/powerpc/include/asm/immap_85xx.h
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -2619,7 +2619,7 @@ typedef struct serdes_corenet {
#define SRDS_PCCR2_RST_XGMII1 0x00800000
#define SRDS_PCCR2_RST_XGMII2 0x00400000
u32 res5[197];
- struct {
+ struct serdes_lane {
u32 gcr0; /* General Control Register 0 */
#define SRDS_GCR0_RRST 0x00400000
#define SRDS_GCR0_1STLANE 0x00010000
@@ -2637,8 +2637,11 @@ typedef struct serdes_corenet {
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];
@@ -2867,9 +2870,9 @@ struct ccsr_pman {
#define CONFIG_SYS_FSL_CORENET_PMAN2_OFFSET 0x5000
#define CONFIG_SYS_FSL_CORENET_PMAN3_OFFSET 0x6000
#endif
-#define CONFIG_SYS_MPC85xx_DDR_OFFSET 0x8000
-#define CONFIG_SYS_MPC85xx_DDR2_OFFSET 0x9000
-#define CONFIG_SYS_MPC85xx_DDR3_OFFSET 0xA000
+#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
@@ -2929,9 +2932,9 @@ struct ccsr_pman {
#define CONFIG_SYS_FSL_CLUSTER_1_L2_OFFSET 0xC20000
#else
#define CONFIG_SYS_MPC85xx_ECM_OFFSET 0x0000
-#define CONFIG_SYS_MPC85xx_DDR_OFFSET 0x2000
+#define CONFIG_SYS_MPC8xxx_DDR_OFFSET 0x2000
#define CONFIG_SYS_MPC85xx_LBC_OFFSET 0x5000
-#define CONFIG_SYS_MPC85xx_DDR2_OFFSET 0x6000
+#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
@@ -2998,12 +3001,12 @@ struct ccsr_pman {
(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_MPC85xx_DDR_ADDR \
- (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR_OFFSET)
-#define CONFIG_SYS_MPC85xx_DDR2_ADDR \
- (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR2_OFFSET)
-#define CONFIG_SYS_MPC85xx_DDR3_ADDR \
- (CONFIG_SYS_IMMR + CONFIG_SYS_MPC85xx_DDR3_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 \
diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/immap_86xx.h
index cc338e4739..2a704fe6b7 100644
--- a/arch/powerpc/include/asm/immap_86xx.h
+++ b/arch/powerpc/include/asm/immap_86xx.h
@@ -1252,10 +1252,10 @@ typedef struct immap {
extern immap_t *immr;
-#define CONFIG_SYS_MPC86xx_DDR_OFFSET 0x2000
-#define CONFIG_SYS_MPC86xx_DDR_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_DDR_OFFSET)
-#define CONFIG_SYS_MPC86xx_DDR2_OFFSET 0x6000
-#define CONFIG_SYS_MPC86xx_DDR2_ADDR (CONFIG_SYS_IMMR + CONFIG_SYS_MPC86xx_DDR2_OFFSET)
+#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
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 7aa3231ad4..19fe250305 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -1342,4 +1342,10 @@ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
#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/board/chromebook-x86/coreboot/coreboot_pci.c b/arch/powerpc/include/asm/spl.h
index 732ca3ceaf..f43bc23c92 100644
--- a/board/chromebook-x86/coreboot/coreboot_pci.c
+++ b/arch/powerpc/include/asm/spl.h
@@ -1,10 +1,6 @@
/*
- * Copyright (c) 2011 The Chromium OS Authors.
- * (C) Copyright 2008,2009
- * Graeme Russ, <graeme.russ@gmail.com>
- *
- * (C) Copyright 2002
- * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ * (C) Copyright 2012
+ * Texas Instruments, <www.ti.com>
*
* See file CREDITS for list of people who contributed to this
* project.
@@ -16,7 +12,7 @@
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
@@ -24,7 +20,12 @@
* 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__[];
-void pci_init_board(void)
-{
-}
+#endif
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 808021c42e..844fe8636d 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -38,13 +38,28 @@ endif
LIB = $(obj)lib$(ARCH).o
-SOBJS-y += ppccache.o
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+COBJS-y += cache.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
COBJS-y += board.o
+endif
COBJS-y += bootm.o
COBJS-y += cache.o
COBJS-y += extable.o
@@ -53,6 +68,11 @@ 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
@@ -63,6 +83,13 @@ 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))
@@ -75,12 +102,6 @@ TARGETS += $(LIB)
all: $(TARGETS)
$(LIB): $(obj).depend $(OBJS)
- @if ! $(CROSS_COMPILE)readelf -S $(OBJS) | grep -q '\.fixup.*PROGBITS';\
- then \
- echo "ERROR: Your compiler doesn't generate .fixup sections!";\
- echo " Upgrade to a recent toolchain."; \
- exit 1; \
- fi;
$(call cmd_link_o_target, $(OBJS))
$(LIBGCC): $(obj).depend $(LGOBJS)
diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c
index ac5bd6d4f1..7088293a36 100644
--- a/arch/powerpc/lib/bootm.c
+++ b/arch/powerpc/lib/bootm.c
@@ -87,12 +87,6 @@ static void boot_jump_linux(bootm_headers_t *images)
* r8: 0
* r9: 0
*/
-#if defined(CONFIG_MPC85xx) || defined(CONFIG_440)
- #define EPAPR_MAGIC (0x45504150)
-#else
- #define EPAPR_MAGIC (0x65504150)
-#endif
-
debug (" Booting using OF flat tree...\n");
WATCHDOG_RESET ();
(*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
diff --git a/arch/powerpc/lib/spl.c b/arch/powerpc/lib/spl.c
new file mode 100644
index 0000000000..502c93bebe
--- /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/sh/include/asm/system.h b/arch/sh/include/asm/system.h
index 56fd77acea..24b5ce8e30 100644
--- a/arch/sh/include/asm/system.h
+++ b/arch/sh/include/asm/system.h
@@ -274,8 +274,8 @@ void enable_hlt(void);
static inline void trigger_address_error(void)
{
+ set_bl_bit();
__asm__ __volatile__ (
- "ldc %0, sr\n\t"
"mov.l @%1, %0"
:
: "r" (0x10000000), "r" (0x80000001)
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 7f1fc188cb..57324b6174 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -28,12 +28,13 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(CPU).o
-START = start.o start16.o resetvec.o
-COBJS = interrupts.o cpu.o
+START-y = start.o
+RESET_OBJS-$(CONFIG_X86_NO_RESET_VECTOR) += resetvec.o start16.o
+COBJS = interrupts.o cpu.o timer.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
-START := $(addprefix $(obj),$(START))
+START := $(addprefix $(obj),$(START-y) $(RESET_OBJS-))
all: $(obj).depend $(START) $(LIB)
diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile
index 13f5f8a2f0..b1d3e959f8 100644
--- a/arch/x86/cpu/coreboot/Makefile
+++ b/arch/x86/cpu/coreboot/Makefile
@@ -33,12 +33,13 @@ include $(TOPDIR)/config.mk
LIB := $(obj)lib$(SOC).o
+SOBJS-$(CONFIG_SYS_COREBOOT) += car.o
+COBJS-$(CONFIG_SYS_COREBOOT) += coreboot.o
COBJS-$(CONFIG_SYS_COREBOOT) += tables.o
COBJS-$(CONFIG_SYS_COREBOOT) += ipchecksum.o
COBJS-$(CONFIG_SYS_COREBOOT) += sdram.o
-COBJS-$(CONFIG_SYS_COREBOOT) += sysinfo.o
-
-SOBJS-$(CONFIG_SYS_COREBOOT) += coreboot_car.o
+COBJS-$(CONFIG_SYS_COREBOOT) += timestamp.o
+COBJS-$(CONFIG_PCI) += pci.o
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
diff --git a/arch/x86/cpu/coreboot/coreboot_car.S b/arch/x86/cpu/coreboot/car.S
index 3cc25755fd..3cc25755fd 100644
--- a/arch/x86/cpu/coreboot/coreboot_car.S
+++ b/arch/x86/cpu/coreboot/car.S
diff --git a/board/BuS/eb_cpu5282/config.mk b/arch/x86/cpu/coreboot/config.mk
index 18fb84eb3b..4858fc3728 100644
--- a/board/BuS/eb_cpu5282/config.mk
+++ b/arch/x86/cpu/coreboot/config.mk
@@ -1,7 +1,5 @@
#
-# (C) Copyright 2000-2003
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-# Coldfire contribution by Bernhard Kuhn <bkuhn@metrowerks.com>
+# Copyright (c) 2012 The Chromium OS Authors.
#
# See file CREDITS for list of people who contributed to this
# project.
@@ -22,6 +20,4 @@
# MA 02111-1307 USA
#
-ifndef CONFIG_SYS_TEXT_BASE
-CONFIG_SYS_TEXT_BASE = 0xFE000000
-endif
+CONFIG_ARCH_DEVICE_TREE := coreboot
diff --git a/board/chromebook-x86/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c
index 22a643c9d6..9c9431e0d9 100644
--- a/board/chromebook-x86/coreboot/coreboot.c
+++ b/arch/x86/cpu/coreboot/coreboot.c
@@ -26,13 +26,15 @@
#include <asm/u-boot-x86.h>
#include <flash.h>
#include <netdev.h>
+#include <asm/msr.h>
+#include <asm/cache.h>
+#include <asm/io.h>
#include <asm/arch-coreboot/tables.h>
#include <asm/arch-coreboot/sysinfo.h>
+#include <asm/arch/timestamp.h>
DECLARE_GLOBAL_DATA_PTR;
-unsigned long monitor_flash_len = CONFIG_SYS_MONITOR_LEN;
-
/*
* Miscellaneous platform dependent initializations
*/
@@ -41,6 +43,9 @@ int cpu_init_f(void)
int ret = get_coreboot_info(&lib_sysinfo);
if (ret != 0)
printf("Failed to parse coreboot tables.\n");
+
+ timestamp_init();
+
return ret;
}
@@ -62,8 +67,29 @@ int board_early_init_r(void)
void show_boot_progress(int val)
{
-}
+#if MIN_PORT80_KCLOCKS_DELAY
+ static uint32_t prev_stamp;
+ static uint32_t base;
+
+ /*
+ * Scale the time counter reading to avoid using 64 bit arithmetics.
+ * Can't use get_timer() here becuase it could be not yet
+ * initialized or even implemented.
+ */
+ if (!prev_stamp) {
+ base = rdtsc() / 1000;
+ prev_stamp = 0;
+ } else {
+ uint32_t now;
+ do {
+ now = rdtsc() / 1000 - base;
+ } while (now < (prev_stamp + MIN_PORT80_KCLOCKS_DELAY));
+ prev_stamp = now;
+ }
+#endif
+ outb(val, 0x80);
+}
int last_stage_init(void)
{
@@ -82,6 +108,33 @@ int board_eth_init(bd_t *bis)
return pci_eth_init(bis);
}
-void setup_pcat_compatibility()
+#define MTRR_TYPE_WP 5
+#define MTRRcap_MSR 0xfe
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+int board_final_cleanup(void)
{
+ /* Un-cache the ROM so the kernel has one
+ * more MTRR available.
+ *
+ * Coreboot should have assigned this to the
+ * top available variable MTRR.
+ */
+ u8 top_mtrr = (native_read_msr(MTRRcap_MSR) & 0xff) - 1;
+ u8 top_type = native_read_msr(MTRRphysBase_MSR(top_mtrr)) & 0xff;
+
+ /* Make sure this MTRR is the correct Write-Protected type */
+ if (top_type == MTRR_TYPE_WP) {
+ disable_caches();
+ wrmsrl(MTRRphysBase_MSR(top_mtrr), 0);
+ wrmsrl(MTRRphysMask_MSR(top_mtrr), 0);
+ enable_caches();
+ }
+
+ /* Issue SMI to Coreboot to lock down ME and registers */
+ printf("Finalizing Coreboot\n");
+ outb(0xcb, 0xb2);
+
+ return 0;
}
diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c
new file mode 100644
index 0000000000..8f94167480
--- /dev/null
+++ b/arch/x86/cpu/coreboot/pci.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2008,2009
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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>
+#include <asm/pci.h>
+
+static struct pci_controller coreboot_hose;
+
+static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev,
+ struct pci_config_table *table)
+{
+ u8 secondary;
+ hose->read_byte(hose, dev, PCI_SECONDARY_BUS, &secondary);
+ hose->last_busno = max(hose->last_busno, secondary);
+ pci_hose_scan_bus(hose, secondary);
+}
+
+static struct pci_config_table pci_coreboot_config_table[] = {
+ /* vendor, device, class, bus, dev, func */
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_BRIDGE_PCI,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, &config_pci_bridge },
+ {}
+};
+
+void pci_init_board(void)
+{
+ coreboot_hose.config_table = pci_coreboot_config_table;
+ coreboot_hose.first_busno = 0;
+ coreboot_hose.last_busno = 0;
+
+ pci_set_region(coreboot_hose.regions + 0, 0x0, 0x0, 0xffffffff,
+ PCI_REGION_MEM);
+ coreboot_hose.region_count = 1;
+
+ pci_setup_type1(&coreboot_hose);
+
+ pci_register_hose(&coreboot_hose);
+
+ pci_hose_scan(&coreboot_hose);
+}
diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c
index f8fdac6319..76274cb88e 100644
--- a/arch/x86/cpu/coreboot/sdram.c
+++ b/arch/x86/cpu/coreboot/sdram.c
@@ -27,8 +27,9 @@
#include <asm/e820.h>
#include <asm/u-boot-x86.h>
#include <asm/global_data.h>
-#include <asm/arch-coreboot/sysinfo.h>
-#include <asm/arch-coreboot/tables.h>
+#include <asm/processor.h>
+#include <asm/arch/sysinfo.h>
+#include <asm/arch/tables.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -51,6 +52,58 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
return num_entries;
}
+/*
+ * This function looks for the highest region of memory lower than 4GB which
+ * has enough space for U-Boot where U-Boot is aligned on a page boundary. It
+ * overrides the default implementation found elsewhere which simply picks the
+ * end of ram, wherever that may be. The location of the stack, the relocation
+ * address, and how far U-Boot is moved by relocation are set in the global
+ * data structure.
+ */
+int calculate_relocation_address(void)
+{
+ const uint64_t uboot_size = (uintptr_t)&__bss_end -
+ (uintptr_t)&__text_start;
+ const uint64_t total_size = uboot_size + CONFIG_SYS_MALLOC_LEN +
+ CONFIG_SYS_STACK_SIZE;
+ uintptr_t dest_addr = 0;
+ int i;
+
+ for (i = 0; i < lib_sysinfo.n_memranges; i++) {
+ struct memrange *memrange = &lib_sysinfo.memrange[i];
+ /* Force U-Boot to relocate to a page aligned address. */
+ uint64_t start = roundup(memrange->base, 1 << 12);
+ uint64_t end = memrange->base + memrange->size;
+
+ /* Ignore non-memory regions. */
+ if (memrange->type != CB_MEM_RAM)
+ continue;
+
+ /* Filter memory over 4GB. */
+ if (end > 0xffffffffULL)
+ end = 0x100000000ULL;
+ /* Skip this region if it's too small. */
+ if (end - start < total_size)
+ continue;
+
+ /* Use this address if it's the largest so far. */
+ if (end - uboot_size > dest_addr)
+ dest_addr = end;
+ }
+
+ /* If no suitable area was found, return an error. */
+ if (!dest_addr)
+ return 1;
+
+ dest_addr -= uboot_size;
+ dest_addr &= ~((1 << 12) - 1);
+ gd->relocaddr = dest_addr;
+ gd->reloc_off = dest_addr - (uintptr_t)&__text_start;
+ gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN;
+
+ return 0;
+}
+
int dram_init_f(void)
{
int i;
@@ -71,5 +124,20 @@ int dram_init_f(void)
int dram_init(void)
{
+ int i, j;
+
+ if (CONFIG_NR_DRAM_BANKS) {
+ for (i = 0, j = 0; i < lib_sysinfo.n_memranges; i++) {
+ struct memrange *memrange = &lib_sysinfo.memrange[i];
+
+ if (memrange->type == CB_MEM_RAM) {
+ gd->bd->bi_dram[j].start = memrange->base;
+ gd->bd->bi_dram[j].size = memrange->size;
+ j++;
+ if (j >= CONFIG_NR_DRAM_BANKS)
+ break;
+ }
+ }
+ }
return 0;
}
diff --git a/arch/x86/cpu/coreboot/sysinfo.c b/arch/x86/cpu/coreboot/sysinfo.c
deleted file mode 100644
index 9b3e660dde..0000000000
--- a/arch/x86/cpu/coreboot/sysinfo.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * This file is part of the libpayload project.
- *
- * Copyright (C) 2008 Advanced Micro Devices, Inc.
- * Copyright (C) 2009 coresystems GmbH
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <asm/arch-coreboot/sysinfo.h>
-
-/*
- * This needs to be in the .data section so that it's copied over during
- * relocation. By default it's put in the .bss section which is simply filled
- * with zeroes when transitioning from "ROM", which is really RAM, to other
- * RAM.
- */
-struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c
index 0e3451bb22..b116d59555 100644
--- a/arch/x86/cpu/coreboot/tables.c
+++ b/arch/x86/cpu/coreboot/tables.c
@@ -28,11 +28,20 @@
* SUCH DAMAGE.
*/
+#include <common.h>
#include <asm/arch-coreboot/ipchecksum.h>
#include <asm/arch-coreboot/sysinfo.h>
#include <asm/arch-coreboot/tables.h>
/*
+ * This needs to be in the .data section so that it's copied over during
+ * relocation. By default it's put in the .bss section which is simply filled
+ * with zeroes when transitioning from "ROM", which is really RAM, to other
+ * RAM.
+ */
+struct sysinfo_t lib_sysinfo __attribute__((section(".data")));
+
+/*
* Some of this is x86 specific, and the rest of it is generic. Right now,
* since we only support x86, we'll avoid trying to make lots of infrastructure
* we don't need. If in the future, we want to use coreboot on some other
@@ -72,22 +81,45 @@ static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info)
static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info)
{
struct cb_serial *ser = (struct cb_serial *)ptr;
- if (ser->type != CB_SERIAL_TYPE_IO_MAPPED)
- return;
- info->ser_ioport = ser->baseaddr;
+ info->serial = ser;
}
-static void cb_parse_optiontable(unsigned char *ptr, struct sysinfo_t *info)
+static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info)
{
- info->option_table = (struct cb_cmos_option_table *)ptr;
+ struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr;
+
+ info->vbnv_start = vbnv->vbnv_start;
+ info->vbnv_size = vbnv->vbnv_size;
}
-static void cb_parse_checksum(unsigned char *ptr, struct sysinfo_t *info)
+static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
{
- struct cb_cmos_checksum *cmos_cksum = (struct cb_cmos_checksum *)ptr;
- info->cmos_range_start = cmos_cksum->range_start;
- info->cmos_range_end = cmos_cksum->range_end;
- info->cmos_checksum_location = cmos_cksum->location;
+ int i;
+ struct cb_gpios *gpios = (struct cb_gpios *)ptr;
+
+ info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ?
+ (gpios->count) : SYSINFO_MAX_GPIOS;
+
+ for (i = 0; i < info->num_gpios; i++)
+ info->gpios[i] = gpios->gpios[i];
+}
+
+static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info)
+{
+ struct cb_vdat *vdat = (struct cb_vdat *) ptr;
+
+ info->vdat_addr = vdat->vdat_addr;
+ info->vdat_size = vdat->vdat_size;
+}
+
+static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info)
+{
+ info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
+}
+
+static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info)
+{
+ info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab;
}
static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info)
@@ -95,6 +127,11 @@ static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info)
info->framebuffer = (struct cb_framebuffer *)ptr;
}
+static void cb_parse_string(unsigned char *ptr, char **info)
+{
+ *info = (char *)((struct cb_string *)ptr)->string;
+}
+
static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
{
struct cb_header *header;
@@ -125,6 +162,9 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
/* Now, walk the tables. */
ptr += header->header_bytes;
+ /* Inintialize some fields to sentinel values. */
+ info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
+
for (i = 0; i < header->table_entries; i++) {
struct cb_record *rec = (struct cb_record *)ptr;
@@ -142,11 +182,35 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
case CB_TAG_SERIAL:
cb_parse_serial(ptr, info);
break;
- case CB_TAG_CMOS_OPTION_TABLE:
- cb_parse_optiontable(ptr, info);
+ case CB_TAG_VERSION:
+ cb_parse_string(ptr, &info->version);
+ break;
+ case CB_TAG_EXTRA_VERSION:
+ cb_parse_string(ptr, &info->extra_version);
+ break;
+ case CB_TAG_BUILD:
+ cb_parse_string(ptr, &info->build);
+ break;
+ case CB_TAG_COMPILE_TIME:
+ cb_parse_string(ptr, &info->compile_time);
+ break;
+ case CB_TAG_COMPILE_BY:
+ cb_parse_string(ptr, &info->compile_by);
+ break;
+ case CB_TAG_COMPILE_HOST:
+ cb_parse_string(ptr, &info->compile_host);
+ break;
+ case CB_TAG_COMPILE_DOMAIN:
+ cb_parse_string(ptr, &info->compile_domain);
+ break;
+ case CB_TAG_COMPILER:
+ cb_parse_string(ptr, &info->compiler);
break;
- case CB_TAG_OPTION_CHECKSUM:
- cb_parse_checksum(ptr, info);
+ case CB_TAG_LINKER:
+ cb_parse_string(ptr, &info->linker);
+ break;
+ case CB_TAG_ASSEMBLER:
+ cb_parse_string(ptr, &info->assembler);
break;
/*
* FIXME we should warn on serial if coreboot set up a
@@ -155,6 +219,21 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
case CB_TAG_FRAMEBUFFER:
cb_parse_framebuffer(ptr, info);
break;
+ case CB_TAG_GPIO:
+ cb_parse_gpios(ptr, info);
+ break;
+ case CB_TAG_VDAT:
+ cb_parse_vdat(ptr, info);
+ break;
+ case CB_TAG_TIMESTAMPS:
+ cb_parse_tstamp(ptr, info);
+ break;
+ case CB_TAG_CBMEM_CONSOLE:
+ cb_parse_cbmem_cons(ptr, info);
+ break;
+ case CB_TAG_VBNV:
+ cb_parse_vbnv(ptr, info);
+ break;
}
ptr += rec->size;
@@ -166,18 +245,12 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info)
/* == Architecture specific == */
/* This is the x86 specific stuff. */
-/* Assume no translation or that memory is identity mapped. */
-static void *phys_to_virt(unsigned long virt)
-{
- return (void *)(uintptr_t)virt;
-}
-
int get_coreboot_info(struct sysinfo_t *info)
{
- int ret = cb_parse_header(phys_to_virt(0x00000000), 0x1000, info);
+ int ret = cb_parse_header((void *)0x00000000, 0x1000, info);
if (ret != 1)
- ret = cb_parse_header(phys_to_virt(0x000f0000), 0x1000, info);
+ ret = cb_parse_header((void *)0x000f0000, 0x1000, info);
return (ret == 1) ? 0 : -1;
}
diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c
new file mode 100644
index 0000000000..2ca7a57bce
--- /dev/null
+++ b/arch/x86/cpu/coreboot/timestamp.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include <common.h>
+#include <asm/arch/timestamp.h>
+#include <asm/arch/sysinfo.h>
+#include <linux/compiler.h>
+
+struct timestamp_entry {
+ uint32_t entry_id;
+ uint64_t entry_stamp;
+} __packed;
+
+struct timestamp_table {
+ uint64_t base_time;
+ uint32_t max_entries;
+ uint32_t num_entries;
+ struct timestamp_entry entries[0]; /* Variable number of entries */
+} __packed;
+
+static struct timestamp_table *ts_table __attribute__((section(".data")));
+
+void timestamp_init(void)
+{
+ ts_table = lib_sysinfo.tstamp_table;
+ timer_set_tsc_base(ts_table->base_time);
+ timestamp_add_now(TS_U_BOOT_INITTED);
+}
+
+void timestamp_add(enum timestamp_id id, uint64_t ts_time)
+{
+ struct timestamp_entry *tse;
+
+ if (!ts_table || (ts_table->num_entries == ts_table->max_entries))
+ return;
+
+ tse = &ts_table->entries[ts_table->num_entries++];
+ tse->entry_id = id;
+ tse->entry_stamp = ts_time - ts_table->base_time;
+}
+
+void timestamp_add_now(enum timestamp_id id)
+{
+ timestamp_add(id, rdtsc());
+}
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index e9bb0d770a..315e87afeb 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -34,6 +34,7 @@
#include <common.h>
#include <command.h>
+#include <asm/control_regs.h>
#include <asm/processor.h>
#include <asm/processor-flags.h>
#include <asm/interrupt.h>
@@ -90,12 +91,6 @@ static void load_gdt(const u64 *boot_gdt, u16 num_entries)
asm volatile("lgdtl %0\n" : : "m" (gdt));
}
-void init_gd(gd_t *id, u64 *gdt_addr)
-{
- id->gd_addr = (ulong)id;
- setup_gdt(id, gdt_addr);
-}
-
void setup_gdt(gd_t *id, u64 *gdt_addr)
{
/* CS: code, read/execute, 4 GB, base 0 */
@@ -121,6 +116,11 @@ void setup_gdt(gd_t *id, u64 *gdt_addr)
load_fs(X86_GDT_ENTRY_32BIT_FS);
}
+int __weak x86_cleanup_before_linux(void)
+{
+ return 0;
+}
+
int x86_cpu_init_f(void)
{
const u32 em_rst = ~X86_CR0_EM;
@@ -148,16 +148,27 @@ int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r")));
void x86_enable_caches(void)
{
- const u32 nw_cd_rst = ~(X86_CR0_NW | X86_CR0_CD);
+ unsigned long cr0;
- /* turn on the cache and disable write through */
- asm("movl %%cr0, %%eax\n"
- "andl %0, %%eax\n"
- "movl %%eax, %%cr0\n"
- "wbinvd\n" : : "i" (nw_cd_rst) : "eax");
+ cr0 = read_cr0();
+ cr0 &= ~(X86_CR0_NW | X86_CR0_CD);
+ write_cr0(cr0);
+ wbinvd();
}
void enable_caches(void) __attribute__((weak, alias("x86_enable_caches")));
+void x86_disable_caches(void)
+{
+ unsigned long cr0;
+
+ cr0 = read_cr0();
+ cr0 |= X86_CR0_NW | X86_CR0_CD;
+ wbinvd();
+ write_cr0(cr0);
+ wbinvd();
+}
+void disable_caches(void) __attribute__((weak, alias("x86_disable_caches")));
+
int x86_init_cache(void)
{
enable_caches();
@@ -201,3 +212,17 @@ void __reset_cpu(ulong addr)
generate_gpf(); /* start the show */
}
void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu")));
+
+int dcache_status(void)
+{
+ return !(read_cr0() & 0x40000000);
+}
+
+/* Define these functions to allow ehch-hcd to function */
+void flush_dcache_range(unsigned long start, unsigned long stop)
+{
+}
+
+void invalidate_dcache_range(unsigned long start, unsigned long stop)
+{
+}
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
index 43ec3f8b08..dd30a05a9d 100644
--- a/arch/x86/cpu/interrupts.c
+++ b/arch/x86/cpu/interrupts.c
@@ -28,10 +28,14 @@
*/
#include <common.h>
+#include <asm/cache.h>
+#include <asm/control_regs.h>
#include <asm/interrupt.h>
#include <asm/io.h>
#include <asm/processor-flags.h>
#include <linux/compiler.h>
+#include <asm/msr.h>
+#include <asm/u-boot-x86.h>
#define DECLARE_INTERRUPT(x) \
".globl irq_"#x"\n" \
@@ -41,72 +45,6 @@
"pushl $"#x"\n" \
"jmp irq_common_entry\n"
-/*
- * Volatile isn't enough to prevent the compiler from reordering the
- * read/write functions for the control registers and messing everything up.
- * A memory clobber would solve the problem, but would prevent reordering of
- * all loads stores around it, which can hurt performance. Solution is to
- * use a variable and mimic reads and writes to it to enforce serialisation
- */
-static unsigned long __force_order;
-
-static inline unsigned long read_cr0(void)
-{
- unsigned long val;
- asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
- return val;
-}
-
-static inline unsigned long read_cr2(void)
-{
- unsigned long val;
- asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
- return val;
-}
-
-static inline unsigned long read_cr3(void)
-{
- unsigned long val;
- asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
- return val;
-}
-
-static inline unsigned long read_cr4(void)
-{
- unsigned long val;
- asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
- return val;
-}
-
-static inline unsigned long get_debugreg(int regno)
-{
- unsigned long val = 0; /* Damn you, gcc! */
-
- switch (regno) {
- case 0:
- asm("mov %%db0, %0" : "=r" (val));
- break;
- case 1:
- asm("mov %%db1, %0" : "=r" (val));
- break;
- case 2:
- asm("mov %%db2, %0" : "=r" (val));
- break;
- case 3:
- asm("mov %%db3, %0" : "=r" (val));
- break;
- case 6:
- asm("mov %%db6, %0" : "=r" (val));
- break;
- case 7:
- asm("mov %%db7, %0" : "=r" (val));
- break;
- default:
- val = 0;
- }
- return val;
-}
-
void dump_regs(struct irq_regs *regs)
{
unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
@@ -679,3 +617,32 @@ asm(".globl irq_common_entry\n" \
DECLARE_INTERRUPT(253) \
DECLARE_INTERRUPT(254) \
DECLARE_INTERRUPT(255));
+
+#if defined(CONFIG_INTEL_CORE_ARCH)
+/*
+ * Get the number of CPU time counter ticks since it was read first time after
+ * restart. This yields a free running counter guaranteed to take almost 6
+ * years to wrap around even at 100GHz clock rate.
+ */
+u64 get_ticks(void)
+{
+ static u64 tick_base;
+ u64 now_tick = rdtsc();
+
+ if (!tick_base)
+ tick_base = now_tick;
+
+ return now_tick - tick_base;
+}
+
+#define PLATFORM_INFO_MSR 0xce
+
+unsigned long get_tbclk(void)
+{
+ u32 ratio;
+ u64 platform_info = native_read_msr(PLATFORM_INFO_MSR);
+
+ ratio = (platform_info >> 8) & 0xff;
+ return 100 * 1000 * 1000 * ratio; /* 100MHz times Max Non Turbo ratio */
+}
+#endif
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index ee0dabe4bc..e960e21f6e 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -55,8 +55,16 @@ _x86boot_start:
movl %eax, %cr0
wbinvd
+ /* Tell 32-bit code it is being entered from an in-RAM copy */
+ movw $GD_FLG_WARM_BOOT, %bx
+ jmp 1f
_start:
- /* This is the 32-bit cold-reset entry point */
+ /*
+ * This is the 32-bit cold-reset entry point. Initialize %bx to 0
+ * in case we're preceeded by some sort of boot stub.
+ */
+ movw $GD_FLG_COLD_BOOT, %bx
+1:
/* Load the segement registes to match the gdt loaded in start16.S */
movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax
@@ -83,13 +91,33 @@ car_init_ret:
* or fully initialised SDRAM - we really don't care which)
* starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
*/
- movl $CONFIG_SYS_INIT_SP_ADDR, %esp
- /* Initialise the Global Data Pointer */
- movl $CONFIG_SYS_INIT_GD_ADDR, %eax
- movl %eax, %edx
- addl $GENERATED_GBL_DATA_SIZE, %edx
- call init_gd;
+ /* Stack grows down from top of CAR */
+ movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE), %esp
+
+ /* Reserve space on stack for global data */
+ subl $GENERATED_GBL_DATA_SIZE, %esp
+
+ /* Align global data to 16-byte boundary */
+ andl $0xfffffff0, %esp
+
+ /* Setup first parameter to setup_gdt */
+ movl %esp, %eax
+
+ /* Reserve space for global descriptor table */
+ subl $X86_GDT_SIZE, %esp
+
+ /* Align temporary global descriptor table to 16-byte boundary */
+ andl $0xfffffff0, %esp
+
+ /* Set second parameter to setup_gdt */
+ movl %esp, %edx
+
+ /* gd->gd_addr = gd (Required to allow gd->xyz to work) */
+ movl %eax, (%eax)
+
+ /* Setup global descriptor table so gd->xyz works */
+ call setup_gdt
/* Set parameter to board_init_f() to boot flags */
xorl %eax, %eax
@@ -113,9 +141,42 @@ board_init_f_r_trampoline:
* %eax = Address of top of new stack
*/
- /* Setup stack in RAM */
+ /* Stack grows down from top of SDRAM */
movl %eax, %esp
+ /* Reserve space on stack for global data */
+ subl $GENERATED_GBL_DATA_SIZE, %esp
+
+ /* Align global data to 16-byte boundary */
+ andl $0xfffffff0, %esp
+
+ /* Setup first parameter to memcpy (and setup_gdt) */
+ movl %esp, %eax
+
+ /* Setup second parameter to memcpy */
+ fs movl 0, %edx
+
+ /* Set third parameter to memcpy */
+ movl $GENERATED_GBL_DATA_SIZE, %ecx
+
+ /* Copy global data from CAR to SDRAM stack */
+ call memcpy
+
+ /* Reserve space for global descriptor table */
+ subl $X86_GDT_SIZE, %esp
+
+ /* Align global descriptor table to 16-byte boundary */
+ andl $0xfffffff0, %esp
+
+ /* Set second parameter to setup_gdt */
+ movl %esp, %edx
+
+ /* gd->gd_addr = gd (Required to allow gd->xyz to work) */
+ movl %eax, (%eax)
+
+ /* Setup global descriptor table so gd->xyz works */
+ call setup_gdt
+
/* Re-enter U-Boot by calling board_init_f_r */
call board_init_f_r
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S
index cc393ff54f..603bf1d2d3 100644
--- a/arch/x86/cpu/start16.S
+++ b/arch/x86/cpu/start16.S
@@ -37,6 +37,9 @@
.code16
.globl start16
start16:
+ /* Set the Cold Boot / Hard Reset flag */
+ movl $GD_FLG_COLD_BOOT, %ebx
+
/*
* First we let the BSP do some early initialization
* this code have to map the flash to its final position
diff --git a/arch/x86/cpu/timer.c b/arch/x86/cpu/timer.c
new file mode 100644
index 0000000000..149109d4f4
--- /dev/null
+++ b/arch/x86/cpu/timer.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#include <common.h>
+
+unsigned long timer_get_us(void)
+{
+ printf("timer_get_us used but not implemented.\n");
+ return 0;
+}
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds
index a1ecefafc6..0c6f0e31d8 100644
--- a/arch/x86/cpu/u-boot.lds
+++ b/arch/x86/cpu/u-boot.lds
@@ -86,6 +86,8 @@ SECTIONS
__bios_start = LOADADDR(.bios);
__bios_size = SIZEOF(.bios);
+#ifndef CONFIG_X86_NO_RESET_VECTOR
+
/*
* The following expressions place the 16-bit Real-Mode code and
* Reset Vector at the end of the Flash ROM
@@ -95,4 +97,5 @@ SECTIONS
. = RESET_VEC_LOC;
.resetvec : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + RESET_VEC_LOC)) { KEEP(*(.resetvec)); }
+#endif
}
diff --git a/arch/x86/dts/coreboot.dtsi b/arch/x86/dts/coreboot.dtsi
new file mode 100644
index 0000000000..4862a59704
--- /dev/null
+++ b/arch/x86/dts/coreboot.dtsi
@@ -0,0 +1,16 @@
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ console = "/serial";
+ };
+
+ serial {
+ compatible = "ns16550";
+ reg-shift = <1>;
+ io-mapped = <1>;
+ multiplier = <1>;
+ baudrate = <115200>;
+ status = "disabled";
+ };
+};
diff --git a/arch/x86/dts/skeleton.dtsi b/arch/x86/dts/skeleton.dtsi
new file mode 100644
index 0000000000..b41d241de2
--- /dev/null
+++ b/arch/x86/dts/skeleton.dtsi
@@ -0,0 +1,13 @@
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value. The bootloader will typically populate the memory
+ * node.
+ */
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ chosen { };
+ aliases { };
+ memory { device_type = "memory"; reg = <0 0>; };
+};
diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/arch-coreboot/sysinfo.h
index 5c44e1a47c..77ae304969 100644
--- a/arch/x86/include/asm/arch-coreboot/sysinfo.h
+++ b/arch/x86/include/asm/arch-coreboot/sysinfo.h
@@ -30,32 +30,52 @@
#ifndef _COREBOOT_SYSINFO_H
#define _COREBOOT_SYSINFO_H
+#include <common.h>
#include <compiler.h>
+#include <fdt.h>
+#include <asm/arch/tables.h>
/* Allow a maximum of 16 memory range definitions. */
#define SYSINFO_MAX_MEM_RANGES 16
+/* Allow a maximum of 8 GPIOs */
+#define SYSINFO_MAX_GPIOS 8
struct sysinfo_t {
- unsigned int cpu_khz;
- unsigned short ser_ioport;
- unsigned long ser_base; /* for mmapped serial */
-
int n_memranges;
-
struct memrange {
unsigned long long base;
unsigned long long size;
unsigned int type;
} memrange[SYSINFO_MAX_MEM_RANGES];
- struct cb_cmos_option_table *option_table;
u32 cmos_range_start;
u32 cmos_range_end;
u32 cmos_checksum_location;
+ u32 vbnv_start;
+ u32 vbnv_size;
+
+ char *version;
+ char *extra_version;
+ char *build;
+ char *compile_time;
+ char *compile_by;
+ char *compile_host;
+ char *compile_domain;
+ char *compiler;
+ char *linker;
+ char *assembler;
struct cb_framebuffer *framebuffer;
- unsigned long *mbtable; /** Pointer to the multiboot table */
+ int num_gpios;
+ struct cb_gpio gpios[SYSINFO_MAX_GPIOS];
+
+ void *vdat_addr;
+ u32 vdat_size;
+ void *tstamp_table;
+ void *cbmem_cons;
+
+ struct cb_serial *serial;
};
extern struct sysinfo_t lib_sysinfo;
diff --git a/arch/x86/include/asm/arch-coreboot/tables.h b/arch/x86/include/asm/arch-coreboot/tables.h
index c28697375f..ad34a8b0f1 100644
--- a/arch/x86/include/asm/arch-coreboot/tables.h
+++ b/arch/x86/include/asm/arch-coreboot/tables.h
@@ -164,6 +164,55 @@ struct cb_framebuffer {
u8 reserved_mask_size;
};
+#define CB_TAG_GPIO 0x0013
+#define GPIO_MAX_NAME_LENGTH 16
+struct cb_gpio {
+ u32 port;
+ u32 polarity;
+ u32 value;
+ u8 name[GPIO_MAX_NAME_LENGTH];
+};
+
+struct cb_gpios {
+ u32 tag;
+ u32 size;
+
+ u32 count;
+ struct cb_gpio gpios[0];
+};
+
+#define CB_TAG_FDT 0x0014
+struct cb_fdt {
+ uint32_t tag;
+ uint32_t size; /* size of the entire entry */
+ /* the actual FDT gets placed here */
+};
+
+#define CB_TAG_VDAT 0x0015
+struct cb_vdat {
+ uint32_t tag;
+ uint32_t size; /* size of the entire entry */
+ void *vdat_addr;
+ uint32_t vdat_size;
+};
+
+#define CB_TAG_TIMESTAMPS 0x0016
+#define CB_TAG_CBMEM_CONSOLE 0x0017
+#define CB_TAG_MRC_CACHE 0x0018
+struct cb_cbmem_tab {
+ uint32_t tag;
+ uint32_t size;
+ void *cbmem_tab;
+};
+
+#define CB_TAG_VBNV 0x0019
+struct cb_vbnv {
+ uint32_t tag;
+ uint32_t size;
+ uint32_t vbnv_start;
+ uint32_t vbnv_size;
+};
+
#define CB_TAG_CMOS_OPTION_TABLE 0x00c8
struct cb_cmos_option_table {
u32 tag;
@@ -238,4 +287,29 @@ struct sysinfo_t;
int get_coreboot_info(struct sysinfo_t *info);
+#define CBMEM_TOC_RESERVED 512
+#define MAX_CBMEM_ENTRIES 16
+#define CBMEM_MAGIC 0x434f5245
+
+struct cbmem_entry {
+ u32 magic;
+ u32 id;
+ u64 base;
+ u64 size;
+} __packed;
+
+#define CBMEM_ID_FREESPACE 0x46524545
+#define CBMEM_ID_GDT 0x4c474454
+#define CBMEM_ID_ACPI 0x41435049
+#define CBMEM_ID_CBTABLE 0x43425442
+#define CBMEM_ID_PIRQ 0x49525154
+#define CBMEM_ID_MPTABLE 0x534d5054
+#define CBMEM_ID_RESUME 0x5245534d
+#define CBMEM_ID_RESUME_SCRATCH 0x52455343
+#define CBMEM_ID_SMBIOS 0x534d4254
+#define CBMEM_ID_TIMESTAMP 0x54494d45
+#define CBMEM_ID_MRCDATA 0x4d524344
+#define CBMEM_ID_CONSOLE 0x434f4e53
+#define CBMEM_ID_NONE 0x00000000
+
#endif
diff --git a/arch/x86/include/asm/arch-coreboot/timestamp.h b/arch/x86/include/asm/arch-coreboot/timestamp.h
new file mode 100644
index 0000000000..d104912e06
--- /dev/null
+++ b/arch/x86/include/asm/arch-coreboot/timestamp.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#ifndef __COREBOOT_TIMESTAMP_H__
+#define __COREBOOT_TIMESTAMP_H__
+
+enum timestamp_id {
+ /* coreboot specific timestamp IDs */
+ TS_START_ROMSTAGE = 1,
+ TS_BEFORE_INITRAM = 2,
+ TS_AFTER_INITRAM = 3,
+ TS_END_ROMSTAGE = 4,
+ TS_START_COPYRAM = 8,
+ TS_END_COPYRAM = 9,
+ TS_START_RAMSTAGE = 10,
+ TS_DEVICE_ENUMERATE = 30,
+ TS_DEVICE_CONFIGURE = 40,
+ TS_DEVICE_ENABLE = 50,
+ TS_DEVICE_INITIALIZE = 60,
+ TS_DEVICE_DONE = 70,
+ TS_CBMEM_POST = 75,
+ TS_WRITE_TABLES = 80,
+ TS_LOAD_PAYLOAD = 90,
+ TS_ACPI_WAKE_JUMP = 98,
+ TS_SELFBOOT_JUMP = 99,
+
+ /* U-Boot entry IDs start at 1000 */
+ TS_U_BOOT_INITTED = 1000, /* This is where u-boot starts */
+ TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel. */
+};
+
+void timestamp_init(void);
+void timestamp_add(enum timestamp_id id, uint64_t ts_time);
+void timestamp_add_now(enum timestamp_id id);
+
+#endif
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index c7a38f237a..5a7e4cba2b 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -351,6 +351,11 @@ static __inline__ int ffs(int x)
}
#define PLATFORM_FFS
+static inline int __ilog2(unsigned int x)
+{
+ return generic_fls(x) - 1;
+}
+
/**
* hweightN - returns the hamming weight of a N-bit word
* @x: the word to weigh
diff --git a/arch/x86/include/asm/cache.h b/arch/x86/include/asm/cache.h
index 87c9e0be42..d4678d4916 100644
--- a/arch/x86/include/asm/cache.h
+++ b/arch/x86/include/asm/cache.h
@@ -32,4 +32,20 @@
#define ARCH_DMA_MINALIGN 64
#endif
+static inline void wbinvd(void)
+{
+ asm volatile ("wbinvd" : : : "memory");
+}
+
+static inline void invd(void)
+{
+ asm volatile("invd" : : : "memory");
+}
+
+/* Enable caches and write buffer */
+void enable_caches(void);
+
+/* Disable caches and write buffer */
+void disable_caches(void);
+
#endif /* __X86_CACHE_H__ */
diff --git a/arch/x86/include/asm/control_regs.h b/arch/x86/include/asm/control_regs.h
new file mode 100644
index 0000000000..aa8be30bac
--- /dev/null
+++ b/arch/x86/include/asm/control_regs.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors.
+ *
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * Portions of this file are derived from the Linux kernel source
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * 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 __X86_CONTROL_REGS_H
+#define __X86_CONTROL_REGS_H
+
+/*
+ * The memory clobber prevents the GCC from reordering the read/write order
+ * of CR0
+*/
+static inline unsigned long read_cr0(void)
+{
+ unsigned long val;
+
+ asm volatile ("movl %%cr0, %0" : "=r" (val) : : "memory");
+ return val;
+}
+
+static inline void write_cr0(unsigned long val)
+{
+ asm volatile ("movl %0, %%cr0" : : "r" (val) : "memory");
+}
+
+static inline unsigned long read_cr2(void)
+{
+ unsigned long val;
+
+ asm volatile("mov %%cr2,%0\n\t" : "=r" (val) : : "memory");
+ return val;
+}
+
+static inline unsigned long read_cr3(void)
+{
+ unsigned long val;
+
+ asm volatile("mov %%cr3,%0\n\t" : "=r" (val) : : "memory");
+ return val;
+}
+
+static inline unsigned long read_cr4(void)
+{
+ unsigned long val;
+
+ asm volatile("mov %%cr4,%0\n\t" : "=r" (val) : : "memory");
+ return val;
+}
+
+static inline unsigned long get_debugreg(int regno)
+{
+ unsigned long val = 0; /* Damn you, gcc! */
+
+ switch (regno) {
+ case 0:
+ asm("mov %%db0, %0" : "=r" (val));
+ break;
+ case 1:
+ asm("mov %%db1, %0" : "=r" (val));
+ break;
+ case 2:
+ asm("mov %%db2, %0" : "=r" (val));
+ break;
+ case 3:
+ asm("mov %%db3, %0" : "=r" (val));
+ break;
+ case 6:
+ asm("mov %%db6, %0" : "=r" (val));
+ break;
+ case 7:
+ asm("mov %%db7, %0" : "=r" (val));
+ break;
+ default:
+ val = 0;
+ }
+ return val;
+}
+
+#endif
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index bce999f41c..dc6402b67d 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -33,9 +33,13 @@
#ifndef __ASSEMBLY__
-typedef struct global_data {
+#include <asm/u-boot.h>
+
+typedef struct global_data gd_t;
+
+struct global_data {
/* NOTE: gd_addr MUST be first member of struct global_data! */
- unsigned long gd_addr; /* Location of Global Data */
+ gd_t *gd_addr; /* Location of Global Data */
bd_t *bd;
unsigned long flags;
unsigned int baudrate;
@@ -52,12 +56,12 @@ typedef struct global_data {
unsigned long relocaddr; /* Start address of U-Boot in RAM */
unsigned long start_addr_sp; /* start_addr_stackpointer */
unsigned long gdt_addr; /* Location of GDT */
- unsigned long new_gd_addr; /* New location of Global Data */
phys_size_t ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
+ const void *fdt_blob; /* Our device tree, NULL if none */
void **jt; /* jump table */
char env_buf[32]; /* buffer for getenv() before reloc. */
-} gd_t;
+};
static inline gd_t *get_fs_gd_ptr(void)
{
@@ -74,6 +78,12 @@ static inline gd_t *get_fs_gd_ptr(void)
#include <asm-generic/global_data_flags.h>
+/*
+ * Our private Global Data Flags
+ */
+#define GD_FLG_COLD_BOOT 0x00100 /* Cold Boot */
+#define GD_FLG_WARM_BOOT 0x00200 /* Warm Boot */
+
#define DECLARE_GLOBAL_DATA_PTR
#endif /* __ASM_GBL_DATA_H */
diff --git a/arch/nios2/include/asm/status_led.h b/arch/x86/include/asm/gpio.h
index 20f8d90195..0a37a85ad1 100644
--- a/arch/nios2/include/asm/status_led.h
+++ b/arch/x86/include/asm/gpio.h
@@ -1,7 +1,5 @@
/*
- * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
- * Scott McNutt <smcnutt@psyent.com>
- *
+ * Copyright (c) 2012, Google Inc. All rights reserved.
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -20,12 +18,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
-#ifndef __ASM_STATUS_LED_H__
-#define __ASM_STATUS_LED_H__
-typedef unsigned led_id_t;
-extern void __led_init (led_id_t mask, int state);
-extern void __led_set (led_id_t mask, int state);
-inline void __led_toggle (led_id_t mask);
+#ifndef _X86_GPIO_H_
+#define _X86_GPIO_H_
+
+#include <asm-generic/gpio.h>
-#endif /* __ASM_STATUS_LED_H__ */
+#endif /* _X86_GPIO_H_ */
diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h
index 8afb443290..2f437e0343 100644
--- a/arch/x86/include/asm/init_helpers.h
+++ b/arch/x86/include/asm/init_helpers.h
@@ -29,7 +29,6 @@ int display_dram_config(void);
int init_baudrate_f(void);
int calculate_relocation_address(void);
-int copy_gd_to_ram_f_r(void);
int init_cache_f_r(void);
int set_reloc_flag_r(void);
@@ -38,5 +37,6 @@ int init_bd_struct_r(void);
int flash_init_r(void);
int status_led_set_r(void);
int set_load_addr_r(void);
+int init_func_spi(void);
#endif /* !_INIT_HELPERS_H_ */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 9b757d489e..86bac90e8e 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -1,6 +1,8 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H
+#include <compiler.h>
+
/*
* This file contains the definitions for the x86 IO instructions
* inb/inw/inl/outb/outw/outl and the "string versions" of the same
@@ -36,6 +38,8 @@
#define IO_SPACE_LIMIT 0xffff
+#include <asm/types.h>
+
#ifdef __KERNEL__
@@ -135,7 +139,7 @@ out:
#ifdef SLOW_IO_BY_JUMPING
#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
#else
-#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+#define __SLOW_DOWN_IO "\noutb %%al,$0xed"
#endif
#ifdef REALLY_SLOW_IO
@@ -218,7 +222,7 @@ static inline void sync(void)
static inline void *
map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
{
- return (void *)paddr;
+ return (void *)(uintptr_t)paddr;
}
/*
@@ -231,7 +235,15 @@ static inline void unmap_physmem(void *vaddr, unsigned long flags)
static inline phys_addr_t virt_to_phys(void * vaddr)
{
- return (phys_addr_t)(vaddr);
+ return (phys_addr_t)(uintptr_t)(vaddr);
}
+/*
+ * TODO: The kernel offers some more advanced versions of barriers, it might
+ * have some advantages to use them instead of the simple one here.
+ */
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+#define __iormb() dmb()
+#define __iowmb() dmb()
+
#endif
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
new file mode 100644
index 0000000000..50175994cf
--- /dev/null
+++ b/arch/x86/include/asm/msr-index.h
@@ -0,0 +1,469 @@
+/*
+ * Taken from the linux kernel file of the same name
+ *
+ * (C) Copyright 2012
+ * Graeme Russ, <graeme.russ@gmail.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_X86_MSR_INDEX_H
+#define _ASM_X86_MSR_INDEX_H
+
+/* CPU model specific register (MSR) numbers */
+
+/* x86-64 specific MSRs */
+#define MSR_EFER 0xc0000080 /* extended feature register */
+#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */
+#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */
+#define MSR_CSTAR 0xc0000083 /* compat mode SYSCALL target */
+#define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */
+#define MSR_FS_BASE 0xc0000100 /* 64bit FS base */
+#define MSR_GS_BASE 0xc0000101 /* 64bit GS base */
+#define MSR_KERNEL_GS_BASE 0xc0000102 /* SwapGS GS shadow */
+#define MSR_TSC_AUX 0xc0000103 /* Auxiliary TSC */
+
+/* EFER bits: */
+#define _EFER_SCE 0 /* SYSCALL/SYSRET */
+#define _EFER_LME 8 /* Long mode enable */
+#define _EFER_LMA 10 /* Long mode active (read-only) */
+#define _EFER_NX 11 /* No execute enable */
+#define _EFER_SVME 12 /* Enable virtualization */
+#define _EFER_LMSLE 13 /* Long Mode Segment Limit Enable */
+#define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */
+
+#define EFER_SCE (1<<_EFER_SCE)
+#define EFER_LME (1<<_EFER_LME)
+#define EFER_LMA (1<<_EFER_LMA)
+#define EFER_NX (1<<_EFER_NX)
+#define EFER_SVME (1<<_EFER_SVME)
+#define EFER_LMSLE (1<<_EFER_LMSLE)
+#define EFER_FFXSR (1<<_EFER_FFXSR)
+
+/* Intel MSRs. Some also available on other CPUs */
+#define MSR_IA32_PERFCTR0 0x000000c1
+#define MSR_IA32_PERFCTR1 0x000000c2
+#define MSR_FSB_FREQ 0x000000cd
+
+#define MSR_NHM_SNB_PKG_CST_CFG_CTL 0x000000e2
+#define NHM_C3_AUTO_DEMOTE (1UL << 25)
+#define NHM_C1_AUTO_DEMOTE (1UL << 26)
+#define ATM_LNC_C6_AUTO_DEMOTE (1UL << 25)
+
+#define MSR_MTRRcap 0x000000fe
+#define MSR_IA32_BBL_CR_CTL 0x00000119
+#define MSR_IA32_BBL_CR_CTL3 0x0000011e
+
+#define MSR_IA32_SYSENTER_CS 0x00000174
+#define MSR_IA32_SYSENTER_ESP 0x00000175
+#define MSR_IA32_SYSENTER_EIP 0x00000176
+
+#define MSR_IA32_MCG_CAP 0x00000179
+#define MSR_IA32_MCG_STATUS 0x0000017a
+#define MSR_IA32_MCG_CTL 0x0000017b
+
+#define MSR_OFFCORE_RSP_0 0x000001a6
+#define MSR_OFFCORE_RSP_1 0x000001a7
+
+#define MSR_IA32_PEBS_ENABLE 0x000003f1
+#define MSR_IA32_DS_AREA 0x00000600
+#define MSR_IA32_PERF_CAPABILITIES 0x00000345
+
+#define MSR_MTRRfix64K_00000 0x00000250
+#define MSR_MTRRfix16K_80000 0x00000258
+#define MSR_MTRRfix16K_A0000 0x00000259
+#define MSR_MTRRfix4K_C0000 0x00000268
+#define MSR_MTRRfix4K_C8000 0x00000269
+#define MSR_MTRRfix4K_D0000 0x0000026a
+#define MSR_MTRRfix4K_D8000 0x0000026b
+#define MSR_MTRRfix4K_E0000 0x0000026c
+#define MSR_MTRRfix4K_E8000 0x0000026d
+#define MSR_MTRRfix4K_F0000 0x0000026e
+#define MSR_MTRRfix4K_F8000 0x0000026f
+#define MSR_MTRRdefType 0x000002ff
+
+#define MSR_IA32_CR_PAT 0x00000277
+
+#define MSR_IA32_DEBUGCTLMSR 0x000001d9
+#define MSR_IA32_LASTBRANCHFROMIP 0x000001db
+#define MSR_IA32_LASTBRANCHTOIP 0x000001dc
+#define MSR_IA32_LASTINTFROMIP 0x000001dd
+#define MSR_IA32_LASTINTTOIP 0x000001de
+
+/* DEBUGCTLMSR bits (others vary by model): */
+#define DEBUGCTLMSR_LBR (1UL << 0)
+#define DEBUGCTLMSR_BTF (1UL << 1)
+#define DEBUGCTLMSR_TR (1UL << 6)
+#define DEBUGCTLMSR_BTS (1UL << 7)
+#define DEBUGCTLMSR_BTINT (1UL << 8)
+#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9)
+#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10)
+#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
+
+#define MSR_IA32_MC0_CTL 0x00000400
+#define MSR_IA32_MC0_STATUS 0x00000401
+#define MSR_IA32_MC0_ADDR 0x00000402
+#define MSR_IA32_MC0_MISC 0x00000403
+
+#define MSR_AMD64_MC0_MASK 0xc0010044
+
+#define MSR_IA32_MCx_CTL(x) (MSR_IA32_MC0_CTL + 4*(x))
+#define MSR_IA32_MCx_STATUS(x) (MSR_IA32_MC0_STATUS + 4*(x))
+#define MSR_IA32_MCx_ADDR(x) (MSR_IA32_MC0_ADDR + 4*(x))
+#define MSR_IA32_MCx_MISC(x) (MSR_IA32_MC0_MISC + 4*(x))
+
+#define MSR_AMD64_MCx_MASK(x) (MSR_AMD64_MC0_MASK + (x))
+
+/* These are consecutive and not in the normal 4er MCE bank block */
+#define MSR_IA32_MC0_CTL2 0x00000280
+#define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x))
+
+#define MSR_P6_PERFCTR0 0x000000c1
+#define MSR_P6_PERFCTR1 0x000000c2
+#define MSR_P6_EVNTSEL0 0x00000186
+#define MSR_P6_EVNTSEL1 0x00000187
+
+/* AMD64 MSRs. Not complete. See the architecture manual for a more
+ complete list. */
+
+#define MSR_AMD64_PATCH_LEVEL 0x0000008b
+#define MSR_AMD64_NB_CFG 0xc001001f
+#define MSR_AMD64_PATCH_LOADER 0xc0010020
+#define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
+#define MSR_AMD64_OSVW_STATUS 0xc0010141
+#define MSR_AMD64_DC_CFG 0xc0011022
+#define MSR_AMD64_IBSFETCHCTL 0xc0011030
+#define MSR_AMD64_IBSFETCHLINAD 0xc0011031
+#define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
+#define MSR_AMD64_IBSOPCTL 0xc0011033
+#define MSR_AMD64_IBSOPRIP 0xc0011034
+#define MSR_AMD64_IBSOPDATA 0xc0011035
+#define MSR_AMD64_IBSOPDATA2 0xc0011036
+#define MSR_AMD64_IBSOPDATA3 0xc0011037
+#define MSR_AMD64_IBSDCLINAD 0xc0011038
+#define MSR_AMD64_IBSDCPHYSAD 0xc0011039
+#define MSR_AMD64_IBSCTL 0xc001103a
+#define MSR_AMD64_IBSBRTARGET 0xc001103b
+
+/* Fam 15h MSRs */
+#define MSR_F15H_PERF_CTL 0xc0010200
+#define MSR_F15H_PERF_CTR 0xc0010201
+
+/* Fam 10h MSRs */
+#define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058
+#define FAM10H_MMIO_CONF_ENABLE (1<<0)
+#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
+#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
+#define FAM10H_MMIO_CONF_BASE_MASK 0xfffffffULL
+#define FAM10H_MMIO_CONF_BASE_SHIFT 20
+#define MSR_FAM10H_NODE_ID 0xc001100c
+
+/* K8 MSRs */
+#define MSR_K8_TOP_MEM1 0xc001001a
+#define MSR_K8_TOP_MEM2 0xc001001d
+#define MSR_K8_SYSCFG 0xc0010010
+#define MSR_K8_INT_PENDING_MSG 0xc0010055
+/* C1E active bits in int pending message */
+#define K8_INTP_C1E_ACTIVE_MASK 0x18000000
+#define MSR_K8_TSEG_ADDR 0xc0010112
+#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000 /* MtrrFixDramEn bit */
+#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000 /* MtrrFixDramModEn bit */
+#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818 /* Mask: RdMem|WrMem */
+
+/* K7 MSRs */
+#define MSR_K7_EVNTSEL0 0xc0010000
+#define MSR_K7_PERFCTR0 0xc0010004
+#define MSR_K7_EVNTSEL1 0xc0010001
+#define MSR_K7_PERFCTR1 0xc0010005
+#define MSR_K7_EVNTSEL2 0xc0010002
+#define MSR_K7_PERFCTR2 0xc0010006
+#define MSR_K7_EVNTSEL3 0xc0010003
+#define MSR_K7_PERFCTR3 0xc0010007
+#define MSR_K7_CLK_CTL 0xc001001b
+#define MSR_K7_HWCR 0xc0010015
+#define MSR_K7_FID_VID_CTL 0xc0010041
+#define MSR_K7_FID_VID_STATUS 0xc0010042
+
+/* K6 MSRs */
+#define MSR_K6_WHCR 0xc0000082
+#define MSR_K6_UWCCR 0xc0000085
+#define MSR_K6_EPMR 0xc0000086
+#define MSR_K6_PSOR 0xc0000087
+#define MSR_K6_PFIR 0xc0000088
+
+/* Centaur-Hauls/IDT defined MSRs. */
+#define MSR_IDT_FCR1 0x00000107
+#define MSR_IDT_FCR2 0x00000108
+#define MSR_IDT_FCR3 0x00000109
+#define MSR_IDT_FCR4 0x0000010a
+
+#define MSR_IDT_MCR0 0x00000110
+#define MSR_IDT_MCR1 0x00000111
+#define MSR_IDT_MCR2 0x00000112
+#define MSR_IDT_MCR3 0x00000113
+#define MSR_IDT_MCR4 0x00000114
+#define MSR_IDT_MCR5 0x00000115
+#define MSR_IDT_MCR6 0x00000116
+#define MSR_IDT_MCR7 0x00000117
+#define MSR_IDT_MCR_CTRL 0x00000120
+
+/* VIA Cyrix defined MSRs*/
+#define MSR_VIA_FCR 0x00001107
+#define MSR_VIA_LONGHAUL 0x0000110a
+#define MSR_VIA_RNG 0x0000110b
+#define MSR_VIA_BCR2 0x00001147
+
+/* Transmeta defined MSRs */
+#define MSR_TMTA_LONGRUN_CTRL 0x80868010
+#define MSR_TMTA_LONGRUN_FLAGS 0x80868011
+#define MSR_TMTA_LRTI_READOUT 0x80868018
+#define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a
+
+/* Intel defined MSRs. */
+#define MSR_IA32_P5_MC_ADDR 0x00000000
+#define MSR_IA32_P5_MC_TYPE 0x00000001
+#define MSR_IA32_TSC 0x00000010
+#define MSR_IA32_PLATFORM_ID 0x00000017
+#define MSR_IA32_EBL_CR_POWERON 0x0000002a
+#define MSR_EBC_FREQUENCY_ID 0x0000002c
+#define MSR_IA32_FEATURE_CONTROL 0x0000003a
+
+#define FEATURE_CONTROL_LOCKED (1<<0)
+#define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1)
+#define FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1<<2)
+
+#define MSR_IA32_APICBASE 0x0000001b
+#define MSR_IA32_APICBASE_BSP (1<<8)
+#define MSR_IA32_APICBASE_ENABLE (1<<11)
+#define MSR_IA32_APICBASE_BASE (0xfffff<<12)
+
+#define MSR_IA32_UCODE_WRITE 0x00000079
+#define MSR_IA32_UCODE_REV 0x0000008b
+
+#define MSR_IA32_PERF_STATUS 0x00000198
+#define MSR_IA32_PERF_CTL 0x00000199
+
+#define MSR_IA32_MPERF 0x000000e7
+#define MSR_IA32_APERF 0x000000e8
+
+#define MSR_IA32_THERM_CONTROL 0x0000019a
+#define MSR_IA32_THERM_INTERRUPT 0x0000019b
+
+#define THERM_INT_HIGH_ENABLE (1 << 0)
+#define THERM_INT_LOW_ENABLE (1 << 1)
+#define THERM_INT_PLN_ENABLE (1 << 24)
+
+#define MSR_IA32_THERM_STATUS 0x0000019c
+
+#define THERM_STATUS_PROCHOT (1 << 0)
+#define THERM_STATUS_POWER_LIMIT (1 << 10)
+
+#define MSR_THERM2_CTL 0x0000019d
+
+#define MSR_THERM2_CTL_TM_SELECT (1ULL << 16)
+
+#define MSR_IA32_MISC_ENABLE 0x000001a0
+
+#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
+
+#define MSR_IA32_ENERGY_PERF_BIAS 0x000001b0
+
+#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
+
+#define PACKAGE_THERM_STATUS_PROCHOT (1 << 0)
+#define PACKAGE_THERM_STATUS_POWER_LIMIT (1 << 10)
+
+#define MSR_IA32_PACKAGE_THERM_INTERRUPT 0x000001b2
+
+#define PACKAGE_THERM_INT_HIGH_ENABLE (1 << 0)
+#define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1)
+#define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24)
+
+/* Thermal Thresholds Support */
+#define THERM_INT_THRESHOLD0_ENABLE (1 << 15)
+#define THERM_SHIFT_THRESHOLD0 8
+#define THERM_MASK_THRESHOLD0 (0x7f << THERM_SHIFT_THRESHOLD0)
+#define THERM_INT_THRESHOLD1_ENABLE (1 << 23)
+#define THERM_SHIFT_THRESHOLD1 16
+#define THERM_MASK_THRESHOLD1 (0x7f << THERM_SHIFT_THRESHOLD1)
+#define THERM_STATUS_THRESHOLD0 (1 << 6)
+#define THERM_LOG_THRESHOLD0 (1 << 7)
+#define THERM_STATUS_THRESHOLD1 (1 << 8)
+#define THERM_LOG_THRESHOLD1 (1 << 9)
+
+/* MISC_ENABLE bits: architectural */
+#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0)
+#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1)
+#define MSR_IA32_MISC_ENABLE_EMON (1ULL << 7)
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1ULL << 11)
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1ULL << 12)
+#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16)
+#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18)
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22)
+#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << 23)
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE (1ULL << 34)
+
+/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
+#define MSR_IA32_MISC_ENABLE_X87_COMPAT (1ULL << 2)
+#define MSR_IA32_MISC_ENABLE_TM1 (1ULL << 3)
+#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE (1ULL << 4)
+#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE (1ULL << 6)
+#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK (1ULL << 8)
+#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE (1ULL << 9)
+#define MSR_IA32_MISC_ENABLE_FERR (1ULL << 10)
+#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << 10)
+#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << 13)
+#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE (1ULL << 19)
+#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20)
+#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT (1ULL << 24)
+#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE (1ULL << 37)
+#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38)
+#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39)
+
+/* P4/Xeon+ specific */
+#define MSR_IA32_MCG_EAX 0x00000180
+#define MSR_IA32_MCG_EBX 0x00000181
+#define MSR_IA32_MCG_ECX 0x00000182
+#define MSR_IA32_MCG_EDX 0x00000183
+#define MSR_IA32_MCG_ESI 0x00000184
+#define MSR_IA32_MCG_EDI 0x00000185
+#define MSR_IA32_MCG_EBP 0x00000186
+#define MSR_IA32_MCG_ESP 0x00000187
+#define MSR_IA32_MCG_EFLAGS 0x00000188
+#define MSR_IA32_MCG_EIP 0x00000189
+#define MSR_IA32_MCG_RESERVED 0x0000018a
+
+/* Pentium IV performance counter MSRs */
+#define MSR_P4_BPU_PERFCTR0 0x00000300
+#define MSR_P4_BPU_PERFCTR1 0x00000301
+#define MSR_P4_BPU_PERFCTR2 0x00000302
+#define MSR_P4_BPU_PERFCTR3 0x00000303
+#define MSR_P4_MS_PERFCTR0 0x00000304
+#define MSR_P4_MS_PERFCTR1 0x00000305
+#define MSR_P4_MS_PERFCTR2 0x00000306
+#define MSR_P4_MS_PERFCTR3 0x00000307
+#define MSR_P4_FLAME_PERFCTR0 0x00000308
+#define MSR_P4_FLAME_PERFCTR1 0x00000309
+#define MSR_P4_FLAME_PERFCTR2 0x0000030a
+#define MSR_P4_FLAME_PERFCTR3 0x0000030b
+#define MSR_P4_IQ_PERFCTR0 0x0000030c
+#define MSR_P4_IQ_PERFCTR1 0x0000030d
+#define MSR_P4_IQ_PERFCTR2 0x0000030e
+#define MSR_P4_IQ_PERFCTR3 0x0000030f
+#define MSR_P4_IQ_PERFCTR4 0x00000310
+#define MSR_P4_IQ_PERFCTR5 0x00000311
+#define MSR_P4_BPU_CCCR0 0x00000360
+#define MSR_P4_BPU_CCCR1 0x00000361
+#define MSR_P4_BPU_CCCR2 0x00000362
+#define MSR_P4_BPU_CCCR3 0x00000363
+#define MSR_P4_MS_CCCR0 0x00000364
+#define MSR_P4_MS_CCCR1 0x00000365
+#define MSR_P4_MS_CCCR2 0x00000366
+#define MSR_P4_MS_CCCR3 0x00000367
+#define MSR_P4_FLAME_CCCR0 0x00000368
+#define MSR_P4_FLAME_CCCR1 0x00000369
+#define MSR_P4_FLAME_CCCR2 0x0000036a
+#define MSR_P4_FLAME_CCCR3 0x0000036b
+#define MSR_P4_IQ_CCCR0 0x0000036c
+#define MSR_P4_IQ_CCCR1 0x0000036d
+#define MSR_P4_IQ_CCCR2 0x0000036e
+#define MSR_P4_IQ_CCCR3 0x0000036f
+#define MSR_P4_IQ_CCCR4 0x00000370
+#define MSR_P4_IQ_CCCR5 0x00000371
+#define MSR_P4_ALF_ESCR0 0x000003ca
+#define MSR_P4_ALF_ESCR1 0x000003cb
+#define MSR_P4_BPU_ESCR0 0x000003b2
+#define MSR_P4_BPU_ESCR1 0x000003b3
+#define MSR_P4_BSU_ESCR0 0x000003a0
+#define MSR_P4_BSU_ESCR1 0x000003a1
+#define MSR_P4_CRU_ESCR0 0x000003b8
+#define MSR_P4_CRU_ESCR1 0x000003b9
+#define MSR_P4_CRU_ESCR2 0x000003cc
+#define MSR_P4_CRU_ESCR3 0x000003cd
+#define MSR_P4_CRU_ESCR4 0x000003e0
+#define MSR_P4_CRU_ESCR5 0x000003e1
+#define MSR_P4_DAC_ESCR0 0x000003a8
+#define MSR_P4_DAC_ESCR1 0x000003a9
+#define MSR_P4_FIRM_ESCR0 0x000003a4
+#define MSR_P4_FIRM_ESCR1 0x000003a5
+#define MSR_P4_FLAME_ESCR0 0x000003a6
+#define MSR_P4_FLAME_ESCR1 0x000003a7
+#define MSR_P4_FSB_ESCR0 0x000003a2
+#define MSR_P4_FSB_ESCR1 0x000003a3
+#define MSR_P4_IQ_ESCR0 0x000003ba
+#define MSR_P4_IQ_ESCR1 0x000003bb
+#define MSR_P4_IS_ESCR0 0x000003b4
+#define MSR_P4_IS_ESCR1 0x000003b5
+#define MSR_P4_ITLB_ESCR0 0x000003b6
+#define MSR_P4_ITLB_ESCR1 0x000003b7
+#define MSR_P4_IX_ESCR0 0x000003c8
+#define MSR_P4_IX_ESCR1 0x000003c9
+#define MSR_P4_MOB_ESCR0 0x000003aa
+#define MSR_P4_MOB_ESCR1 0x000003ab
+#define MSR_P4_MS_ESCR0 0x000003c0
+#define MSR_P4_MS_ESCR1 0x000003c1
+#define MSR_P4_PMH_ESCR0 0x000003ac
+#define MSR_P4_PMH_ESCR1 0x000003ad
+#define MSR_P4_RAT_ESCR0 0x000003bc
+#define MSR_P4_RAT_ESCR1 0x000003bd
+#define MSR_P4_SAAT_ESCR0 0x000003ae
+#define MSR_P4_SAAT_ESCR1 0x000003af
+#define MSR_P4_SSU_ESCR0 0x000003be
+#define MSR_P4_SSU_ESCR1 0x000003bf /* guess: not in manual */
+
+#define MSR_P4_TBPU_ESCR0 0x000003c2
+#define MSR_P4_TBPU_ESCR1 0x000003c3
+#define MSR_P4_TC_ESCR0 0x000003c4
+#define MSR_P4_TC_ESCR1 0x000003c5
+#define MSR_P4_U2L_ESCR0 0x000003b0
+#define MSR_P4_U2L_ESCR1 0x000003b1
+
+#define MSR_P4_PEBS_MATRIX_VERT 0x000003f2
+
+/* Intel Core-based CPU performance counters */
+#define MSR_CORE_PERF_FIXED_CTR0 0x00000309
+#define MSR_CORE_PERF_FIXED_CTR1 0x0000030a
+#define MSR_CORE_PERF_FIXED_CTR2 0x0000030b
+#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x0000038d
+#define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e
+#define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f
+#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390
+
+/* Geode defined MSRs */
+#define MSR_GEODE_BUSCONT_CONF0 0x00001900
+
+/* Intel VT MSRs */
+#define MSR_IA32_VMX_BASIC 0x00000480
+#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481
+#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482
+#define MSR_IA32_VMX_EXIT_CTLS 0x00000483
+#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484
+#define MSR_IA32_VMX_MISC 0x00000485
+#define MSR_IA32_VMX_CR0_FIXED0 0x00000486
+#define MSR_IA32_VMX_CR0_FIXED1 0x00000487
+#define MSR_IA32_VMX_CR4_FIXED0 0x00000488
+#define MSR_IA32_VMX_CR4_FIXED1 0x00000489
+#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a
+#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b
+#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c
+
+/* AMD-V MSRs */
+
+#define MSR_VM_CR 0xc0010114
+#define MSR_VM_IGNNE 0xc0010115
+#define MSR_VM_HSAVE_PA 0xc0010117
+
+#endif /* _ASM_X86_MSR_INDEX_H */
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
new file mode 100644
index 0000000000..6030633d10
--- /dev/null
+++ b/arch/x86/include/asm/msr.h
@@ -0,0 +1,238 @@
+/*
+ * Taken from the linux kernel file of the same name
+ *
+ * (C) Copyright 2012
+ * Graeme Russ, <graeme.russ@gmail.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_X86_MSR_H
+#define _ASM_X86_MSR_H
+
+#include <asm/msr-index.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define X86_IOC_RDMSR_REGS _IOWR('c', 0xA0, __u32[8])
+#define X86_IOC_WRMSR_REGS _IOWR('c', 0xA1, __u32[8])
+
+#ifdef __KERNEL__
+
+#include <asm/errno.h>
+
+struct msr {
+ union {
+ struct {
+ u32 l;
+ u32 h;
+ };
+ u64 q;
+ };
+};
+
+struct msr_info {
+ u32 msr_no;
+ struct msr reg;
+ struct msr *msrs;
+ int err;
+};
+
+struct msr_regs_info {
+ u32 *regs;
+ int err;
+};
+
+static inline unsigned long long native_read_tscp(unsigned int *aux)
+{
+ unsigned long low, high;
+ asm volatile(".byte 0x0f,0x01,0xf9"
+ : "=a" (low), "=d" (high), "=c" (*aux));
+ return low | ((u64)high << 32);
+}
+
+/*
+ * both i386 and x86_64 returns 64-bit value in edx:eax, but gcc's "A"
+ * constraint has different meanings. For i386, "A" means exactly
+ * edx:eax, while for x86_64 it doesn't mean rdx:rax or edx:eax. Instead,
+ * it means rax *or* rdx.
+ */
+#ifdef CONFIG_X86_64
+#define DECLARE_ARGS(val, low, high) unsigned low, high
+#define EAX_EDX_VAL(val, low, high) ((low) | ((u64)(high) << 32))
+#define EAX_EDX_ARGS(val, low, high) "a" (low), "d" (high)
+#define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high)
+#else
+#define DECLARE_ARGS(val, low, high) unsigned long long val
+#define EAX_EDX_VAL(val, low, high) (val)
+#define EAX_EDX_ARGS(val, low, high) "A" (val)
+#define EAX_EDX_RET(val, low, high) "=A" (val)
+#endif
+
+static inline unsigned long long native_read_msr(unsigned int msr)
+{
+ DECLARE_ARGS(val, low, high);
+
+ asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
+ return EAX_EDX_VAL(val, low, high);
+}
+
+static inline void native_write_msr(unsigned int msr,
+ unsigned low, unsigned high)
+{
+ asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory");
+}
+
+extern unsigned long long native_read_tsc(void);
+
+extern int native_rdmsr_safe_regs(u32 regs[8]);
+extern int native_wrmsr_safe_regs(u32 regs[8]);
+
+static inline unsigned long long native_read_pmc(int counter)
+{
+ DECLARE_ARGS(val, low, high);
+
+ asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter));
+ return EAX_EDX_VAL(val, low, high);
+}
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#include <errno.h>
+/*
+ * Access to machine-specific registers (available on 586 and better only)
+ * Note: the rd* operations modify the parameters directly (without using
+ * pointer indirection), this allows gcc to optimize better
+ */
+
+#define rdmsr(msr, val1, val2) \
+do { \
+ u64 __val = native_read_msr((msr)); \
+ (void)((val1) = (u32)__val); \
+ (void)((val2) = (u32)(__val >> 32)); \
+} while (0)
+
+static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
+{
+ native_write_msr(msr, low, high);
+}
+
+#define rdmsrl(msr, val) \
+ ((val) = native_read_msr((msr)))
+
+#define wrmsrl(msr, val) \
+ native_write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32))
+
+/* rdmsr with exception handling */
+#define rdmsr_safe(msr, p1, p2) \
+({ \
+ int __err; \
+ u64 __val = native_read_msr_safe((msr), &__err); \
+ (*p1) = (u32)__val; \
+ (*p2) = (u32)(__val >> 32); \
+ __err; \
+})
+
+static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
+{
+ u32 gprs[8] = { 0 };
+ int err;
+
+ gprs[1] = msr;
+ gprs[7] = 0x9c5a203a;
+
+ err = native_rdmsr_safe_regs(gprs);
+
+ *p = gprs[0] | ((u64)gprs[2] << 32);
+
+ return err;
+}
+
+static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
+{
+ u32 gprs[8] = { 0 };
+
+ gprs[0] = (u32)val;
+ gprs[1] = msr;
+ gprs[2] = val >> 32;
+ gprs[7] = 0x9c5a203a;
+
+ return native_wrmsr_safe_regs(gprs);
+}
+
+static inline int rdmsr_safe_regs(u32 regs[8])
+{
+ return native_rdmsr_safe_regs(regs);
+}
+
+static inline int wrmsr_safe_regs(u32 regs[8])
+{
+ return native_wrmsr_safe_regs(regs);
+}
+
+#define rdtscl(low) \
+ ((low) = (u32)__native_read_tsc())
+
+#define rdtscll(val) \
+ ((val) = __native_read_tsc())
+
+#define rdpmc(counter, low, high) \
+do { \
+ u64 _l = native_read_pmc((counter)); \
+ (low) = (u32)_l; \
+ (high) = (u32)(_l >> 32); \
+} while (0)
+
+#define rdtscp(low, high, aux) \
+do { \
+ unsigned long long _val = native_read_tscp(&(aux)); \
+ (low) = (u32)_val; \
+ (high) = (u32)(_val >> 32); \
+} while (0)
+
+#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
+
+#endif /* !CONFIG_PARAVIRT */
+
+
+#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val), \
+ (u32)((val) >> 32))
+
+#define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2))
+
+#define write_rdtscp_aux(val) wrmsr(MSR_TSC_AUX, (val), 0)
+
+struct msr *msrs_alloc(void);
+void msrs_free(struct msr *msrs);
+
+#ifdef CONFIG_SMP
+int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
+void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
+int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
+int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
+int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
+
+#endif /* CONFIG_SMP */
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_X86_MSR_H */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
new file mode 100644
index 0000000000..6842da500a
--- /dev/null
+++ b/arch/x86/include/asm/mtrr.h
@@ -0,0 +1,206 @@
+/*
+ * Generic MTRR (Memory Type Range Register) ioctls.
+ * Taken from the Linux kernel
+ *
+ * (C) Copyright 2012
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * Copyright (C) 1997-1999 Richard Gooch <rgooch@atnf.csiro.au>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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_X86_MTRR_H
+#define _ASM_X86_MTRR_H
+
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <errno.h>
+
+#define MTRR_IOCTL_BASE 'M'
+
+struct mtrr_sentry {
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int type; /* Type of region */
+};
+
+/*
+ * Warning: this structure has a different order from i386
+ * on x86-64. The 32bit emulation code takes care of that.
+ * But you need to use this for 64bit, otherwise your X server
+ * will break.
+ */
+
+#ifdef __i386__
+struct mtrr_gentry {
+ unsigned int regnum; /* Register number */
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int type; /* Type of region */
+};
+
+#else /* __i386__ */
+
+struct mtrr_gentry {
+ unsigned long base; /* Base address */
+ unsigned int size; /* Size of region */
+ unsigned int regnum; /* Register number */
+ unsigned int type; /* Type of region */
+};
+#endif /* !__i386__ */
+
+struct mtrr_var_range {
+ __u32 base_lo;
+ __u32 base_hi;
+ __u32 mask_lo;
+ __u32 mask_hi;
+};
+
+/*
+ * In the Intel processor's MTRR interface, the MTRR type is always held in
+ * an 8 bit field:
+ */
+typedef __u8 mtrr_type;
+
+#define MTRR_NUM_FIXED_RANGES 88
+#define MTRR_MAX_VAR_RANGES 256
+
+struct mtrr_state_type {
+ struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES];
+ mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES];
+ unsigned char enabled;
+ unsigned char have_fixed;
+ mtrr_type def_type;
+};
+
+/* These are the various ioctls */
+#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry)
+#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry)
+#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry)
+#define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
+#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry)
+#define MTRRIOC_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry)
+#define MTRRIOC_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry)
+#define MTRRIOC_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry)
+#define MTRRIOC_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
+#define MTRRIOC_KILL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry)
+
+/* These are the region types */
+#define MTRR_TYPE_UNCACHABLE 0
+#define MTRR_TYPE_WRCOMB 1
+/*#define MTRR_TYPE_ 2*/
+/*#define MTRR_TYPE_ 3*/
+#define MTRR_TYPE_WRTHROUGH 4
+#define MTRR_TYPE_WRPROT 5
+#define MTRR_TYPE_WRBACK 6
+#define MTRR_NUM_TYPES 7
+
+#ifdef __KERNEL__
+
+/* The following functions are for use by other drivers */
+# ifdef CONFIG_MTRR
+extern u8 mtrr_type_lookup(u64 addr, u64 end);
+extern void mtrr_save_fixed_ranges(void *);
+extern void mtrr_save_state(void);
+extern int mtrr_add(unsigned long base, unsigned long size,
+ unsigned int type, bool increment);
+extern int mtrr_add_page(unsigned long base, unsigned long size,
+ unsigned int type, bool increment);
+extern int mtrr_del(int reg, unsigned long base, unsigned long size);
+extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
+extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
+extern void mtrr_ap_init(void);
+extern void mtrr_bp_init(void);
+extern void set_mtrr_aps_delayed_init(void);
+extern void mtrr_aps_init(void);
+extern void mtrr_bp_restore(void);
+extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
+extern int amd_special_default_mtrr(void);
+# else
+static inline u8 mtrr_type_lookup(u64 addr, u64 end)
+{
+ /*
+ * Return no-MTRRs:
+ */
+ return 0xff;
+}
+#define mtrr_save_fixed_ranges(arg) do {} while (0)
+#define mtrr_save_state() do {} while (0)
+static inline int mtrr_del(int reg, unsigned long base, unsigned long size)
+{
+ return -ENODEV;
+}
+static inline int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+{
+ return -ENODEV;
+}
+static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
+{
+ return 0;
+}
+static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
+{
+}
+
+#define mtrr_ap_init() do {} while (0)
+#define mtrr_bp_init() do {} while (0)
+#define set_mtrr_aps_delayed_init() do {} while (0)
+#define mtrr_aps_init() do {} while (0)
+#define mtrr_bp_restore() do {} while (0)
+# endif
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+struct mtrr_sentry32 {
+ compat_ulong_t base; /* Base address */
+ compat_uint_t size; /* Size of region */
+ compat_uint_t type; /* Type of region */
+};
+
+struct mtrr_gentry32 {
+ compat_ulong_t regnum; /* Register number */
+ compat_uint_t base; /* Base address */
+ compat_uint_t size; /* Size of region */
+ compat_uint_t type; /* Type of region */
+};
+
+#define MTRR_IOCTL_BASE 'M'
+
+#define MTRRIOC32_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry32)
+#define MTRRIOC32_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry32)
+#define MTRRIOC32_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry32)
+#define MTRRIOC32_ADD_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 5, struct mtrr_sentry32)
+#define MTRRIOC32_SET_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 6, struct mtrr_sentry32)
+#define MTRRIOC32_DEL_PAGE_ENTRY _IOW(MTRR_IOCTL_BASE, 7, struct mtrr_sentry32)
+#define MTRRIOC32_GET_PAGE_ENTRY _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry32)
+#define MTRRIOC32_KILL_PAGE_ENTRY \
+ _IOW(MTRR_IOCTL_BASE, 9, struct mtrr_sentry32)
+#endif /* CONFIG_COMPAT */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_X86_MTRR_H */
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 37cc7e3a0f..6d68ab6c92 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -24,7 +24,7 @@
*/
#ifndef _PCI_I386_H_
-#define _PCI_I386_H_ 1
+#define _PCI_I386_H_
#define DEFINE_PCI_DEVICE_TABLE(_table) \
const struct pci_device_id _table[]
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 6eb518063b..17f27cbb68 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -41,6 +41,7 @@ enum {
#else
/* NOTE: If the above enum is modified, this define must be checked */
#define X86_GDT_ENTRY_32BIT_DS 3
+#define X86_GDT_NUM_ENTRIES 7
#endif
#define X86_GDT_SIZE (X86_GDT_NUM_ENTRIES * X86_GDT_ENTRY_SIZE)
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index 9a40e383eb..e9fde88f7d 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -45,8 +45,8 @@ typedef unsigned long long u64;
typedef u32 dma_addr_t;
-typedef unsigned long phys_addr_t;
-typedef unsigned long phys_size_t;
+typedef unsigned long long phys_addr_t;
+typedef unsigned long long phys_size_t;
#endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 878a1ee77b..99062e5955 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -40,6 +40,7 @@ int cpu_init_f(void);
void init_gd(gd_t *id, u64 *gdt_addr);
void setup_gdt(gd_t *id, u64 *gdt_addr);
int init_cache(void);
+int cleanup_before_linux(void);
/* cpu/.../timer.c */
void timer_isr(void *);
@@ -62,9 +63,20 @@ u32 isa_map_rom(u32 bus_addr, int size);
/* arch/x86/lib/... */
int video_bios_init(void);
-int video_init(void);
void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
void board_init_f_r(void) __attribute__ ((noreturn));
+/* Read the time stamp counter */
+static inline uint64_t rdtsc(void)
+{
+ uint32_t high, low;
+ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
+ return (((uint64_t)high) << 32) | low;
+}
+
+/* board/... */
+void timer_set_tsc_base(uint64_t new_base);
+uint64_t timer_get_tsc(void);
+
#endif /* _U_BOOT_I386_H_ */
diff --git a/arch/x86/include/asm/u-boot.h b/arch/x86/include/asm/u-boot.h
index da667c50a4..2f45c7b3d7 100644
--- a/arch/x86/include/asm/u-boot.h
+++ b/arch/x86/include/asm/u-boot.h
@@ -36,6 +36,9 @@
#ifndef _U_BOOT_H_
#define _U_BOOT_H_ 1
+#include <config.h>
+#include <compiler.h>
+
typedef struct bd_info {
unsigned long bi_memstart; /* start of DRAM memory */
phys_size_t bi_memsize; /* size of DRAM memory in bytes */
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 51836dacca..0a52cc896c 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -25,11 +25,16 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(ARCH).o
+ifeq ($(CONFIG_X86_NO_REAL_MODE),)
SOBJS-$(CONFIG_SYS_PC_BIOS) += bios.o
SOBJS-$(CONFIG_SYS_PCI_BIOS) += bios_pci.o
-SOBJS-$(CONFIG_SYS_X86_REALMODE) += realmode_switch.o
+COBJS-y += realmode.o
+SOBJS-y += realmode_switch.o
COBJS-$(CONFIG_SYS_PC_BIOS) += bios_setup.o
+COBJS-$(CONFIG_VIDEO_VGA) += video_bios.o
+endif
+
COBJS-y += board.o
COBJS-y += bootm.o
COBJS-y += cmd_boot.o
@@ -41,12 +46,11 @@ COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o
COBJS-$(CONFIG_PCI) += pci.o
COBJS-$(CONFIG_PCI) += pci_type1.o
-COBJS-$(CONFIG_SYS_X86_REALMODE) += realmode.o
COBJS-y += relocate.o
+COBJS-y += physmem.o
COBJS-y += string.o
COBJS-$(CONFIG_SYS_X86_ISR_TIMER) += timer.o
-COBJS-$(CONFIG_VIDEO) += video_bios.o
-COBJS-$(CONFIG_VIDEO) += video.o
+COBJS-$(CONFIG_VIDEO_VGA) += video.o
COBJS-$(CONFIG_CMD_ZBOOT) += zimage.o
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index e5caf13561..22bc26dde9 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -36,6 +36,7 @@
#include <stdio_dev.h>
#include <asm/u-boot-x86.h>
#include <asm/relocate.h>
+#include <asm/processor.h>
#include <asm/init_helpers.h>
#include <asm/init_wrappers.h>
@@ -98,10 +99,17 @@ typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence_f[] = {
cpu_init_f,
board_early_init_f,
+#ifdef CONFIG_OF_CONTROL
+ find_fdt,
+ fdtdec_check_fdt,
+#endif
env_init,
init_baudrate_f,
serial_init,
console_init_f,
+#ifdef CONFIG_OF_CONTROL
+ prepare_fdt,
+#endif
dram_init_f,
calculate_relocation_address,
@@ -121,7 +129,6 @@ init_fnc_t *init_sequence_f[] = {
* initialise the CPU caches (to speed up the relocation process)
*/
init_fnc_t *init_sequence_f_r[] = {
- copy_gd_to_ram_f_r,
init_cache_f_r,
copy_uboot_to_ram,
clear_bss,
@@ -154,6 +161,9 @@ init_fnc_t *init_sequence_r[] = {
#ifndef CONFIG_SYS_NO_FLASH
flash_init_r,
#endif
+#ifdef CONFIG_SPI
+ init_func_spi;
+#endif
env_relocate_r,
#ifdef CONFIG_PCI
pci_init_r,
@@ -164,9 +174,6 @@ init_fnc_t *init_sequence_r[] = {
#ifdef CONFIG_MISC_INIT_R
misc_init_r,
#endif
-#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE)
- pci_init_r,
-#endif
#if defined(CONFIG_CMD_KGDB)
kgdb_init_r,
#endif
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c
index 9ec34ff992..3eec9a61d6 100644
--- a/arch/x86/lib/init_helpers.c
+++ b/arch/x86/lib/init_helpers.c
@@ -28,9 +28,11 @@
#include <net.h>
#include <ide.h>
#include <serial.h>
+#include <spi.h>
#include <status_led.h>
#include <asm/processor.h>
#include <asm/u-boot-x86.h>
+#include <linux/compiler.h>
#include <asm/init_helpers.h>
@@ -71,7 +73,7 @@ int init_baudrate_f(void)
return 0;
}
-int calculate_relocation_address(void)
+__weak int calculate_relocation_address(void)
{
ulong text_start = (ulong)&__text_start;
ulong bss_end = (ulong)&__bss_end;
@@ -83,51 +85,17 @@ int calculate_relocation_address(void)
* requirements
*/
- /* Global Data is at top of available memory */
+ /* Stack is at top of available memory */
dest_addr = gd->ram_size;
- dest_addr -= GENERATED_GBL_DATA_SIZE;
- dest_addr &= ~15;
- gd->new_gd_addr = dest_addr;
-
- /* GDT is below Global Data */
- dest_addr -= X86_GDT_SIZE;
- dest_addr &= ~15;
- gd->gdt_addr = dest_addr;
-
- /* Stack is below GDT */
- gd->start_addr_sp = dest_addr;
- /* U-Boot is below the stack */
- dest_addr -= CONFIG_SYS_STACK_SIZE;
+ /* U-Boot is at the top */
dest_addr -= (bss_end - text_start);
dest_addr &= ~15;
gd->relocaddr = dest_addr;
gd->reloc_off = (dest_addr - text_start);
- return 0;
-}
-
-int copy_gd_to_ram_f_r(void)
-{
- gd_t *ram_gd;
-
- /*
- * Global data is still in temporary memory (the CPU cache).
- * calculate_relocation_address() has set gd->new_gd_addr to
- * where the global data lives in RAM but getting it there
- * safely is a bit tricky due to the 'F-Segment Hack' that
- * we need to use for x86
- */
- ram_gd = (gd_t *)gd->new_gd_addr;
- memcpy((void *)ram_gd, gd, sizeof(gd_t));
-
- /*
- * Reload the Global Descriptor Table so FS points to the
- * in-RAM copy of Global Data (calculate_relocation_address()
- * has already calculated the in-RAM location of the GDT)
- */
- ram_gd->gd_addr = (ulong)ram_gd;
- init_gd(ram_gd, (u64 *)gd->gdt_addr);
+ /* Stack is at the bottom, so it can grow down */
+ gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN;
return 0;
}
@@ -195,3 +163,40 @@ int set_load_addr_r(void)
return 0;
}
+
+int init_func_spi(void)
+{
+ puts("SPI: ");
+ spi_init();
+ puts("ready\n");
+ return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int find_fdt(void)
+{
+#ifdef CONFIG_OF_EMBED
+ /* Get a pointer to the FDT */
+ gd->fdt_blob = _binary_dt_dtb_start;
+#elif defined CONFIG_OF_SEPARATE
+ /* FDT is at end of image */
+ gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
+#endif
+ /* Allow the early environment to override the fdt address */
+ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
+ (uintptr_t)gd->fdt_blob);
+
+ return 0;
+}
+
+int prepare_fdt(void)
+{
+ /* For now, put this check after the console is ready */
+ if (fdtdec_prepare_fdt()) {
+ panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
+ "doc/README.fdt-control");
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/x86/lib/init_wrappers.c b/arch/x86/lib/init_wrappers.c
index 71449fe6fa..cca018fa9b 100644
--- a/arch/x86/lib/init_wrappers.c
+++ b/arch/x86/lib/init_wrappers.c
@@ -21,6 +21,7 @@
* MA 02111-1307 USA
*/
#include <common.h>
+#include <environment.h>
#include <serial.h>
#include <kgdb.h>
#include <scsi.h>
@@ -36,10 +37,35 @@ int serial_initialize_r(void)
return 0;
}
+/*
+ * Tell if it's OK to load the environment early in boot.
+ *
+ * If CONFIG_OF_CONFIG is defined, we'll check with the FDT to see
+ * if this is OK (defaulting to saying it's not OK).
+ *
+ * NOTE: Loading the environment early can be a bad idea if security is
+ * important, since no verification is done on the environment.
+ *
+ * @return 0 if environment should not be loaded, !=0 if it is ok to load
+ */
+static int should_load_env(void)
+{
+#ifdef CONFIG_OF_CONTROL
+ return fdtdec_get_config_int(gd->fdt_blob, "load-environment", 0);
+#elif defined CONFIG_DELAY_ENVIRONMENT
+ return 0;
+#else
+ return 1;
+#endif
+}
+
int env_relocate_r(void)
{
/* initialize environment */
- env_relocate();
+ if (should_load_env())
+ env_relocate();
+ else
+ set_default_env(NULL);
return 0;
}
diff --git a/arch/x86/lib/pcat_timer.c b/arch/x86/lib/pcat_timer.c
index 6b3db69447..b0b6637f3a 100644
--- a/arch/x86/lib/pcat_timer.c
+++ b/arch/x86/lib/pcat_timer.c
@@ -39,7 +39,7 @@ int timer_init(void)
* Timer 0 is used to increment system_tick 1000 times/sec
* Timer 1 was used for DRAM refresh in early PC's
* Timer 2 is used to drive the speaker
- * (to stasrt a beep: write 3 to port 0x61,
+ * (to start a beep: write 3 to port 0x61,
* to stop it again: write 0)
*/
outb(PIT_CMD_CTR0 | PIT_CMD_BOTH | PIT_CMD_MODE2,
diff --git a/arch/x86/lib/physmem.c b/arch/x86/lib/physmem.c
new file mode 100644
index 0000000000..18f0e62acd
--- /dev/null
+++ b/arch/x86/lib/physmem.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#include <common.h>
+#include <physmem.h>
+#include <linux/compiler.h>
+
+/* Large pages are 2MB. */
+#define LARGE_PAGE_SIZE ((1 << 20) * 2)
+
+/*
+ * Paging data structures.
+ */
+
+struct pdpe {
+ uint64_t p:1;
+ uint64_t mbz_0:2;
+ uint64_t pwt:1;
+ uint64_t pcd:1;
+ uint64_t mbz_1:4;
+ uint64_t avl:3;
+ uint64_t base:40;
+ uint64_t mbz_2:12;
+};
+
+typedef struct pdpe pdpt_t[512];
+
+struct pde {
+ uint64_t p:1; /* present */
+ uint64_t rw:1; /* read/write */
+ uint64_t us:1; /* user/supervisor */
+ uint64_t pwt:1; /* page-level writethrough */
+ uint64_t pcd:1; /* page-level cache disable */
+ uint64_t a:1; /* accessed */
+ uint64_t d:1; /* dirty */
+ uint64_t ps:1; /* page size */
+ uint64_t g:1; /* global page */
+ uint64_t avl:3; /* available to software */
+ uint64_t pat:1; /* page-attribute table */
+ uint64_t mbz_0:8; /* must be zero */
+ uint64_t base:31; /* base address */
+};
+
+typedef struct pde pdt_t[512];
+
+static pdpt_t pdpt __aligned(4096);
+static pdt_t pdts[4] __aligned(4096);
+
+/*
+ * Map a virtual address to a physical address and optionally invalidate any
+ * old mapping.
+ *
+ * @param virt The virtual address to use.
+ * @param phys The physical address to use.
+ * @param invlpg Whether to use invlpg to clear any old mappings.
+ */
+static void x86_phys_map_page(uintptr_t virt, phys_addr_t phys, int invlpg)
+{
+ /* Extract the two bit PDPT index and the 9 bit PDT index. */
+ uintptr_t pdpt_idx = (virt >> 30) & 0x3;
+ uintptr_t pdt_idx = (virt >> 21) & 0x1ff;
+
+ /* Set up a handy pointer to the appropriate PDE. */
+ struct pde *pde = &(pdts[pdpt_idx][pdt_idx]);
+
+ memset(pde, 0, sizeof(struct pde));
+ pde->p = 1;
+ pde->rw = 1;
+ pde->us = 1;
+ pde->ps = 1;
+ pde->base = phys >> 21;
+
+ if (invlpg) {
+ /* Flush any stale mapping out of the TLBs. */
+ __asm__ __volatile__(
+ "invlpg %0\n\t"
+ :
+ : "m" (*(uint8_t *)virt)
+ );
+ }
+}
+
+/* Identity map the lower 4GB and turn on paging with PAE. */
+static void x86_phys_enter_paging(void)
+{
+ phys_addr_t page_addr;
+ unsigned i;
+
+ /* Zero out the page tables. */
+ memset(pdpt, 0, sizeof(pdpt));
+ memset(pdts, 0, sizeof(pdts));
+
+ /* Set up the PDPT. */
+ for (i = 0; i < ARRAY_SIZE(pdts); i++) {
+ pdpt[i].p = 1;
+ pdpt[i].base = ((uintptr_t)&pdts[i]) >> 12;
+ }
+
+ /* Identity map everything up to 4GB. */
+ for (page_addr = 0; page_addr < (1ULL << 32);
+ page_addr += LARGE_PAGE_SIZE) {
+ /* There's no reason to invalidate the TLB with paging off. */
+ x86_phys_map_page(page_addr, page_addr, 0);
+ }
+
+ /* Turn on paging */
+ __asm__ __volatile__(
+ /* Load the page table address */
+ "movl %0, %%cr3\n\t"
+ /* Enable pae */
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x00000020, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ /* Enable paging */
+ "movl %%cr0, %%eax\n\t"
+ "orl $0x80000000, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ :
+ : "r" (pdpt)
+ : "eax"
+ );
+}
+
+/* Disable paging and PAE mode. */
+static void x86_phys_exit_paging(void)
+{
+ /* Turn off paging */
+ __asm__ __volatile__ (
+ /* Disable paging */
+ "movl %%cr0, %%eax\n\t"
+ "andl $0x7fffffff, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ /* Disable pae */
+ "movl %%cr4, %%eax\n\t"
+ "andl $0xffffffdf, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ :
+ :
+ : "eax"
+ );
+}
+
+/*
+ * Set physical memory to a particular value when the whole region fits on one
+ * page.
+ *
+ * @param map_addr The address that starts the physical page.
+ * @param offset How far into that page to start setting a value.
+ * @param c The value to set memory to.
+ * @param size The size in bytes of the area to set.
+ */
+static void x86_phys_memset_page(phys_addr_t map_addr, uintptr_t offset, int c,
+ unsigned size)
+{
+ /*
+ * U-Boot should be far away from the beginning of memory, so that's a
+ * good place to map our window on top of.
+ */
+ const uintptr_t window = LARGE_PAGE_SIZE;
+
+ /* Make sure the window is below U-Boot. */
+ assert(window + LARGE_PAGE_SIZE <
+ gd->relocaddr - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_STACK_SIZE);
+ /* Map the page into the window and then memset the appropriate part. */
+ x86_phys_map_page(window, map_addr, 1);
+ memset((void *)(window + offset), c, size);
+}
+
+/*
+ * A physical memory anologue to memset with matching parameters and return
+ * value.
+ */
+phys_addr_t arch_phys_memset(phys_addr_t start, int c, phys_size_t size)
+{
+ const phys_addr_t max_addr = (phys_addr_t)~(uintptr_t)0;
+ const phys_addr_t orig_start = start;
+
+ if (!size)
+ return orig_start;
+
+ /* Handle memory below 4GB. */
+ if (start <= max_addr) {
+ phys_size_t low_size = MIN(max_addr + 1 - start, size);
+ void *start_ptr = (void *)(uintptr_t)start;
+
+ assert(((phys_addr_t)(uintptr_t)start) == start);
+ memset(start_ptr, c, low_size);
+ start += low_size;
+ size -= low_size;
+ }
+
+ /* Use paging and PAE to handle memory above 4GB up to 64GB. */
+ if (size) {
+ phys_addr_t map_addr = start & ~(LARGE_PAGE_SIZE - 1);
+ phys_addr_t offset = start - map_addr;
+
+ x86_phys_enter_paging();
+
+ /* Handle the first partial page. */
+ if (offset) {
+ phys_addr_t end =
+ MIN(map_addr + LARGE_PAGE_SIZE, start + size);
+ phys_size_t cur_size = end - start;
+ x86_phys_memset_page(map_addr, offset, c, cur_size);
+ size -= cur_size;
+ map_addr += LARGE_PAGE_SIZE;
+ }
+ /* Handle the complete pages. */
+ while (size > LARGE_PAGE_SIZE) {
+ x86_phys_memset_page(map_addr, 0, c, LARGE_PAGE_SIZE);
+ size -= LARGE_PAGE_SIZE;
+ map_addr += LARGE_PAGE_SIZE;
+ }
+ /* Handle the last partial page. */
+ if (size)
+ x86_phys_memset_page(map_addr, 0, c, size);
+
+ x86_phys_exit_paging();
+ }
+ return orig_start;
+}
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c
index 200baaba6a..23edca9526 100644
--- a/arch/x86/lib/relocate.c
+++ b/arch/x86/lib/relocate.c
@@ -80,12 +80,12 @@ int do_elf_reloc_fixups(void)
/* Check that the target points into .text */
if (*offset_ptr_ram >= CONFIG_SYS_TEXT_BASE &&
- *offset_ptr_ram <
+ *offset_ptr_ram <=
(CONFIG_SYS_TEXT_BASE + size)) {
*offset_ptr_ram += gd->reloc_off;
}
}
- } while (re_src++ < re_end);
+ } while (++re_src < re_end);
return 0;
}
diff --git a/arch/x86/lib/timer.c b/arch/x86/lib/timer.c
index fd7032e92c..a13424b3e3 100644
--- a/arch/x86/lib/timer.c
+++ b/arch/x86/lib/timer.c
@@ -37,6 +37,7 @@ struct timer_isr_function {
static struct timer_isr_function *first_timer_isr;
static unsigned long system_ticks;
+static uint64_t base_value;
/*
* register_timer_isr() allows multiple architecture and board specific
@@ -98,3 +99,19 @@ ulong get_timer(ulong base)
{
return system_ticks - base;
}
+
+void timer_set_tsc_base(uint64_t new_base)
+{
+ base_value = new_base;
+}
+
+uint64_t timer_get_tsc(void)
+{
+ uint64_t time_now;
+
+ time_now = rdtsc();
+ if (!base_value)
+ base_value = time_now;
+
+ return time_now - base_value;
+}
diff --git a/arch/x86/lib/video.c b/arch/x86/lib/video.c
index 3d6b24d620..20e2416ae1 100644
--- a/arch/x86/lib/video.c
+++ b/arch/x86/lib/video.c
@@ -222,8 +222,10 @@ int video_init(void)
int drv_video_init(void)
{
+#ifndef CONFIG_X86_NO_REAL_MODE
if (video_bios_init())
return 1;
+#endif
return video_init();
}
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index 22142864c2..46af391f29 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -36,6 +36,10 @@
#include <asm/realmode.h>
#include <asm/byteorder.h>
#include <asm/bootparam.h>
+#ifdef CONFIG_SYS_COREBOOT
+#include <asm/arch/timestamp.h>
+#endif
+#include <linux/compiler.h>
/*
* Memory lay-out:
@@ -171,7 +175,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
else
*load_address = (void *)ZIMAGE_LOAD_ADDR;
-#if defined CONFIG_ZBOOT_32
+#if (defined CONFIG_ZBOOT_32 || defined CONFIG_X86_NO_REAL_MODE)
printf("Building boot_params at 0x%8.8lx\n", (ulong)setup_base);
memset(setup_base, 0, sizeof(*setup_base));
setup_base->hdr = params->hdr;
@@ -237,7 +241,7 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
struct setup_header *hdr = &setup_base->hdr;
int bootproto = get_boot_protocol(hdr);
-#if defined CONFIG_ZBOOT_32
+#if (defined CONFIG_ZBOOT_32 || defined CONFIG_X86_NO_REAL_MODE)
setup_base->e820_entries = install_e820_map(
ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map);
#endif
@@ -279,10 +283,23 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
return 0;
}
+/*
+ * Implement a weak default function for boards that optionally
+ * need to clean up the system before jumping to the kernel.
+ */
+__weak void board_final_cleanup(void)
+{
+}
+
void boot_zimage(void *setup_base, void *load_address)
{
+ board_final_cleanup();
+
printf("\nStarting kernel ...\n\n");
+#ifdef CONFIG_SYS_COREBOOT
+ timestamp_add_now(TS_U_BOOT_START_KERNEL);
+#endif
#if defined CONFIG_ZBOOT_32
/*
* Set %ebx, %ebp, and %edi to 0, %esi to point to the boot_params
@@ -292,9 +309,9 @@ void boot_zimage(void *setup_base, void *load_address)
* itself in arch/i386/cpu/cpu.c.
*/
__asm__ __volatile__ (
- "movl $0, %%ebp \n"
- "cli \n"
- "jmp %[kernel_entry] \n"
+ "movl $0, %%ebp\n"
+ "cli\n"
+ "jmp *%[kernel_entry]\n"
:: [kernel_entry]"a"(load_address),
[boot_params] "S"(setup_base),
"b"(0), "D"(0)
diff --git a/board/BuS/eb_cpu5282/Makefile b/board/BuS/eb_cpu5282/Makefile
index 0f14699c5e..ac860c1348 100644
--- a/board/BuS/eb_cpu5282/Makefile
+++ b/board/BuS/eb_cpu5282/Makefile
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
-COBJS = $(BOARD).o cfm_flash.o flash.o
+COBJS = $(BOARD).o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/board/BuS/eb_cpu5282/cfm_flash.c b/board/BuS/eb_cpu5282/cfm_flash.c
deleted file mode 100644
index fe03b17581..0000000000
--- a/board/BuS/eb_cpu5282/cfm_flash.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Basic Flash Driver for Freescale MCF 5281/5282 internal FLASH
- *
- * (C) Copyright 2005 BuS Elektronik GmbH & Co.KG <esw@bus-elektonik.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/m5282.h>
-#include "cfm_flash.h"
-
-#if defined(CONFIG_M5281) || defined(CONFIG_M5282)
-
-#if (CONFIG_SYS_CLK>20000000)
- #define CFM_CLK (((long) CONFIG_SYS_CLK / (400000 * 8) + 1) | 0x40)
-#else
- #define CFM_CLK ((long) CONFIG_SYS_CLK / 400000 + 1)
-#endif
-
-#define cmf_backdoor_address(addr) (((addr) & 0x0007FFFF) | 0x04000000 | \
- (CONFIG_SYS_MBAR & 0xC0000000))
-
-void cfm_flash_print_info (flash_info_t * info)
-{
- printf ("Freescale: ");
- switch (info->flash_id & FLASH_TYPEMASK) {
- case FREESCALE_ID_MCF5281 & FLASH_TYPEMASK:
- printf ("MCF5281 internal FLASH\n");
- break;
- case FREESCALE_ID_MCF5282 & FLASH_TYPEMASK:
- printf ("MCF5282 internal FLASH\n");
- break;
- default:
- printf ("Unknown Chip Type\n");
- break;
- }
-}
-
-void cfm_flash_init (flash_info_t * info)
-{
- int sector;
- ulong protection;
- MCFCFM_MCR = 0;
- MCFCFM_CLKD = CFM_CLK;
- debug ("CFM Clock divider: %ld (%d Hz @ %ld Hz)\n",CFM_CLK,\
- CONFIG_SYS_CLK / (2* ((CFM_CLK & 0x3F)+1) * (1+((CFM_CLK & 0x40)>>6)*7)),\
- CONFIG_SYS_CLK);
- MCFCFM_SACC = 0;
- MCFCFM_DACC = 0;
-
- if (MCFCFM_SEC & MCFCFM_SEC_KEYEN)
- puts("CFM backdoor access is enabled\n");
- if (MCFCFM_SEC & MCFCFM_SEC_SECSTAT)
- puts("CFM securety is enabled\n");
-
- #ifdef CONFIG_M5281
- info->flash_id = (FREESCALE_MANUFACT & FLASH_VENDMASK) |
- (FREESCALE_ID_MCF5281 & FLASH_TYPEMASK);
- info->size = 256*1024;
- info->sector_count = 16;
- #else
- info->flash_id = (FREESCALE_MANUFACT & FLASH_VENDMASK) |
- (FREESCALE_ID_MCF5282 & FLASH_TYPEMASK);
- info->size = 512*1024;
- info->sector_count = 32;
- #endif
- protection = MCFCFM_PROT;
- for (sector = 0; sector < info->sector_count; sector++)
- {
- if (sector == 0)
- {
- info->start[sector] = CONFIG_SYS_INT_FLASH_BASE;
- }
- else
- {
- info->start[sector] = info->start[sector-1] + 0x04000;
- }
- info->protect[sector] = protection & 1;
- protection >>= 1;
- }
-}
-
-int cfm_flash_readycheck(int checkblank)
-{
- int rc;
- unsigned char state;
-
- rc = ERR_OK;
- while (!(MCFCFM_USTAT & MCFCFM_USTAT_CCIF));
- state = MCFCFM_USTAT;
- if (state & MCFCFM_USTAT_ACCERR)
- {
- debug ("%s(): CFM access error",__FUNCTION__);
- rc = ERR_PROG_ERROR;
- }
- if (state & MCFCFM_USTAT_PVIOL)
- {
- debug ("%s(): CFM protection violation",__FUNCTION__);
- rc = ERR_PROTECTED;
- }
- if (checkblank)
- {
- if (!(state & MCFCFM_USTAT_BLANK))
- {
- debug ("%s(): CFM erras error",__FUNCTION__);
- rc = ERR_NOT_ERASED;
- }
- }
- MCFCFM_USTAT = state & 0x34; /* reset state */
- return rc;
-}
-
-/* Erase 16KiB = 8 2KiB pages */
-
-int cfm_flash_erase_sector (flash_info_t * info, int sector)
-{
- ulong address;
- int page;
- int rc;
- rc= ERR_OK;
- address = cmf_backdoor_address(info->start[sector]);
- for (page=0; (page<8) && (rc==ERR_OK); page++)
- {
- *(volatile __u32*) address = 0;
- MCFCFM_CMD = MCFCFM_CMD_PGERS;
- MCFCFM_USTAT = MCFCFM_USTAT_CBEIF;
- rc = cfm_flash_readycheck(0);
- if (rc==ERR_OK)
- {
- *(volatile __u32*) address = 0;
- MCFCFM_CMD = MCFCFM_CMD_PGERSVER;
- MCFCFM_USTAT = MCFCFM_USTAT_CBEIF;
- rc = cfm_flash_readycheck(1);
- }
- address += 0x800;
- }
- return rc;
-}
-
-int cfm_flash_write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
-{
- int rc;
- ulong dest, data;
-
- rc = ERR_OK;
- if (addr & 3)
- {
- debug ("Byte and Word alignment not supported\n");
- rc = ERR_ALIGN;
- }
- if (cnt & 3)
- {
- debug ("Byte and Word transfer not supported\n");
- rc = ERR_ALIGN;
- }
- dest = cmf_backdoor_address(addr);
- while ((cnt>=4) && (rc == ERR_OK))
- {
- data = *((volatile u32 *) src);
- *(volatile u32*) dest = data;
- MCFCFM_CMD = MCFCFM_CMD_PGM;
- MCFCFM_USTAT = MCFCFM_USTAT_CBEIF;
- rc = cfm_flash_readycheck(0);
- if (*(volatile u32*) addr != data) rc = ERR_PROG_ERROR;
- src +=4;
- dest +=4;
- addr +=4;
- cnt -=4;
- }
- return rc;
-}
-
-#ifdef CONFIG_SYS_FLASH_PROTECTION
-
-int cfm_flash_protect(flash_info_t * info,long sector,int prot)
-{
- int rc;
-
- rc= ERR_OK;
- if (prot)
- {
- MCFCFM_PROT |= (1<<sector);
- info->protect[sector]=1;
- }
- else
- {
- MCFCFM_PROT &= ~(1<<sector);
- info->protect[sector]=0;
- }
- return rc;
-}
-
-#endif
-
-#endif
diff --git a/board/BuS/eb_cpu5282/cfm_flash.h b/board/BuS/eb_cpu5282/cfm_flash.h
deleted file mode 100644
index ed4e7943e7..0000000000
--- a/board/BuS/eb_cpu5282/cfm_flash.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Basic Flash Driver for Freescale MCF 5282 internal FLASH
- *
- * (C) Copyright 2005 BuS Elektronik GmbH & Co.KG <esw@bus-elektonik.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 __CFM_FLASH_H_
-#define __CFM_FLASH_H_
-
-#define FREESCALE_MANUFACT 0xFACFFACF
-#define FREESCALE_ID_MCF5281 0x5281
-#define FREESCALE_ID_MCF5282 0x5282
-
-extern void cfm_flash_print_info (flash_info_t * info);
-extern int cfm_flash_erase_sector (flash_info_t * info, int sector);
-extern void cfm_flash_init (flash_info_t * info);
-extern int cfm_flash_write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt);
-#ifdef CONFIG_SYS_FLASH_PROTECTION
-extern int cfm_flash_protect(flash_info_t * info,long sector,int prot);
-#endif
-
-#endif
diff --git a/board/BuS/eb_cpu5282/eb_cpu5282.c b/board/BuS/eb_cpu5282/eb_cpu5282.c
index d64ad1b705..f73431eff5 100644
--- a/board/BuS/eb_cpu5282/eb_cpu5282.c
+++ b/board/BuS/eb_cpu5282/eb_cpu5282.c
@@ -35,18 +35,19 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifdef CONFIG_VIDEO
unsigned long display_width;
unsigned long display_height;
+#endif
/*---------------------------------------------------------------------------*/
int checkboard (void)
{
- puts ("Board: MCF-EV1 + MCF-EV23 (BuS Elektronik GmbH & Co. KG)\n");
+ puts("Board: EB+CPU5282 (BuS Elektronik GmbH & Co. KG)\n");
#if (CONFIG_SYS_TEXT_BASE == CONFIG_SYS_INT_FLASH_BASE)
- puts (" Boot from Internal FLASH\n");
+ puts(" Boot from Internal FLASH\n");
#endif
-
return 0;
}
@@ -55,29 +56,39 @@ phys_size_t initdram (int board_type)
int size, i;
size = 0;
- MCFSDRAMC_DCR = MCFSDRAMC_DCR_RTIM_6
- | MCFSDRAMC_DCR_RC ((15 * CONFIG_SYS_CLK) >> 4);
+ MCFSDRAMC_DCR = MCFSDRAMC_DCR_RTIM_6 |
+ MCFSDRAMC_DCR_RC((15 * CONFIG_SYS_CLK / 1000000) >> 4);
+ asm (" nop");
#ifdef CONFIG_SYS_SDRAM_BASE0
-
- MCFSDRAMC_DACR0 = MCFSDRAMC_DACR_BASE (CONFIG_SYS_SDRAM_BASE0)
- | MCFSDRAMC_DACR_CASL (1)
- | MCFSDRAMC_DACR_CBM (3)
- | MCFSDRAMC_DACR_PS_16;
+ MCFSDRAMC_DACR0 = MCFSDRAMC_DACR_BASE(CONFIG_SYS_SDRAM_BASE0)|
+ MCFSDRAMC_DACR_CASL(1) | MCFSDRAMC_DACR_CBM(3) |
+ MCFSDRAMC_DACR_PS_32;
+ asm (" nop");
MCFSDRAMC_DMR0 = MCFSDRAMC_DMR_BAM_16M | MCFSDRAMC_DMR_V;
+ asm (" nop");
MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IP;
+ asm (" nop");
+ for (i = 0; i < 10; i++)
+ asm (" nop");
- *(unsigned short *) (CONFIG_SYS_SDRAM_BASE0) = 0xA5A5;
+ *(unsigned long *)(CONFIG_SYS_SDRAM_BASE0) = 0xA5A5A5A5;
+ asm (" nop");
MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_RE;
+ asm (" nop");
+
for (i = 0; i < 2000; i++)
asm (" nop");
- mbar_writeLong (MCFSDRAMC_DACR0,
- mbar_readLong (MCFSDRAMC_DACR0) | MCFSDRAMC_DACR_IMRS);
- *(unsigned int *) (CONFIG_SYS_SDRAM_BASE0 + 0x220) = 0xA5A5;
- size += CONFIG_SYS_SDRAM_SIZE * 1024 * 1024;
+
+ MCFSDRAMC_DACR0 |= MCFSDRAMC_DACR_IMRS;
+ asm (" nop");
+ /* write SDRAM mode register */
+ *(unsigned long *)(CONFIG_SYS_SDRAM_BASE0 + 0x80440) = 0xA5A5A5A5;
+ asm (" nop");
+ size += CONFIG_SYS_SDRAM_SIZE0 * 1024 * 1024;
#endif
-#ifdef CONFIG_SYS_SDRAM_BASE1
+#ifdef CONFIG_SYS_SDRAM_BASE1xx
MCFSDRAMC_DACR1 = MCFSDRAMC_DACR_BASE (CONFIG_SYS_SDRAM_BASE1)
| MCFSDRAMC_DACR_CASL (1)
| MCFSDRAMC_DACR_CBM (3)
@@ -134,38 +145,74 @@ int testdram (void)
}
#endif
+#if defined(CONFIG_HW_WATCHDOG)
+
+void hw_watchdog_init(void)
+{
+ char *s;
+ int enable;
+
+ enable = 1;
+ s = getenv("watchdog");
+ if (s != NULL)
+ if ((strncmp(s, "off", 3) == 0) || (strncmp(s, "0", 1) == 0))
+ enable = 0;
+ if (enable)
+ MCFGPTA_GPTDDR |= (1<<2);
+ else
+ MCFGPTA_GPTDDR &= ~(1<<2);
+}
+
+void hw_watchdog_reset(void)
+{
+ MCFGPTA_GPTPORT ^= (1<<2);
+}
+#endif
+
int misc_init_r(void)
{
#ifdef CONFIG_HW_WATCHDOG
hw_watchdog_init();
#endif
-#ifndef CONFIG_VIDEO
- vcxk_init(16, 16);
-#endif
return 1;
}
-#if defined(CONFIG_VIDEO)
+void __led_toggle(led_id_t mask)
+{
+ MCFGPTA_GPTPORT ^= (1 << 3);
+}
-/*
- ****h* EB+CPU5282-T1/drv_video_init
- * FUNCTION
- ***
- */
+void __led_init(led_id_t mask, int state)
+{
+ __led_set(mask, state);
+ MCFGPTA_GPTDDR |= (1 << 3);
+}
+
+void __led_set(led_id_t mask, int state)
+{
+ if (state == STATUS_LED_ON)
+ MCFGPTA_GPTPORT |= (1 << 3);
+ else
+ MCFGPTA_GPTPORT &= ~(1 << 3);
+}
+
+#if defined(CONFIG_VIDEO)
int drv_video_init(void)
{
char *s;
+#ifdef CONFIG_SPLASH_SCREEN
unsigned long splash;
-
+#endif
printf("Init Video as ");
-
- if ((s = getenv("displaywidth")) != NULL)
+ s = getenv("displaywidth");
+ if (s != NULL)
display_width = simple_strtoul(s, NULL, 10);
else
display_width = 256;
- if ((s = getenv("displayheight")) != NULL)
+ s = getenv("displayheight");
+ if (s != NULL)
display_height = simple_strtoul(s, NULL, 10);
else
display_height = 256;
@@ -178,10 +225,9 @@ int drv_video_init(void)
vcxk_init(display_width, display_height);
#ifdef CONFIG_SPLASH_SCREEN
- if ((s = getenv("splashimage")) != NULL) {
- debug("use splashimage: %s\n", s);
+ s = getenv("splashimage");
+ if (s != NULL) {
splash = simple_strtoul(s, NULL, 16);
- debug("use splashimage: %x\n", splash);
vcxk_acknowledge_wait();
video_display_bitmap(splash, 0, 0);
}
diff --git a/board/BuS/eb_cpu5282/flash.c b/board/BuS/eb_cpu5282/flash.c
deleted file mode 100644
index 8b7f9578fc..0000000000
--- a/board/BuS/eb_cpu5282/flash.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * (C) Copyright 2005
- * BuS Elektronik GmbH & Co.KG <esw@bus-elektonik.de>
- *
- * Based On
- * 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 "cfm_flash.h"
-
-#define PHYS_FLASH_1 CONFIG_SYS_FLASH_BASE
-#define FLASH_BANK_SIZE 0x200000
-
-flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
-
-void flash_print_info (flash_info_t * info)
-{
- int i;
-
- switch (info->flash_id & FLASH_VENDMASK) {
- case (AMD_MANUFACT & FLASH_VENDMASK):
- printf ("AMD: ");
- switch (info->flash_id & FLASH_TYPEMASK) {
- case (AMD_ID_LV160B & FLASH_TYPEMASK):
- printf ("AM29LV160B (16Bit)\n");
- break;
- default:
- printf ("Unknown Chip Type\n");
- break;
- }
- break;
- case FREESCALE_MANUFACT & FLASH_VENDMASK:
- cfm_flash_print_info (info);
- break;
- default:
- printf ("Unknown Vendor ");
- break;
- }
-
- puts (" Size: ");
- if ((info->size >> 20) > 0)
- {
- printf ("%ld MiB",info->size >> 20);
- }
- else
- {
- printf ("%ld KiB",info->size >> 10);
- }
- printf (" in %d Sectors\n", info->sector_count);
-
- printf (" Sector Start Addresses:");
- for (i = 0; i < info->sector_count; i++) {
- if ((i % 4) == 0) {
- printf ("\n ");
- }
- printf ("%02d: %08lX%s ", i,info->start[i],
- info->protect[i] ? " P" : " ");
- }
- printf ("\n\n");
-}
-
-unsigned long flash_init (void)
-{
- int i, j;
- ulong size = 0;
-
- for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
- ulong flashbase = 0;
-
- switch (i)
- {
- case 1:
- flash_info[i].flash_id =
- (AMD_MANUFACT & FLASH_VENDMASK) |
- (AMD_ID_LV160B & FLASH_TYPEMASK);
- flash_info[i].size = FLASH_BANK_SIZE;
- flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
- memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
- flashbase = PHYS_FLASH_1;
- for (j = 0; j < flash_info[i].sector_count; j++) {
- if (j == 0) {
- /* 1st is 16 KiB */
- flash_info[i].start[j] = flashbase;
- }
- if ((j >= 1) && (j <= 2)) {
- /* 2nd and 3rd are 8 KiB */
- flash_info[i].start[j] =
- flashbase + 0x4000 + 0x2000 * (j - 1);
- }
- if (j == 3) {
- /* 4th is 32 KiB */
- flash_info[i].start[j] = flashbase + 0x8000;
- }
- if ((j >= 4) && (j <= 34)) {
- /* rest is 256 KiB */
- flash_info[i].start[j] =
- flashbase + 0x10000 + 0x10000 * (j - 4);
- }
- }
- break;
- case 0:
- cfm_flash_init (&flash_info[i]);
- break;
- default:
- panic ("configured to many flash banks!\n");
- }
-
- size += flash_info[i].size;
- }
-
- flash_protect (FLAG_PROTECT_SET,
- CONFIG_SYS_FLASH_BASE,
- CONFIG_SYS_FLASH_BASE + 0xffff, &flash_info[0]);
-
- return size;
-}
-
-#define CMD_READ_ARRAY 0x00F0
-#define CMD_UNLOCK1 0x00AA
-#define CMD_UNLOCK2 0x0055
-#define CMD_ERASE_SETUP 0x0080
-#define CMD_ERASE_CONFIRM 0x0030
-#define CMD_PROGRAM 0x00A0
-#define CMD_UNLOCK_BYPASS 0x0020
-
-#define MEM_FLASH_ADDR1 (*(volatile u16 *)(info->start[0] + (0x00000555<<1)))
-#define MEM_FLASH_ADDR2 (*(volatile u16 *)(info->start[0] + (0x000002AA<<1)))
-
-
-#define BIT_ERASE_DONE 0x0080
-#define BIT_RDY_MASK 0x0080
-#define BIT_PROGRAM_ERROR 0x0020
-#define BIT_TIMEOUT 0x80000000 /* our flag */
-
-#define ERR_READY -1
-
-int amd_flash_erase_sector(flash_info_t * info, int sector)
-{
- int state;
- ulong result;
- ulong start;
-
- volatile u16 *addr =
- (volatile u16 *) (info->start[sector]);
-
- MEM_FLASH_ADDR1 = CMD_UNLOCK1;
- MEM_FLASH_ADDR2 = CMD_UNLOCK2;
- MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
-
- MEM_FLASH_ADDR1 = CMD_UNLOCK1;
- MEM_FLASH_ADDR2 = CMD_UNLOCK2;
- *addr = CMD_ERASE_CONFIRM;
-
- /* wait until flash is ready */
- state = 0;
- start = get_timer(0);
-
- do {
- result = *addr;
-
- /* check timeout */
- if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
- MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
- state = ERR_TIMOUT;
- }
-
- if (!state && (result & 0xFFFF) & BIT_ERASE_DONE)
- state = ERR_READY;
- }
- while (!state);
- if (state == ERR_READY)
- state = ERR_OK;
-
- MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
-
- return state;
-}
-
-int flash_erase (flash_info_t * info, int s_first, int s_last)
-{
- int iflag, cflag;
- int sector;
- int rc;
-
- rc = ERR_OK;
-
- if (info->flash_id == FLASH_UNKNOWN)
- {
- rc = ERR_UNKNOWN_FLASH_TYPE;
- } /* (info->flash_id == FLASH_UNKNOWN) */
-
- if ((s_first < 0) || (s_first > s_last) || s_last >= info->sector_count)
- {
- rc = ERR_INVAL;
- }
-
- cflag = icache_status ();
- icache_disable ();
- iflag = disable_interrupts ();
-
- for (sector = s_first; (sector <= s_last) && (rc == ERR_OK); sector++) {
-
- if (info->protect[sector])
- {
- putc('P'); /* protected sector will not erase */
- }
- else
- {
- /* erase on unprotected sector */
- puts("E\b");
- switch (info->flash_id & FLASH_VENDMASK)
- {
- case (AMD_MANUFACT & FLASH_VENDMASK):
- rc = amd_flash_erase_sector(info,sector);
- break;
- case (FREESCALE_MANUFACT & FLASH_VENDMASK):
- rc = cfm_flash_erase_sector(info,sector);
- break;
- default:
- return ERR_UNKNOWN_FLASH_VENDOR;
- }
- putc('.');
- }
- }
- if (rc!=ERR_OK)
- {
- printf ("\n ");
- flash_perror (rc);
- }
- else
- {
- printf (" done\n");
- }
-
- udelay (10000); /* allow flash to settle - wait 10 ms */
-
- if (iflag)
- enable_interrupts ();
-
- if (cflag)
- icache_enable ();
-
- return rc;
-}
-
-volatile static int amd_write_word (flash_info_t * info, ulong dest, u16 data)
-{
- volatile u16 *addr;
- ulong result;
- int cflag, iflag;
- int state;
- ulong start;
-
- /*
- * Check if Flash is (sufficiently) erased
- */
- addr = (volatile u16 *) dest;
-
- result = *addr;
- if ((result & data) != data)
- return ERR_NOT_ERASED;
-
- /*
- * Disable interrupts which might cause a timeout
- * here. Remember that our exception vectors are
- * at address 0 in the flash, and we don't want a
- * (ticker) exception to happen while the flash
- * chip is in programming mode.
- */
-
- cflag = icache_status ();
- icache_disable ();
- iflag = disable_interrupts ();
-
- MEM_FLASH_ADDR1 = CMD_UNLOCK1;
- MEM_FLASH_ADDR2 = CMD_UNLOCK2;
- MEM_FLASH_ADDR1 = CMD_PROGRAM;
- *addr = data;
-
- /* arm simple, non interrupt dependent timer */
- start = get_timer(0);
-
- /* wait until flash is ready */
- state = 0;
- do {
- result = *addr;
-
- /* check timeout */
- if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
- state = ERR_TIMOUT;
- }
- if (!state && ((result & BIT_RDY_MASK) == (data & BIT_RDY_MASK)))
- state = ERR_READY;
-
- } while (!state);
-
- *addr = CMD_READ_ARRAY;
-
- if (state == ERR_READY)
- state = ERR_OK;
- if ((*addr != data) && (state != ERR_TIMOUT))
- state = ERR_PROG_ERROR;
-
- if (iflag)
- enable_interrupts ();
-
- if (cflag)
- icache_enable ();
-
- return state;
-}
-
-int amd_flash_write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
-{
- int rc;
- ulong dest;
- u16 data;
-
- rc = ERR_OK;
- if (addr & 1)
- {
- debug ("Byte alignment not supported\n");
- rc = ERR_ALIGN;
- }
- if (cnt & 1)
- {
- debug ("Byte transfer not supported\n");
- rc = ERR_ALIGN;
- }
-
- dest = addr;
- while ((cnt>=2) && (rc == ERR_OK))
- {
- data = *((volatile u16 *) src);
- rc=amd_write_word (info,dest,data);
- src +=2;
- dest +=2;
- cnt -=2;
- }
- return rc;
-}
-
-int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
-{
- int rc;
-
- switch (info->flash_id & FLASH_VENDMASK)
- {
- case (AMD_MANUFACT & FLASH_VENDMASK):
- rc = amd_flash_write_buff(info,src,addr,cnt);
- break;
- case (FREESCALE_MANUFACT & FLASH_VENDMASK):
- rc = cfm_flash_write_buff(info,src,addr,cnt);
- break;
- default:
- rc = ERR_UNKNOWN_FLASH_VENDOR;
- }
- return rc;
-
-}
-int amd_flash_protect(flash_info_t * info,long sector,int prot)
-{
- int rc;
- rc= ERR_OK;
- if (prot)
- {
- info->protect[sector]=1;
- }
- else
- {
- info->protect[sector]=0;
- }
- return rc;
-}
-
-#ifdef CONFIG_SYS_FLASH_PROTECTION
-
-int flash_real_protect(flash_info_t * info,long sector,int prot)
-{
- int rc;
-
- switch (info->flash_id & FLASH_VENDMASK)
- {
- case (AMD_MANUFACT & FLASH_VENDMASK):
- rc = amd_flash_protect(info,sector,prot);
- break;
- case (FREESCALE_MANUFACT & FLASH_VENDMASK):
- rc = cfm_flash_protect(info,sector,prot);
- break;
- default:
- rc = ERR_UNKNOWN_FLASH_VENDOR;
- }
- return rc;
-}
-
-#endif
diff --git a/board/a3m071/Makefile b/board/a3m071/Makefile
new file mode 100644
index 0000000000..6f961fb6e3
--- /dev/null
+++ b/board/a3m071/Makefile
@@ -0,0 +1,36 @@
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(BOARD).o
+
+COBJS := $(BOARD).o
+
+SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+SOBJS := $(addprefix $(obj),$(SOBJS))
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/board/a3m071/README b/board/a3m071/README
new file mode 100644
index 0000000000..7698614a62
--- /dev/null
+++ b/board/a3m071/README
@@ -0,0 +1,80 @@
+------------------------------------------------------------------------
+A3M071 board support
+------------------------------------------------------------------------
+
+
+SPL NOR flash support:
+----------------------
+To boot fast into the OS (Linux), this board port integrates the SPL
+framework. This means, that a special, stripped-down version of
+U-Boot runs in the beginning. In the case of the A3M071 board, this
+SPL U-Boot version is less than 16 KiB big. This SPL U-Boot can either
+boot the OS (Linux) or a "real", full-blown U-Boot. This detection
+on whether to boot Linux or U-Boot is done by using the "boot_os"
+environment variable. If "boot_os" is set to "yes", Linux will be
+loaded and booted from the SPL U-Boot version. Otherwise, the
+full-blown U-Boot version will be loaded and run.
+
+Enabling Linux booting:
+-----------------------
+From U-Boot:
+=> setenv boot_os yes
+=> saveenv
+
+From Linux:
+$ fw_setenv boot_os yes
+
+Enabling U-Boot booting:
+------------------------
+From U-Boot:
+=> setenv boot_os no
+=> saveenv
+
+From Linux:
+$ fw_setenv boot_os no
+
+
+Preparing Linux image(s) for booting from SPL U-Boot:
+-----------------------------------------------------
+To boot the Linux kernel from the SPL, the DT blob (fdt) needs to get
+prepard/patched first. U-Boot usually inserts some dynamic values into
+the DT binary (blob), e.g. autodetected memory size, MAC addresses,
+clocks speeds etc. To generate this patched DT blob, you can use
+the following command:
+
+1. Load fdt blob to SDRAM:
+=> tftp 1800000 a3m071/a3m071.dtb
+
+2. Set bootargs as desired for Linux booting (e.g. flash_mtd):
+=> run mtdargs addip2 addtty
+
+3. Use "fdt" commands to patch the DT blob:
+=> fdt addr 1800000
+=> fdt boardsetup
+=> fdt chosen
+
+4. Display patched DT blob (optional):
+=> fdt print
+
+5. Save fdt to NOR flash:
+=> erase fc060000 fc07ffff
+=> cp.b 1800000 fc060000 10000
+
+All this can be integrated into an environment command:
+=> setenv upd_fdt 'tftp 1800000 a3m071/a3m071.dtb;run mtdargs addip2 addtty; \
+ fdt addr 1800000;fdt boardsetup;erase fc060000 fc07ffff; \
+ cp.b 1800000 fc060000 10000'
+=> saveenv
+
+After this, only "run upd_fdt" needs to get called to load, patch
+and save the DT blob into NOR flash.
+
+Additionally, the Linux kernel image has to be saved uncompressed in
+its uImage file (and not gzip compressed). This can be done with this
+command:
+
+$ mkimage -A ppc -O linux -T kernel -C none -a 0 -e 0 \
+ -n "Linux Kernel Image" -d vmlinux.bin uImage.uncompressed
+
+------------------------------------------------------------------------
+Stefan Roese, 2012-08-23
diff --git a/board/a3m071/a3m071.c b/board/a3m071/a3m071.c
new file mode 100644
index 0000000000..89ced824eb
--- /dev/null
+++ b/board/a3m071/a3m071.c
@@ -0,0 +1,335 @@
+/*
+ * (C) Copyright 2003-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com.
+ *
+ * (C) Copyright 2006
+ * MicroSys GmbH
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <mpc5xxx.h>
+#include <pci.h>
+#include <miiphy.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#include "mt46v16m16-75.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_SYS_RAMBOOT) && \
+ (defined(CONFIG_SPL) && defined(CONFIG_SPL_BUILD))
+static void sdram_start(int hi_addr)
+{
+ long hi_addr_bit = hi_addr ? 0x01000000 : 0;
+ long control = SDRAM_CONTROL | hi_addr_bit;
+
+ /* unlock mode register */
+ out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000000);
+
+ /* precharge all banks */
+ out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
+
+#ifdef SDRAM_DDR
+ /* set mode register: extended mode */
+ out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_EMODE);
+
+ /* set mode register: reset DLL */
+ out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE | 0x04000000);
+#endif
+
+ /* precharge all banks */
+ out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000002);
+
+ /* auto refresh */
+ out_be32((void *)MPC5XXX_SDRAM_CTRL, control | 0x80000004);
+
+ /* set mode register */
+ out_be32((void *)MPC5XXX_SDRAM_MODE, SDRAM_MODE);
+
+ /* normal operation */
+ out_be32((void *)MPC5XXX_SDRAM_CTRL, control);
+}
+#endif
+
+/*
+ * ATTENTION: Although partially referenced initdram does NOT make real use
+ * use of CONFIG_SYS_SDRAM_BASE. The code does not work if
+ * CONFIG_SYS_SDRAM_BASE is something else than 0x00000000.
+ */
+phys_size_t initdram(int board_type)
+{
+ ulong dramsize = 0;
+ ulong dramsize2 = 0;
+ uint svr, pvr;
+#if !defined(CONFIG_SYS_RAMBOOT) && \
+ (defined(CONFIG_SPL) && defined(CONFIG_SPL_BUILD))
+ ulong test1, test2;
+
+ /* setup SDRAM chip selects */
+ out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0x0000001e); /* 2GB at 0x0 */
+ out_be32((void *)MPC5XXX_SDRAM_CS1CFG, 0x80000000); /* disabled */
+
+ /* setup config registers */
+ out_be32((void *)MPC5XXX_SDRAM_CONFIG1, SDRAM_CONFIG1);
+ out_be32((void *)MPC5XXX_SDRAM_CONFIG2, SDRAM_CONFIG2);
+
+#ifdef SDRAM_DDR
+ /* set tap delay */
+ out_be32((void *)MPC5XXX_CDM_PORCFG, SDRAM_TAPDELAY);
+#endif
+
+ /* find RAM size using SDRAM CS0 only */
+ sdram_start(0);
+ test1 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
+ sdram_start(1);
+ test2 = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, 0x80000000);
+ if (test1 > test2) {
+ sdram_start(0);
+ dramsize = test1;
+ } else {
+ dramsize = test2;
+ }
+
+ /* memory smaller than 1MB is impossible */
+ if (dramsize < (1 << 20))
+ dramsize = 0;
+
+ /* set SDRAM CS0 size according to the amount of RAM found */
+ if (dramsize > 0) {
+ out_be32((void *)MPC5XXX_SDRAM_CS0CFG,
+ 0x13 + __builtin_ffs(dramsize >> 20) - 1);
+ } else {
+ out_be32((void *)MPC5XXX_SDRAM_CS0CFG, 0); /* disabled */
+ }
+#else /* CONFIG_SYS_RAMBOOT */
+
+ /* retrieve size of memory connected to SDRAM CS0 */
+ dramsize = in_be32((void *)MPC5XXX_SDRAM_CS0CFG) & 0xFF;
+ if (dramsize >= 0x13)
+ dramsize = (1 << (dramsize - 0x13)) << 20;
+ else
+ dramsize = 0;
+
+ /* retrieve size of memory connected to SDRAM CS1 */
+ dramsize2 = in_be32((void *)MPC5XXX_SDRAM_CS1CFG) & 0xFF;
+ if (dramsize2 >= 0x13)
+ dramsize2 = (1 << (dramsize2 - 0x13)) << 20;
+ else
+ dramsize2 = 0;
+
+#endif /* CONFIG_SYS_RAMBOOT */
+
+ /*
+ * On MPC5200B we need to set the special configuration delay in the
+ * DDR controller. Please refer to Freescale's AN3221 "MPC5200B SDRAM
+ * Initialization and Configuration", 3.3.1 SDelay--MBAR + 0x0190:
+ *
+ * "The SDelay should be written to a value of 0x00000004. It is
+ * required to account for changes caused by normal wafer processing
+ * parameters."
+ */
+ svr = get_svr();
+ pvr = get_pvr();
+ if ((SVR_MJREV(svr) >= 2) && (PVR_MAJ(pvr) == 1) && (PVR_MIN(pvr) == 4))
+ out_be32((void *)MPC5XXX_SDRAM_SDELAY, 0x04);
+
+ return dramsize + dramsize2;
+}
+
+static void get_revisions(int *failsavelevel, int *digiboardversion,
+ int *fpgaversion)
+{
+ struct mpc5xxx_gpt_0_7 *gpt = (struct mpc5xxx_gpt_0_7 *)MPC5XXX_GPT;
+ u8 val;
+
+ /*
+ * Figure out failsavelevel
+ * see ticket dsvk#59
+ */
+ *failsavelevel = 0; /* 0=failsave, 1=board ok, 2=fpga ok */
+
+ /* read digitalboard-version from TMR[2..4] */
+ val = 0;
+ val |= (gpt->gpt2.sr & (1 << (31 - 23))) ? (1) : 0;
+ val |= (gpt->gpt3.sr & (1 << (31 - 23))) ? (1 << 1) : 0;
+ val |= (gpt->gpt4.sr & (1 << (31 - 23))) ? (1 << 2) : 0;
+ *digiboardversion = val;
+
+ if (*digiboardversion == 0) {
+ *failsavelevel = 1; /* digiboard-version ok */
+
+ /* read fpga-version from TMR[5..7] */
+ val = 0;
+ val |= (gpt->gpt5.sr & (1 << (31 - 23))) ? (1) : 0;
+ val |= (gpt->gpt6.sr & (1 << (31 - 23))) ? (1 << 1) : 0;
+ val |= (gpt->gpt7.sr & (1 << (31 - 23))) ? (1 << 2) : 0;
+ *fpgaversion = val;
+
+ if (*fpgaversion == 1)
+ *failsavelevel = 2; /* fpga-version ok */
+ }
+}
+
+/*
+ * This function is called from the SPL U-Boot version for
+ * early init stuff, that needs to be done for OS (e.g. Linux)
+ * booting. Doing it later in the real U-Boot would not work
+ * in case that the SPL U-Boot boots Linux directly.
+ */
+void spl_board_init(void)
+{
+ struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5XXX_GPIO;
+ struct mpc5xxx_mmap_ctl *mm =
+ (struct mpc5xxx_mmap_ctl *)CONFIG_SYS_MBAR;
+ int digiboardversion;
+ int failsavelevel;
+ int fpgaversion;
+ u32 val;
+
+ get_revisions(&failsavelevel, &digiboardversion, &fpgaversion);
+
+ val = in_be32(&mm->ipbi_ws_ctrl);
+
+ /* first clear bits 19..21 (CS3...5) */
+ val &= ~((1 << 19) | (1 << 20) | (1 << 21));
+ if (failsavelevel == 2) {
+ /* FPGA ok */
+ val |= (1 << 19) | (1 << 21);
+ }
+
+ if (failsavelevel >= 1) {
+ /* at least digiboard-version ok */
+ val |= (1 << 20);
+ }
+
+ /* And write new value back to register */
+ out_be32(&mm->ipbi_ws_ctrl, val);
+
+ /*
+ * No need to change the pin multiplexing (MPC5XXX_GPS_PORT_CONFIG)
+ * as all 3 config versions (failsave level) have the same setup.
+ */
+
+ /*
+ * Setup gpio_wkup_7 as watchdog AS INPUT to disable it - see
+ * ticket #60
+ *
+ * MPC5XXX_WU_GPIO_DIR direction is already 0 (INPUT)
+ * set bit 0(msb) to 1
+ */
+ setbits_be32((void *)MPC5XXX_WU_GPIO_ENABLE, 1 << (31 - 0));
+
+ /* setup GPIOs for status-leds if needed - see ticket #57 */
+ if (failsavelevel > 0) {
+ /* digiboard-version is OK */
+ /* LED is LOW ACTIVE - so deactivate by set output to 1 */
+ gpio->simple_dvo |= 1 << (31 - 12);
+ gpio->simple_dvo |= 1 << (31 - 13);
+ /* set GPIO direction to output */
+ gpio->simple_ddr |= 1 << (31 - 12);
+ gpio->simple_ddr |= 1 << (31 - 13);
+ /* open drain config is set to "normal output" at reset */
+ /* gpio->simple_ode &=~ ( 1 << (31-12) ); */
+ /* gpio->simple_ode &=~ ( 1 << (31-13) ); */
+ /* enable as GPIO */
+ gpio->simple_gpioe |= 1 << (31 - 12);
+ gpio->simple_gpioe |= 1 << (31 - 13);
+ }
+
+ /* setup fpga irq - see ticket #65 */
+ if (failsavelevel > 1) {
+ /*
+ * The main irq initialisation is done in interrupts.c
+ * mpc5xxx_init_irq
+ */
+ struct mpc5xxx_intr *intr =
+ (struct mpc5xxx_intr *)(MPC5XXX_ICTL);
+
+ setbits_be32(&intr->ctrl, 0x08C01801);
+
+ /*
+ * The MBAR+0x0524 Bit 21:23 CSe are ignored here due to the
+ * already cleared (intr_ctrl) MBAR+0x0510 ECLR[0] bit above
+ */
+ }
+
+}
+
+int checkboard(void)
+{
+ int digiboardversion;
+ int failsavelevel;
+ int fpgaversion;
+
+ get_revisions(&failsavelevel, &digiboardversion, &fpgaversion);
+
+ puts("Board: A3M071\n");
+ printf("Rev: failsave level %u\n", failsavelevel);
+ printf(" digiboard IO version %u\n", digiboardversion);
+ if (failsavelevel > 0) /* only if fpga-version red */
+ printf(" fpga IO version %u\n", fpgaversion);
+
+ return 0;
+}
+
+/* miscellaneous platform dependent initialisations */
+int misc_init_r(void)
+{
+ /* adjust flash start and offset to detected values */
+ gd->bd->bi_flashstart = flash_info[0].start[0];
+ gd->bd->bi_flashoffset = 0;
+
+ /* adjust mapping */
+ out_be32((void *)MPC5XXX_BOOTCS_START,
+ START_REG(gd->bd->bi_flashstart));
+ out_be32((void *)MPC5XXX_CS0_START, START_REG(gd->bd->bi_flashstart));
+ out_be32((void *)MPC5XXX_BOOTCS_STOP,
+ STOP_REG(gd->bd->bi_flashstart, gd->bd->bi_flashsize));
+ out_be32((void *)MPC5XXX_CS0_STOP,
+ STOP_REG(gd->bd->bi_flashstart, gd->bd->bi_flashsize));
+
+ return 0;
+}
+
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP)
+void ft_board_setup(void *blob, bd_t * bd)
+{
+ ft_cpu_setup(blob, bd);
+}
+#endif /* defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) */
+
+#ifdef CONFIG_SPL_OS_BOOT
+/*
+ * A3M071 specific implementation of spl_start_uboot()
+ *
+ * RETURN
+ * 0 if booting into OS is selected (default)
+ * 1 if booting into U-Boot is selected
+ */
+int spl_start_uboot(void)
+{
+ char s[8];
+
+ env_init();
+ getenv_f("boot_os", s, sizeof(s));
+ if ((s != NULL) && (strcmp(s, "yes") == 0))
+ return 0;
+
+ return 1;
+}
+#endif
diff --git a/board/a3m071/mt46v16m16-75.h b/board/a3m071/mt46v16m16-75.h
new file mode 100644
index 0000000000..e49e99618a
--- /dev/null
+++ b/board/a3m071/mt46v16m16-75.h
@@ -0,0 +1,32 @@
+/*
+ * (C) Copyright 2004
+ * Mark Jonas, Freescale Semiconductor, mark.jonas@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.
+ */
+
+#define SDRAM_DDR /* is DDR */
+
+#if defined(CONFIG_MPC5200)
+/* Settings for XLB = 132 MHz */
+#define SDRAM_MODE 0x018D0000
+#define SDRAM_EMODE 0x40090000
+#define SDRAM_CONTROL 0x704f0f00
+#define SDRAM_CONFIG1 0x73722930
+#define SDRAM_CONFIG2 0x47770000
+#define SDRAM_TAPDELAY 0x10000000
+
+#else
+#error CONFIG_MPC5200 not defined
+#endif
diff --git a/board/chromebook-x86/coreboot/Makefile b/board/chromebook-x86/coreboot/Makefile
index cfcc0dfbe5..886baf6c96 100644
--- a/board/chromebook-x86/coreboot/Makefile
+++ b/board/chromebook-x86/coreboot/Makefile
@@ -32,9 +32,6 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
-COBJS-y += coreboot.o
-COBJS-$(CONFIG_PCI) += coreboot_pci.o
-SOBJS-y += coreboot_start16.o
SOBJS-y += coreboot_start.o
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
diff --git a/board/chromebook-x86/coreboot/config.mk b/board/chromebook-x86/coreboot/config.mk
new file mode 100644
index 0000000000..f720851aac
--- /dev/null
+++ b/board/chromebook-x86/coreboot/config.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Alternatively, this software may be distributed under the terms of the
+# GNU General Public License ("GPL") version 2 as published by the Free
+# Software Foundation.
+#
+
+HOSTCFLAGS_autoconf.mk.dep = -Wno-variadic-macros
diff --git a/board/chromebook-x86/dts/alex.dts b/board/chromebook-x86/dts/alex.dts
new file mode 100644
index 0000000000..cb6a9e41ee
--- /dev/null
+++ b/board/chromebook-x86/dts/alex.dts
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/include/ "coreboot.dtsi"
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "Google Alex";
+ compatible = "google,alex", "intel,atom-pineview";
+
+ config {
+ silent_console = <0>;
+ };
+
+ gpio: gpio {};
+
+ serial {
+ reg = <0x3f8 8>;
+ clock-frequency = <115200>;
+ };
+
+ chosen { };
+ memory { device_type = "memory"; reg = <0 0>; };
+};
diff --git a/board/chromebook-x86/dts/link.dts b/board/chromebook-x86/dts/link.dts
new file mode 100644
index 0000000000..af60f59de7
--- /dev/null
+++ b/board/chromebook-x86/dts/link.dts
@@ -0,0 +1,24 @@
+/dts-v1/;
+
+/include/ "coreboot.dtsi"
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "Google Link";
+ compatible = "google,link", "intel,celeron-ivybridge";
+
+ config {
+ silent_console = <0>;
+ };
+
+ gpio: gpio {};
+
+ serial {
+ reg = <0x3f8 8>;
+ clock-frequency = <115200>;
+ };
+
+ chosen { };
+ memory { device_type = "memory"; reg = <0 0>; };
+};
diff --git a/board/davedenx/qong/qong.c b/board/davedenx/qong/qong.c
index c41f11d60c..a3079dbca3 100644
--- a/board/davedenx/qong/qong.c
+++ b/board/davedenx/qong/qong.c
@@ -28,11 +28,12 @@
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <nand.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
#include <asm/gpio.h>
#include "qong_fpga.h"
#include <watchdog.h>
+#include <errno.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -172,10 +173,15 @@ int board_late_init(void)
{
u32 val;
struct pmic *p;
+ int ret;
- pmic_init();
- p = get_pmic();
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return ret;
+ p = pmic_get("FSL_PMIC");
+ if (!p)
+ return -ENODEV;
/* Enable RTC battery */
pmic_reg_read(p, REG_POWER_CTL0, &val);
pmic_reg_write(p, REG_POWER_CTL0, val | COINCHEN);
diff --git a/board/exmeritus/hww1u1a/hww1u1a.c b/board/exmeritus/hww1u1a/hww1u1a.c
index 52c22faaa0..89cfaad91f 100644
--- a/board/exmeritus/hww1u1a/hww1u1a.c
+++ b/board/exmeritus/hww1u1a/hww1u1a.c
@@ -105,7 +105,7 @@ int checkboard(void)
* and delay a while before we continue.
*/
if (mpc85xx_gpio_get(GPIO_RESETS)) {
- ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
puts("Debugger detected... extra device reset enabled!\n");
diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile
index 36f7c4f30f..75725b49ad 100644
--- a/board/freescale/common/Makefile
+++ b/board/freescale/common/Makefile
@@ -53,6 +53,7 @@ COBJS-$(CONFIG_P2020DS) += ics307_clk.o
COBJS-$(CONFIG_P3041DS) += ics307_clk.o
COBJS-$(CONFIG_P4080DS) += ics307_clk.o
COBJS-$(CONFIG_P5020DS) += ics307_clk.o
+COBJS-$(CONFIG_P5040DS) += ics307_clk.o
COBJS-$(CONFIG_VSC_CROSSBAR) += vsc3316_3308.o
# deal with common files for P-series corenet based devices
@@ -60,6 +61,7 @@ SUBLIB-$(CONFIG_P2041RDB) += p_corenet/libp_corenet.o
SUBLIB-$(CONFIG_P3041DS) += p_corenet/libp_corenet.o
SUBLIB-$(CONFIG_P4080DS) += p_corenet/libp_corenet.o
SUBLIB-$(CONFIG_P5020DS) += p_corenet/libp_corenet.o
+SUBLIB-$(CONFIG_P5040DS) += p_corenet/libp_corenet.o
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
diff --git a/board/freescale/common/ngpixis.h b/board/freescale/common/ngpixis.h
index 1d4483d8b9..a239ee31df 100644
--- a/board/freescale/common/ngpixis.h
+++ b/board/freescale/common/ngpixis.h
@@ -45,7 +45,7 @@ typedef struct ngpixis {
struct {
u8 sw;
u8 en;
- } s[8];
+ } s[9]; /* s[0]..s[7] is SW1..SW8, and s[8] is SW11 */
} __attribute__ ((packed)) ngpixis_t;
/* Pointer to the PIXIS register set */
diff --git a/board/freescale/corenet_ds/Makefile b/board/freescale/corenet_ds/Makefile
index 1fdf8b706b..d79193af2a 100644
--- a/board/freescale/corenet_ds/Makefile
+++ b/board/freescale/corenet_ds/Makefile
@@ -31,9 +31,11 @@ COBJS-y += ddr.o
COBJS-$(CONFIG_P3041DS) += eth_hydra.o
COBJS-$(CONFIG_P4080DS) += eth_p4080.o
COBJS-$(CONFIG_P5020DS) += eth_hydra.o
+COBJS-$(CONFIG_P5040DS) += eth_superhydra.o
COBJS-$(CONFIG_P3041DS) += p3041ds_ddr.o
COBJS-$(CONFIG_P4080DS) += p4080ds_ddr.o
COBJS-$(CONFIG_P5020DS) += p5020ds_ddr.o
+COBJS-$(CONFIG_P5040DS) += p5040ds_ddr.o
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
diff --git a/board/freescale/corenet_ds/corenet_ds.c b/board/freescale/corenet_ds/corenet_ds.c
index a33c936fa0..21428e3347 100644
--- a/board/freescale/corenet_ds/corenet_ds.c
+++ b/board/freescale/corenet_ds/corenet_ds.c
@@ -45,6 +45,7 @@ int checkboard (void)
struct cpu_type *cpu = gd->cpu;
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
unsigned int i;
+ static const char * const freq[] = {"100", "125", "156.25", "212.5" };
printf("Board: %sDS, ", cpu->name);
printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, FPGA Ver: 0x%02x, ",
@@ -83,20 +84,28 @@ int checkboard (void)
* don't match.
*/
puts("SERDES Reference Clocks: ");
-#if defined(CONFIG_P3041DS) || defined(CONFIG_P5020DS)
+#if defined(CONFIG_P3041DS) || defined(CONFIG_P5020DS) \
+ || defined(CONFIG_P5040DS)
sw = in_8(&PIXIS_SW(5));
for (i = 0; i < 3; i++) {
- static const char *freq[] = {"100", "125", "156.25", "212.5" };
unsigned int clock = (sw >> (6 - (2 * i))) & 3;
printf("Bank%u=%sMhz ", i+1, freq[clock]);
}
+#ifdef CONFIG_P5040DS
+ /* On P5040DS, SW11[7:8] determines the Bank 4 frequency */
+ sw = in_8(&PIXIS_SW(9));
+ printf("Bank4=%sMhz ", freq[sw & 3]);
+#endif
puts("\n");
#else
sw = in_8(&PIXIS_SW(3));
- printf("Bank1=%uMHz ", (sw & 0x40) ? 125 : 100);
- printf("Bank2=%sMHz ", (sw & 0x20) ? "156.25" : "125");
- printf("Bank3=%sMHz\n", (sw & 0x10) ? "156.25" : "125");
+ /* SW3[2]: 0 = 100 Mhz, 1 = 125 MHz */
+ /* SW3[3]: 0 = 125 Mhz, 1 = 156.25 MHz */
+ /* SW3[4]: 0 = 125 Mhz, 1 = 156.25 MHz */
+ printf("Bank1=%sMHz ", freq[!!(sw & 0x40)]);
+ printf("Bank2=%sMHz ", freq[1 + !!(sw & 0x20)]);
+ printf("Bank3=%sMHz\n", freq[1 + !!(sw & 0x10)]);
#endif
return 0;
@@ -168,7 +177,8 @@ int misc_init_r(void)
unsigned int i;
u8 sw;
-#if defined(CONFIG_P3041DS) || defined(CONFIG_P5020DS)
+#if defined(CONFIG_P3041DS) || defined(CONFIG_P5020DS) \
+ || defined(CONFIG_P5040DS)
sw = in_8(&PIXIS_SW(5));
for (i = 0; i < 3; i++) {
unsigned int clock = (sw >> (6 - (2 * i))) & 3;
diff --git a/board/freescale/corenet_ds/ddr.c b/board/freescale/corenet_ds/ddr.c
index 4a53b8d933..da284cde95 100644
--- a/board/freescale/corenet_ds/ddr.c
+++ b/board/freescale/corenet_ds/ddr.c
@@ -139,8 +139,8 @@ static const struct board_specific_parameters udimm0[] = {
{2, 1250, 4, 6, 0xff, 2, 0},
{2, 1350, 5, 7, 0xff, 2, 0},
{2, 1666, 5, 8, 0xff, 2, 0},
- {1, 850, 4, 5, 0xff, 2, 0},
- {1, 950, 4, 7, 0xff, 2, 0},
+ {1, 1250, 4, 6, 0xff, 2, 0},
+ {1, 1335, 4, 7, 0xff, 2, 0},
{1, 1666, 4, 8, 0xff, 2, 0},
{}
};
diff --git a/board/freescale/corenet_ds/eth_superhydra.c b/board/freescale/corenet_ds/eth_superhydra.c
new file mode 100644
index 0000000000..ef9de25bd8
--- /dev/null
+++ b/board/freescale/corenet_ds/eth_superhydra.c
@@ -0,0 +1,722 @@
+/*
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ * Author: 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
+ */
+
+/*
+ * This file handles the board muxing between the Fman Ethernet MACs and
+ * the RGMII/SGMII/XGMII PHYs on a Freescale P5040 "Super Hydra" reference
+ * board. The RGMII PHYs are the two on-board 1Gb ports. The SGMII PHYs are
+ * provided by the standard Freescale four-port SGMII riser card. The 10Gb
+ * XGMII PHYs are provided via the XAUI riser card. The P5040 has 2 FMans
+ * and 5 1G interfaces and 10G interface per FMan. Based on the options in
+ * the RCW, we could have upto 3 SGMII cards and 1 XAUI card at a time.
+ *
+ * Muxing is handled via the PIXIS BRDCFG1 register. The EMI1 bits control
+ * muxing among the RGMII PHYs and the SGMII PHYs. The value for RGMII is
+ * always the same (0). The value for SGMII depends on which slot the riser is
+ * inserted in. The EMI2 bits control muxing for the the XGMII. Like SGMII,
+ * the value is based on which slot the XAUI is inserted in.
+ *
+ * The SERDES configuration is used to determine where the SGMII and XAUI cards
+ * exist, and also which Fman's MACs are routed to which PHYs. So for a given
+ * Fman MAC, there is one and only PHY it connects to. MACs cannot be routed
+ * to PHYs dynamically.
+ *
+ *
+ * This file also updates the device tree in three ways:
+ *
+ * 1) The status of each virtual MDIO node that is referenced by an Ethernet
+ * node is set to "okay".
+ *
+ * 2) The phy-handle property of each active Ethernet MAC node is set to the
+ * appropriate PHY node.
+ *
+ * 3) The "mux value" for each virtual MDIO node is set to the correct value,
+ * if necessary. Some virtual MDIO nodes do not have configurable mux
+ * values, so those values are hard-coded in the DTS. On the HYDRA board,
+ * the virtual MDIO node for the SGMII card needs to be updated.
+ *
+ * For all this to work, the device tree needs to have the following:
+ *
+ * 1) An alias for each PHY node that an Ethernet node could be routed to.
+ *
+ * 2) An alias for each real and virtual MDIO node that is disabled by default
+ * and might need to be enabled, and also might need to have its mux-value
+ * updated.
+ */
+
+#include <common.h>
+#include <netdev.h>
+#include <asm/fsl_serdes.h>
+#include <fm_eth.h>
+#include <fsl_mdio.h>
+#include <malloc.h>
+#include <fdt_support.h>
+#include <asm/fsl_dtsec.h>
+
+#include "../common/ngpixis.h"
+#include "../common/fman.h"
+
+#ifdef CONFIG_FMAN_ENET
+
+#define BRDCFG1_EMI1_SEL_MASK 0x70
+#define BRDCFG1_EMI1_SEL_SLOT1 0x10
+#define BRDCFG1_EMI1_SEL_SLOT2 0x20
+#define BRDCFG1_EMI1_SEL_SLOT5 0x30
+#define BRDCFG1_EMI1_SEL_SLOT6 0x40
+#define BRDCFG1_EMI1_SEL_SLOT7 0x50
+#define BRDCFG1_EMI1_SEL_SLOT3 0x60
+#define BRDCFG1_EMI1_SEL_RGMII 0x00
+#define BRDCFG1_EMI1_EN 0x08
+#define BRDCFG1_EMI2_SEL_MASK 0x06
+#define BRDCFG1_EMI2_SEL_SLOT1 0x00
+#define BRDCFG1_EMI2_SEL_SLOT2 0x02
+
+#define BRDCFG2_REG_GPIO_SEL 0x20
+
+/*
+ * BRDCFG1 mask and value for each MAC
+ *
+ * This array contains the BRDCFG1 values (in mask/val format) that route the
+ * MDIO bus to a particular RGMII or SGMII PHY.
+ */
+static struct {
+ u8 mask;
+ u8 val;
+} mdio_mux[NUM_FM_PORTS];
+
+/*
+ * Mapping of all 18 SERDES lanes to board slots. A value of '0' here means
+ * that the mapping must be determined dynamically, or that the lane maps to
+ * something other than a board slot
+ */
+static u8 lane_to_slot[] = {
+ 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0
+};
+
+/*
+ * Set the board muxing for a given MAC
+ *
+ * The MDIO layer calls this function every time it wants to talk to a PHY.
+ */
+void super_hydra_mux_mdio(u8 mask, u8 val)
+{
+ clrsetbits_8(&pixis->brdcfg1, mask, val);
+}
+
+struct super_hydra_mdio {
+ u8 mask;
+ u8 val;
+ struct mii_dev *realbus;
+};
+
+static int super_hydra_mdio_read(struct mii_dev *bus, int addr, int devad,
+ int regnum)
+{
+ struct super_hydra_mdio *priv = bus->priv;
+
+ super_hydra_mux_mdio(priv->mask, priv->val);
+
+ return priv->realbus->read(priv->realbus, addr, devad, regnum);
+}
+
+static int super_hydra_mdio_write(struct mii_dev *bus, int addr, int devad,
+ int regnum, u16 value)
+{
+ struct super_hydra_mdio *priv = bus->priv;
+
+ super_hydra_mux_mdio(priv->mask, priv->val);
+
+ return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
+}
+
+static int super_hydra_mdio_reset(struct mii_dev *bus)
+{
+ struct super_hydra_mdio *priv = bus->priv;
+
+ return priv->realbus->reset(priv->realbus);
+}
+
+static void super_hydra_mdio_set_mux(char *name, u8 mask, u8 val)
+{
+ struct mii_dev *bus = miiphy_get_dev_by_name(name);
+ struct super_hydra_mdio *priv = bus->priv;
+
+ priv->mask = mask;
+ priv->val = val;
+}
+
+static int super_hydra_mdio_init(char *realbusname, char *fakebusname)
+{
+ struct super_hydra_mdio *hmdio;
+ struct mii_dev *bus = mdio_alloc();
+
+ if (!bus) {
+ printf("Failed to allocate Hydra MDIO bus\n");
+ return -1;
+ }
+
+ hmdio = malloc(sizeof(*hmdio));
+ if (!hmdio) {
+ printf("Failed to allocate Hydra private data\n");
+ free(bus);
+ return -1;
+ }
+
+ bus->read = super_hydra_mdio_read;
+ bus->write = super_hydra_mdio_write;
+ bus->reset = super_hydra_mdio_reset;
+ sprintf(bus->name, fakebusname);
+
+ hmdio->realbus = miiphy_get_dev_by_name(realbusname);
+
+ if (!hmdio->realbus) {
+ printf("No bus with name %s\n", realbusname);
+ free(bus);
+ free(hmdio);
+ return -1;
+ }
+
+ bus->priv = hmdio;
+
+ return mdio_register(bus);
+}
+
+/*
+ * Given the following ...
+ *
+ * 1) A pointer to an Fman Ethernet node (as identified by the 'compat'
+ * compatible string and 'addr' physical address)
+ *
+ * 2) An Fman port
+ *
+ * ... update the phy-handle property of the Ethernet node to point to the
+ * right PHY. This assumes that we already know the PHY for each port. That
+ * information is stored in mdio_mux[].
+ *
+ * The offset of the Fman Ethernet node is also passed in for convenience, but
+ * it is not used.
+ *
+ * Note that what we call "Fman ports" (enum fm_port) is really an Fman MAC.
+ * Inside the Fman, "ports" are things that connect to MACs. We only call them
+ * ports in U-Boot because on previous Ethernet devices (e.g. Gianfar), MACs
+ * and ports are the same thing.
+ */
+void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
+ enum fm_port port, int offset)
+{
+ enum srds_prtcl device;
+ int lane, slot, phy;
+ char alias[32];
+
+ /* RGMII and XGMII are already mapped correctly in the DTS */
+
+ if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) {
+ device = serdes_device_from_fm_port(port);
+ lane = serdes_get_first_lane(device);
+ slot = lane_to_slot[lane];
+ phy = fm_info_get_phy_address(port);
+
+ sprintf(alias, "phy_sgmii_slot%u_%x", slot, phy);
+ fdt_set_phy_handle(fdt, compat, addr, alias);
+ }
+}
+
+#define PIXIS_SW2_LANE_23_SEL 0x80
+#define PIXIS_SW2_LANE_45_SEL 0x40
+#define PIXIS_SW2_LANE_67_SEL_MASK 0x30
+#define PIXIS_SW2_LANE_67_SEL_5 0x00
+#define PIXIS_SW2_LANE_67_SEL_6 0x20
+#define PIXIS_SW2_LANE_67_SEL_7 0x10
+#define PIXIS_SW2_LANE_8_SEL 0x08
+#define PIXIS_SW2_LANE_1617_SEL 0x04
+#define PIXIS_SW11_LANE_9_SEL 0x04
+/*
+ * Initialize the lane_to_slot[] array.
+ *
+ * On the P4080DS "Expedition" board, the mapping of SERDES lanes to board
+ * slots is hard-coded. On the Hydra board, however, the mapping is controlled
+ * by board switch SW2, so the lane_to_slot[] array needs to be dynamically
+ * initialized.
+ */
+static void initialize_lane_to_slot(void)
+{
+ u8 sw2 = in_8(&PIXIS_SW(2));
+ /* SW11 appears in the programming model as SW9 */
+ u8 sw11 = in_8(&PIXIS_SW(9));
+
+ lane_to_slot[2] = (sw2 & PIXIS_SW2_LANE_23_SEL) ? 7 : 4;
+ lane_to_slot[3] = lane_to_slot[2];
+
+ lane_to_slot[4] = (sw2 & PIXIS_SW2_LANE_45_SEL) ? 7 : 6;
+ lane_to_slot[5] = lane_to_slot[4];
+
+ switch (sw2 & PIXIS_SW2_LANE_67_SEL_MASK) {
+ case PIXIS_SW2_LANE_67_SEL_5:
+ lane_to_slot[6] = 5;
+ break;
+ case PIXIS_SW2_LANE_67_SEL_6:
+ lane_to_slot[6] = 6;
+ break;
+ case PIXIS_SW2_LANE_67_SEL_7:
+ lane_to_slot[6] = 7;
+ break;
+ }
+ lane_to_slot[7] = lane_to_slot[6];
+
+ lane_to_slot[8] = (sw2 & PIXIS_SW2_LANE_8_SEL) ? 3 : 0;
+ lane_to_slot[9] = (sw11 & PIXIS_SW11_LANE_9_SEL) ? 0 : 3;
+
+ lane_to_slot[16] = (sw2 & PIXIS_SW2_LANE_1617_SEL) ? 1 : 0;
+ lane_to_slot[17] = lane_to_slot[16];
+}
+
+#endif /* #ifdef CONFIG_FMAN_ENET */
+
+/*
+ * Configure the status for the virtual MDIO nodes
+ *
+ * Rather than create the virtual MDIO nodes from scratch for each active
+ * virtual MDIO, we expect the DTS to have the nodes defined already, and we
+ * only enable the ones that are actually active.
+ *
+ * We assume that the DTS already hard-codes the status for all the
+ * virtual MDIO nodes to "disabled", so all we need to do is enable the
+ * active ones.
+ */
+void fdt_fixup_board_enet(void *fdt)
+{
+#ifdef CONFIG_FMAN_ENET
+ enum fm_port i;
+ int lane, slot;
+
+ for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
+ int idx = i - FM1_DTSEC1;
+
+ switch (fm_info_get_enet_if(i)) {
+ case PHY_INTERFACE_MODE_SGMII:
+ lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
+ if (lane >= 0) {
+ char alias[32];
+
+ slot = lane_to_slot[lane];
+ sprintf(alias, "hydra_sg_slot%u", slot);
+ fdt_status_okay_by_alias(fdt, alias);
+ debug("Enabled MDIO node %s (slot %i)\n",
+ alias, slot);
+ }
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ fdt_status_okay_by_alias(fdt, "hydra_rg");
+ debug("Enabled MDIO node hydra_rg\n");
+ break;
+ default:
+ break;
+ }
+ }
+
+ lane = serdes_get_first_lane(XAUI_FM1);
+ if (lane >= 0) {
+ char alias[32];
+
+ slot = lane_to_slot[lane];
+ sprintf(alias, "hydra_xg_slot%u", slot);
+ fdt_status_okay_by_alias(fdt, alias);
+ debug("Enabled MDIO node %s (slot %i)\n", alias, slot);
+ }
+
+#if CONFIG_SYS_NUM_FMAN == 2
+ for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) {
+ int idx = i - FM2_DTSEC1;
+
+ switch (fm_info_get_enet_if(i)) {
+ case PHY_INTERFACE_MODE_SGMII:
+ lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx);
+ if (lane >= 0) {
+ char alias[32];
+
+ slot = lane_to_slot[lane];
+ sprintf(alias, "hydra_sg_slot%u", slot);
+ fdt_status_okay_by_alias(fdt, alias);
+ debug("Enabled MDIO node %s (slot %i)\n",
+ alias, slot);
+ }
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ fdt_status_okay_by_alias(fdt, "hydra_rg");
+ debug("Enabled MDIO node hydra_rg\n");
+ break;
+ default:
+ break;
+ }
+ }
+
+ lane = serdes_get_first_lane(XAUI_FM2);
+ if (lane >= 0) {
+ char alias[32];
+
+ slot = lane_to_slot[lane];
+ sprintf(alias, "hydra_xg_slot%u", slot);
+ fdt_status_okay_by_alias(fdt, alias);
+ debug("Enabled MDIO node %s (slot %i)\n", alias, slot);
+ }
+#endif /* CONFIG_SYS_NUM_FMAN == 2 */
+#endif /* CONFIG_FMAN_ENET */
+}
+
+/*
+ * Mapping of SerDes Protocol to MDIO MUX value and PHY address.
+ *
+ * Fman 1:
+ * DTSEC1 | DTSEC2 | DTSEC3 | DTSEC4
+ * Mux Phy | Mux Phy | Mux Phy | Mux Phy
+ * Value Addr | Value Addr | Value Addr | Value Addr
+ * 0x00 2 1c | 2 1d | 2 1e | 2 1f
+ * 0x01 | | 6 1c |
+ * 0x02 | | 3 1c | 3 1d
+ * 0x03 2 1c | 2 1d | 2 1e | 2 1f
+ * 0x04 2 1c | 2 1d | 2 1e | 2 1f
+ * 0x05 | | 3 1c | 3 1d
+ * 0x06 2 1c | 2 1d | 2 1e | 2 1f
+ * 0x07 | | 6 1c |
+ * 0x11 2 1c | 2 1d | 2 1e | 2 1f
+ * 0x2a 2 | | 2 1e | 2 1f
+ * 0x34 6 1c | 6 1d | 4 1e | 4 1f
+ * 0x35 | | 3 1c | 3 1d
+ * 0x36 6 1c | 6 1d | 4 1e | 4 1f
+ * | | |
+ * Fman 2: | | |
+ * DTSEC1 | DTSEC2 | DTSEC3 | DTSEC4
+ * EMI1 | EMI1 | EMI1 | EMI1
+ * Mux Phy | Mux Phy | Mux Phy | Mux Phy
+ * Value Addr | Value Addr | Value Addr | Value Addr
+ * 0x00 | | 6 1c | 6 1d
+ * 0x01 | | |
+ * 0x02 | | 6 1c | 6 1d
+ * 0x03 3 1c | 3 1d | 6 1c | 6 1d
+ * 0x04 3 1c | 3 1d | 6 1c | 6 1d
+ * 0x05 | | 6 1c | 6 1d
+ * 0x06 | | 6 1c | 6 1d
+ * 0x07 | | |
+ * 0x11 | | |
+ * 0x2a | | |
+ * 0x34 | | |
+ * 0x35 | | |
+ * 0x36 | | |
+ */
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_FMAN_ENET
+ struct fsl_pq_mdio_info dtsec_mdio_info;
+ struct tgec_mdio_info tgec_mdio_info;
+ unsigned int i, slot;
+ int lane;
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ int srds_prtcl = (in_be32(&gur->rcwsr[4]) &
+ FSL_CORENET_RCWSR4_SRDS_PRTCL) >> 26;
+
+ printf("Initializing Fman\n");
+
+ initialize_lane_to_slot();
+
+ /* We want to use the PIXIS to configure MUX routing, not GPIOs. */
+ setbits_8(&pixis->brdcfg2, BRDCFG2_REG_GPIO_SEL);
+
+ memset(mdio_mux, 0, sizeof(mdio_mux));
+
+ dtsec_mdio_info.regs =
+ (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
+ dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
+
+ /* Register the real 1G MDIO bus */
+ fsl_pq_mdio_init(bis, &dtsec_mdio_info);
+
+ tgec_mdio_info.regs =
+ (struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
+ tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
+
+ /* Register the real 10G MDIO bus */
+ fm_tgec_mdio_init(bis, &tgec_mdio_info);
+
+ /* Register the three virtual MDIO front-ends */
+ super_hydra_mdio_init(DEFAULT_FM_MDIO_NAME,
+ "SUPER_HYDRA_RGMII_MDIO");
+ super_hydra_mdio_init(DEFAULT_FM_MDIO_NAME,
+ "SUPER_HYDRA_FM1_SGMII_MDIO");
+ super_hydra_mdio_init(DEFAULT_FM_MDIO_NAME,
+ "SUPER_HYDRA_FM2_SGMII_MDIO");
+ super_hydra_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME,
+ "SUPER_HYDRA_FM1_TGEC_MDIO");
+ super_hydra_mdio_init(DEFAULT_FM_TGEC_MDIO_NAME,
+ "SUPER_HYDRA_FM2_TGEC_MDIO");
+
+ /*
+ * Program the DTSEC PHY addresses assuming that they are all SGMII.
+ * For any DTSEC that's RGMII, we'll override its PHY address later.
+ * We assume that DTSEC5 is only used for RGMII.
+ */
+ fm_info_set_phy_address(FM1_DTSEC1, CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
+ fm_info_set_phy_address(FM1_DTSEC2, CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
+ fm_info_set_phy_address(FM1_10GEC1, CONFIG_SYS_FM2_10GEC1_PHY_ADDR);
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ fm_info_set_phy_address(FM2_DTSEC1, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR);
+ fm_info_set_phy_address(FM2_DTSEC2, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR);
+ fm_info_set_phy_address(FM2_DTSEC3, CONFIG_SYS_FM2_DTSEC1_PHY_ADDR);
+ fm_info_set_phy_address(FM2_DTSEC4, CONFIG_SYS_FM2_DTSEC2_PHY_ADDR);
+ fm_info_set_phy_address(FM2_10GEC1, CONFIG_SYS_FM1_10GEC1_PHY_ADDR);
+#endif
+
+ switch (srds_prtcl) {
+ case 0:
+ case 3:
+ case 4:
+ case 6:
+ case 0x11:
+ case 0x2a:
+ case 0x34:
+ case 0x36:
+ fm_info_set_phy_address(FM1_DTSEC3,
+ CONFIG_SYS_FM1_DTSEC3_PHY_ADDR);
+ fm_info_set_phy_address(FM1_DTSEC4,
+ CONFIG_SYS_FM1_DTSEC4_PHY_ADDR);
+ break;
+ case 1:
+ case 2:
+ case 5:
+ case 7:
+ case 0x35:
+ fm_info_set_phy_address(FM1_DTSEC3,
+ CONFIG_SYS_FM1_DTSEC1_PHY_ADDR);
+ fm_info_set_phy_address(FM1_DTSEC4,
+ CONFIG_SYS_FM1_DTSEC2_PHY_ADDR);
+ break;
+ default:
+ printf("Fman: Unsupport SerDes Protocol 0x%02x\n", srds_prtcl);
+ break;
+ }
+
+ for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) {
+ int idx = i - FM1_DTSEC1;
+
+ switch (fm_info_get_enet_if(i)) {
+ case PHY_INTERFACE_MODE_SGMII:
+ lane = serdes_get_first_lane(SGMII_FM1_DTSEC1 + idx);
+ if (lane < 0)
+ break;
+ slot = lane_to_slot[lane];
+ mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
+ debug("FM1@DTSEC%u expects SGMII in slot %u\n",
+ idx + 1, slot);
+ switch (slot) {
+ case 1:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT1 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 2:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT2 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 3:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT3 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 5:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT5 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 6:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT6 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 7:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT7 |
+ BRDCFG1_EMI1_EN;
+ break;
+ };
+
+ super_hydra_mdio_set_mux("SUPER_HYDRA_FM1_SGMII_MDIO",
+ mdio_mux[i].mask, mdio_mux[i].val);
+ fm_info_set_mdio(i,
+ miiphy_get_dev_by_name("SUPER_HYDRA_FM1_SGMII_MDIO"));
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ /*
+ * FM1 DTSEC5 is routed via EC1 to the first on-board
+ * RGMII port. FM2 DTSEC5 is routed via EC2 to the
+ * second on-board RGMII port. The other DTSECs cannot
+ * be routed to RGMII.
+ */
+ debug("FM1@DTSEC%u is RGMII at address %u\n",
+ idx + 1, 0);
+ fm_info_set_phy_address(i, 0);
+ mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_RGMII |
+ BRDCFG1_EMI1_EN;
+ super_hydra_mdio_set_mux("SUPER_HYDRA_RGMII_MDIO",
+ mdio_mux[i].mask, mdio_mux[i].val);
+ fm_info_set_mdio(i,
+ miiphy_get_dev_by_name("SUPER_HYDRA_RGMII_MDIO"));
+ break;
+ case PHY_INTERFACE_MODE_NONE:
+ fm_info_set_phy_address(i, 0);
+ break;
+ default:
+ printf("Fman1: DTSEC%u set to unknown interface %i\n",
+ idx + 1, fm_info_get_enet_if(i));
+ fm_info_set_phy_address(i, 0);
+ break;
+ }
+ }
+
+ /*
+ * For 10G, we only support one XAUI card per Fman. If present, then we
+ * force its routing and never touch those bits again, which removes the
+ * need for Linux to do any muxing. This works because of the way
+ * BRDCFG1 is defined, but it's a bit hackish.
+ *
+ * The PHY address for the XAUI card depends on which slot it's in. The
+ * macros we use imply that the PHY address is based on which FM, but
+ * that's not true. On the P4080DS, FM1 could only use XAUI in slot 5,
+ * and FM2 could only use a XAUI in slot 4. On the Hydra board, we
+ * check the actual slot and just use the macros as-is, even though
+ * the P3041 and P5020 only have one Fman.
+ */
+ lane = serdes_get_first_lane(XAUI_FM1);
+ if (lane >= 0) {
+ debug("FM1@TGEC1 expects XAUI in slot %u\n", lane_to_slot[lane]);
+ mdio_mux[FM1_10GEC1].mask = BRDCFG1_EMI2_SEL_MASK;
+ mdio_mux[FM1_10GEC1].val = BRDCFG1_EMI2_SEL_SLOT2;
+ super_hydra_mdio_set_mux("SUPER_HYDRA_FM1_TGEC_MDIO",
+ mdio_mux[i].mask, mdio_mux[i].val);
+ }
+
+ fm_info_set_mdio(FM1_10GEC1,
+ miiphy_get_dev_by_name("SUPER_HYDRA_FM1_TGEC_MDIO"));
+
+#if (CONFIG_SYS_NUM_FMAN == 2)
+ for (i = FM2_DTSEC1; i < FM2_DTSEC1 + CONFIG_SYS_NUM_FM2_DTSEC; i++) {
+ int idx = i - FM2_DTSEC1;
+
+ switch (fm_info_get_enet_if(i)) {
+ case PHY_INTERFACE_MODE_SGMII:
+ lane = serdes_get_first_lane(SGMII_FM2_DTSEC1 + idx);
+ if (lane < 0)
+ break;
+ slot = lane_to_slot[lane];
+ mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
+ debug("FM2@DTSEC%u expects SGMII in slot %u\n",
+ idx + 1, slot);
+ switch (slot) {
+ case 1:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT1 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 2:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT2 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 3:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT3 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 5:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT5 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 6:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT6 |
+ BRDCFG1_EMI1_EN;
+ break;
+ case 7:
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_SLOT7 |
+ BRDCFG1_EMI1_EN;
+ break;
+ };
+
+ super_hydra_mdio_set_mux("SUPER_HYDRA_FM2_SGMII_MDIO",
+ mdio_mux[i].mask, mdio_mux[i].val);
+ fm_info_set_mdio(i,
+ miiphy_get_dev_by_name("SUPER_HYDRA_FM2_SGMII_MDIO"));
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ /*
+ * FM1 DTSEC5 is routed via EC1 to the first on-board
+ * RGMII port. FM2 DTSEC5 is routed via EC2 to the
+ * second on-board RGMII port. The other DTSECs cannot
+ * be routed to RGMII.
+ */
+ debug("FM2@DTSEC%u is RGMII at address %u\n",
+ idx + 1, 1);
+ fm_info_set_phy_address(i, 1);
+ mdio_mux[i].mask = BRDCFG1_EMI1_SEL_MASK;
+ mdio_mux[i].val = BRDCFG1_EMI1_SEL_RGMII |
+ BRDCFG1_EMI1_EN;
+ super_hydra_mdio_set_mux("SUPER_HYDRA_RGMII_MDIO",
+ mdio_mux[i].mask, mdio_mux[i].val);
+ fm_info_set_mdio(i,
+ miiphy_get_dev_by_name("SUPER_HYDRA_RGMII_MDIO"));
+ break;
+ case PHY_INTERFACE_MODE_NONE:
+ fm_info_set_phy_address(i, 0);
+ break;
+ default:
+ printf("Fman2: DTSEC%u set to unknown interface %i\n",
+ idx + 1, fm_info_get_enet_if(i));
+ fm_info_set_phy_address(i, 0);
+ break;
+ }
+ }
+
+ /*
+ * For 10G, we only support one XAUI card per Fman. If present, then we
+ * force its routing and never touch those bits again, which removes the
+ * need for Linux to do any muxing. This works because of the way
+ * BRDCFG1 is defined, but it's a bit hackish.
+ *
+ * The PHY address for the XAUI card depends on which slot it's in. The
+ * macros we use imply that the PHY address is based on which FM, but
+ * that's not true. On the P4080DS, FM1 could only use XAUI in slot 5,
+ * and FM2 could only use a XAUI in slot 4. On the Hydra board, we
+ * check the actual slot and just use the macros as-is, even though
+ * the P3041 and P5020 only have one Fman.
+ */
+ lane = serdes_get_first_lane(XAUI_FM2);
+ if (lane >= 0) {
+ debug("FM2@TGEC1 expects XAUI in slot %u\n", lane_to_slot[lane]);
+ mdio_mux[FM2_10GEC1].mask = BRDCFG1_EMI2_SEL_MASK;
+ mdio_mux[FM2_10GEC1].val = BRDCFG1_EMI2_SEL_SLOT1;
+ super_hydra_mdio_set_mux("SUPER_HYDRA_FM2_TGEC_MDIO",
+ mdio_mux[i].mask, mdio_mux[i].val);
+ }
+
+ fm_info_set_mdio(FM2_10GEC1,
+ miiphy_get_dev_by_name("SUPER_HYDRA_FM2_TGEC_MDIO"));
+
+#endif
+
+ cpu_eth_init(bis);
+#endif
+
+ return pci_eth_init(bis);
+}
diff --git a/board/freescale/corenet_ds/p5040ds_ddr.c b/board/freescale/corenet_ds/p5040ds_ddr.c
new file mode 100644
index 0000000000..e65de364d7
--- /dev/null
+++ b/board/freescale/corenet_ds/p5040ds_ddr.c
@@ -0,0 +1,18 @@
+/*
+ * 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 <common.h>
+#include <asm/fsl_ddr_sdram.h>
+
+fixed_ddr_parm_t fixed_ddr_parm_0[] = {
+ {0, 0, NULL}
+};
+
+fixed_ddr_parm_t fixed_ddr_parm_1[] = {
+ {0, 0, NULL}
+};
diff --git a/board/freescale/mpc8540ads/mpc8540ads.c b/board/freescale/mpc8540ads/mpc8540ads.c
index a275d3a074..418c06b655 100644
--- a/board/freescale/mpc8540ads/mpc8540ads.c
+++ b/board/freescale/mpc8540ads/mpc8540ads.c
@@ -184,7 +184,7 @@ void lbc_sdram_init(void)
phys_size_t fixed_sdram(void)
{
#ifndef CONFIG_SYS_RAMBOOT
- volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+ volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR);
ddr->cs0_bnds = CONFIG_SYS_DDR_CS0_BNDS;
ddr->cs0_config = CONFIG_SYS_DDR_CS0_CONFIG;
diff --git a/board/freescale/mpc8560ads/mpc8560ads.c b/board/freescale/mpc8560ads/mpc8560ads.c
index 285edbce6b..a4f48bb234 100644
--- a/board/freescale/mpc8560ads/mpc8560ads.c
+++ b/board/freescale/mpc8560ads/mpc8560ads.c
@@ -389,7 +389,7 @@ void lbc_sdram_init(void)
phys_size_t fixed_sdram(void)
{
#ifndef CONFIG_SYS_RAMBOOT
- volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+ volatile ccsr_ddr_t *ddr= (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR);
ddr->cs0_bnds = CONFIG_SYS_DDR_CS0_BNDS;
ddr->cs0_config = CONFIG_SYS_DDR_CS0_CONFIG;
diff --git a/board/freescale/mpc8569mds/mpc8569mds.c b/board/freescale/mpc8569mds/mpc8569mds.c
index d119c6517f..0d3b418625 100644
--- a/board/freescale/mpc8569mds/mpc8569mds.c
+++ b/board/freescale/mpc8569mds/mpc8569mds.c
@@ -247,7 +247,7 @@ int checkboard (void)
#if !defined(CONFIG_SPD_EEPROM)
phys_size_t fixed_sdram(void)
{
- volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
uint d_init;
out_be32(&ddr->cs0_bnds, CONFIG_SYS_DDR_CS0_BNDS);
diff --git a/board/freescale/mx31pdk/mx31pdk.c b/board/freescale/mx31pdk/mx31pdk.c
index 9f8bc53e71..bc60632aa0 100644
--- a/board/freescale/mx31pdk/mx31pdk.c
+++ b/board/freescale/mx31pdk/mx31pdk.c
@@ -30,8 +30,9 @@
#include <asm/arch/imx-regs.h>
#include <asm/arch/sys_proto.h>
#include <watchdog.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
+#include <errno.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -83,10 +84,15 @@ int board_late_init(void)
{
u32 val;
struct pmic *p;
+ int ret;
- pmic_init();
- p = get_pmic();
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return ret;
+ p = pmic_get("FSL_PMIC");
+ if (!p)
+ return -ENODEV;
/* Enable RTC battery */
pmic_reg_read(p, REG_POWER_CTL0, &val);
pmic_reg_write(p, REG_POWER_CTL0, val | COINCHEN);
diff --git a/board/freescale/mx35pdk/mx35pdk.c b/board/freescale/mx35pdk/mx35pdk.c
index 4d8f2f5eea..2aa000f238 100644
--- a/board/freescale/mx35pdk/mx35pdk.c
+++ b/board/freescale/mx35pdk/mx35pdk.c
@@ -31,7 +31,7 @@
#include <asm/arch/mx35_pins.h>
#include <asm/arch/iomux.h>
#include <i2c.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
#include <mmc.h>
#include <fsl_esdhc.h>
@@ -228,7 +228,9 @@ int board_init(void)
static inline int pmic_detect(void)
{
unsigned int id;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("FSL_PMIC");
+ if (!p)
+ return -ENODEV;
pmic_reg_read(p, REG_IDENTIFICATION, &id);
@@ -252,10 +254,14 @@ int board_late_init(void)
u8 val;
u32 pmic_val;
struct pmic *p;
+ int ret;
+
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return ret;
- pmic_init();
if (pmic_detect()) {
- p = get_pmic();
+ p = pmic_get("FSL_PMIC");
mxc_request_iomux(MX35_PIN_WATCHDOG_RST, MUX_CONFIG_SION |
MUX_CONFIG_ALT1);
diff --git a/board/freescale/mx51evk/Makefile b/board/freescale/mx51evk/Makefile
index 224eaa3c73..2310fe137d 100644
--- a/board/freescale/mx51evk/Makefile
+++ b/board/freescale/mx51evk/Makefile
@@ -23,8 +23,10 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
-COBJS := mx51evk.o
+COBJS-y += mx51evk.o
+COBJS-$(CONFIG_VIDEO) += mx51evk_video.o
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/board/freescale/mx51evk/mx51evk.c b/board/freescale/mx51evk/mx51evk.c
index 421d8c2244..d1ef431895 100644
--- a/board/freescale/mx51evk/mx51evk.c
+++ b/board/freescale/mx51evk/mx51evk.c
@@ -30,19 +30,14 @@
#include <asm/arch/sys_proto.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/clock.h>
+#include <asm/imx-common/mx5_video.h>
#include <i2c.h>
#include <mmc.h>
#include <fsl_esdhc.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
#include <mc13892.h>
#include <usb/ehci-fsl.h>
-#include <linux/fb.h>
-#include <ipu_pixfmt.h>
-
-#define MX51EVK_LCD_3V3 IMX_GPIO_NR(4, 9)
-#define MX51EVK_LCD_5V IMX_GPIO_NR(4, 10)
-#define MX51EVK_LCD_BACKLIGHT IMX_GPIO_NR(3, 4)
DECLARE_GLOBAL_DATA_PTR;
@@ -252,9 +247,15 @@ static void power_init(void)
unsigned int val;
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
struct pmic *p;
+ int ret;
+
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return;
- pmic_init();
- p = get_pmic();
+ p = pmic_get("FSL_PMIC");
+ if (!p)
+ return;
/* Write needed to Power Gate 2 register */
pmic_reg_read(p, REG_POWER_MISC, &val);
@@ -471,54 +472,6 @@ int board_mmc_init(bd_t *bis)
}
#endif
-static struct fb_videomode const claa_wvga = {
- .name = "CLAA07LC0ACW",
- .refresh = 57,
- .xres = 800,
- .yres = 480,
- .pixclock = 37037,
- .left_margin = 40,
- .right_margin = 60,
- .upper_margin = 10,
- .lower_margin = 10,
- .hsync_len = 20,
- .vsync_len = 10,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-void lcd_iomux(void)
-{
- /* DI2_PIN15 */
- mxc_request_iomux(MX51_PIN_DI_GP4, IOMUX_CONFIG_ALT4);
-
- /* Pad settings for MX51_PIN_DI2_DISP_CLK */
- mxc_iomux_set_pad(MX51_PIN_DI2_DISP_CLK, PAD_CTL_HYS_NONE |
- PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
- PAD_CTL_DRV_MAX | PAD_CTL_SRE_SLOW);
-
- /* Turn on 3.3V voltage for LCD */
- mxc_request_iomux(MX51_PIN_CSI2_D12, IOMUX_CONFIG_ALT3);
- gpio_direction_output(MX51EVK_LCD_3V3, 1);
-
- /* Turn on 5V voltage for LCD */
- mxc_request_iomux(MX51_PIN_CSI2_D13, IOMUX_CONFIG_ALT3);
- gpio_direction_output(MX51EVK_LCD_5V, 1);
-
- /* Turn on GPIO backlight */
- mxc_request_iomux(MX51_PIN_DI1_D1_CS, IOMUX_CONFIG_ALT4);
- mxc_iomux_set_input(MX51_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT,
- INPUT_CTL_PATH1);
- gpio_direction_output(MX51EVK_LCD_BACKLIGHT, 1);
-}
-
-void lcd_enable(void)
-{
- int ret = ipuv3_fb_init(&claa_wvga, 1, IPU_PIX_FMT_RGB565);
- if (ret)
- printf("LCD cannot be configured: %d\n", ret);
-}
-
int board_early_init_f(void)
{
setup_iomux_uart();
@@ -526,7 +479,7 @@ int board_early_init_f(void)
#ifdef CONFIG_USB_EHCI_MX5
setup_usb_h1();
#endif
- lcd_iomux();
+ setup_iomux_lcd();
return 0;
}
diff --git a/board/freescale/mx51evk/mx51evk_video.c b/board/freescale/mx51evk/mx51evk_video.c
new file mode 100644
index 0000000000..f036cf73b2
--- /dev/null
+++ b/board/freescale/mx51evk/mx51evk_video.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Fabio Estevam <fabio.estevam@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 <linux/list.h>
+#include <asm/gpio.h>
+#include <asm/arch/iomux.h>
+#include <linux/fb.h>
+#include <ipu_pixfmt.h>
+
+#define MX51EVK_LCD_3V3 IMX_GPIO_NR(4, 9)
+#define MX51EVK_LCD_5V IMX_GPIO_NR(4, 10)
+#define MX51EVK_LCD_BACKLIGHT IMX_GPIO_NR(3, 4)
+
+static struct fb_videomode const claa_wvga = {
+ .name = "CLAA07LC0ACW",
+ .refresh = 57,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 37037,
+ .left_margin = 40,
+ .right_margin = 60,
+ .upper_margin = 10,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 10,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
+void setup_iomux_lcd(void)
+{
+ /* DI2_PIN15 */
+ mxc_request_iomux(MX51_PIN_DI_GP4, IOMUX_CONFIG_ALT4);
+
+ /* Pad settings for MX51_PIN_DI2_DISP_CLK */
+ mxc_iomux_set_pad(MX51_PIN_DI2_DISP_CLK, PAD_CTL_HYS_NONE |
+ PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_KEEPER |
+ PAD_CTL_DRV_MAX | PAD_CTL_SRE_SLOW);
+
+ /* Turn on 3.3V voltage for LCD */
+ mxc_request_iomux(MX51_PIN_CSI2_D12, IOMUX_CONFIG_ALT3);
+ gpio_direction_output(MX51EVK_LCD_3V3, 1);
+
+ /* Turn on 5V voltage for LCD */
+ mxc_request_iomux(MX51_PIN_CSI2_D13, IOMUX_CONFIG_ALT3);
+ gpio_direction_output(MX51EVK_LCD_5V, 1);
+
+ /* Turn on GPIO backlight */
+ mxc_request_iomux(MX51_PIN_DI1_D1_CS, IOMUX_CONFIG_ALT4);
+ mxc_iomux_set_input(MX51_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT,
+ INPUT_CTL_PATH1);
+ gpio_direction_output(MX51EVK_LCD_BACKLIGHT, 1);
+}
+
+void lcd_enable(void)
+{
+ int ret = ipuv3_fb_init(&claa_wvga, 1, IPU_PIX_FMT_RGB565);
+ if (ret)
+ printf("LCD cannot be configured: %d\n", ret);
+}
diff --git a/board/freescale/mx53evk/mx53evk.c b/board/freescale/mx53evk/mx53evk.c
index bb4621d62e..1273501476 100644
--- a/board/freescale/mx53evk/mx53evk.c
+++ b/board/freescale/mx53evk/mx53evk.c
@@ -34,7 +34,7 @@
#include <i2c.h>
#include <mmc.h>
#include <fsl_esdhc.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
#include <asm/gpio.h>
#include <mc13892.h>
@@ -123,9 +123,15 @@ void power_init(void)
{
unsigned int val;
struct pmic *p;
+ int ret;
+
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return;
- pmic_init();
- p = get_pmic();
+ p = pmic_get("FSL_PMIC");
+ if (!p)
+ return;
/* Set VDDA to 1.25V */
pmic_reg_read(p, REG_SW_2, &val);
diff --git a/board/freescale/mx53loco/Makefile b/board/freescale/mx53loco/Makefile
index 8bc69a92c1..3be17c5917 100644
--- a/board/freescale/mx53loco/Makefile
+++ b/board/freescale/mx53loco/Makefile
@@ -22,8 +22,10 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
-COBJS := mx53loco.o
+COBJS-y += mx53loco.o
+COBJS-$(CONFIG_VIDEO) += mx53loco_video.o
+COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS))
diff --git a/board/freescale/mx53loco/mx53loco.c b/board/freescale/mx53loco/mx53loco.c
index a11e883186..81c511cdc1 100644
--- a/board/freescale/mx53loco/mx53loco.c
+++ b/board/freescale/mx53loco/mx53loco.c
@@ -31,12 +31,13 @@
#include <asm/arch/iomux.h>
#include <asm/arch/clock.h>
#include <asm/errno.h>
+#include <asm/imx-common/mx5_video.h>
#include <netdev.h>
#include <i2c.h>
#include <mmc.h>
#include <fsl_esdhc.h>
#include <asm/gpio.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <dialog_pmic.h>
#include <fsl_pmic.h>
#include <linux/fb.h>
@@ -344,10 +345,16 @@ static int power_init(void)
unsigned int val;
int ret = -1;
struct pmic *p;
+ int retval;
if (!i2c_probe(CONFIG_SYS_DIALOG_PMIC_I2C_ADDR)) {
- pmic_dialog_init();
- p = get_pmic();
+ retval = pmic_dialog_init(I2C_PMIC);
+ if (retval)
+ return retval;
+
+ p = pmic_get("DIALOG_PMIC");
+ if (!p)
+ return -ENODEV;
/* Set VDDA to 1.25V */
val = DA9052_BUCKCORE_BCOREEN | DA_BUCKCORE_VBCORE_1_250V;
@@ -363,8 +370,13 @@ static int power_init(void)
}
if (!i2c_probe(CONFIG_SYS_FSL_PMIC_I2C_ADDR)) {
- pmic_init();
- p = get_pmic();
+ retval = pmic_init(I2C_PMIC);
+ if (retval)
+ return retval;
+
+ p = pmic_get("DIALOG_PMIC");
+ if (!p)
+ return -ENODEV;
/* Set VDDGP to 1.25V for 1GHz on SW1 */
pmic_reg_read(p, REG_SW_0, &val);
@@ -412,74 +424,11 @@ static void clock_1GHz(void)
printf("CPU: Switch DDR clock to 400MHz failed\n");
}
-static struct fb_videomode const claa_wvga = {
- .name = "CLAA07LC0ACW",
- .refresh = 57,
- .xres = 800,
- .yres = 480,
- .pixclock = 37037,
- .left_margin = 40,
- .right_margin = 60,
- .upper_margin = 10,
- .lower_margin = 10,
- .hsync_len = 20,
- .vsync_len = 10,
- .sync = 0,
- .vmode = FB_VMODE_NONINTERLACED
-};
-
-void lcd_iomux(void)
-{
- mxc_request_iomux(MX53_PIN_DI0_DISP_CLK, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DI0_PIN15, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DI0_PIN2, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DI0_PIN3, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT0, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT1, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT2, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT3, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT4, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT5, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT6, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT7, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT8, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT9, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT10, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT11, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT12, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT13, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT14, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT15, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT16, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT17, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT18, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT19, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT20, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT21, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT22, IOMUX_CONFIG_ALT0);
- mxc_request_iomux(MX53_PIN_DISP0_DAT23, IOMUX_CONFIG_ALT0);
-
- /* Turn on GPIO backlight */
- mxc_request_iomux(MX53_PIN_EIM_D24, IOMUX_CONFIG_ALT1);
- gpio_direction_output(MX53LOCO_LCD_POWER, 1);
-
- /* Turn on display contrast */
- mxc_request_iomux(MX53_PIN_GPIO_1, IOMUX_CONFIG_ALT1);
- gpio_direction_output(IOMUX_TO_GPIO(MX53_PIN_GPIO_1), 1);
-}
-
-void lcd_enable(void)
-{
- int ret = ipuv3_fb_init(&claa_wvga, 0, IPU_PIX_FMT_RGB565);
- if (ret)
- printf("LCD cannot be configured: %d\n", ret);
-}
-
int board_early_init_f(void)
{
setup_iomux_uart();
setup_iomux_fec();
- lcd_iomux();
+ setup_iomux_lcd();
return 0;
}
diff --git a/board/freescale/mx53loco/mx53loco_video.c b/board/freescale/mx53loco/mx53loco_video.c
new file mode 100644
index 0000000000..69991e8511
--- /dev/null
+++ b/board/freescale/mx53loco/mx53loco_video.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ * Fabio Estevam <fabio.estevam@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 <linux/list.h>
+#include <asm/gpio.h>
+#include <asm/arch/iomux.h>
+#include <linux/fb.h>
+#include <ipu_pixfmt.h>
+
+#define MX53LOCO_LCD_POWER IMX_GPIO_NR(3, 24)
+
+static struct fb_videomode const claa_wvga = {
+ .name = "CLAA07LC0ACW",
+ .refresh = 57,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 37037,
+ .left_margin = 40,
+ .right_margin = 60,
+ .upper_margin = 10,
+ .lower_margin = 10,
+ .hsync_len = 20,
+ .vsync_len = 10,
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
+void setup_iomux_lcd(void)
+{
+ mxc_request_iomux(MX53_PIN_DI0_DISP_CLK, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DI0_PIN15, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DI0_PIN2, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DI0_PIN3, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT0, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT1, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT2, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT3, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT4, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT5, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT6, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT7, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT8, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT9, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT10, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT11, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT12, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT13, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT14, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT15, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT16, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT17, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT18, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT19, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT20, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT21, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT22, IOMUX_CONFIG_ALT0);
+ mxc_request_iomux(MX53_PIN_DISP0_DAT23, IOMUX_CONFIG_ALT0);
+
+ /* Turn on GPIO backlight */
+ mxc_request_iomux(MX53_PIN_EIM_D24, IOMUX_CONFIG_ALT1);
+ gpio_direction_output(MX53LOCO_LCD_POWER, 1);
+
+ /* Turn on display contrast */
+ mxc_request_iomux(MX53_PIN_GPIO_1, IOMUX_CONFIG_ALT1);
+ gpio_direction_output(IOMUX_TO_GPIO(MX53_PIN_GPIO_1), 1);
+}
+
+void lcd_enable(void)
+{
+ int ret = ipuv3_fb_init(&claa_wvga, 0, IPU_PIX_FMT_RGB565);
+ if (ret)
+ printf("LCD cannot be configured: %d\n", ret);
+}
diff --git a/board/freescale/p1023rds/p1023rds.c b/board/freescale/p1023rds/p1023rds.c
index eb11f3fe12..9110767a14 100644
--- a/board/freescale/p1023rds/p1023rds.c
+++ b/board/freescale/p1023rds/p1023rds.c
@@ -74,7 +74,7 @@ int checkboard(void)
phys_size_t fixed_sdram(void)
{
#ifndef CONFIG_SYS_RAMBOOT
- ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
set_next_law(0, LAW_SIZE_2G, LAW_TRGT_IF_DDR_1);
diff --git a/board/freescale/p1_p2_rdb_pc/Makefile b/board/freescale/p1_p2_rdb_pc/Makefile
index 0dcf7d1ab1..5b45d72f51 100644
--- a/board/freescale/p1_p2_rdb_pc/Makefile
+++ b/board/freescale/p1_p2_rdb_pc/Makefile
@@ -24,11 +24,27 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
+MINIMAL=
+
+ifdef CONFIG_SPL_BUILD
+ifdef CONFIG_SPL_INIT_MINIMAL
+MINIMAL=y
+endif
+endif
+
+ifdef MINIMAL
+
+COBJS-y += spl_minimal.o tlb.o law.o
+
+else
+
COBJS-y += $(BOARD).o
COBJS-y += ddr.o
COBJS-y += law.o
COBJS-y += tlb.o
+endif
+
SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c)
OBJS := $(addprefix $(obj),$(COBJS-y))
SOBJS := $(addprefix $(obj),$(SOBJS))
diff --git a/board/freescale/p1_p2_rdb_pc/ddr.c b/board/freescale/p1_p2_rdb_pc/ddr.c
index 88ba56f457..9355536b35 100644
--- a/board/freescale/p1_p2_rdb_pc/ddr.c
+++ b/board/freescale/p1_p2_rdb_pc/ddr.c
@@ -206,6 +206,7 @@ int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
}
#endif /* CONFIG_SYS_DDR_RAW_TIMING */
+#ifdef CONFIG_SYS_DDR_CS0_BNDS
/* Fixed sdram init -- doesn't use serial presence detect. */
phys_size_t fixed_sdram(void)
{
@@ -260,6 +261,7 @@ phys_size_t fixed_sdram(void)
return ddr_size;
}
+#endif
void fsl_ddr_board_options(memctl_options_t *popts,
dimm_params_t *pdimm,
diff --git a/board/freescale/p1_p2_rdb_pc/law.c b/board/freescale/p1_p2_rdb_pc/law.c
index 0da8300c6f..cb5e7b7c0c 100644
--- a/board/freescale/p1_p2_rdb_pc/law.c
+++ b/board/freescale/p1_p2_rdb_pc/law.c
@@ -32,7 +32,7 @@ struct law_entry law_table[] = {
#endif
SET_LAW(CONFIG_SYS_FLASH_BASE_PHYS, LAW_SIZE_64M, LAW_TRGT_IF_LBC),
#ifdef CONFIG_SYS_NAND_BASE_PHYS
- SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_LBC),
+ SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_32K, LAW_TRGT_IF_LBC),
#endif
};
diff --git a/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c b/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c
index aa39260ca7..5b5b86c822 100644
--- a/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c
+++ b/board/freescale/p1_p2_rdb_pc/p1_p2_rdb_pc.c
@@ -177,7 +177,7 @@ void board_gpio_init(void)
*/
setbits_be32(&pgpio->gpdir, 0x02130000);
-#ifndef CONFIG_SYS_RAMBOOT
+#if !defined(CONFIG_SYS_RAMBOOT) && !defined(CONFIG_SPL)
/* init DDR3 reset signal */
setbits_be32(&pgpio->gpdir, 0x00200000);
setbits_be32(&pgpio->gpodr, 0x00200000);
diff --git a/nand_spl/board/freescale/p1_p2_rdb_pc/nand_boot.c b/board/freescale/p1_p2_rdb_pc/spl_minimal.c
index 4c140c1572..09019e98af 100644
--- a/nand_spl/board/freescale/p1_p2_rdb_pc/nand_boot.c
+++ b/board/freescale/p1_p2_rdb_pc/spl_minimal.c
@@ -23,18 +23,20 @@
#include <ns16550.h>
#include <asm/io.h>
#include <nand.h>
+#include <linux/compiler.h>
#include <asm/fsl_law.h>
#include <asm/fsl_ddr_sdram.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_SYS_INIT_L2_ADDR
/*
* Fixed sdram init -- doesn't use serial presence detect.
*/
-void sdram_init(void)
+static void sdram_init(void)
{
- ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
__raw_writel(CONFIG_SYS_DDR_CS0_BNDS, &ddr->cs0_bnds);
__raw_writel(CONFIG_SYS_DDR_CS0_CONFIG, &ddr->cs0_config);
@@ -71,6 +73,7 @@ void sdram_init(void)
set_next_law(0, CONFIG_SYS_SDRAM_SIZE_LAW, LAW_TRGT_IF_DDR_1);
}
+#endif
void board_init_f(ulong bootflag)
{
@@ -101,15 +104,16 @@ void board_init_f(ulong bootflag)
__raw_writel(0x00000000, &pgpio->gpdir);
#endif
+#ifndef CONFIG_SYS_INIT_L2_ADDR
/* Initialize the DDR3 */
sdram_init();
+#endif
/* copy code to RAM and jump to it - this should not return */
/* NOTE - code has to be copied out of NAND buffer before
* other blocks can be read.
*/
- relocate_code(CONFIG_SYS_NAND_U_BOOT_RELOC_SP, 0,
- CONFIG_SYS_NAND_U_BOOT_RELOC);
+ relocate_code(CONFIG_SPL_RELOC_STACK, 0, CONFIG_SPL_RELOC_TEXT_BASE);
}
void board_init_r(gd_t *gd, ulong dest_addr)
diff --git a/board/freescale/p1_p2_rdb_pc/tlb.c b/board/freescale/p1_p2_rdb_pc/tlb.c
index 6d2246387a..3e4dffd237 100644
--- a/board/freescale/p1_p2_rdb_pc/tlb.c
+++ b/board/freescale/p1_p2_rdb_pc/tlb.c
@@ -53,7 +53,7 @@ struct fsl_e_tlb_entry tlb_table[] = {
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 1, BOOKE_PAGESZ_1M, 1),
-#ifndef CONFIG_NAND_SPL
+#ifndef CONFIG_SPL_BUILD
/* W**G* - Flash/promjet, localbus */
/* This will be changed to *I*G* after relocation to RAM. */
SET_TLB_ENTRY(1, CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE_PHYS,
@@ -85,7 +85,7 @@ struct fsl_e_tlb_entry tlb_table[] = {
SET_TLB_ENTRY(1, CONFIG_SYS_PMC_BASE, CONFIG_SYS_PMC_BASE_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 10, BOOKE_PAGESZ_64K, 1),
-#endif
+#endif /* not SPL */
#ifdef CONFIG_SYS_NAND_BASE
/* *I*G - NAND */
@@ -94,7 +94,17 @@ struct fsl_e_tlb_entry tlb_table[] = {
0, 7, BOOKE_PAGESZ_1M, 1),
#endif
-#ifdef CONFIG_SYS_RAMBOOT
+#if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_SPL)
+#ifdef CONFIG_SYS_INIT_L2_ADDR
+ /* L2SRAM */
+ SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L2_ADDR, CONFIG_SYS_INIT_L2_ADDR_PHYS,
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+ 0, 8, BOOKE_PAGESZ_256K, 1),
+ SET_TLB_ENTRY(1, CONFIG_SYS_INIT_L2_ADDR + 0x40000,
+ CONFIG_SYS_INIT_L2_ADDR_PHYS + 0x40000,
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+ 0, 12, BOOKE_PAGESZ_256K, 1),
+#else
/* *I*G - eSDHC/eSPI/NAND boot */
SET_TLB_ENTRY(1, CONFIG_SYS_DDR_SDRAM_BASE, CONFIG_SYS_DDR_SDRAM_BASE,
MAS3_SX|MAS3_SW|MAS3_SR, 0,
@@ -106,9 +116,9 @@ struct fsl_e_tlb_entry tlb_table[] = {
CONFIG_SYS_DDR_SDRAM_BASE + 0x40000000,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 9, BOOKE_PAGESZ_1G, 1),
-#endif
-#endif
-
+#endif /* P1020MBG */
+#endif /* not L2 SRAM */
+#endif /* RAMBOOT/SPL */
};
int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/board/freescale/p2020ds/p2020ds.c b/board/freescale/p2020ds/p2020ds.c
index 3188f59e4b..d4a445108a 100644
--- a/board/freescale/p2020ds/p2020ds.c
+++ b/board/freescale/p2020ds/p2020ds.c
@@ -84,7 +84,7 @@ int checkboard(void)
phys_size_t fixed_sdram(void)
{
- volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ volatile ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
uint d_init;
ddr->cs0_config = CONFIG_SYS_DDR_CS0_CONFIG;
diff --git a/board/genesi/mx51_efikamx/efikamx.c b/board/genesi/mx51_efikamx/efikamx.c
index c2b2823ef9..69d41db530 100644
--- a/board/genesi/mx51_efikamx/efikamx.c
+++ b/board/genesi/mx51_efikamx/efikamx.c
@@ -33,7 +33,7 @@
#include <i2c.h>
#include <mmc.h>
#include <fsl_esdhc.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
#include <mc13892.h>
@@ -173,9 +173,15 @@ static void power_init(void)
unsigned int val;
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
struct pmic *p;
+ int ret;
+
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return;
- pmic_init();
- p = get_pmic();
+ p = pmic_get("FSL_PMIC");
+ if (!p)
+ return;
/* Write needed to Power Gate 2 register */
pmic_reg_read(p, REG_POWER_MISC, &val);
diff --git a/board/hale/tt01/tt01.c b/board/hale/tt01/tt01.c
index 143fcefedf..0c2cb795dd 100644
--- a/board/hale/tt01/tt01.c
+++ b/board/hale/tt01/tt01.c
@@ -25,12 +25,13 @@
#include <common.h>
#include <netdev.h>
#include <command.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
#include <mc13783.h>
#include <asm/arch/clock.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
+#include <errno.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -195,14 +196,21 @@ int board_mmc_init(bd_t *bis)
{
u32 val;
struct pmic *p;
+ int ret;
/*
* this is the first driver to use the pmic, so call
* pmic_init() here. board_late_init() is too late for
* the MMC driver.
*/
- pmic_init();
- p = get_pmic();
+
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return ret;
+
+ p = pmic_get("FSL_PMIC");
+ if (!p)
+ return -ENODEV;
/* configure pins for SDHC1 only */
mx31_gpio_mux(IOMUX_MODE(MUX_CTL_SD1_CLK, MUX_CTL_FUNC));
diff --git a/board/iomega/iconnect/iconnect.c b/board/iomega/iconnect/iconnect.c
index 6ee2128aab..8cfb4e6620 100644
--- a/board/iomega/iconnect/iconnect.c
+++ b/board/iomega/iconnect/iconnect.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2009-2012
* Wojciech Dubowik <wojciech.dubowik@neratec.com>
- * Luka Perkov <uboot@lukaperkov.net>
+ * Luka Perkov <luka@openwrt.org>
*
* See file CREDITS for list of people who contributed to this
* project.
diff --git a/board/iomega/iconnect/iconnect.h b/board/iomega/iconnect/iconnect.h
index 2fb3e5ed8f..8b6fe1bcad 100644
--- a/board/iomega/iconnect/iconnect.h
+++ b/board/iomega/iconnect/iconnect.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2009-2012
* Wojciech Dubowik <wojciech.dubowik@neratec.com>
- * Luka Perkov <uboot@lukaperkov.net>
+ * Luka Perkov <luka@openwrt.org>
*
* See file CREDITS for list of people who contributed to this
* project.
diff --git a/board/iomega/iconnect/kwbimage.cfg b/board/iomega/iconnect/kwbimage.cfg
index 6c9dfe3d31..4b64dab592 100644
--- a/board/iomega/iconnect/kwbimage.cfg
+++ b/board/iomega/iconnect/kwbimage.cfg
@@ -1,7 +1,7 @@
#
# (C) Copyright 2009-2012
# Wojciech Dubowik <wojciech.dubowik@neratec.com>
-# Luka Perkov <uboot@lukaperkov.net>
+# Luka Perkov <luka@openwrt.org>
#
# See file CREDITS for list of people who contributed to this
# project.
diff --git a/board/logicpd/am3517evm/am3517evm.c b/board/logicpd/am3517evm/am3517evm.c
index d316f33cd1..0b3721ed85 100644
--- a/board/logicpd/am3517evm/am3517evm.c
+++ b/board/logicpd/am3517evm/am3517evm.c
@@ -25,12 +25,20 @@
#include <common.h>
#include <asm/io.h>
+#include <asm/omap_musb.h>
+#include <asm/arch/am35x_def.h>
#include <asm/arch/mem.h>
#include <asm/arch/mux.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/mmc_host_def.h>
+#include <asm/arch/musb.h>
#include <asm/mach-types.h>
+#include <asm/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/musb.h>
#include <i2c.h>
+#include <netdev.h>
#include "am3517evm.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -50,6 +58,52 @@ int board_init(void)
return 0;
}
+#ifdef CONFIG_USB_MUSB_AM35X
+static struct musb_hdrc_config musb_config = {
+ .multipoint = 1,
+ .dyn_fifo = 1,
+ .num_eps = 16,
+ .ram_bits = 12,
+};
+
+static struct omap_musb_board_data musb_board_data = {
+ .set_phy_power = am35x_musb_phy_power,
+ .clear_irq = am35x_musb_clear_irq,
+ .reset = am35x_musb_reset,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_MUSB_HOST)
+ .mode = MUSB_HOST,
+#elif defined(CONFIG_MUSB_GADGET)
+ .mode = MUSB_PERIPHERAL,
+#else
+#error "Please define either CONFIG_MUSB_HOST or CONFIG_MUSB_GADGET"
+#endif
+ .config = &musb_config,
+ .power = 250,
+ .platform_ops = &am35x_ops,
+ .board_data = &musb_board_data,
+};
+
+static void am3517_evm_musb_init(void)
+{
+ /*
+ * Set up USB clock/mode in the DEVCONF2 register.
+ * USB2.0 PHY reference clock is 13 MHz
+ */
+ clrsetbits_le32(&am35x_scm_general_regs->devconf2,
+ CONF2_REFFREQ | CONF2_OTGMODE | CONF2_PHY_GPIOMODE,
+ CONF2_REFFREQ_13MHZ | CONF2_SESENDEN |
+ CONF2_VBDTCTEN | CONF2_DATPOL);
+
+ musb_register(&musb_plat, &musb_board_data,
+ (void *)AM35XX_IPSS_USBOTGSS_BASE);
+}
+#else
+#define am3517_evm_musb_init() do {} while (0)
+#endif
+
/*
* Routine: misc_init_r
* Description: Init i2c, ethernet, etc... (done here so udelay works)
@@ -62,6 +116,8 @@ int misc_init_r(void)
dieid_num_r();
+ am3517_evm_musb_init();
+
return 0;
}
@@ -83,3 +139,21 @@ int board_mmc_init(bd_t *bis)
return 0;
}
#endif
+
+#if defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)
+int board_eth_init(bd_t *bis)
+{
+ int rv, n = 0;
+
+ rv = cpu_eth_init(bis);
+ if (rv > 0)
+ n += rv;
+
+ rv = usb_eth_initialize(bis);
+ if (rv > 0)
+ n += rv;
+
+ return n;
+}
+#endif
+
diff --git a/board/raidsonic/ib62x0/ib62x0.c b/board/raidsonic/ib62x0/ib62x0.c
index b7e6e4107c..5f0f3961d3 100644
--- a/board/raidsonic/ib62x0/ib62x0.c
+++ b/board/raidsonic/ib62x0/ib62x0.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2011-2012
* Gerald Kerma <dreagle@doukki.net>
- * Luka Perkov <uboot@lukaperkov.net>
+ * Luka Perkov <luka@openwrt.org>
* Simon Baatz <gmbnomis@gmail.com>
*
* See file CREDITS for list of people who contributed to this
diff --git a/board/raidsonic/ib62x0/ib62x0.h b/board/raidsonic/ib62x0/ib62x0.h
index 0118c2b69a..3315696dda 100644
--- a/board/raidsonic/ib62x0/ib62x0.h
+++ b/board/raidsonic/ib62x0/ib62x0.h
@@ -2,7 +2,7 @@
* Copyright (C) 2011-2012
* Gerald Kerma <dreagle@doukki.net>
* Simon Baatz <gmbnomis@gmail.com>
- * Luka Perkov <uboot@lukaperkov.net>
+ * Luka Perkov <luka@openwrt.org>
*
* See file CREDITS for list of people who contributed to this
* project.
diff --git a/board/raidsonic/ib62x0/kwbimage.cfg b/board/raidsonic/ib62x0/kwbimage.cfg
index bd594ebd5d..bade627ccf 100644
--- a/board/raidsonic/ib62x0/kwbimage.cfg
+++ b/board/raidsonic/ib62x0/kwbimage.cfg
@@ -2,7 +2,7 @@
# Copyright (C) 2011-2012
# Gerald Kerma <dreagle@doukki.net>
# Simon Baatz <gmbnomis@gmail.com>
-# Luka Perkov <uboot@lukaperkov.net>
+# Luka Perkov <luka@openwrt.org>
#
# See file CREDITS for list of people who contributed to this
# project.
diff --git a/board/samsung/goni/goni.c b/board/samsung/goni/goni.c
index e8fb1ea413..ff76963925 100644
--- a/board/samsung/goni/goni.c
+++ b/board/samsung/goni/goni.c
@@ -25,10 +25,10 @@
#include <common.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mmc.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <usb/s3c_udc.h>
#include <asm/arch/cpu.h>
-#include <max8998_pmic.h>
+#include <power/max8998_pmic.h>
DECLARE_GLOBAL_DATA_PTR;
static struct s5pc110_gpio *s5pc110_gpio;
@@ -41,9 +41,17 @@ int board_init(void)
gd->bd->bi_arch_number = MACH_TYPE_GONI;
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
-#if defined(CONFIG_PMIC)
- pmic_init();
-#endif
+ return 0;
+}
+
+int power_init_board(void)
+{
+ int ret;
+
+ ret = pmic_init(I2C_5);
+ if (ret)
+ return ret;
+
return 0;
}
@@ -108,7 +116,9 @@ static int s5pc1xx_phy_control(int on)
{
int ret;
static int status;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("MAX8998_PMIC");
+ if (!p)
+ return -ENODEV;
if (pmic_probe(p))
return -1;
diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index d5c681c05e..4724029424 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -35,10 +35,13 @@
#include <asm/arch/mipi_dsim.h>
#include <asm/arch/watchdog.h>
#include <asm/arch/power.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <usb/s3c_udc.h>
-#include <max8997_pmic.h>
+#include <power/max8997_pmic.h>
#include <libtizen.h>
+#include <power/max8997_muic.h>
+#include <power/battery.h>
+#include <power/max17042_fg.h>
#include "setup.h"
@@ -69,10 +72,6 @@ int board_init(void)
check_hw_revision();
printf("HW Revision:\t0x%x\n", board_rev);
-#if defined(CONFIG_PMIC)
- pmic_init();
-#endif
-
return 0;
}
@@ -91,6 +90,275 @@ void i2c_init_board(void)
s5p_gpio_direction_output(&gpio2->y4, 1, 1);
}
+static void trats_low_power_mode(void)
+{
+ struct exynos4_clock *clk =
+ (struct exynos4_clock *)samsung_get_base_clock();
+ struct exynos4_power *pwr =
+ (struct exynos4_power *)samsung_get_base_power();
+
+ /* Power down CORE1 */
+ /* LOCAL_PWR_CFG [1:0] 0x3 EN, 0x0 DIS */
+ writel(0x0, &pwr->arm_core1_configuration);
+
+ /* Change the APLL frequency */
+ /* ENABLE (1 enable) | LOCKED (1 locked) */
+ /* [31] | [29] */
+ /* FSEL | MDIV | PDIV | SDIV */
+ /* [27] | [25:16] | [13:8] | [2:0] */
+ writel(0xa0c80604, &clk->apll_con0);
+
+ /* Change CPU0 clock divider */
+ /* CORE2_RATIO | APLL_RATIO | PCLK_DBG_RATIO | ATB_RATIO */
+ /* [30:28] | [26:24] | [22:20] | [18:16] */
+ /* PERIPH_RATIO | COREM1_RATIO | COREM0_RATIO | CORE_RATIO */
+ /* [14:12] | [10:8] | [6:4] | [2:0] */
+ writel(0x00000100, &clk->div_cpu0);
+
+ /* CLK_DIV_STAT_CPU0 - wait until clock gets stable (0 = stable) */
+ while (readl(&clk->div_stat_cpu0) & 0x1111111)
+ continue;
+
+ /* Change clock divider ratio for DMC */
+ /* DMCP_RATIO | DMCD_RATIO */
+ /* [22:20] | [18:16] */
+ /* DMC_RATIO | DPHY_RATIO | ACP_PCLK_RATIO | ACP_RATIO */
+ /* [14:12] | [10:8] | [6:4] | [2:0] */
+ writel(0x13113117, &clk->div_dmc0);
+
+ /* CLK_DIV_STAT_DMC0 - wait until clock gets stable (0 = stable) */
+ while (readl(&clk->div_stat_dmc0) & 0x11111111)
+ continue;
+
+ /* Turn off unnecessary power domains */
+ writel(0x0, &pwr->xxti_configuration); /* XXTI */
+ writel(0x0, &pwr->cam_configuration); /* CAM */
+ writel(0x0, &pwr->tv_configuration); /* TV */
+ writel(0x0, &pwr->mfc_configuration); /* MFC */
+ writel(0x0, &pwr->g3d_configuration); /* G3D */
+ writel(0x0, &pwr->gps_configuration); /* GPS */
+ writel(0x0, &pwr->gps_alive_configuration); /* GPS_ALIVE */
+
+ /* Turn off unnecessary clocks */
+ writel(0x0, &clk->gate_ip_cam); /* CAM */
+ writel(0x0, &clk->gate_ip_tv); /* TV */
+ writel(0x0, &clk->gate_ip_mfc); /* MFC */
+ writel(0x0, &clk->gate_ip_g3d); /* G3D */
+ writel(0x0, &clk->gate_ip_image); /* IMAGE */
+ writel(0x0, &clk->gate_ip_gps); /* GPS */
+}
+
+static int pmic_init_max8997(void)
+{
+ struct pmic *p = pmic_get("MAX8997_PMIC");
+ int i = 0, ret = 0;
+ u32 val;
+
+ if (pmic_probe(p))
+ return -1;
+
+ /* BUCK1 VARM: 1.2V */
+ val = (1200000 - 650000) / 25000;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK1DVS1, val);
+ val = ENBUCK | ACTIVE_DISCHARGE; /* DVS OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK1CTRL, val);
+
+ /* BUCK2 VINT: 1.1V */
+ val = (1100000 - 650000) / 25000;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK2DVS1, val);
+ val = ENBUCK | ACTIVE_DISCHARGE; /* DVS OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK2CTRL, val);
+
+
+ /* BUCK3 G3D: 1.1V - OFF */
+ ret |= pmic_reg_read(p, MAX8997_REG_BUCK3CTRL, &val);
+ val &= ~ENBUCK;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK3CTRL, val);
+
+ val = (1100000 - 750000) / 50000;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK3DVS, val);
+
+ /* BUCK4 CAMISP: 1.2V - OFF */
+ ret |= pmic_reg_read(p, MAX8997_REG_BUCK4CTRL, &val);
+ val &= ~ENBUCK;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK4CTRL, val);
+
+ val = (1200000 - 650000) / 25000;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK4DVS, val);
+
+ /* BUCK5 VMEM: 1.2V */
+ val = (1200000 - 650000) / 25000;
+ for (i = 0; i < 8; i++)
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK5DVS1 + i, val);
+
+ val = ENBUCK | ACTIVE_DISCHARGE; /* DVS OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK5CTRL, val);
+
+ /* BUCK6 CAM AF: 2.8V */
+ /* No Voltage Setting Register */
+ /* GNSLCT 3.0X */
+ val = GNSLCT;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK6CTRL, val);
+
+ /* BUCK7 VCC_SUB: 2.0V */
+ val = (2000000 - 750000) / 50000;
+ ret |= pmic_reg_write(p, MAX8997_REG_BUCK7DVS, val);
+
+ /* LDO1 VADC: 3.3V */
+ val = max8997_reg_ldo(3300000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO1CTRL, val);
+
+ /* LDO1 Disable active discharging */
+ ret |= pmic_reg_read(p, MAX8997_REG_LDO1CONFIG, &val);
+ val &= ~LDO_ADE;
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO1CONFIG, val);
+
+ /* LDO2 VALIVE: 1.1V */
+ val = max8997_reg_ldo(1100000) | EN_LDO;
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO2CTRL, val);
+
+ /* LDO3 VUSB/MIPI: 1.1V */
+ val = max8997_reg_ldo(1100000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO3CTRL, val);
+
+ /* LDO4 VMIPI: 1.8V */
+ val = max8997_reg_ldo(1800000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO4CTRL, val);
+
+ /* LDO5 VHSIC: 1.2V */
+ val = max8997_reg_ldo(1200000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO5CTRL, val);
+
+ /* LDO6 VCC_1.8V_PDA: 1.8V */
+ val = max8997_reg_ldo(1800000) | EN_LDO;
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO6CTRL, val);
+
+ /* LDO7 CAM_ISP: 1.8V */
+ val = max8997_reg_ldo(1800000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO7CTRL, val);
+
+ /* LDO8 VDAC/VUSB: 3.3V */
+ val = max8997_reg_ldo(3300000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO8CTRL, val);
+
+ /* LDO9 VCC_2.8V_PDA: 2.8V */
+ val = max8997_reg_ldo(2800000) | EN_LDO;
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO9CTRL, val);
+
+ /* LDO10 VPLL: 1.1V */
+ val = max8997_reg_ldo(1100000) | EN_LDO;
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO10CTRL, val);
+
+ /* LDO11 TOUCH: 2.8V */
+ val = max8997_reg_ldo(2800000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO11CTRL, val);
+
+ /* LDO12 VTCAM: 1.8V */
+ val = max8997_reg_ldo(1800000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO12CTRL, val);
+
+ /* LDO13 VCC_3.0_LCD: 3.0V */
+ val = max8997_reg_ldo(3000000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO13CTRL, val);
+
+ /* LDO14 MOTOR: 3.0V */
+ val = max8997_reg_ldo(3000000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO14CTRL, val);
+
+ /* LDO15 LED_A: 2.8V */
+ val = max8997_reg_ldo(2800000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO15CTRL, val);
+
+ /* LDO16 CAM_SENSOR: 1.8V */
+ val = max8997_reg_ldo(1800000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO16CTRL, val);
+
+ /* LDO17 VTF: 2.8V */
+ val = max8997_reg_ldo(2800000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO17CTRL, val);
+
+ /* LDO18 TOUCH_LED 3.3V */
+ val = max8997_reg_ldo(3300000) | DIS_LDO; /* OFF */
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO18CTRL, val);
+
+ /* LDO21 VDDQ: 1.2V */
+ val = max8997_reg_ldo(1200000) | EN_LDO;
+ ret |= pmic_reg_write(p, MAX8997_REG_LDO21CTRL, val);
+
+ /* SAFEOUT for both 1 and 2: 4.9V, Active discharge, Enable */
+ val = (SAFEOUT_4_90V << 0) | (SAFEOUT_4_90V << 2) |
+ ACTDISSAFEO1 | ACTDISSAFEO2 | ENSAFEOUT1 | ENSAFEOUT2;
+ ret |= pmic_reg_write(p, MAX8997_REG_SAFEOUTCTRL, val);
+
+ if (ret) {
+ puts("MAX8997 PMIC setting error!\n");
+ return -1;
+ }
+ return 0;
+}
+
+int power_init_board(void)
+{
+ int chrg, ret;
+ struct power_battery *pb;
+ struct pmic *p_fg, *p_chrg, *p_muic, *p_bat;
+
+ ret = pmic_init(I2C_5);
+ ret |= pmic_init_max8997();
+ ret |= power_fg_init(I2C_9);
+ ret |= power_muic_init(I2C_5);
+ ret |= power_bat_init(0);
+ if (ret)
+ return ret;
+
+ p_fg = pmic_get("MAX17042_FG");
+ if (!p_fg) {
+ puts("MAX17042_FG: Not found\n");
+ return -ENODEV;
+ }
+
+ p_chrg = pmic_get("MAX8997_PMIC");
+ if (!p_chrg) {
+ puts("MAX8997_PMIC: Not found\n");
+ return -ENODEV;
+ }
+
+ p_muic = pmic_get("MAX8997_MUIC");
+ if (!p_muic) {
+ puts("MAX8997_MUIC: Not found\n");
+ return -ENODEV;
+ }
+
+ p_bat = pmic_get("BAT_TRATS");
+ if (!p_bat) {
+ puts("BAT_TRATS: Not found\n");
+ return -ENODEV;
+ }
+
+ p_fg->parent = p_bat;
+ p_chrg->parent = p_bat;
+ p_muic->parent = p_bat;
+
+ p_bat->low_power_mode = trats_low_power_mode;
+ p_bat->pbat->battery_init(p_bat, p_fg, p_chrg, p_muic);
+
+ pb = p_bat->pbat;
+ chrg = p_muic->chrg->chrg_type(p_muic);
+ debug("CHARGER TYPE: %d\n", chrg);
+
+ if (!p_chrg->chrg->chrg_bat_present(p_chrg)) {
+ puts("No battery detected\n");
+ return -1;
+ }
+
+ p_fg->fg->fg_battery_check(p_fg, p_bat);
+
+ if (pb->bat->state == CHARGE && chrg == CHARGER_USB)
+ puts("CHARGE Battery !\n");
+
+ return 0;
+}
+
int dram_init(void)
{
gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE) +
@@ -200,7 +468,9 @@ static int s5pc210_phy_control(int on)
{
int ret = 0;
u32 val = 0;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("MAX8997_PMIC");
+ if (!p)
+ return -ENODEV;
if (pmic_probe(p))
return -1;
@@ -379,7 +649,9 @@ static void lcd_reset(void)
static int lcd_power(void)
{
int ret = 0;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("MAX8997_PMIC");
+ if (!p)
+ return -ENODEV;
if (pmic_probe(p))
return 0;
@@ -439,7 +711,9 @@ static struct mipi_dsim_lcd_device mipi_lcd_device = {
static int mipi_power(void)
{
int ret = 0;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("MAX8997_PMIC");
+ if (!p)
+ return -ENODEV;
if (pmic_probe(p))
return 0;
diff --git a/board/samsung/universal_c210/universal.c b/board/samsung/universal_c210/universal.c
index afe3bb0aeb..3d508bea23 100644
--- a/board/samsung/universal_c210/universal.c
+++ b/board/samsung/universal_c210/universal.c
@@ -31,13 +31,13 @@
#include <asm/arch/gpio.h>
#include <asm/arch/mmc.h>
#include <asm/arch/pinmux.h>
-#include <pmic.h>
-#include <usb/s3c_udc.h>
-#include <asm/arch/cpu.h>
-#include <max8998_pmic.h>
#include <asm/arch/watchdog.h>
#include <libtizen.h>
#include <ld9040.h>
+#include <power/pmic.h>
+#include <usb/s3c_udc.h>
+#include <asm/arch/cpu.h>
+#include <power/max8998_pmic.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -55,7 +55,16 @@ static int get_hwrev(void)
return board_rev & 0xFF;
}
-static void check_hw_revision(void);
+int power_init_board(void)
+{
+ int ret;
+
+ ret = pmic_init(I2C_5);
+ if (ret)
+ return ret;
+
+ return 0;
+}
int dram_init(void)
{
@@ -101,7 +110,9 @@ static unsigned short get_adc_value(int channel)
static int adc_power_control(int on)
{
int ret;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("MAX8998_PMIC");
+ if (!p)
+ return -ENODEV;
if (pmic_probe(p))
return -1;
@@ -224,7 +235,9 @@ int board_mmc_init(bd_t *bis)
static int s5pc210_phy_control(int on)
{
int ret = 0;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("MAX8998_PMIC");
+ if (!p)
+ return -ENODEV;
if (pmic_probe(p))
return -1;
@@ -489,10 +502,6 @@ int board_init(void)
gd->bd->bi_arch_number = MACH_TYPE_UNIVERSAL_C210;
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
-#if defined(CONFIG_PMIC)
- pmic_init();
- init_pmic_lcd();
-#endif
#ifdef CONFIG_SOFT_SPI
soft_spi_init();
#endif
diff --git a/board/sbc8548/ddr.c b/board/sbc8548/ddr.c
index 45ec485c50..9508561133 100644
--- a/board/sbc8548/ddr.c
+++ b/board/sbc8548/ddr.c
@@ -91,7 +91,7 @@ void get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
*/
phys_size_t fixed_sdram(void)
{
- volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+ volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR);
out_be32(&ddr->cs0_bnds, 0x0000007f);
out_be32(&ddr->cs1_bnds, 0x008000ff);
diff --git a/board/socrates/sdram.c b/board/socrates/sdram.c
index c8235f4a9b..8a9ce790f1 100644
--- a/board/socrates/sdram.c
+++ b/board/socrates/sdram.c
@@ -41,7 +41,7 @@
*/
phys_size_t fixed_sdram(void)
{
- volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC85xx_DDR_ADDR);
+ volatile ccsr_ddr_t *ddr = (void *)(CONFIG_SYS_MPC8xxx_DDR_ADDR);
/*
* Disable memory controller.
diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c
index b56a801a4d..f0eca54c9e 100644
--- a/board/ti/am335x/board.c
+++ b/board/ti/am335x/board.c
@@ -379,9 +379,14 @@ static struct cpsw_platform_data cpsw_data = {
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,
};
+#endif
+#if defined(CONFIG_DRIVER_TI_CPSW) || \
+ (defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET))
int board_eth_init(bd_t *bis)
{
+ int rv, n = 0;
+#ifdef CONFIG_DRIVER_TI_CPSW
uint8_t mac_addr[6];
uint32_t mac_hi, mac_lo;
@@ -400,7 +405,7 @@ int board_eth_init(bd_t *bis)
if (is_valid_ether_addr(mac_addr))
eth_setenv_enetaddr("ethaddr", mac_addr);
else
- return -1;
+ goto try_usbether;
}
if (board_is_bone() || board_is_bone_lt() || board_is_idk()) {
@@ -413,6 +418,20 @@ int board_eth_init(bd_t *bis)
PHY_INTERFACE_MODE_RGMII;
}
- return cpsw_register(&cpsw_data);
+ rv = cpsw_register(&cpsw_data);
+ if (rv < 0)
+ printf("Error %d registering CPSW switch\n", rv);
+ else
+ n += rv;
+#endif
+try_usbether:
+#if defined(CONFIG_USB_ETHER) && !defined(CONFIG_SPL_BUILD)
+ rv = usb_eth_initialize(bis);
+ if (rv < 0)
+ printf("Error %d registering USB_ETHER\n", rv);
+ else
+ n += rv;
+#endif
+ return n;
}
#endif
diff --git a/board/ti/beagle/beagle.c b/board/ti/beagle/beagle.c
index 6175e1d1ac..f20ebed452 100644
--- a/board/ti/beagle/beagle.c
+++ b/board/ti/beagle/beagle.c
@@ -42,6 +42,11 @@
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>
#include <asm/mach-types.h>
+#include <asm/omap_musb.h>
+#include <asm/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/musb.h>
#include "beagle.h"
#include <command.h>
@@ -285,6 +290,33 @@ static void beagle_dvi_pup(void)
}
#endif
+#ifdef CONFIG_USB_MUSB_OMAP2PLUS
+static struct musb_hdrc_config musb_config = {
+ .multipoint = 1,
+ .dyn_fifo = 1,
+ .num_eps = 16,
+ .ram_bits = 12,
+};
+
+static struct omap_musb_board_data musb_board_data = {
+ .interface_type = MUSB_INTERFACE_ULPI,
+};
+
+static struct musb_hdrc_platform_data musb_plat = {
+#if defined(CONFIG_MUSB_HOST)
+ .mode = MUSB_HOST,
+#elif defined(CONFIG_MUSB_GADGET)
+ .mode = MUSB_PERIPHERAL,
+#else
+#error "Please define either CONFIG_MUSB_HOST or CONFIG_MUSB_GADGET"
+#endif
+ .config = &musb_config,
+ .power = 100,
+ .platform_ops = &omap2430_ops,
+ .board_data = &musb_board_data,
+};
+#endif
+
/*
* Routine: misc_init_r
* Description: Configure board specific parts
@@ -466,6 +498,10 @@ int misc_init_r(void)
omap3_dss_enable();
#endif
+#ifdef CONFIG_USB_MUSB_OMAP2PLUS
+ musb_register(&musb_plat, &musb_board_data, (void *)MUSB_BASE);
+#endif
+
return 0;
}
@@ -513,3 +549,10 @@ int ehci_hcd_stop(int index)
}
#endif /* CONFIG_USB_EHCI */
+
+#if defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)
+int board_eth_init(bd_t *bis)
+{
+ return usb_eth_initialize(bis);
+}
+#endif
diff --git a/board/ttcontrol/vision2/vision2.c b/board/ttcontrol/vision2/vision2.c
index abdd1aac2b..a471fec23d 100644
--- a/board/ttcontrol/vision2/vision2.c
+++ b/board/ttcontrol/vision2/vision2.c
@@ -34,7 +34,7 @@
#include <asm/arch/sys_proto.h>
#include <i2c.h>
#include <mmc.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_esdhc.h>
#include <fsl_pmic.h>
#include <mc13892.h>
@@ -306,9 +306,15 @@ static void power_init_mx51(void)
{
unsigned int val;
struct pmic *p;
+ int ret;
+
+ ret = pmic_init(I2C_PMIC);
+ if (ret)
+ return;
- pmic_init();
- p = get_pmic();
+ p = pmic_get("FSL_PMIC");
+ if (!p)
+ return;
/* Write needed to Power Gate 2 register */
pmic_reg_read(p, REG_POWER_MISC, &val);
diff --git a/boards.cfg b/boards.cfg
index 6f21af0821..388e4a4461 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -100,6 +100,7 @@ at91sam9rlek_dataflash arm arm926ejs at91sam9rlek atmel
at91sam9rlek_nandflash arm arm926ejs at91sam9rlek atmel at91 at91sam9rlek:AT91SAM9RL,SYS_USE_NANDFLASH
at91sam9x5ek_nandflash arm arm926ejs at91sam9x5ek atmel at91 at91sam9x5ek:AT91SAM9X5,SYS_USE_NANDFLASH
at91sam9x5ek_spiflash arm arm926ejs at91sam9x5ek atmel at91 at91sam9x5ek:AT91SAM9X5,SYS_USE_SPIFLASH
+at91sam9x5ek_mmc arm arm926ejs at91sam9x5ek atmel at91 at91sam9x5ek:AT91SAM9X5,SYS_USE_MMC
at91sam9xeek_dataflash_cs0 arm arm926ejs at91sam9260ek atmel at91 at91sam9260ek:AT91SAM9XE,SYS_USE_DATAFLASH_CS0
at91sam9xeek_dataflash_cs1 arm arm926ejs at91sam9260ek atmel at91 at91sam9260ek:AT91SAM9XE,SYS_USE_DATAFLASH_CS1
at91sam9xeek_nandflash arm arm926ejs at91sam9260ek atmel at91 at91sam9260ek:AT91SAM9XE,SYS_USE_NANDFLASH
@@ -374,7 +375,7 @@ M5235EVB m68k mcf523x m5235evb freesca
M5235EVB_Flash32 m68k mcf523x m5235evb freescale - M5235EVB:NORFLASH_PS32BIT,SYS_TEXT_BASE=0xFFC00000
cobra5272 m68k mcf52x2 cobra5272 -
idmr m68k mcf52x2
-eb_cpu5282 m68k mcf52x2 eb_cpu5282 BuS - eb_cpu5282:SYS_TEXT_BASE=0xFFE00000
+eb_cpu5282 m68k mcf52x2 eb_cpu5282 BuS - eb_cpu5282:SYS_TEXT_BASE=0xFF000000
eb_cpu5282_internal m68k mcf52x2 eb_cpu5282 BuS - eb_cpu5282:SYS_TEXT_BASE=0xF0000000
TASREG m68k mcf52x2 tasreg esd
M5208EVBE m68k mcf52x2 m5208evbe freescale
@@ -474,6 +475,7 @@ mpc5121ads powerpc mpc512x mpc5121ads freesca
mpc5121ads_rev2 powerpc mpc512x mpc5121ads freescale - mpc5121ads:MPC5121ADS_REV2
cmi_mpc5xx powerpc mpc5xx cmi
PATI powerpc mpc5xx pati mpl
+a3m071 powerpc mpc5xxx a3m071
a4m072 powerpc mpc5xxx a4m072
BC3450 powerpc mpc5xxx bc3450
canmb powerpc mpc5xxx
@@ -850,6 +852,7 @@ P5020DS_SDCARD powerpc mpc85xx corenet_ds freescale
P5020DS_SECURE_BOOT powerpc mpc85xx corenet_ds freescale - P5020DS:SECURE_BOOT
P5020DS_SPIFLASH powerpc mpc85xx corenet_ds freescale - P5020DS:RAMBOOT_PBL,SPIFLASH,SYS_TEXT_BASE=0xFFF80000
P5020DS_SRIO_PCIE_BOOT powerpc mpc85xx corenet_ds freescale - P5020DS:SRIO_PCIE_BOOT_SLAVE,SYS_TEXT_BASE=0xFFF80000
+P5040DS powerpc mpc85xx corenet_ds freescale
BSC9131RDB_SPIFLASH powerpc mpc85xx bsc9131rdb freescale - BSC9131RDB:BSC9131RDB,SPIFLASH
stxgp3 powerpc mpc85xx stxgp3 stx
stxssa powerpc mpc85xx stxssa stx - stxssa
@@ -1099,7 +1102,7 @@ gr_cpci_ax2000 sparc leon3 - gaisler
gr_ep2s60 sparc leon3 - gaisler
grsim sparc leon3 - gaisler
gr_xc3s_1500 sparc leon3 - gaisler
-coreboot-x86 x86 x86 coreboot chromebook-x86 coreboot coreboot:SYS_TEXT_BASE=0xFC0000
+coreboot-x86 x86 x86 coreboot chromebook-x86 coreboot coreboot:SYS_TEXT_BASE=0x01110000
eNET x86 x86 eNET - sc520 eNET:SYS_TEXT_BASE=0x38040000
eNET_SRAM x86 x86 eNET - sc520 eNET:SYS_TEXT_BASE=0x19000000
# Target ARCH CPU Board name Vendor SoC Options
diff --git a/common/Makefile b/common/Makefile
index ded6318dc6..132b3bd79c 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -196,6 +196,9 @@ COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
endif
ifdef CONFIG_SPL_BUILD
+COBJS-y += cmd_nvedit.o
+COBJS-y += env_common.o
+COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
COBJS-$(CONFIG_SPL_NET_SUPPORT) += cmd_nvedit.o
COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_common.o
diff --git a/common/bouncebuf.c b/common/bouncebuf.c
index 4f827f893d..1df12cdda0 100644
--- a/common/bouncebuf.c
+++ b/common/bouncebuf.c
@@ -27,21 +27,19 @@
#include <errno.h>
#include <bouncebuf.h>
-static int addr_aligned(void *data, size_t len)
+static int addr_aligned(struct bounce_buffer *state)
{
const ulong align_mask = ARCH_DMA_MINALIGN - 1;
/* Check if start is aligned */
- if ((ulong)data & align_mask) {
- debug("Unaligned start address %p\n", data);
+ if ((ulong)state->user_buffer & align_mask) {
+ debug("Unaligned buffer address %p\n", state->user_buffer);
return 0;
}
- data += len;
-
- /* Check if end is aligned */
- if ((ulong)data & align_mask) {
- debug("Unaligned end address %p\n", data);
+ /* Check if length is aligned */
+ if (state->len != state->len_aligned) {
+ debug("Unaligned buffer length %d\n", state->len);
return 0;
}
@@ -49,44 +47,53 @@ static int addr_aligned(void *data, size_t len)
return 1;
}
-int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags)
+int bounce_buffer_start(struct bounce_buffer *state, void *data,
+ size_t len, unsigned int flags)
{
- void *tmp;
- size_t alen;
-
- if (addr_aligned(*data, len)) {
- *backup = NULL;
- return 0;
+ state->user_buffer = data;
+ state->bounce_buffer = data;
+ state->len = len;
+ state->len_aligned = roundup(len, ARCH_DMA_MINALIGN);
+ state->flags = flags;
+
+ if (!addr_aligned(state)) {
+ state->bounce_buffer = memalign(ARCH_DMA_MINALIGN,
+ state->len_aligned);
+ if (!state->bounce_buffer)
+ return -ENOMEM;
+
+ if (state->flags & GEN_BB_READ)
+ memcpy(state->bounce_buffer, state->user_buffer,
+ state->len);
}
- alen = roundup(len, ARCH_DMA_MINALIGN);
- tmp = memalign(ARCH_DMA_MINALIGN, alen);
-
- if (!tmp)
- return -ENOMEM;
-
- if (flags & GEN_BB_READ)
- memcpy(tmp, *data, len);
-
- *backup = *data;
- *data = tmp;
+ /*
+ * Flush data to RAM so DMA reads can pick it up,
+ * and any CPU writebacks don't race with DMA writes
+ */
+ flush_dcache_range((unsigned long)state->bounce_buffer,
+ (unsigned long)(state->bounce_buffer) +
+ state->len_aligned);
return 0;
}
-int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags)
+int bounce_buffer_stop(struct bounce_buffer *state)
{
- void *tmp = *data;
+ if (state->flags & GEN_BB_WRITE) {
+ /* Invalidate cache so that CPU can see any newly DMA'd data */
+ invalidate_dcache_range((unsigned long)state->bounce_buffer,
+ (unsigned long)(state->bounce_buffer) +
+ state->len_aligned);
+ }
- /* The buffer was already aligned, since "backup" is NULL. */
- if (!*backup)
+ if (state->bounce_buffer == state->user_buffer)
return 0;
- if (flags & GEN_BB_WRITE)
- memcpy(*backup, *data, len);
+ if (state->flags & GEN_BB_WRITE)
+ memcpy(state->user_buffer, state->bounce_buffer, state->len);
- *data = *backup;
- free(tmp);
+ free(state->bounce_buffer);
return 0;
}
diff --git a/common/cmd_bmp.c b/common/cmd_bmp.c
index b8809e3bf5..5a52edde31 100644
--- a/common/cmd_bmp.c
+++ b/common/cmd_bmp.c
@@ -31,6 +31,7 @@
#include <command.h>
#include <asm/byteorder.h>
#include <malloc.h>
+#include <video.h>
static int bmp_info (ulong addr);
@@ -238,9 +239,7 @@ int bmp_display(ulong addr, int x, int y)
#if defined(CONFIG_LCD)
ret = lcd_display_bitmap((ulong)bmp, x, y);
#elif defined(CONFIG_VIDEO)
- extern int video_display_bitmap (ulong, int, int);
-
- ret = video_display_bitmap ((unsigned long)bmp, x, y);
+ ret = video_display_bitmap((unsigned long)bmp, x, y);
#else
# error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO
#endif
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index d256ddfaa6..4dbe952bb0 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -949,8 +949,19 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
* node
*/
bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
+#ifdef CONFIG_FIT_BEST_MATCH
+ if (fit_uname_config)
+ cfg_noffset =
+ fit_conf_get_node(fit_hdr,
+ fit_uname_config);
+ else
+ cfg_noffset =
+ fit_conf_find_compat(fit_hdr,
+ gd->fdt_blob);
+#else
cfg_noffset = fit_conf_get_node(fit_hdr,
fit_uname_config);
+#endif
if (cfg_noffset < 0) {
bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
return NULL;
diff --git a/common/cmd_led.c b/common/cmd_led.c
index d83b3ba69b..7f5ab43c7f 100644
--- a/common/cmd_led.c
+++ b/common/cmd_led.c
@@ -140,7 +140,7 @@ int do_led (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
U_BOOT_CMD(
led, 3, 1, do_led,
- "led\t- ["
+ "["
#ifdef CONFIG_BOARD_SPECIFIC_LED
#ifdef STATUS_LED_BIT
"0|"
@@ -167,6 +167,6 @@ U_BOOT_CMD(
#ifdef STATUS_LED_BLUE
"blue|"
#endif
- "all] [on|off|toggle]\n",
- "led [led_name] [on|off|toggle] sets or clears led(s)\n"
+ "all] [on|off|toggle]",
+ "[led_name] [on|off|toggle] sets or clears led(s)"
);
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 62a1c224d3..7dacd5114c 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -144,7 +144,7 @@ static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
U_BOOT_CMD(
mmcinfo, 1, 0, do_mmcinfo,
"display MMC info",
- "- dislay info of the current MMC device"
+ "- display info of the current MMC device"
);
static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -250,14 +250,13 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 0;
}
- if (strcmp(argv[1], "read") == 0)
+ state = MMC_INVALID;
+ if (argc == 5 && strcmp(argv[1], "read") == 0)
state = MMC_READ;
- else if (strcmp(argv[1], "write") == 0)
+ else if (argc == 5 && strcmp(argv[1], "write") == 0)
state = MMC_WRITE;
- else if (strcmp(argv[1], "erase") == 0)
+ else if (argc == 4 && strcmp(argv[1], "erase") == 0)
state = MMC_ERASE;
- else
- state = MMC_INVALID;
if (state != MMC_INVALID) {
struct mmc *mmc = find_mmc_device(curr_device);
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 4b1606972b..1568594ca4 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -700,6 +700,25 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return ret == 0 ? 0 : 1;
}
+#ifdef CONFIG_CMD_NAND_TORTURE
+ if (strcmp(cmd, "torture") == 0) {
+ if (argc < 3)
+ goto usage;
+
+ if (!str2off(argv[2], &off)) {
+ puts("Offset is not a valid number\n");
+ return 1;
+ }
+
+ printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
+ dev, off, nand->erasesize);
+ ret = nand_torture(nand, off);
+ printf(" %s\n", ret ? "Failed" : "Passed");
+
+ return ret == 0 ? 0 : 1;
+ }
+#endif
+
if (strcmp(cmd, "markbad") == 0) {
argc -= 2;
argv += 2;
@@ -810,6 +829,9 @@ static char nand_help_text[] =
"nand erase.chip [clean] - erase entire chip'\n"
"nand bad - show bad blocks\n"
"nand dump[.oob] off - dump page\n"
+#ifdef CONFIG_CMD_NAND_TORTURE
+ "nand torture off - torture block at offset\n"
+#endif
"nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
" really clean NAND erasing bad blocks (UNSAFE)\n"
"nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 8ad0b23058..dacdc2d5b1 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -192,7 +192,7 @@ static void usb_display_desc(struct usb_device *dev)
}
-static void usb_display_conf_desc(struct usb_configuration_descriptor *config,
+static void usb_display_conf_desc(struct usb_config_descriptor *config,
struct usb_device *dev)
{
printf(" Configuration: %d\n", config->bConfigurationValue);
diff --git a/common/image.c b/common/image.c
index df642e656c..e93b6e89cf 100644
--- a/common/image.c
+++ b/common/image.c
@@ -3049,6 +3049,133 @@ int fit_check_format(const void *fit)
return 1;
}
+
+/**
+ * fit_conf_find_compat
+ * @fit: pointer to the FIT format image header
+ * @fdt: pointer to the device tree to compare against
+ *
+ * fit_conf_find_compat() attempts to find the configuration whose fdt is the
+ * most compatible with the passed in device tree.
+ *
+ * Example:
+ *
+ * / o image-tree
+ * |-o images
+ * | |-o fdt@1
+ * | |-o fdt@2
+ * |
+ * |-o configurations
+ * |-o config@1
+ * | |-fdt = fdt@1
+ * |
+ * |-o config@2
+ * |-fdt = fdt@2
+ *
+ * / o U-Boot fdt
+ * |-compatible = "foo,bar", "bim,bam"
+ *
+ * / o kernel fdt1
+ * |-compatible = "foo,bar",
+ *
+ * / o kernel fdt2
+ * |-compatible = "bim,bam", "baz,biz"
+ *
+ * Configuration 1 would be picked because the first string in U-Boot's
+ * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
+ * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
+ *
+ * returns:
+ * offset to the configuration to use if one was found
+ * -1 otherwise
+ */
+int fit_conf_find_compat(const void *fit, const void *fdt)
+{
+ int ndepth = 0;
+ int noffset, confs_noffset, images_noffset;
+ const void *fdt_compat;
+ int fdt_compat_len;
+ int best_match_offset = 0;
+ int best_match_pos = 0;
+
+ confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
+ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+ if (confs_noffset < 0 || images_noffset < 0) {
+ debug("Can't find configurations or images nodes.\n");
+ return -1;
+ }
+
+ fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
+ if (!fdt_compat) {
+ debug("Fdt for comparison has no \"compatible\" property.\n");
+ return -1;
+ }
+
+ /*
+ * Loop over the configurations in the FIT image.
+ */
+ for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
+ (noffset >= 0) && (ndepth > 0);
+ noffset = fdt_next_node(fit, noffset, &ndepth)) {
+ const void *kfdt;
+ const char *kfdt_name;
+ int kfdt_noffset;
+ const char *cur_fdt_compat;
+ int len;
+ size_t size;
+ int i;
+
+ if (ndepth > 1)
+ continue;
+
+ kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
+ if (!kfdt_name) {
+ debug("No fdt property found.\n");
+ continue;
+ }
+ kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
+ kfdt_name);
+ if (kfdt_noffset < 0) {
+ debug("No image node named \"%s\" found.\n",
+ kfdt_name);
+ continue;
+ }
+ /*
+ * Get a pointer to this configuration's fdt.
+ */
+ if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
+ debug("Failed to get fdt \"%s\".\n", kfdt_name);
+ continue;
+ }
+
+ len = fdt_compat_len;
+ cur_fdt_compat = fdt_compat;
+ /*
+ * Look for a match for each U-Boot compatibility string in
+ * turn in this configuration's fdt.
+ */
+ for (i = 0; len > 0 &&
+ (!best_match_offset || best_match_pos > i); i++) {
+ int cur_len = strlen(cur_fdt_compat) + 1;
+
+ if (!fdt_node_check_compatible(kfdt, 0,
+ cur_fdt_compat)) {
+ best_match_offset = noffset;
+ best_match_pos = i;
+ break;
+ }
+ len -= cur_len;
+ cur_fdt_compat += cur_len;
+ }
+ }
+ if (!best_match_offset) {
+ debug("No match found.\n");
+ return -1;
+ }
+
+ return best_match_offset;
+}
+
/**
* fit_conf_get_node - get node offset for configuration of a given unit name
* @fit: pointer to the FIT format image header
diff --git a/common/lcd.c b/common/lcd.c
index 3017604734..4778655a26 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -696,6 +696,138 @@ static void splash_align_axis(int *axis, unsigned long panel_size,
}
#endif
+
+#ifdef CONFIG_LCD_BMP_RLE8
+
+#define BMP_RLE8_ESCAPE 0
+#define BMP_RLE8_EOL 0
+#define BMP_RLE8_EOBMP 1
+#define BMP_RLE8_DELTA 2
+
+static void draw_unencoded_bitmap(ushort **fbp, uchar *bmap, ushort *cmap,
+ int cnt)
+{
+ while (cnt > 0) {
+ *(*fbp)++ = cmap[*bmap++];
+ cnt--;
+ }
+}
+
+static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt)
+{
+ ushort *fb = *fbp;
+ int cnt_8copy = cnt >> 3;
+
+ cnt -= cnt_8copy << 3;
+ while (cnt_8copy > 0) {
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ cnt_8copy--;
+ }
+ while (cnt > 0) {
+ *fb++ = c;
+ cnt--;
+ }
+ (*fbp) = fb;
+}
+
+/*
+ * Do not call this function directly, must be called from
+ * lcd_display_bitmap.
+ */
+static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb,
+ int x_off, int y_off)
+{
+ uchar *bmap;
+ ulong width, height;
+ ulong cnt, runlen;
+ int x, y;
+ int decode = 1;
+
+ width = le32_to_cpu(bmp->header.width);
+ height = le32_to_cpu(bmp->header.height);
+ bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset);
+
+ x = 0;
+ y = height - 1;
+
+ while (decode) {
+ if (bmap[0] == BMP_RLE8_ESCAPE) {
+ switch (bmap[1]) {
+ case BMP_RLE8_EOL:
+ /* end of line */
+ bmap += 2;
+ x = 0;
+ y--;
+ /* 16bpix, 2-byte per pixel, width should *2 */
+ fb -= (width * 2 + lcd_line_length);
+ break;
+ case BMP_RLE8_EOBMP:
+ /* end of bitmap */
+ decode = 0;
+ break;
+ case BMP_RLE8_DELTA:
+ /* delta run */
+ x += bmap[2];
+ y -= bmap[3];
+ /* 16bpix, 2-byte per pixel, x should *2 */
+ fb = (uchar *) (lcd_base + (y + y_off - 1)
+ * lcd_line_length + (x + x_off) * 2);
+ bmap += 4;
+ break;
+ default:
+ /* unencoded run */
+ runlen = bmap[1];
+ bmap += 2;
+ if (y < height) {
+ if (x < width) {
+ if (x + runlen > width)
+ cnt = width - x;
+ else
+ cnt = runlen;
+ draw_unencoded_bitmap(
+ (ushort **)&fb,
+ bmap, cmap, cnt);
+ }
+ x += runlen;
+ }
+ bmap += runlen;
+ if (runlen & 1)
+ bmap++;
+ }
+ } else {
+ /* encoded run */
+ if (y < height) {
+ runlen = bmap[0];
+ if (x < width) {
+ /* aggregate the same code */
+ while (bmap[0] == 0xff &&
+ bmap[2] != BMP_RLE8_ESCAPE &&
+ bmap[1] == bmap[3]) {
+ runlen += bmap[2];
+ bmap += 2;
+ }
+ if (x + runlen > width)
+ cnt = width - x;
+ else
+ cnt = runlen;
+ draw_encoded_bitmap((ushort **)&fb,
+ cmap[bmap[1]], cnt);
+ }
+ x += runlen;
+ }
+ bmap += 2;
+ }
+ }
+}
+#endif
+
#if defined(CONFIG_MPC823) || defined(CONFIG_MCC200)
#define FB_PUT_BYTE(fb, from) *(fb)++ = (255 - *(from)++)
#else
@@ -729,7 +861,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
uchar *fb;
bmp_image_t *bmp=(bmp_image_t *)bmp_image;
uchar *bmap;
- ushort padded_line;
+ ushort padded_width;
unsigned long width, height, byte_width;
unsigned long pwidth = panel_info.vl_col;
unsigned colors, bpix, bmp_bpix;
@@ -816,7 +948,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
}
#endif
- padded_line = (width&0x3) ? ((width&~0x3)+4) : (width);
+ padded_width = (width&0x3) ? ((width&~0x3)+4) : (width);
#ifdef CONFIG_SPLASH_SCREEN_ALIGN
splash_align_axis(&x, pwidth, width);
@@ -835,6 +967,18 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
switch (bmp_bpix) {
case 1: /* pass through */
case 8:
+#ifdef CONFIG_LCD_BMP_RLE8
+ if (le32_to_cpu(bmp->header.compression) == BMP_BI_RLE8) {
+ if (bpix != 16) {
+ /* TODO implement render code for bpix != 16 */
+ printf("Error: only support 16 bpix");
+ return 1;
+ }
+ lcd_display_rle8_bitmap(bmp, cmap_base, fb, x, y);
+ break;
+ }
+#endif
+
if (bpix != 16)
byte_width = width;
else
@@ -850,7 +994,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
fb += sizeof(uint16_t) / sizeof(*fb);
}
}
- bmap += (width - padded_line);
+ bmap += (padded_width - width);
fb -= (byte_width + lcd_line_length);
}
break;
@@ -862,7 +1006,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)
for (j = 0; j < width; j++)
fb_put_word(&fb, &bmap);
- bmap += (padded_line - width) * 2;
+ bmap += (padded_width - width) * 2;
fb -= (width * 2 + lcd_line_length);
}
break;
@@ -940,5 +1084,31 @@ static void *lcd_logo(void)
#endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */
}
+void lcd_position_cursor(unsigned col, unsigned row)
+{
+ console_col = min(col, CONSOLE_COLS - 1);
+ console_row = min(row, CONSOLE_ROWS - 1);
+}
+
+int lcd_get_pixel_width(void)
+{
+ return panel_info.vl_col;
+}
+
+int lcd_get_pixel_height(void)
+{
+ return panel_info.vl_row;
+}
+
+int lcd_get_screen_rows(void)
+{
+ return CONSOLE_ROWS;
+}
+
+int lcd_get_screen_columns(void)
+{
+ return CONSOLE_COLS;
+}
+
/************************************************************************/
/************************************************************************/
diff --git a/common/main.c b/common/main.c
index 5fdfff2e28..44fa20dd6a 100644
--- a/common/main.c
+++ b/common/main.c
@@ -30,6 +30,7 @@
#include <common.h>
#include <watchdog.h>
#include <command.h>
+#include <fdtdec.h>
#include <malloc.h>
#include <version.h>
#ifdef CONFIG_MODEM_SUPPORT
@@ -40,13 +41,19 @@
#include <hush.h>
#endif
+#ifdef CONFIG_OF_CONTROL
+#include <fdtdec.h>
+#endif
+
+#ifdef CONFIG_OF_LIBFDT
+#include <fdt_support.h>
+#endif /* CONFIG_OF_LIBFDT */
+
#include <post.h>
#include <linux/ctype.h>
#include <menu.h>
-#if defined(CONFIG_SILENT_CONSOLE) || defined(CONFIG_POST) || defined(CONFIG_CMDLINE_EDITING)
DECLARE_GLOBAL_DATA_PTR;
-#endif
/*
* Board-specific Platform code can reimplement show_boot_progress () if needed
@@ -274,6 +281,73 @@ int abortboot(int bootdelay)
# endif /* CONFIG_AUTOBOOT_KEYED */
#endif /* CONFIG_BOOTDELAY >= 0 */
+/*
+ * Runs the given boot command securely. Specifically:
+ * - Doesn't run the command with the shell (run_command or parse_string_outer),
+ * since that's a lot of code surface that an attacker might exploit.
+ * Because of this, we don't do any argument parsing--the secure boot command
+ * has to be a full-fledged u-boot command.
+ * - Doesn't check for keypresses before booting, since that could be a
+ * security hole; also disables Ctrl-C.
+ * - Doesn't allow the command to return.
+ *
+ * Upon any failures, this function will drop into an infinite loop after
+ * printing the error message to console.
+ */
+
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) && \
+ defined(CONFIG_OF_CONTROL)
+static void secure_boot_cmd(char *cmd)
+{
+ cmd_tbl_t *cmdtp;
+ int rc;
+
+ if (!cmd) {
+ printf("## Error: Secure boot command not specified\n");
+ goto err;
+ }
+
+ /* Disable Ctrl-C just in case some command is used that checks it. */
+ disable_ctrlc(1);
+
+ /* Find the command directly. */
+ cmdtp = find_cmd(cmd);
+ if (!cmdtp) {
+ printf("## Error: \"%s\" not defined\n", cmd);
+ goto err;
+ }
+
+ /* Run the command, forcing no flags and faking argc and argv. */
+ rc = (cmdtp->cmd)(cmdtp, 0, 1, &cmd);
+
+ /* Shouldn't ever return from boot command. */
+ printf("## Error: \"%s\" returned (code %d)\n", cmd, rc);
+
+err:
+ /*
+ * Not a whole lot to do here. Rebooting won't help much, since we'll
+ * just end up right back here. Just loop.
+ */
+ hang();
+}
+
+static void process_fdt_options(const void *blob)
+{
+ ulong addr;
+
+ /* Add an env variable to point to a kernel payload, if available */
+ addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
+ if (addr)
+ setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
+
+ /* Add an env variable to point to a root disk, if available */
+ addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
+ if (addr)
+ setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
+}
+#endif /* CONFIG_OF_CONTROL */
+
+
/****************************************************************************/
void main_loop (void)
@@ -284,7 +358,10 @@ void main_loop (void)
int rc = 1;
int flag;
#endif
-
+#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) && \
+ defined(CONFIG_OF_CONTROL)
+ char *env;
+#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
char *s;
int bootdelay;
@@ -380,6 +457,23 @@ void main_loop (void)
else
#endif /* CONFIG_BOOTCOUNT_LIMIT */
s = getenv ("bootcmd");
+#ifdef CONFIG_OF_CONTROL
+ /* Allow the fdt to override the boot command */
+ env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd");
+ if (env)
+ s = env;
+
+ process_fdt_options(gd->fdt_blob);
+
+ /*
+ * If the bootsecure option was chosen, use secure_boot_cmd().
+ * Always use 'env' in this case, since bootsecure requres that the
+ * bootcmd was specified in the FDT too.
+ */
+ if (fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0))
+ secure_boot_cmd(env);
+
+#endif /* CONFIG_OF_CONTROL */
debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
@@ -404,6 +498,10 @@ void main_loop (void)
#endif /* CONFIG_MENUKEY */
#endif /* CONFIG_BOOTDELAY */
+#if defined CONFIG_OF_CONTROL
+ set_working_fdt_addr((void *)gd->fdt_blob);
+#endif /* CONFIG_OF_CONTROL */
+
/*
* Main Loop for Monitor Command Processing
*/
diff --git a/common/spl/spl.c b/common/spl/spl.c
index f068abd8f8..ff9ba7b0a5 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -74,6 +74,16 @@ __weak int spl_start_uboot(void)
}
#endif
+/*
+ * Weak default function for board specific cleanup/preparation before
+ * Linux boot. Some boards/platforms might not need it, so just provide
+ * an empty stub here.
+ */
+__weak void spl_board_prepare_for_linux(void)
+{
+ /* Nothing to do! */
+}
+
void spl_parse_image_header(const struct image_header *header)
{
u32 header_size = sizeof(struct image_header);
@@ -155,7 +165,13 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
CONFIG_SYS_SPL_MALLOC_SIZE);
#endif
+#ifndef CONFIG_PPC
+ /*
+ * timer_init() does not exist on PPC systems. The timer is initialized
+ * and enabled (decrementer) in interrupt_init() here.
+ */
timer_init();
+#endif
#ifdef CONFIG_SPL_BOARD_INIT
spl_board_init();
diff --git a/common/stdio.c b/common/stdio.c
index 605ff3fde3..9f48e5f503 100644
--- a/common/stdio.c
+++ b/common/stdio.c
@@ -237,6 +237,8 @@ int stdio_init (void)
#ifdef CONFIG_JTAG_CONSOLE
drv_jtag_console_init ();
#endif
-
+#ifdef CONFIG_CBMEM_CONSOLE
+ cbmemc_init();
+#endif
return (0);
}
diff --git a/common/usb.c b/common/usb.c
index 50b81752eb..ac9b4ca8d5 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -492,9 +492,9 @@ int usb_get_configuration_no(struct usb_device *dev,
{
int result;
unsigned int tmp;
- struct usb_configuration_descriptor *config;
+ struct usb_config_descriptor *config;
- config = (struct usb_configuration_descriptor *)&buffer[0];
+ config = (struct usb_config_descriptor *)&buffer[0];
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
if (result < 9) {
if (result < 0)
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index 19f01db1ca..4efbcfe90d 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -94,6 +94,15 @@ static const unsigned char usb_kbd_num_keypad[] = {
};
/*
+ * map arrow keys to ^F/^B ^N/^P, can't really use the proper
+ * ANSI sequence for arrow keys because the queuing code breaks
+ * when a single keypress expands to 3 queue elements
+ */
+static const unsigned char usb_kbd_arrow[] = {
+ 0x6, 0x2, 0xe, 0x10
+};
+
+/*
* NOTE: It's important for the NUM, CAPS, SCROLL-lock bits to be in this
* order. See usb_kbd_setled() function!
*/
@@ -112,7 +121,7 @@ struct usb_kbd_pdata {
uint32_t usb_out_pointer;
uint8_t usb_kbd_buffer[USB_KBD_BUFFER_LEN];
- uint8_t new[8];
+ uint8_t *new;
uint8_t old[8];
uint8_t flags;
@@ -224,6 +233,10 @@ static int usb_kbd_translate(struct usb_kbd_pdata *data, unsigned char scancode,
keycode = usb_kbd_numkey[scancode - 0x1e];
}
+ /* Arrow keys */
+ if ((scancode >= 0x4f) && (scancode <= 0x52))
+ keycode = usb_kbd_arrow[scancode - 0x4f];
+
/* Numeric keypad */
if ((scancode >= 0x54) && (scancode <= 0x67))
keycode = usb_kbd_num_keypad[scancode - 0x54];
@@ -435,6 +448,9 @@ static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
/* Clear private data */
memset(data, 0, sizeof(struct usb_kbd_pdata));
+ /* allocate input buffer aligned and sized to USB DMA alignment */
+ data->new = memalign(USB_DMA_MINALIGN, roundup(8, USB_DMA_MINALIGN));
+
/* Insert private data into USB device structure */
dev->privptr = data;
diff --git a/disk/part.c b/disk/part.c
index 4646f682d2..7bdc90eff7 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -199,7 +199,7 @@ void dev_print (block_dev_desc_t *dev_desc)
break;
}
puts ("\n");
- if ((dev_desc->lba * dev_desc->blksz)>0L) {
+ if (dev_desc->lba > 0L && dev_desc->blksz > 0L) {
ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
lbaint_t lba;
diff --git a/doc/DocBook/Makefile b/doc/DocBook/Makefile
index da88b32419..521e8bc0e9 100644
--- a/doc/DocBook/Makefile
+++ b/doc/DocBook/Makefile
@@ -8,7 +8,7 @@
include $(TOPDIR)/config.mk
-DOCBOOKS := linker_lists.xml stdio.xml
+DOCBOOKS := fs.xml linker_lists.xml stdio.xml
###
# The build process is as follows (targets):
diff --git a/doc/README.mpc85xx b/doc/README.mpc85xx
index 5a4b591a89..f9b023f284 100644
--- a/doc/README.mpc85xx
+++ b/doc/README.mpc85xx
@@ -26,7 +26,7 @@ Major Config Switches during various boot Modes
----------------------------------------------
NOR boot
- !defined(CONFIG_SYS_RAMBOOT)
+ !defined(CONFIG_SYS_RAMBOOT) && !defined(CONFIG_SPL)
NOR boot Secure
!defined(CONFIG_SYS_RAMBOOT) && defined(CONFIG_SECURE_BOOT)
RAMBOOT(SD, SPI & NAND boot)
diff --git a/doc/README.nand b/doc/README.nand
index c130189587..a1a511c533 100644
--- a/doc/README.nand
+++ b/doc/README.nand
@@ -108,6 +108,9 @@ Configuration Options:
CONFIG_CMD_NAND
Enables NAND support and commmands.
+ CONFIG_CMD_NAND_TORTURE
+ Enables the torture command (see description of this command below).
+
CONFIG_MTD_NAND_ECC_JFFS2
Define this if you want the Error Correction Code information in
the out-of-band data to be formatted to match the JFFS2 file system.
@@ -213,6 +216,24 @@ Miscellaneous and testing commands:
DANGEROUS!!! Factory set bad blocks will be lost. Use only
to remove artificial bad blocks created with the "markbad" command.
+ "torture offset"
+ Torture block to determine if it is still reliable.
+ Enabled by the CONFIG_CMD_NAND_TORTURE configuration option.
+ This command returns 0 if the block is still reliable, else 1.
+ If the block is detected as unreliable, it is up to the user to decide to
+ mark this block as bad.
+ The analyzed block is put through 3 erase / write cycles (or less if the block
+ is detected as unreliable earlier).
+ This command can be used in scripts, e.g. together with the markbad command to
+ automate retries and handling of possibly newly detected bad blocks if the
+ nand write command fails.
+ It can also be used manually by users having seen some NAND errors in logs to
+ search the root cause of these errors.
+ The underlying nand_torture() function is also useful for code willing to
+ automate actions following a nand->write() error. This would e.g. be required
+ in order to program or update safely firmware to NAND, especially for the UBI
+ part of such firmware.
+
NAND locking command (for chips with active LOCKPRE pin)
diff --git a/doc/kwboot.1 b/doc/kwboot.1
index ed0839836e..25fe69aa5c 100644
--- a/doc/kwboot.1
+++ b/doc/kwboot.1
@@ -79,6 +79,6 @@ Adjust the baud rate on \fITTY\fP. Default rate is 115200.
Daniel Stodden <daniel.stodden@gmail.com>
.br
-Luka Perkov <uboot@lukaperkov.net>
+Luka Perkov <luka@openwrt.org>
.br
David Purdy <david.c.purdy@gmail.com>
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index d50ac3bfef..2d97b4f1e4 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libgpio.o
COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o
+COBJS-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o
COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
new file mode 100644
index 0000000000..6fed01f71a
--- /dev/null
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -0,0 +1,290 @@
+/*
+ * 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
+ */
+
+/*
+ * This is a GPIO driver for Intel ICH6 and later. The x86 GPIOs are accessed
+ * through the PCI bus. Each PCI device has 256 bytes of configuration space,
+ * consisting of a standard header and a device-specific set of registers. PCI
+ * bus 0, device 31, function 0 gives us access to the chipset GPIOs (among
+ * other things). Within the PCI configuration space, the GPIOBASE register
+ * tells us where in the device's I/O region we can find more registers to
+ * actually access the GPIOs.
+ *
+ * PCI bus/device/function 0:1f:0 => PCI config registers
+ * PCI config register "GPIOBASE"
+ * PCI I/O space + [GPIOBASE] => start of GPIO registers
+ * GPIO registers => gpio pin function, direction, value
+ *
+ *
+ * Danger Will Robinson! Bank 0 (GPIOs 0-31) seems to be fairly stable. Most
+ * ICH versions have more, but the decoding the matrix that describes them is
+ * absurdly complex and constantly changing. We'll provide Bank 1 and Bank 2,
+ * but they will ONLY work for certain unspecified chipsets because the offset
+ * from GPIOBASE changes randomly. Even then, many GPIOs are unimplemented or
+ * reserved or subject to arcane restrictions.
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+/* Where in config space is the register that points to the GPIO registers? */
+#define PCI_CFG_GPIOBASE 0x48
+
+#define NUM_BANKS 3
+
+/* Within the I/O space, where are the registers to control the GPIOs? */
+static struct {
+ u8 use_sel;
+ u8 io_sel;
+ u8 lvl;
+} gpio_bank[NUM_BANKS] = {
+ { 0x00, 0x04, 0x0c }, /* Bank 0 */
+ { 0x30, 0x34, 0x38 }, /* Bank 1 */
+ { 0x40, 0x44, 0x48 } /* Bank 2 */
+};
+
+static pci_dev_t dev; /* handle for 0:1f:0 */
+static u32 gpiobase; /* offset into I/O space */
+static int found_it_once; /* valid GPIO device? */
+static u32 lock[NUM_BANKS]; /* "lock" for access to pins */
+
+static int bad_arg(int num, int *bank, int *bitnum)
+{
+ int i = num / 32;
+ int j = num % 32;
+
+ if (num < 0 || i > NUM_BANKS) {
+ debug("%s: bogus gpio num: %d\n", __func__, num);
+ return -1;
+ }
+ *bank = i;
+ *bitnum = j;
+ return 0;
+}
+
+static int mark_gpio(int bank, int bitnum)
+{
+ if (lock[bank] & (1UL << bitnum)) {
+ debug("%s: %d.%d already marked\n", __func__, bank, bitnum);
+ return -1;
+ }
+ lock[bank] |= (1 << bitnum);
+ return 0;
+}
+
+static void clear_gpio(int bank, int bitnum)
+{
+ lock[bank] &= ~(1 << bitnum);
+}
+
+static int notmine(int num, int *bank, int *bitnum)
+{
+ if (bad_arg(num, bank, bitnum))
+ return -1;
+ return !(lock[*bank] & (1UL << *bitnum));
+}
+
+static int gpio_init(void)
+{
+ u8 tmpbyte;
+ u16 tmpword;
+ u32 tmplong;
+
+ /* Have we already done this? */
+ if (found_it_once)
+ return 0;
+
+ /* Where should it be? */
+ dev = PCI_BDF(0, 0x1f, 0);
+
+ /* Is the device present? */
+ pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
+ if (tmpword != PCI_VENDOR_ID_INTEL) {
+ debug("%s: wrong VendorID\n", __func__);
+ return -1;
+ }
+
+ pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword);
+ debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
+ /*
+ * We'd like to validate the Device ID too, but pretty much any
+ * value is either a) correct with slight differences, or b)
+ * correct but undocumented. We'll have to check a bunch of other
+ * things instead...
+ */
+
+ /* I/O should already be enabled (it's a RO bit). */
+ pci_read_config_word(dev, PCI_COMMAND, &tmpword);
+ if (!(tmpword & PCI_COMMAND_IO)) {
+ debug("%s: device IO not enabled\n", __func__);
+ return -1;
+ }
+
+ /* Header Type must be normal (bits 6-0 only; see spec.) */
+ pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
+ if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
+ debug("%s: invalid Header type\n", __func__);
+ return -1;
+ }
+
+ /* Base Class must be a bridge device */
+ pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
+ if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
+ debug("%s: invalid class\n", __func__);
+ return -1;
+ }
+ /* Sub Class must be ISA */
+ pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
+ if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
+ debug("%s: invalid subclass\n", __func__);
+ return -1;
+ }
+
+ /* Programming Interface must be 0x00 (no others exist) */
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
+ if (tmpbyte != 0x00) {
+ debug("%s: invalid interface type\n", __func__);
+ return -1;
+ }
+
+ /*
+ * GPIOBASE moved to its current offset with ICH6, but prior to
+ * that it was unused (or undocumented). Check that it looks
+ * okay: not all ones or zeros, and mapped to I/O space (bit 0).
+ */
+ pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
+ if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
+ !(tmplong & 0x00000001)) {
+ debug("%s: unexpected GPIOBASE value\n", __func__);
+ return -1;
+ }
+
+ /*
+ * Okay, I guess we're looking at the right device. The actual
+ * GPIO registers are in the PCI device's I/O space, starting
+ * at the offset that we just read. Bit 0 indicates that it's
+ * an I/O address, not a memory address, so mask that off.
+ */
+ gpiobase = tmplong & 0xfffffffe;
+
+ /* Finally. These are the droids we're looking for. */
+ found_it_once = 1;
+ return 0;
+}
+
+int gpio_request(unsigned num, const char *label /* UNUSED */)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ /* Is the hardware ready? */
+ if (gpio_init())
+ return -1;
+
+ if (bad_arg(num, &i, &j))
+ return -1;
+
+ /*
+ * Make sure that the GPIO pin we want isn't already in use for some
+ * built-in hardware function. We have to check this for every
+ * requested pin.
+ */
+ tmplong = inl(gpiobase + gpio_bank[i].use_sel);
+ if (!(tmplong & (1UL << j))) {
+ debug("%s: gpio %d is reserved for internal use\n", __func__,
+ num);
+ return -1;
+ }
+
+ return mark_gpio(i, j);
+}
+
+int gpio_free(unsigned num)
+{
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ clear_gpio(i, j);
+ return 0;
+}
+
+int gpio_direction_input(unsigned num)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].io_sel);
+ tmplong |= (1UL << j);
+ outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ return 0;
+}
+
+int gpio_direction_output(unsigned num, int value)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].io_sel);
+ tmplong &= ~(1UL << j);
+ outl(gpiobase + gpio_bank[i].io_sel, tmplong);
+ return 0;
+}
+
+int gpio_get_value(unsigned num)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+ int r;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].lvl);
+ r = (tmplong & (1UL << j)) ? 1 : 0;
+ return r;
+}
+
+int gpio_set_value(unsigned num, int value)
+{
+ u32 tmplong;
+ int i = 0, j = 0;
+
+ if (notmine(num, &i, &j))
+ return -1;
+
+ tmplong = inl(gpiobase + gpio_bank[i].lvl);
+ if (value)
+ tmplong |= (1UL << j);
+ else
+ tmplong &= ~(1UL << j);
+ outl(gpiobase + gpio_bank[i].lvl, tmplong);
+ return 0;
+}
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 9fac190a6a..8cdc3b649c 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -27,21 +27,13 @@ LIB := $(obj)libmisc.o
COBJS-$(CONFIG_ALI152X) += ali512x.o
COBJS-$(CONFIG_DS4510) += ds4510.o
-COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
+COBJS-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
COBJS-$(CONFIG_GPIO_LED) += gpio_led.o
COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
COBJS-$(CONFIG_NS87308) += ns87308.o
COBJS-$(CONFIG_PDSP188x) += pdsp188x.o
COBJS-$(CONFIG_STATUS_LED) += status_led.o
COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
-COBJS-$(CONFIG_PMIC) += pmic_core.o
-COBJS-$(CONFIG_DIALOG_PMIC) += pmic_dialog.o
-COBJS-$(CONFIG_PMIC_FSL) += pmic_fsl.o
-COBJS-$(CONFIG_PMIC_I2C) += pmic_i2c.o
-COBJS-$(CONFIG_PMIC_SPI) += pmic_spi.o
-COBJS-$(CONFIG_PMIC_MAX77686) += pmic_max77686.o
-COBJS-$(CONFIG_PMIC_MAX8998) += pmic_max8998.o
-COBJS-$(CONFIG_PMIC_MAX8997) += pmic_max8997.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/misc/cbmem_console.c b/drivers/misc/cbmem_console.c
new file mode 100644
index 0000000000..80a84fdf8f
--- /dev/null
+++ b/drivers/misc/cbmem_console.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include <common.h>
+
+#ifndef CONFIG_SYS_COREBOOT
+#error This driver requires coreboot
+#endif
+
+#include <asm/arch/sysinfo.h>
+
+struct cbmem_console {
+ u32 buffer_size;
+ u32 buffer_cursor;
+ u8 buffer_body[0];
+} __attribute__ ((__packed__));
+
+static struct cbmem_console *cbmem_console_p;
+
+void cbmemc_putc(char data)
+{
+ int cursor;
+
+ cursor = cbmem_console_p->buffer_cursor++;
+ if (cursor < cbmem_console_p->buffer_size)
+ cbmem_console_p->buffer_body[cursor] = data;
+}
+
+void cbmemc_puts(const char *str)
+{
+ char c;
+
+ while ((c = *str++) != 0)
+ cbmemc_putc(c);
+}
+
+int cbmemc_init(void)
+{
+ int rc;
+ struct stdio_dev cons_dev;
+ cbmem_console_p = lib_sysinfo.cbmem_cons;
+
+ memset(&cons_dev, 0, sizeof(cons_dev));
+
+ strcpy(cons_dev.name, "cbmem");
+ cons_dev.flags = DEV_FLAGS_OUTPUT; /* Output only */
+ cons_dev.putc = cbmemc_putc;
+ cons_dev.puts = cbmemc_puts;
+
+ rc = stdio_register(&cons_dev);
+
+ return (rc == 0) ? 1 : rc;
+}
diff --git a/drivers/misc/pmic_core.c b/drivers/misc/pmic_core.c
deleted file mode 100644
index 5d62a56d34..0000000000
--- a/drivers/misc/pmic_core.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics
- * Lukasz Majewski <l.majewski@samsung.com>
- *
- * (C) Copyright 2010
- * Stefano Babic, DENX Software Engineering, sbabic@denx.de
- *
- * (C) Copyright 2008-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 <linux/types.h>
-#include <pmic.h>
-
-static struct pmic pmic;
-
-int check_reg(u32 reg)
-{
- if (reg >= pmic.number_of_regs) {
- printf("<reg num> = %d is invalid. Should be less than %d\n",
- reg, pmic.number_of_regs);
- return -1;
- }
- return 0;
-}
-
-int pmic_set_output(struct pmic *p, u32 reg, int out, int on)
-{
- u32 val;
-
- if (pmic_reg_read(p, reg, &val))
- return -1;
-
- if (on)
- val |= out;
- else
- val &= ~out;
-
- if (pmic_reg_write(p, reg, val))
- return -1;
-
- return 0;
-}
-
-static void pmic_show_info(struct pmic *p)
-{
- printf("PMIC: %s\n", p->name);
-}
-
-static void pmic_dump(struct pmic *p)
-{
- int i, ret;
- u32 val;
-
- pmic_show_info(p);
- for (i = 0; i < p->number_of_regs; i++) {
- ret = pmic_reg_read(p, i, &val);
- if (ret)
- puts("PMIC: Registers dump failed\n");
-
- if (!(i % 8))
- printf("\n0x%02x: ", i);
-
- printf("%08x ", val);
- }
- puts("\n");
-}
-
-struct pmic *get_pmic(void)
-{
- return &pmic;
-}
-
-int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
- u32 ret, reg, val;
- char *cmd;
-
- struct pmic *p = &pmic;
-
- /* at least two arguments please */
- if (argc < 2)
- return cmd_usage(cmdtp);
-
- cmd = argv[1];
- if (strcmp(cmd, "dump") == 0) {
- pmic_dump(p);
- return 0;
- }
-
- if (strcmp(cmd, "read") == 0) {
- if (argc < 3)
- return cmd_usage(cmdtp);
-
- reg = simple_strtoul(argv[2], NULL, 16);
-
- ret = pmic_reg_read(p, reg, &val);
-
- if (ret)
- puts("PMIC: Register read failed\n");
-
- printf("\n0x%02x: 0x%08x\n", reg, val);
-
- return 0;
- }
-
- if (strcmp(cmd, "write") == 0) {
- if (argc < 4)
- return cmd_usage(cmdtp);
-
- reg = simple_strtoul(argv[2], NULL, 16);
- val = simple_strtoul(argv[3], NULL, 16);
-
- pmic_reg_write(p, reg, val);
-
- return 0;
- }
-
- /* No subcommand found */
- return 1;
-}
-
-U_BOOT_CMD(
- pmic, CONFIG_SYS_MAXARGS, 1, do_pmic,
- "PMIC",
- "dump - dump PMIC registers\n"
- "pmic read <reg> - read register\n"
- "pmic write <reg> <value> - write register"
-);
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index a1dd7302bf..65791aa218 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -47,6 +47,7 @@ COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
COBJS-$(CONFIG_DWMMC) += dw_mmc.o
+COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
new file mode 100644
index 0000000000..72a31b73fd
--- /dev/null
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung@samsung.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 <malloc.h>
+#include <dwmmc.h>
+#include <asm/arch/dwmmc.h>
+#include <asm/arch/clk.h>
+
+static char *EXYNOS_NAME = "EXYNOS DWMMC";
+
+static void exynos_dwmci_clksel(struct dwmci_host *host)
+{
+ u32 val;
+ val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
+ DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(0);
+
+ dwmci_writel(host, DWMCI_CLKSEL, val);
+}
+
+int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+{
+ struct dwmci_host *host = NULL;
+ host = malloc(sizeof(struct dwmci_host));
+ if (!host) {
+ printf("dwmci_host malloc fail!\n");
+ return 1;
+ }
+
+ host->name = EXYNOS_NAME;
+ host->ioaddr = (void *)regbase;
+ host->buswidth = bus_width;
+ host->clksel = exynos_dwmci_clksel;
+ host->dev_index = index;
+
+ add_dwmci(host, 52000000, 400000);
+
+ return 0;
+}
+
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 5ffd8c59e6..72e8ce6da4 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -868,7 +868,7 @@ static void mmc_set_bus_width(struct mmc *mmc, uint width)
static int mmc_startup(struct mmc *mmc)
{
- int err, width;
+ int err;
uint mult, freq;
u64 cmult, csize, capacity;
struct mmc_cmd cmd;
@@ -1087,21 +1087,44 @@ static int mmc_startup(struct mmc *mmc)
else
mmc->tran_speed = 25000000;
} else {
- width = ((mmc->host_caps & MMC_MODE_MASK_WIDTH_BITS) >>
- MMC_MODE_WIDTH_BITS_SHIFT);
- for (; width >= 0; width--) {
- /* Set the card to use 4 bit*/
+ int idx;
+
+ /* An array of possible bus widths in order of preference */
+ static unsigned ext_csd_bits[] = {
+ EXT_CSD_BUS_WIDTH_8,
+ EXT_CSD_BUS_WIDTH_4,
+ EXT_CSD_BUS_WIDTH_1,
+ };
+
+ /* An array to map CSD bus widths to host cap bits */
+ static unsigned ext_to_hostcaps[] = {
+ [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT,
+ [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT,
+ };
+
+ /* An array to map chosen bus width to an integer */
+ static unsigned widths[] = {
+ 8, 4, 1,
+ };
+
+ for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) {
+ unsigned int extw = ext_csd_bits[idx];
+
+ /*
+ * Check to make sure the controller supports
+ * this bus width, if it's more than 1
+ */
+ if (extw != EXT_CSD_BUS_WIDTH_1 &&
+ !(mmc->host_caps & ext_to_hostcaps[extw]))
+ continue;
+
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH, width);
+ EXT_CSD_BUS_WIDTH, extw);
if (err)
continue;
- if (!width) {
- mmc_set_bus_width(mmc, 1);
- break;
- } else
- mmc_set_bus_width(mmc, 4 * width);
+ mmc_set_bus_width(mmc, widths[idx]);
err = mmc_send_ext_csd(mmc, test_csd);
if (!err && ext_csd[EXT_CSD_PARTITIONING_SUPPORT] \
@@ -1115,7 +1138,7 @@ static int mmc_startup(struct mmc *mmc)
&& memcmp(&ext_csd[EXT_CSD_SEC_CNT], \
&test_csd[EXT_CSD_SEC_CNT], 4) == 0) {
- mmc->card_caps |= width;
+ mmc->card_caps |= ext_to_hostcaps[extw];
break;
}
}
@@ -1135,13 +1158,15 @@ static int mmc_startup(struct mmc *mmc)
mmc->block_dev.type = 0;
mmc->block_dev.blksz = mmc->read_bl_len;
mmc->block_dev.lba = lldiv(mmc->capacity, mmc->read_bl_len);
- sprintf(mmc->block_dev.vendor, "Man %06x Snr %08x", mmc->cid[0] >> 8,
- (mmc->cid[2] << 8) | (mmc->cid[3] >> 24));
- sprintf(mmc->block_dev.product, "%c%c%c%c%c", mmc->cid[0] & 0xff,
- (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
- (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
- sprintf(mmc->block_dev.revision, "%d.%d", mmc->cid[2] >> 28,
- (mmc->cid[2] >> 24) & 0xf);
+ sprintf(mmc->block_dev.vendor, "Man %06x Snr %04x%04x",
+ mmc->cid[0] >> 24, (mmc->cid[2] & 0xffff),
+ (mmc->cid[3] >> 16) & 0xffff);
+ sprintf(mmc->block_dev.product, "%c%c%c%c%c%c", mmc->cid[0] & 0xff,
+ (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
+ (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff,
+ (mmc->cid[2] >> 24) & 0xff);
+ sprintf(mmc->block_dev.revision, "%d.%d", (mmc->cid[2] >> 20) & 0xf,
+ (mmc->cid[2] >> 16) & 0xf);
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
init_part(&mmc->block_dev);
#endif
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 109acbf623..024df592f2 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -96,11 +96,11 @@ static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data)
static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
{
uint32_t data_count = data->blocksize * data->blocks;
- uint32_t cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN);
int dmach;
struct mxs_dma_desc *desc = priv->desc;
- void *addr, *backup;
- uint8_t flags;
+ void *addr;
+ unsigned int flags;
+ struct bounce_buffer bbstate;
memset(desc, 0, sizeof(struct mxs_dma_desc));
desc->address = (dma_addr_t)desc;
@@ -115,19 +115,9 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
flags = GEN_BB_READ;
}
- bounce_buffer_start(&addr, data_count, &backup, flags);
+ bounce_buffer_start(&bbstate, addr, data_count, flags);
- priv->desc->cmd.address = (dma_addr_t)addr;
-
- if (data->flags & MMC_DATA_WRITE) {
- /* Flush data to DRAM so DMA can pick them up */
- flush_dcache_range((uint32_t)addr,
- (uint32_t)(addr) + cache_data_count);
- }
-
- /* Invalidate the area, so no writeback into the RAM races with DMA */
- invalidate_dcache_range((uint32_t)priv->desc->cmd.address,
- (uint32_t)(priv->desc->cmd.address + cache_data_count));
+ priv->desc->cmd.address = (dma_addr_t)bbstate.bounce_buffer;
priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM |
(data_count << MXS_DMA_DESC_BYTES_OFFSET);
@@ -135,17 +125,11 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id;
mxs_dma_desc_append(dmach, priv->desc);
if (mxs_dma_go(dmach)) {
- bounce_buffer_stop(&addr, data_count, &backup, flags);
+ bounce_buffer_stop(&bbstate);
return COMM_ERR;
}
- /* The data arrived into DRAM, invalidate cache over them */
- if (data->flags & MMC_DATA_READ) {
- invalidate_dcache_range((uint32_t)addr,
- (uint32_t)(addr) + cache_data_count);
- }
-
- bounce_buffer_stop(&addr, data_count, &backup, flags);
+ bounce_buffer_stop(&bbstate);
return 0;
}
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 7845f873ac..b9cbe34f1f 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -340,6 +340,9 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
return;
}
+ if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)
+ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 1fd5592f2d..d749ab095e 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <bouncebuf.h>
#include <common.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -66,14 +67,17 @@ static void tegra_get_setup(struct mmc_host *host, int dev_index)
host->reg = (struct tegra_mmc *)host->base;
}
-static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data)
+static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data,
+ struct bounce_buffer *bbstate)
{
unsigned char ctrl;
- debug("data->dest: %08X, data->blocks: %u, data->blocksize: %u\n",
- (u32)data->dest, data->blocks, data->blocksize);
- writel((u32)data->dest, &host->reg->sysad);
+ debug("buf: %p (%p), data->blocks: %u, data->blocksize: %u\n",
+ bbstate->bounce_buffer, bbstate->user_buffer, data->blocks,
+ data->blocksize);
+
+ writel((u32)bbstate->bounce_buffer, &host->reg->sysad);
/*
* DMASEL[4:3]
* 00 = Selects SDMA
@@ -114,14 +118,6 @@ static void mmc_set_transfer_mode(struct mmc_host *host, struct mmc_data *data)
if (data->flags & MMC_DATA_READ)
mode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ;
- if (data->flags & MMC_DATA_WRITE) {
- if ((uintptr_t)data->src & (ARCH_DMA_MINALIGN - 1))
- printf("Warning: unaligned write to %p may fail\n",
- data->src);
- flush_dcache_range((ulong)data->src, (ulong)data->src +
- data->blocks * data->blocksize);
- }
-
writew(mode, &host->reg->trnmod);
}
@@ -156,8 +152,8 @@ static int mmc_wait_inhibit(struct mmc_host *host,
return 0;
}
-static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
+static int mmc_send_cmd_bounced(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data, struct bounce_buffer *bbstate)
{
struct mmc_host *host = (struct mmc_host *)mmc->priv;
int flags, i;
@@ -172,7 +168,7 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
return result;
if (data)
- mmc_prepare_data(host, data);
+ mmc_prepare_data(host, data, bbstate);
debug("cmd->arg: %08x\n", cmd->cmdarg);
writel(cmd->cmdarg, &host->reg->argument);
@@ -322,20 +318,42 @@ static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
}
}
writel(mask, &host->reg->norintsts);
- if (data->flags & MMC_DATA_READ) {
- if ((uintptr_t)data->dest & (ARCH_DMA_MINALIGN - 1))
- printf("Warning: unaligned read from %p "
- "may fail\n", data->dest);
- invalidate_dcache_range((ulong)data->dest,
- (ulong)data->dest +
- data->blocks * data->blocksize);
- }
}
udelay(1000);
return 0;
}
+static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ void *buf;
+ unsigned int bbflags;
+ size_t len;
+ struct bounce_buffer bbstate;
+ int ret;
+
+ if (data) {
+ if (data->flags & MMC_DATA_READ) {
+ buf = data->dest;
+ bbflags = GEN_BB_WRITE;
+ } else {
+ buf = (void *)data->src;
+ bbflags = GEN_BB_READ;
+ }
+ len = data->blocks * data->blocksize;
+
+ bounce_buffer_start(&bbstate, buf, len, bbflags);
+ }
+
+ ret = mmc_send_cmd_bounced(mmc, cmd, data, &bbstate);
+
+ if (data)
+ bounce_buffer_stop(&bbstate);
+
+ return ret;
+}
+
static void mmc_change_clock(struct mmc_host *host, uint clock)
{
int div;
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index beb99cacb6..28e52bd08e 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -26,21 +26,33 @@ include $(TOPDIR)/config.mk
LIB := $(obj)libnand.o
ifdef CONFIG_CMD_NAND
+
ifdef CONFIG_SPL_BUILD
-ifdef CONFIG_SPL_NAND_SIMPLE
-COBJS-y += nand_spl_simple.o
-endif
-ifdef CONFIG_SPL_NAND_LOAD
-COBJS-y += nand_spl_load.o
+
+ifdef CONFIG_SPL_NAND_DRIVERS
+NORMAL_DRIVERS=y
endif
-else
+
+COBJS-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
+COBJS-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
+COBJS-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
+COBJS-$(CONFIG_SPL_NAND_BASE) += nand_base.o
+
+else # not spl
+
+NORMAL_DRIVERS=y
+
COBJS-y += nand.o
COBJS-y += nand_bbt.o
COBJS-y += nand_ids.o
COBJS-y += nand_util.o
-endif
COBJS-y += nand_ecc.o
COBJS-y += nand_base.o
+
+endif # not spl
+
+ifdef NORMAL_DRIVERS
+
COBJS-$(CONFIG_NAND_ECC_BCH) += nand_bch.o
COBJS-$(CONFIG_NAND_ATMEL) += atmel_nand.o
@@ -65,7 +77,13 @@ COBJS-$(CONFIG_NAND_SPEAR) += spr_nand.o
COBJS-$(CONFIG_TEGRA_NAND) += tegra_nand.o
COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
-endif
+
+else # minimal SPL drivers
+
+COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o
+
+endif # drivers
+endif # nand
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 9076ad4cdc..834a8a6498 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -748,7 +748,7 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr)
/* set up nand options */
nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
- NAND_USE_FLASH_BBT;
+ NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE;
nand->controller = &elbc_ctrl->controller;
nand->priv = priv;
diff --git a/drivers/mtd/nand/fsl_elbc_spl.c b/drivers/mtd/nand/fsl_elbc_spl.c
new file mode 100644
index 0000000000..50ff4fe93e
--- /dev/null
+++ b/drivers/mtd/nand/fsl_elbc_spl.c
@@ -0,0 +1,168 @@
+/*
+ * NAND boot for Freescale Enhanced Local Bus Controller, Flash Control Machine
+ *
+ * (C) Copyright 2006-2008
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
+ * Copyright (c) 2008 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood@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/io.h>
+#include <asm/fsl_lbc.h>
+#include <nand.h>
+
+#define WINDOW_SIZE 8192
+
+static void nand_wait(void)
+{
+ fsl_lbc_t *regs = LBC_BASE_ADDR;
+
+ for (;;) {
+ uint32_t status = in_be32(&regs->ltesr);
+
+ if (status == 1)
+ return;
+
+ if (status & 1) {
+ puts("read failed (ltesr)\n");
+ for (;;);
+ }
+ }
+}
+
+static int nand_load_image(uint32_t offs, unsigned int uboot_size, void *vdst)
+{
+ fsl_lbc_t *regs = LBC_BASE_ADDR;
+ uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
+ const int large = CONFIG_SYS_NAND_OR_PRELIM & OR_FCM_PGS;
+ const int block_shift = large ? 17 : 14;
+ const int block_size = 1 << block_shift;
+ const int page_size = large ? 2048 : 512;
+ const int bad_marker = large ? page_size + 0 : page_size + 5;
+ int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2;
+ int pos = 0;
+ char *dst = vdst;
+
+ if (offs & (block_size - 1)) {
+ puts("bad offset\n");
+ for (;;);
+ }
+
+ if (large) {
+ fmr |= FMR_ECCM;
+ out_be32(&regs->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
+ (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
+ out_be32(&regs->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+ (FIR_OP_RBW << FIR_OP4_SHIFT));
+ } else {
+ out_be32(&regs->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
+ out_be32(&regs->fir,
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_RBW << FIR_OP3_SHIFT));
+ }
+
+ out_be32(&regs->fbcr, 0);
+ clrsetbits_be32(&regs->bank[0].br, BR_DECC, BR_DECC_CHK_GEN);
+
+ while (pos < uboot_size) {
+ int i = 0;
+ out_be32(&regs->fbar, offs >> block_shift);
+
+ do {
+ int j;
+ unsigned int page_offs = (offs & (block_size - 1)) << 1;
+
+ out_be32(&regs->ltesr, ~0);
+ out_be32(&regs->lteatr, 0);
+ out_be32(&regs->fpar, page_offs);
+ out_be32(&regs->fmr, fmr);
+ out_be32(&regs->lsor, 0);
+ nand_wait();
+
+ page_offs %= WINDOW_SIZE;
+
+ /*
+ * If either of the first two pages are marked bad,
+ * continue to the next block.
+ */
+ if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) {
+ puts("skipping\n");
+ offs = (offs + block_size) & ~(block_size - 1);
+ pos &= ~(block_size - 1);
+ break;
+ }
+
+ for (j = 0; j < page_size; j++)
+ dst[pos + j] = buf[page_offs + j];
+
+ pos += page_size;
+ offs += page_size;
+ } while ((offs & (block_size - 1)) && (pos < uboot_size));
+ }
+
+ return 0;
+}
+
+/*
+ * The main entry for NAND booting. It's necessary that SDRAM is already
+ * configured and available since this code loads the main U-Boot image
+ * from NAND into SDRAM and starts it from there.
+ */
+void nand_boot(void)
+{
+ __attribute__((noreturn)) void (*uboot)(void);
+ /*
+ * Load U-Boot image from NAND into RAM
+ */
+ nand_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
+ CONFIG_SYS_NAND_U_BOOT_SIZE,
+ (void *)CONFIG_SYS_NAND_U_BOOT_DST);
+
+#ifdef CONFIG_NAND_ENV_DST
+ nand_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
+ (void *)CONFIG_NAND_ENV_DST);
+
+#ifdef CONFIG_ENV_OFFSET_REDUND
+ nand_load_image(CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
+ (void *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
+#endif
+#endif
+
+#ifdef CONFIG_SPL_FLUSH_IMAGE
+ /*
+ * Clean d-cache and invalidate i-cache, to
+ * make sure that no stale data is executed.
+ */
+ flush_cache(CONFIG_SYS_NAND_U_BOOT_DST, CONFIG_SYS_NAND_U_BOOT_SIZE);
+#endif
+
+ puts("transfering control\n");
+ /*
+ * Jump to U-Boot image
+ */
+ uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
+ (*uboot)();
+}
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index b3b7c705e1..0878bece67 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -30,6 +30,7 @@
#include <asm/errno.h>
#include <asm/fsl_ifc.h>
+#define FSL_IFC_V1_1_0 0x01010000
#define MAX_BANKS 4
#define ERR_BYTE 0xFF /* Value returned for read bytes
when read failed */
@@ -738,11 +739,66 @@ static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip)
{
}
+static void fsl_ifc_sram_init(void)
+{
+ struct fsl_ifc *ifc = ifc_ctrl->regs;
+ uint32_t cs = 0, csor = 0, csor_8k = 0, csor_ext = 0;
+ long long end_tick;
+
+ cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT;
+
+ /* Save CSOR and CSOR_ext */
+ csor = in_be32(&ifc_ctrl->regs->csor_cs[cs].csor);
+ csor_ext = in_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext);
+
+ /* chage PageSize 8K and SpareSize 1K*/
+ csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000;
+ out_be32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k);
+ out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400);
+
+ /* READID */
+ out_be32(&ifc->ifc_nand.nand_fir0,
+ (IFC_FIR_OP_CMD0 << IFC_NAND_FIR0_OP0_SHIFT) |
+ (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) |
+ (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT));
+ out_be32(&ifc->ifc_nand.nand_fcr0,
+ NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT);
+ out_be32(&ifc->ifc_nand.row3, 0x0);
+
+ out_be32(&ifc->ifc_nand.nand_fbcr, 0x0);
+
+ /* Program ROW0/COL0 */
+ out_be32(&ifc->ifc_nand.row0, 0x0);
+ out_be32(&ifc->ifc_nand.col0, 0x0);
+
+ /* set the chip select for NAND Transaction */
+ out_be32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand);
+
+ /* start read seq */
+ out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT);
+
+ /* wait for NAND Machine complete flag or timeout */
+ end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks();
+
+ while (end_tick > get_ticks()) {
+ ifc_ctrl->status = in_be32(&ifc->ifc_nand.nand_evter_stat);
+
+ if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC)
+ break;
+ }
+
+ out_be32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status);
+
+ /* Restore CSOR and CSOR_ext */
+ out_be32(&ifc_ctrl->regs->csor_cs[cs].csor, csor);
+ out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext);
+}
+
int board_nand_init(struct nand_chip *nand)
{
struct fsl_ifc_mtd *priv;
struct nand_ecclayout *layout;
- uint32_t cspr = 0, csor = 0;
+ uint32_t cspr = 0, csor = 0, ver = 0;
if (!ifc_ctrl) {
fsl_ifc_ctrl_init();
@@ -797,7 +853,7 @@ int board_nand_init(struct nand_chip *nand)
/* set up nand options */
nand->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
- NAND_USE_FLASH_BBT;
+ NAND_USE_FLASH_BBT | NAND_NO_SUBPAGE_WRITE;
if (cspr & CSPR_PORT_SIZE_16) {
nand->read_byte = fsl_ifc_read_byte16;
@@ -861,5 +917,9 @@ int board_nand_init(struct nand_chip *nand)
nand->ecc.mode = NAND_ECC_SOFT;
}
+ ver = in_be32(&ifc_ctrl->regs->ifc_rev);
+ if (ver == FSL_IFC_V1_1_0)
+ fsl_ifc_sram_init();
+
return 0;
}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index d3b71a50ad..a2d06be99f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1245,7 +1245,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
if (unlikely(ops->mode == MTD_OOB_RAW))
ret = chip->ecc.read_page_raw(mtd, chip,
bufpoi, page);
- else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
+ else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) &&
+ !oob)
ret = chip->ecc.read_subpage(mtd, chip,
col, bytes, bufpoi);
else
@@ -1256,7 +1257,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Transfer not aligned data */
if (!aligned) {
- if (!NAND_SUBPAGE_READ(chip) && !oob &&
+ if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
!(mtd->ecc_stats.failed - stats.failed))
chip->pagebuf = realpage;
memcpy(buf, chip->buffers->databuf + col, bytes);
@@ -3150,6 +3151,10 @@ int nand_scan_tail(struct mtd_info *mtd)
/* Invalidate the pagebuffer reference */
chip->pagebuf = -1;
+ /* Large page NAND with SOFT_ECC should support subpage reads */
+ if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9))
+ chip->options |= NAND_SUBPAGE_READ;
+
/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index c4752a7cbf..2ba0c5ef95 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -50,8 +50,8 @@
#include <nand.h>
#include <jffs2/jffs2.h>
-typedef struct erase_info erase_info_t;
-typedef struct mtd_info mtd_info_t;
+typedef struct erase_info erase_info_t;
+typedef struct mtd_info mtd_info_t;
/* support only for native endian JFFS2 */
#define cpu_to_je16(x) (x)
@@ -59,7 +59,7 @@ typedef struct mtd_info mtd_info_t;
/**
* nand_erase_opts: - erase NAND flash with support for various options
- * (jffs2 formating)
+ * (jffs2 formatting)
*
* @param meminfo NAND device to erase
* @param opts options, @see struct nand_erase_options
@@ -80,8 +80,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
struct mtd_oob_ops oob_opts;
struct nand_chip *chip = meminfo->priv;
- if ((opts->offset & (meminfo->writesize - 1)) != 0) {
- printf("Attempt to erase non page aligned data\n");
+ if ((opts->offset & (meminfo->erasesize - 1)) != 0) {
+ printf("Attempt to erase non block-aligned data\n");
return -1;
}
@@ -94,8 +94,8 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
erase_length = lldiv(opts->length + meminfo->erasesize - 1,
meminfo->erasesize);
- cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
- cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
+ cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
cleanmarker.totlen = cpu_to_je32(8);
/* scrub option allows to erase badblock. To prevent internal
@@ -118,7 +118,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
erased_length < erase_length;
erase.addr += meminfo->erasesize) {
- WATCHDOG_RESET ();
+ WATCHDOG_RESET();
if (!opts->scrub && bbtest) {
int ret = meminfo->block_isbad(meminfo, erase.addr);
@@ -259,7 +259,7 @@ int nand_lock(struct mtd_info *mtd, int tight)
* flash
*
* @param mtd nand mtd instance
- * @param offset page address to query (muss be page aligned!)
+ * @param offset page address to query (must be page-aligned!)
*
* @return -1 in case of error
* >0 lock status:
@@ -281,7 +281,7 @@ int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)
if ((offset & (mtd->writesize - 1)) != 0) {
- printf ("nand_get_lock_status: "
+ printf("nand_get_lock_status: "
"Start address must be beginning of "
"nand page!\n");
ret = -1;
@@ -332,20 +332,20 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
/* check the WP bit */
chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
if (!(chip->read_byte(mtd) & NAND_STATUS_WP)) {
- printf ("nand_unlock: Device is write protected!\n");
+ printf("nand_unlock: Device is write protected!\n");
ret = -1;
goto out;
}
if ((start & (mtd->erasesize - 1)) != 0) {
- printf ("nand_unlock: Start address must be beginning of "
+ printf("nand_unlock: Start address must be beginning of "
"nand block!\n");
ret = -1;
goto out;
}
if (length == 0 || (length & (mtd->erasesize - 1)) != 0) {
- printf ("nand_unlock: Length must be a multiple of nand block "
+ printf("nand_unlock: Length must be a multiple of nand block "
"size %08x!\n", mtd->erasesize);
ret = -1;
goto out;
@@ -485,7 +485,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
pages = nand->erasesize / nand->writesize;
blocksize = (pages * nand->oobsize) + nand->erasesize;
if (*length % (nand->writesize + nand->oobsize)) {
- printf ("Attempt to write incomplete page"
+ printf("Attempt to write incomplete page"
" in yaffs mode\n");
return -EINVAL;
}
@@ -507,25 +507,25 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
* partition boundary). So don't try to handle that.
*/
if ((offset & (nand->writesize - 1)) != 0) {
- printf ("Attempt to write non page aligned data\n");
+ printf("Attempt to write non page-aligned data\n");
*length = 0;
return -EINVAL;
}
need_skip = check_skip_len(nand, offset, *length);
if (need_skip < 0) {
- printf ("Attempt to write outside the flash area\n");
+ printf("Attempt to write outside the flash area\n");
*length = 0;
return -EINVAL;
}
if (!need_skip && !(flags & WITH_DROP_FFS)) {
- rval = nand_write (nand, offset, length, buffer);
+ rval = nand_write(nand, offset, length, buffer);
if (rval == 0)
return 0;
*length = 0;
- printf ("NAND write to offset %llx failed %d\n",
+ printf("NAND write to offset %llx failed %d\n",
offset, rval);
return rval;
}
@@ -534,10 +534,10 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
size_t block_offset = offset & (nand->erasesize - 1);
size_t write_size, truncated_write_size;
- WATCHDOG_RESET ();
+ WATCHDOG_RESET();
- if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
- printf ("Skip bad block 0x%08llx\n",
+ if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
+ printf("Skip bad block 0x%08llx\n",
offset & ~(nand->erasesize - 1));
offset += nand->erasesize - block_offset;
continue;
@@ -592,7 +592,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
}
if (rval != 0) {
- printf ("NAND write to offset %llx failed %d\n",
+ printf("NAND write to offset %llx failed %d\n",
offset, rval);
*length -= left_to_write;
return rval;
@@ -608,13 +608,13 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
* nand_read_skip_bad:
*
* Read image from NAND flash.
- * Blocks that are marked bad are skipped and the next block is readen
+ * Blocks that are marked bad are skipped and the next block is read
* instead as long as the image is short enough to fit even after skipping the
* bad blocks.
*
* @param nand NAND device
* @param offset offset in flash
- * @param length buffer length, on return holds remaining bytes to read
+ * @param length buffer length, on return holds number of read bytes
* @param buffer buffer to write to
* @return 0 in case of success
*/
@@ -627,25 +627,25 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
int need_skip;
if ((offset & (nand->writesize - 1)) != 0) {
- printf ("Attempt to read non page aligned data\n");
+ printf("Attempt to read non page-aligned data\n");
*length = 0;
return -EINVAL;
}
need_skip = check_skip_len(nand, offset, *length);
if (need_skip < 0) {
- printf ("Attempt to read outside the flash area\n");
+ printf("Attempt to read outside the flash area\n");
*length = 0;
return -EINVAL;
}
if (!need_skip) {
- rval = nand_read (nand, offset, length, buffer);
+ rval = nand_read(nand, offset, length, buffer);
if (!rval || rval == -EUCLEAN)
return 0;
*length = 0;
- printf ("NAND read from offset %llx failed %d\n",
+ printf("NAND read from offset %llx failed %d\n",
offset, rval);
return rval;
}
@@ -654,10 +654,10 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
size_t block_offset = offset & (nand->erasesize - 1);
size_t read_length;
- WATCHDOG_RESET ();
+ WATCHDOG_RESET();
- if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
- printf ("Skipping bad block 0x%08llx\n",
+ if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
+ printf("Skipping bad block 0x%08llx\n",
offset & ~(nand->erasesize - 1));
offset += nand->erasesize - block_offset;
continue;
@@ -668,9 +668,9 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
else
read_length = nand->erasesize - block_offset;
- rval = nand_read (nand, offset, &read_length, p_buffer);
+ rval = nand_read(nand, offset, &read_length, p_buffer);
if (rval && rval != -EUCLEAN) {
- printf ("NAND read from offset %llx failed %d\n",
+ printf("NAND read from offset %llx failed %d\n",
offset, rval);
*length -= left_to_read;
return rval;
@@ -683,3 +683,125 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
return 0;
}
+
+#ifdef CONFIG_CMD_NAND_TORTURE
+
+/**
+ * check_pattern:
+ *
+ * Check if buffer contains only a certain byte pattern.
+ *
+ * @param buf buffer to check
+ * @param patt the pattern to check
+ * @param size buffer size in bytes
+ * @return 1 if there are only patt bytes in buf
+ * 0 if something else was found
+ */
+static int check_pattern(const u_char *buf, u_char patt, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ if (buf[i] != patt)
+ return 0;
+ return 1;
+}
+
+/**
+ * nand_torture:
+ *
+ * Torture a block of NAND flash.
+ * This is useful to determine if a block that caused a write error is still
+ * good or should be marked as bad.
+ *
+ * @param nand NAND device
+ * @param offset offset in flash
+ * @return 0 if the block is still good
+ */
+int nand_torture(nand_info_t *nand, loff_t offset)
+{
+ u_char patterns[] = {0xa5, 0x5a, 0x00};
+ struct erase_info instr = {
+ .mtd = nand,
+ .addr = offset,
+ .len = nand->erasesize,
+ };
+ size_t retlen;
+ int err, ret = -1, i, patt_count;
+ u_char *buf;
+
+ if ((offset & (nand->erasesize - 1)) != 0) {
+ puts("Attempt to torture a block at a non block-aligned offset\n");
+ return -EINVAL;
+ }
+
+ if (offset + nand->erasesize > nand->size) {
+ puts("Attempt to torture a block outside the flash area\n");
+ return -EINVAL;
+ }
+
+ patt_count = ARRAY_SIZE(patterns);
+
+ buf = malloc(nand->erasesize);
+ if (buf == NULL) {
+ puts("Out of memory for erase block buffer\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < patt_count; i++) {
+ err = nand->erase(nand, &instr);
+ if (err) {
+ printf("%s: erase() failed for block at 0x%llx: %d\n",
+ nand->name, instr.addr, err);
+ goto out;
+ }
+
+ /* Make sure the block contains only 0xff bytes */
+ err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
+ if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
+ printf("%s: read() failed for block at 0x%llx: %d\n",
+ nand->name, instr.addr, err);
+ goto out;
+ }
+
+ err = check_pattern(buf, 0xff, nand->erasesize);
+ if (!err) {
+ printf("Erased block at 0x%llx, but a non-0xff byte was found\n",
+ offset);
+ ret = -EIO;
+ goto out;
+ }
+
+ /* Write a pattern and check it */
+ memset(buf, patterns[i], nand->erasesize);
+ err = nand->write(nand, offset, nand->erasesize, &retlen, buf);
+ if (err || retlen != nand->erasesize) {
+ printf("%s: write() failed for block at 0x%llx: %d\n",
+ nand->name, instr.addr, err);
+ goto out;
+ }
+
+ err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
+ if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
+ printf("%s: read() failed for block at 0x%llx: %d\n",
+ nand->name, instr.addr, err);
+ goto out;
+ }
+
+ err = check_pattern(buf, patterns[i], nand->erasesize);
+ if (!err) {
+ printf("Pattern 0x%.2x checking failed for block at "
+ "0x%llx\n", patterns[i], offset);
+ ret = -EIO;
+ goto out;
+ }
+ }
+
+ ret = 0;
+
+out:
+ free(buf);
+ return ret;
+}
+
+#endif
diff --git a/drivers/net/fm/Makefile b/drivers/net/fm/Makefile
index 7a1fcdd81f..7fbb50a562 100644
--- a/drivers/net/fm/Makefile
+++ b/drivers/net/fm/Makefile
@@ -44,6 +44,7 @@ COBJS-$(CONFIG_PPC_P2041) += p5020.o
COBJS-$(CONFIG_PPC_P3041) += p5020.o
COBJS-$(CONFIG_PPC_P4080) += p4080.o
COBJS-$(CONFIG_PPC_P5020) += p5020.o
+COBJS-$(CONFIG_PPC_P5040) += p5040.o
COBJS-$(CONFIG_PPC_T4240) += t4240.o
COBJS-$(CONFIG_PPC_B4860) += b4860.o
endif
diff --git a/drivers/net/fm/p5040.c b/drivers/net/fm/p5040.c
new file mode 100644
index 0000000000..bc6b4ba0bb
--- /dev/null
+++ b/drivers/net/fm/p5040.c
@@ -0,0 +1,113 @@
+/*
+ * 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 <phy.h>
+#include <fm_eth.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+u32 port_to_devdisr[] = {
+ [FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1,
+ [FM1_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC1_2,
+ [FM1_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC1_3,
+ [FM1_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC1_4,
+ [FM1_DTSEC5] = FSL_CORENET_DEVDISR2_DTSEC1_5,
+ [FM1_10GEC1] = FSL_CORENET_DEVDISR2_10GEC1,
+ [FM2_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC2_1,
+ [FM2_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC2_2,
+ [FM2_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC2_3,
+ [FM2_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC2_4,
+ [FM2_DTSEC5] = FSL_CORENET_DEVDISR2_DTSEC2_5,
+ [FM2_10GEC1] = FSL_CORENET_DEVDISR2_10GEC2,
+};
+
+static int is_device_disabled(enum fm_port port)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 devdisr2 = in_be32(&gur->devdisr2);
+
+ return port_to_devdisr[port] & devdisr2;
+}
+
+void fman_disable_port(enum fm_port port)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ /* don't allow disabling of DTSEC1 as its needed for MDIO */
+ if (port == FM1_DTSEC1)
+ return;
+
+ setbits_be32(&gur->devdisr2, port_to_devdisr[port]);
+}
+
+phy_interface_t fman_port_enet_if(enum fm_port port)
+{
+ ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 rcwsr11 = in_be32(&gur->rcwsr[11]);
+
+ if (is_device_disabled(port))
+ return PHY_INTERFACE_MODE_NONE;
+
+ if ((port == FM1_10GEC1) && (is_serdes_configured(XAUI_FM1)))
+ return PHY_INTERFACE_MODE_XGMII;
+
+ if ((port == FM2_10GEC1) && (is_serdes_configured(XAUI_FM2)))
+ return PHY_INTERFACE_MODE_XGMII;
+
+ /* handle RGMII first */
+ if ((port == FM1_DTSEC5) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC1) ==
+ FSL_CORENET_RCWSR11_EC1_FM1_DTSEC5_RGMII))
+ return PHY_INTERFACE_MODE_RGMII;
+
+ if ((port == FM1_DTSEC5) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC1) ==
+ FSL_CORENET_RCWSR11_EC1_FM1_DTSEC5_MII))
+ return PHY_INTERFACE_MODE_MII;
+
+ if ((port == FM2_DTSEC5) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+ FSL_CORENET_RCWSR11_EC2_FM2_DTSEC5_RGMII))
+ return PHY_INTERFACE_MODE_RGMII;
+
+ if ((port == FM2_DTSEC5) && ((rcwsr11 & FSL_CORENET_RCWSR11_EC2) ==
+ FSL_CORENET_RCWSR11_EC2_FM2_DTSEC5_MII))
+ return PHY_INTERFACE_MODE_MII;
+
+ switch (port) {
+ case FM1_DTSEC1:
+ case FM1_DTSEC2:
+ case FM1_DTSEC3:
+ case FM1_DTSEC4:
+ case FM1_DTSEC5:
+ if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1))
+ return PHY_INTERFACE_MODE_SGMII;
+ break;
+ case FM2_DTSEC1:
+ case FM2_DTSEC2:
+ case FM2_DTSEC3:
+ case FM2_DTSEC4:
+ case FM2_DTSEC5:
+ if (is_serdes_configured(SGMII_FM2_DTSEC1 + port - FM2_DTSEC1))
+ return PHY_INTERFACE_MODE_SGMII;
+ break;
+ default:
+ return PHY_INTERFACE_MODE_NONE;
+ }
+
+ return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 48ae16374d..77ac1f7c7b 100644
--- a/drivers/pci/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -470,6 +470,28 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
}
#endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
+ if (enabled == 0) {
+ serdes_corenet_t *srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
+ temp32 = in_be32(&srds_regs->srdspccr0);
+
+ if ((temp32 >> 28) == 3) {
+ int i;
+
+ out_be32(&srds_regs->srdspccr0, 2 << 28);
+ setbits_be32(&pci->pdb_stat, 0x08000000);
+ in_be32(&pci->pdb_stat);
+ udelay(100);
+ clrbits_be32(&pci->pdb_stat, 0x08000000);
+ asm("sync;isync");
+ for (i=0; i < 100 && ltssm < PCI_LTSSM_L0; i++) {
+ pci_hose_read_config_word(hose, dev, PCI_LTSSM, &ltssm);
+ udelay(1000);
+ }
+ enabled = ltssm >= PCI_LTSSM_L0;
+ }
+ }
+#endif
if (!enabled) {
/* Let the user know there's no PCIe link */
printf("no link, regs @ 0x%lx\n", pci_info->regs);
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 6bf388cb7d..8c7190156c 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -23,7 +23,7 @@
include $(TOPDIR)/config.mk
-LIB := $(obj)libpower.o
+LIB := $(obj)libpower.o
COBJS-$(CONFIG_FTPMU010_POWER) += ftpmu010.o
COBJS-$(CONFIG_TPS6586X_POWER) += tps6586x.o
@@ -31,9 +31,15 @@ COBJS-$(CONFIG_TWL4030_POWER) += twl4030.o
COBJS-$(CONFIG_TWL6030_POWER) += twl6030.o
COBJS-$(CONFIG_TWL6035_POWER) += twl6035.o
+COBJS-$(CONFIG_POWER) += power_core.o
+COBJS-$(CONFIG_DIALOG_POWER) += power_dialog.o
+COBJS-$(CONFIG_POWER_FSL) += power_fsl.o
+COBJS-$(CONFIG_POWER_I2C) += power_i2c.o
+COBJS-$(CONFIG_POWER_SPI) += power_spi.o
+
COBJS := $(COBJS-y)
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
all: $(LIB)
diff --git a/drivers/power/battery/Makefile b/drivers/power/battery/Makefile
new file mode 100644
index 0000000000..b176701234
--- /dev/null
+++ b/drivers/power/battery/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.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)libbattery.o
+
+COBJS-$(CONFIG_POWER_BATTERY_TRATS) += bat_trats.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+########################################################################
diff --git a/drivers/power/battery/bat_trats.c b/drivers/power/battery/bat_trats.c
new file mode 100644
index 0000000000..ca0d214659
--- /dev/null
+++ b/drivers/power/battery/bat_trats.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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 <power/pmic.h>
+#include <power/battery.h>
+#include <power/max8997_pmic.h>
+#include <errno.h>
+
+static struct battery battery_trats;
+
+static int power_battery_charge(struct pmic *bat)
+{
+ struct power_battery *p_bat = bat->pbat;
+ struct battery *battery = p_bat->bat;
+ int k;
+
+ if (bat->chrg->chrg_state(p_bat->chrg, CHARGER_ENABLE, 450))
+ return -1;
+
+ for (k = 0; bat->chrg->chrg_bat_present(p_bat->chrg) &&
+ bat->chrg->chrg_type(p_bat->muic) &&
+ battery->state_of_chrg < 100; k++) {
+ udelay(10000000);
+ puts(".");
+ bat->fg->fg_battery_update(p_bat->fg, bat);
+
+ if (k == 100) {
+ debug(" %d [V]", battery->voltage_uV);
+ puts("\n");
+ k = 0;
+ }
+
+ }
+
+ bat->chrg->chrg_state(p_bat->chrg, CHARGER_DISABLE, 0);
+
+ return 0;
+}
+
+static int power_battery_init_trats(struct pmic *bat_,
+ struct pmic *fg_,
+ struct pmic *chrg_,
+ struct pmic *muic_)
+{
+ bat_->pbat->fg = fg_;
+ bat_->pbat->chrg = chrg_;
+ bat_->pbat->muic = muic_;
+
+ bat_->fg = fg_->fg;
+ bat_->chrg = chrg_->chrg;
+ bat_->chrg->chrg_type = muic_->chrg->chrg_type;
+ return 0;
+}
+
+static struct power_battery power_bat_trats = {
+ .bat = &battery_trats,
+ .battery_init = power_battery_init_trats,
+ .battery_charge = power_battery_charge,
+};
+
+int power_bat_init(unsigned char bus)
+{
+ static const char name[] = "BAT_TRATS";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ debug("Board BAT init\n");
+
+ p->interface = PMIC_NONE;
+ p->name = name;
+ p->bus = bus;
+
+ p->pbat = &power_bat_trats;
+ return 0;
+}
diff --git a/drivers/power/fuel_gauge/Makefile b/drivers/power/fuel_gauge/Makefile
new file mode 100644
index 0000000000..da1541412b
--- /dev/null
+++ b/drivers/power/fuel_gauge/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.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)libfuel_gauge.o
+
+COBJS-$(CONFIG_POWER_FG_MAX17042) += fg_max17042.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+########################################################################
diff --git a/drivers/power/fuel_gauge/fg_max17042.c b/drivers/power/fuel_gauge/fg_max17042.c
new file mode 100644
index 0000000000..9b7c184cb0
--- /dev/null
+++ b/drivers/power/fuel_gauge/fg_max17042.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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 <power/pmic.h>
+#include <power/max17042_fg.h>
+#include <i2c.h>
+#include <power/max8997_pmic.h>
+#include <power/power_chrg.h>
+#include <power/battery.h>
+#include <power/fg_battery_cell_params.h>
+#include <errno.h>
+
+static int fg_write_regs(struct pmic *p, u8 addr, u16 *data, int num)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < num; i++, addr++)
+ ret |= pmic_reg_write(p, addr, *(data + i));
+
+ return ret;
+}
+
+static int fg_read_regs(struct pmic *p, u8 addr, u16 *data, int num)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < num; i++, addr++)
+ ret |= pmic_reg_read(p, addr, (u32 *) (data + i));
+
+ return ret;
+}
+
+static int fg_write_and_verify(struct pmic *p, u8 addr, u16 data)
+{
+ unsigned int val = data;
+ int ret = 0;
+
+ ret |= pmic_reg_write(p, addr, val);
+ ret |= pmic_reg_read(p, addr, &val);
+
+ if (ret)
+ return ret;
+
+ if (((u16) val) == data)
+ return 0;
+
+ return -1;
+}
+
+static void por_fuelgauge_init(struct pmic *p)
+{
+ u16 r_data0[16], r_data1[16], r_data2[16];
+ u32 rewrite_count = 5, i = 0;
+ unsigned int val;
+ int ret = 0;
+
+ /* Delay 500 ms */
+ mdelay(500);
+ /* Initilize Configuration */
+ pmic_reg_write(p, MAX17042_CONFIG, 0x2310);
+
+rewrite_model:
+ /* Unlock Model Access */
+ pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_UNLOCK1);
+ pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_UNLOCK2);
+
+ /* Write/Read/Verify the Custom Model */
+ ret |= fg_write_regs(p, MAX17042_MODEL1, cell_character0,
+ ARRAY_SIZE(cell_character0));
+ ret |= fg_write_regs(p, MAX17042_MODEL2, cell_character1,
+ ARRAY_SIZE(cell_character1));
+ ret |= fg_write_regs(p, MAX17042_MODEL3, cell_character2,
+ ARRAY_SIZE(cell_character2));
+
+ if (ret) {
+ printf("%s: Cell parameters write failed!\n", __func__);
+ return;
+ }
+
+ ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
+ ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
+ ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
+
+ if (ret)
+ printf("%s: Cell parameters read failed!\n", __func__);
+
+ for (i = 0; i < 16; i++) {
+ if ((cell_character0[i] != r_data0[i])
+ || (cell_character1[i] != r_data1[i])
+ || (cell_character2[i] != r_data2[i]))
+ goto rewrite_model;
+ }
+
+ /* Lock model access */
+ pmic_reg_write(p, MAX17042_MLOCKReg1, MODEL_LOCK1);
+ pmic_reg_write(p, MAX17042_MLOCKReg2, MODEL_LOCK2);
+
+ /* Verify the model access is locked */
+ ret |= fg_read_regs(p, MAX17042_MODEL1, r_data0, ARRAY_SIZE(r_data0));
+ ret |= fg_read_regs(p, MAX17042_MODEL2, r_data1, ARRAY_SIZE(r_data1));
+ ret |= fg_read_regs(p, MAX17042_MODEL3, r_data2, ARRAY_SIZE(r_data2));
+
+ if (ret) {
+ printf("%s: Cell parameters read failed!\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(r_data0); i++) {
+ /* Check if model locked */
+ if (r_data0[i] || r_data1[i] || r_data2[i]) {
+ /* Rewrite model data - prevent from endless loop */
+ if (rewrite_count--) {
+ puts("FG - Lock model access failed!\n");
+ goto rewrite_model;
+ }
+ }
+ }
+
+ /* Write Custom Parameters */
+ fg_write_and_verify(p, MAX17042_RCOMP0, RCOMP0);
+ fg_write_and_verify(p, MAX17042_TEMPCO, TempCo);
+
+ /* Delay at least 350mS */
+ mdelay(350);
+
+ /* Initialization Complete */
+ pmic_reg_read(p, MAX17042_STATUS, &val);
+ /* Write and Verify Status with POR bit Cleared */
+ fg_write_and_verify(p, MAX17042_STATUS, val & ~MAX17042_POR);
+
+ /* Delay at least 350 ms */
+ mdelay(350);
+}
+
+static int power_update_battery(struct pmic *p, struct pmic *bat)
+{
+ struct power_battery *pb = bat->pbat;
+ unsigned int val;
+ int ret = 0;
+
+ if (pmic_probe(p)) {
+ puts("Can't find max17042 fuel gauge\n");
+ return -1;
+ }
+
+ ret |= pmic_reg_read(p, MAX17042_VFSOC, &val);
+ pb->bat->state_of_chrg = (val >> 8);
+
+ pmic_reg_read(p, MAX17042_VCELL, &val);
+ debug("vfsoc: 0x%x\n", val);
+ pb->bat->voltage_uV = ((val & 0xFFUL) >> 3) + ((val & 0xFF00) >> 3);
+ pb->bat->voltage_uV = (pb->bat->voltage_uV * 625);
+
+ pmic_reg_read(p, 0x05, &val);
+ pb->bat->capacity = val >> 2;
+
+ return ret;
+}
+
+static int power_check_battery(struct pmic *p, struct pmic *bat)
+{
+ struct power_battery *pb = bat->pbat;
+ unsigned int val;
+ int ret = 0;
+
+ if (pmic_probe(p)) {
+ puts("Can't find max17042 fuel gauge\n");
+ return -1;
+ }
+
+ ret |= pmic_reg_read(p, MAX17042_STATUS, &val);
+ debug("fg status: 0x%x\n", val);
+
+ if (val == MAX17042_POR)
+ por_fuelgauge_init(p);
+
+ ret |= pmic_reg_read(p, MAX17042_VERSION, &val);
+ pb->bat->version = val;
+
+ power_update_battery(p, bat);
+ debug("fg ver: 0x%x\n", pb->bat->version);
+ printf("BAT: state_of_charge(SOC):%d%%\n",
+ pb->bat->state_of_chrg);
+
+ printf(" voltage: %d.%6.6d [V] (expected to be %d [mAh])\n",
+ pb->bat->voltage_uV / 1000000,
+ pb->bat->voltage_uV % 1000000,
+ pb->bat->capacity);
+
+ if (pb->bat->voltage_uV > 3850000)
+ pb->bat->state = EXT_SOURCE;
+ else if (pb->bat->voltage_uV < 3600000 || pb->bat->state_of_chrg < 5)
+ pb->bat->state = CHARGE;
+ else
+ pb->bat->state = NORMAL;
+
+ return ret;
+}
+
+static struct power_fg power_fg_ops = {
+ .fg_battery_check = power_check_battery,
+ .fg_battery_update = power_update_battery,
+};
+
+int power_fg_init(unsigned char bus)
+{
+ static const char name[] = "MAX17042_FG";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ debug("Board Fuel Gauge init\n");
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = FG_NUM_OF_REGS;
+ p->hw.i2c.addr = MAX17042_I2C_ADDR;
+ p->hw.i2c.tx_num = 2;
+ p->sensor_byte_order = PMIC_SENSOR_BYTE_ORDER_BIG;
+ p->bus = bus;
+
+ p->fg = &power_fg_ops;
+ return 0;
+}
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
new file mode 100644
index 0000000000..e19a9a8195
--- /dev/null
+++ b/drivers/power/pmic/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.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)libpmic.o
+
+COBJS-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
+COBJS-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
+COBJS-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+########################################################################
diff --git a/drivers/power/pmic/muic_max8997.c b/drivers/power/pmic/muic_max8997.c
new file mode 100644
index 0000000000..d5095c899e
--- /dev/null
+++ b/drivers/power/pmic/muic_max8997.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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 <power/pmic.h>
+#include <power/power_chrg.h>
+#include <power/max8997_muic.h>
+#include <i2c.h>
+#include <errno.h>
+
+static int power_chrg_get_type(struct pmic *p)
+{
+ unsigned int val;
+ unsigned char charge_type, charger;
+
+ if (pmic_probe(p))
+ return CHARGER_NO;
+
+ pmic_reg_read(p, MAX8997_MUIC_STATUS2, &val);
+ charge_type = val & MAX8997_MUIC_CHG_MASK;
+
+ switch (charge_type) {
+ case MAX8997_MUIC_CHG_NO:
+ charger = CHARGER_NO;
+ break;
+ case MAX8997_MUIC_CHG_USB:
+ case MAX8997_MUIC_CHG_USB_D:
+ charger = CHARGER_USB;
+ break;
+ case MAX8997_MUIC_CHG_TA:
+ case MAX8997_MUIC_CHG_TA_1A:
+ charger = CHARGER_TA;
+ break;
+ case MAX8997_MUIC_CHG_TA_500:
+ charger = CHARGER_TA_500;
+ break;
+ default:
+ charger = CHARGER_UNKNOWN;
+ break;
+ }
+
+ return charger;
+}
+
+static struct power_chrg power_chrg_muic_ops = {
+ .chrg_type = power_chrg_get_type,
+};
+
+int power_muic_init(unsigned int bus)
+{
+ static const char name[] = "MAX8997_MUIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ debug("Board Micro USB Interface Controller init\n");
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = MUIC_NUM_OF_REGS;
+ p->hw.i2c.addr = MAX8997_MUIC_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ p->chrg = &power_chrg_muic_ops;
+ return 0;
+}
diff --git a/drivers/power/pmic/pmic_max8997.c b/drivers/power/pmic/pmic_max8997.c
new file mode 100644
index 0000000000..4e5c6d647f
--- /dev/null
+++ b/drivers/power/pmic/pmic_max8997.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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 <power/pmic.h>
+#include <power/max8997_pmic.h>
+#include <i2c.h>
+#include <errno.h>
+
+unsigned char max8997_reg_ldo(int uV)
+{
+ unsigned char ret;
+ if (uV <= 800000)
+ return 0;
+ if (uV >= 3950000)
+ return MAX8997_LDO_MAX_VAL;
+ ret = (uV - 800000) / 50000;
+ if (ret > MAX8997_LDO_MAX_VAL) {
+ printf("MAX8997 LDO SETTING ERROR (%duV) -> %u\n", uV, ret);
+ ret = MAX8997_LDO_MAX_VAL;
+ }
+
+ return ret;
+}
+
+static int pmic_charger_state(struct pmic *p, int state, int current)
+{
+ unsigned char fc;
+ u32 val = 0;
+
+ if (pmic_probe(p))
+ return -1;
+
+ if (state == CHARGER_DISABLE) {
+ puts("Disable the charger.\n");
+ pmic_reg_read(p, MAX8997_REG_MBCCTRL2, &val);
+ val &= ~(MBCHOSTEN | VCHGR_FC);
+ pmic_reg_write(p, MAX8997_REG_MBCCTRL2, val);
+
+ return -1;
+ }
+
+ if (current < CHARGER_MIN_CURRENT || current > CHARGER_MAX_CURRENT) {
+ printf("%s: Wrong charge current: %d [mA]\n",
+ __func__, current);
+ return -1;
+ }
+
+ fc = (current - CHARGER_MIN_CURRENT) / CHARGER_CURRENT_RESOLUTION;
+ fc = fc & 0xf; /* up to 950 mA */
+
+ printf("Enable the charger @ %d [mA]\n", fc * CHARGER_CURRENT_RESOLUTION
+ + CHARGER_MIN_CURRENT);
+
+ val = fc | MBCICHFCSET;
+ pmic_reg_write(p, MAX8997_REG_MBCCTRL4, val);
+
+ pmic_reg_read(p, MAX8997_REG_MBCCTRL2, &val);
+ val = MBCHOSTEN | VCHGR_FC; /* enable charger & fast charge */
+ pmic_reg_write(p, MAX8997_REG_MBCCTRL2, val);
+
+ return 0;
+}
+
+static int pmic_charger_bat_present(struct pmic *p)
+{
+ u32 val;
+
+ if (pmic_probe(p))
+ return -1;
+
+ pmic_reg_read(p, MAX8997_REG_STATUS4, &val);
+
+ return !(val & DETBAT);
+}
+
+static struct power_chrg power_chrg_pmic_ops = {
+ .chrg_bat_present = pmic_charger_bat_present,
+ .chrg_state = pmic_charger_state,
+};
+
+int pmic_init(unsigned char bus)
+{
+ static const char name[] = "MAX8997_PMIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
+
+ debug("Board PMIC init\n");
+
+ p->name = name;
+ p->interface = PMIC_I2C;
+ p->number_of_regs = PMIC_NUM_OF_REGS;
+ p->hw.i2c.addr = MAX8997_I2C_ADDR;
+ p->hw.i2c.tx_num = 1;
+ p->bus = bus;
+
+ p->chrg = &power_chrg_pmic_ops;
+ return 0;
+}
diff --git a/drivers/misc/pmic_max8998.c b/drivers/power/pmic/pmic_max8998.c
index cc69fd7080..452e1c8d86 100644
--- a/drivers/misc/pmic_max8998.c
+++ b/drivers/power/pmic/pmic_max8998.c
@@ -22,13 +22,19 @@
*/
#include <common.h>
-#include <pmic.h>
-#include <max8998_pmic.h>
+#include <power/pmic.h>
+#include <power/max8998_pmic.h>
+#include <errno.h>
-int pmic_init(void)
+int pmic_init(unsigned char bus)
{
- struct pmic *p = get_pmic();
static const char name[] = "MAX8998_PMIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
puts("Board PMIC init\n");
@@ -37,7 +43,7 @@ int pmic_init(void)
p->number_of_regs = PMIC_NUM_OF_REGS;
p->hw.i2c.addr = MAX8998_I2C_ADDR;
p->hw.i2c.tx_num = 1;
- p->bus = I2C_PMIC;
+ p->bus = bus;
return 0;
}
diff --git a/drivers/power/power_core.c b/drivers/power/power_core.c
new file mode 100644
index 0000000000..90df2c58c4
--- /dev/null
+++ b/drivers/power/power_core.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * (C) Copyright 2010
+ * Stefano Babic, DENX Software Engineering, sbabic@denx.de
+ *
+ * (C) Copyright 2008-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 <malloc.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <power/pmic.h>
+
+static LIST_HEAD(pmic_list);
+
+int check_reg(struct pmic *p, u32 reg)
+{
+ if (reg >= p->number_of_regs) {
+ printf("<reg num> = %d is invalid. Should be less than %d\n",
+ reg, p->number_of_regs);
+ return -1;
+ }
+
+ return 0;
+}
+
+int pmic_set_output(struct pmic *p, u32 reg, int out, int on)
+{
+ u32 val;
+
+ if (pmic_reg_read(p, reg, &val))
+ return -1;
+
+ if (on)
+ val |= out;
+ else
+ val &= ~out;
+
+ if (pmic_reg_write(p, reg, val))
+ return -1;
+
+ return 0;
+}
+
+static void pmic_show_info(struct pmic *p)
+{
+ printf("PMIC: %s\n", p->name);
+}
+
+static int pmic_dump(struct pmic *p)
+{
+ int i, ret;
+ u32 val;
+
+ if (!p) {
+ puts("Wrong PMIC name!\n");
+ return -1;
+ }
+
+ pmic_show_info(p);
+ for (i = 0; i < p->number_of_regs; i++) {
+ ret = pmic_reg_read(p, i, &val);
+ if (ret)
+ puts("PMIC: Registers dump failed\n");
+
+ if (!(i % 8))
+ printf("\n0x%02x: ", i);
+
+ printf("%08x ", val);
+ }
+ puts("\n");
+ return 0;
+}
+
+struct pmic *pmic_alloc(void)
+{
+ struct pmic *p;
+
+ p = calloc(sizeof(*p), 1);
+ if (!p) {
+ printf("%s: No available memory for allocation!\n", __func__);
+ return NULL;
+ }
+
+ list_add_tail(&p->list, &pmic_list);
+
+ debug("%s: new pmic struct: 0x%p\n", __func__, p);
+
+ return p;
+}
+
+struct pmic *pmic_get(const char *s)
+{
+ struct pmic *p;
+
+ list_for_each_entry(p, &pmic_list, list) {
+ if (strcmp(p->name, s) == 0) {
+ debug("%s: pmic %s -> 0x%p\n", __func__, p->name, p);
+ return p;
+ }
+ }
+
+ return NULL;
+}
+
+const char *power_get_interface(int interface)
+{
+ const char *power_interface[] = {"I2C", "SPI", "|+|-|"};
+ return power_interface[interface];
+}
+
+static void pmic_list_names(void)
+{
+ struct pmic *p;
+
+ puts("PMIC devices:\n");
+ list_for_each_entry(p, &pmic_list, list) {
+ printf("name: %s bus: %s_%d\n", p->name,
+ power_get_interface(p->interface), p->bus);
+ }
+}
+
+int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ u32 ret, reg, val;
+ char *cmd, *name;
+ struct pmic *p;
+
+ /* at least two arguments please */
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[1], "list") == 0) {
+ pmic_list_names();
+ return CMD_RET_SUCCESS;
+ }
+
+ name = argv[1];
+ cmd = argv[2];
+
+ debug("%s: name: %s cmd: %s\n", __func__, name, cmd);
+ p = pmic_get(name);
+ if (!p)
+ return CMD_RET_FAILURE;
+
+ if (strcmp(cmd, "dump") == 0) {
+ if (pmic_dump(p))
+ return CMD_RET_FAILURE;
+ return CMD_RET_SUCCESS;
+ }
+
+ if (strcmp(cmd, "read") == 0) {
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ reg = simple_strtoul(argv[3], NULL, 16);
+ ret = pmic_reg_read(p, reg, &val);
+
+ if (ret)
+ puts("PMIC: Register read failed\n");
+
+ printf("\n0x%02x: 0x%08x\n", reg, val);
+
+ return CMD_RET_SUCCESS;
+ }
+
+ if (strcmp(cmd, "write") == 0) {
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ reg = simple_strtoul(argv[3], NULL, 16);
+ val = simple_strtoul(argv[4], NULL, 16);
+ pmic_reg_write(p, reg, val);
+
+ return CMD_RET_SUCCESS;
+ }
+
+ if (strcmp(cmd, "bat") == 0) {
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ if (strcmp(argv[3], "state") == 0)
+ p->fg->fg_battery_check(p->pbat->fg, p);
+
+ if (strcmp(argv[3], "charge") == 0) {
+ if (p->pbat) {
+ printf("PRINT BAT charge %s\n", p->name);
+ if (p->low_power_mode)
+ p->low_power_mode();
+ if (p->pbat->battery_charge)
+ p->pbat->battery_charge(p);
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+ }
+
+ /* No subcommand found */
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ pmic, CONFIG_SYS_MAXARGS, 1, do_pmic,
+ "PMIC",
+ "list - list available PMICs\n"
+ "pmic name dump - dump named PMIC registers\n"
+ "pmic name read <reg> - read register\n"
+ "pmic name write <reg> <value> - write register\n"
+ "pmic name bat state - write register\n"
+ "pmic name bat charge - write register\n"
+);
diff --git a/drivers/misc/pmic_dialog.c b/drivers/power/power_dialog.c
index e97af1d1d0..d7ebd1583e 100644
--- a/drivers/misc/pmic_dialog.c
+++ b/drivers/power/power_dialog.c
@@ -17,13 +17,19 @@
*/
#include <common.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <dialog_pmic.h>
+#include <errno.h>
-int pmic_dialog_init(void)
+int pmic_dialog_init(unsigned char bus)
{
- struct pmic *p = get_pmic();
static const char name[] = "DIALOG_PMIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
p->name = name;
p->number_of_regs = DIALOG_NUM_OF_REGS;
@@ -31,7 +37,7 @@ int pmic_dialog_init(void)
p->interface = PMIC_I2C;
p->hw.i2c.addr = CONFIG_SYS_DIALOG_PMIC_I2C_ADDR;
p->hw.i2c.tx_num = 1;
- p->bus = I2C_PMIC;
+ p->bus = bus;
return 0;
}
diff --git a/drivers/misc/pmic_fsl.c b/drivers/power/power_fsl.c
index c8d4c8d9ec..a663831589 100644
--- a/drivers/misc/pmic_fsl.c
+++ b/drivers/power/power_fsl.c
@@ -23,8 +23,9 @@
#include <common.h>
#include <spi.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
+#include <errno.h>
#if defined(CONFIG_PMIC_FSL_MC13892)
#define FSL_PMIC_I2C_LENGTH 3
@@ -32,22 +33,27 @@
#define FSL_PMIC_I2C_LENGTH 1
#endif
-#if defined(CONFIG_PMIC_SPI)
+#if defined(CONFIG_POWER_SPI)
static u32 pmic_spi_prepare_tx(u32 reg, u32 *val, u32 write)
{
return (write << 31) | (reg << 25) | (*val & 0x00FFFFFF);
}
#endif
-int pmic_init(void)
+int pmic_init(unsigned char bus)
{
- struct pmic *p = get_pmic();
static const char name[] = "FSL_PMIC";
+ struct pmic *p = pmic_alloc();
+
+ if (!p) {
+ printf("%s: POWER allocation error!\n", __func__);
+ return -ENOMEM;
+ }
p->name = name;
p->number_of_regs = PMIC_NUM_OF_REGS;
-#if defined(CONFIG_PMIC_SPI)
+#if defined(CONFIG_POWER_SPI)
p->interface = PMIC_SPI;
p->bus = CONFIG_FSL_PMIC_BUS;
p->hw.spi.cs = CONFIG_FSL_PMIC_CS;
@@ -56,13 +62,13 @@ int pmic_init(void)
p->hw.spi.bitlen = CONFIG_FSL_PMIC_BITLEN;
p->hw.spi.flags = SPI_XFER_BEGIN | SPI_XFER_END;
p->hw.spi.prepare_tx = pmic_spi_prepare_tx;
-#elif defined(CONFIG_PMIC_I2C)
+#elif defined(CONFIG_POWER_I2C)
p->interface = PMIC_I2C;
p->hw.i2c.addr = CONFIG_SYS_FSL_PMIC_I2C_ADDR;
p->hw.i2c.tx_num = FSL_PMIC_I2C_LENGTH;
- p->bus = I2C_PMIC;
+ p->bus = bus;
#else
-#error "You must select CONFIG_PMIC_SPI or CONFIG_PMIC_I2C"
+#error "You must select CONFIG_POWER_SPI or CONFIG_PMIC_I2C"
#endif
return 0;
diff --git a/drivers/misc/pmic_i2c.c b/drivers/power/power_i2c.c
index 95a3365b9f..3e5a784cf5 100644
--- a/drivers/misc/pmic_i2c.c
+++ b/drivers/power/power_i2c.c
@@ -28,24 +28,40 @@
#include <common.h>
#include <linux/types.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <i2c.h>
+#include <compiler.h>
int pmic_reg_write(struct pmic *p, u32 reg, u32 val)
{
unsigned char buf[4] = { 0 };
- if (check_reg(reg))
+ if (check_reg(p, reg))
return -1;
switch (pmic_i2c_tx_num) {
case 3:
- buf[0] = (val >> 16) & 0xff;
- buf[1] = (val >> 8) & 0xff;
- buf[2] = val & 0xff;
+ if (p->sensor_byte_order == PMIC_SENSOR_BYTE_ORDER_BIG) {
+ buf[2] = (cpu_to_le32(val) >> 16) & 0xff;
+ buf[1] = (cpu_to_le32(val) >> 8) & 0xff;
+ buf[0] = cpu_to_le32(val) & 0xff;
+ } else {
+ buf[0] = (cpu_to_le32(val) >> 16) & 0xff;
+ buf[1] = (cpu_to_le32(val) >> 8) & 0xff;
+ buf[2] = cpu_to_le32(val) & 0xff;
+ }
+ break;
+ case 2:
+ if (p->sensor_byte_order == PMIC_SENSOR_BYTE_ORDER_BIG) {
+ buf[1] = (cpu_to_le32(val) >> 8) & 0xff;
+ buf[0] = cpu_to_le32(val) & 0xff;
+ } else {
+ buf[0] = (cpu_to_le32(val) >> 8) & 0xff;
+ buf[1] = cpu_to_le32(val) & 0xff;
+ }
break;
case 1:
- buf[0] = val & 0xff;
+ buf[0] = cpu_to_le32(val) & 0xff;
break;
default:
printf("%s: invalid tx_num: %d", __func__, pmic_i2c_tx_num);
@@ -63,7 +79,7 @@ int pmic_reg_read(struct pmic *p, u32 reg, u32 *val)
unsigned char buf[4] = { 0 };
u32 ret_val = 0;
- if (check_reg(reg))
+ if (check_reg(p, reg))
return -1;
if (i2c_read(pmic_i2c_addr, reg, 1, buf, pmic_i2c_tx_num))
@@ -71,10 +87,21 @@ int pmic_reg_read(struct pmic *p, u32 reg, u32 *val)
switch (pmic_i2c_tx_num) {
case 3:
- ret_val = buf[0] << 16 | buf[1] << 8 | buf[2];
+ if (p->sensor_byte_order == PMIC_SENSOR_BYTE_ORDER_BIG)
+ ret_val = le32_to_cpu(buf[2] << 16
+ | buf[1] << 8 | buf[0]);
+ else
+ ret_val = le32_to_cpu(buf[0] << 16 |
+ buf[1] << 8 | buf[2]);
+ break;
+ case 2:
+ if (p->sensor_byte_order == PMIC_SENSOR_BYTE_ORDER_BIG)
+ ret_val = le32_to_cpu(buf[1] << 8 | buf[0]);
+ else
+ ret_val = le32_to_cpu(buf[0] << 8 | buf[1]);
break;
case 1:
- ret_val = buf[0];
+ ret_val = le32_to_cpu(buf[0]);
break;
default:
printf("%s: invalid tx_num: %d", __func__, pmic_i2c_tx_num);
@@ -88,7 +115,7 @@ int pmic_reg_read(struct pmic *p, u32 reg, u32 *val)
int pmic_probe(struct pmic *p)
{
I2C_SET_BUS(p->bus);
- debug("PMIC:%s probed!\n", p->name);
+ debug("Bus: %d PMIC:%s probed!\n", p->bus, p->name);
if (i2c_probe(pmic_i2c_addr)) {
printf("Can't find PMIC:%s\n", p->name);
return -1;
diff --git a/drivers/misc/pmic_spi.c b/drivers/power/power_spi.c
index 5a0dd22e29..27488ea5d9 100644
--- a/drivers/misc/pmic_spi.c
+++ b/drivers/power/power_spi.c
@@ -28,7 +28,7 @@
#include <common.h>
#include <linux/types.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <spi.h>
static struct spi_slave *slave;
@@ -59,7 +59,7 @@ static u32 pmic_reg(struct pmic *p, u32 reg, u32 *val, u32 write)
return -1;
}
- if (check_reg(reg))
+ if (check_reg(p, reg))
return -1;
if (spi_claim_bus(slave))
diff --git a/drivers/rtc/mc13xxx-rtc.c b/drivers/rtc/mc13xxx-rtc.c
index 70ea8a1589..e79f4621d3 100644
--- a/drivers/rtc/mc13xxx-rtc.c
+++ b/drivers/rtc/mc13xxx-rtc.c
@@ -23,16 +23,18 @@
#include <common.h>
#include <rtc.h>
#include <spi.h>
-#include <pmic.h>
+#include <power/pmic.h>
#include <fsl_pmic.h>
int rtc_get(struct rtc_time *rtc)
{
u32 day1, day2, time;
int tim, i = 0;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("FSL_PMIC");
int ret;
+ if (!p)
+ return -1;
do {
ret = pmic_reg_read(p, REG_RTC_DAY, &day1);
if (ret < 0)
@@ -61,7 +63,9 @@ int rtc_get(struct rtc_time *rtc)
int rtc_set(struct rtc_time *rtc)
{
u32 time, day;
- struct pmic *p = get_pmic();
+ struct pmic *p = pmic_get("FSL_PMIC");
+ if (!p)
+ return -1;
time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday,
rtc->tm_hour, rtc->tm_min, rtc->tm_sec);
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 9027781445..bbd91ca247 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -36,6 +36,9 @@
void NS16550_init(NS16550_t com_port, int baud_divisor)
{
+ while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT))
+ ;
+
serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
#if (defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2)) || \
defined(CONFIG_AM33XX)
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index c1c0134bcb..fc01a3c516 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -31,6 +31,8 @@
#include <serial.h>
+#ifndef CONFIG_NS16550_MIN_FUNCTIONS
+
DECLARE_GLOBAL_DATA_PTR;
#if !defined(CONFIG_CONS_INDEX)
@@ -304,3 +306,5 @@ void ns16550_serial_initialize(void)
serial_register(&eserial6_device);
#endif
}
+
+#endif /* !CONFIG_NS16550_MIN_FUNCTIONS */
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index b331be794b..dfdba9f64e 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -163,8 +163,8 @@ static int pl01x_serial_init(void)
}
#endif
/* Finally, enable the UART */
- writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE,
- &regs->pl011_cr);
+ writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE |
+ UART_PL011_CR_RTS, &regs->pl011_cr);
return 0;
}
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 3c931d0212..ee1f2d768a 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -117,6 +117,14 @@ static int serial_rx_fifo_level(void)
return scif_rxfill(&sh_sci);
}
+static void handle_error(void)
+{
+ sci_in(&sh_sci, SCxSR);
+ sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci));
+ sci_in(&sh_sci, SCLSR);
+ sci_out(&sh_sci, SCLSR, 0x00);
+}
+
void serial_raw_putc(const char c)
{
while (1) {
@@ -138,16 +146,14 @@ static void sh_serial_putc(const char c)
static int sh_serial_tstc(void)
{
+ if (sci_in(&sh_sci, SCxSR) & SCIF_ERRORS) {
+ handle_error();
+ return 0;
+ }
+
return serial_rx_fifo_level() ? 1 : 0;
}
-void handle_error(void)
-{
- sci_in(&sh_sci, SCxSR);
- sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci));
- sci_in(&sh_sci, SCLSR);
- sci_out(&sh_sci, SCLSR, 0x00);
-}
int serial_getc_check(void)
{
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index f88d0c190c..f9163a80ed 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -27,7 +27,6 @@
#include <linux/string.h>
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <linux/usb/gadget.h>
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index b656c8b9f4..5b8776e0b7 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -23,7 +23,6 @@
#include <common.h>
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <asm/errno.h>
#include <linux/usb/gadget.h>
#include <asm/unaligned.h>
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 8b24e00e27..de880ffeb8 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -24,7 +24,6 @@
#include <asm/errno.h>
#include <linux/netdevice.h>
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <linux/usb/cdc.h>
#include <linux/usb/gadget.h>
#include <net.h>
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 3ec4c65e74..10547e3279 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -25,7 +25,6 @@
#include <malloc.h>
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 02cae0fc75..e5701422fa 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -125,8 +125,8 @@
#endif
/* Mentor high speed "dual role" controller, in peripheral role */
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-#define gadget_is_musbhdrc(g) (!strcmp("musb_hdrc", (g)->name))
+#ifdef CONFIG_MUSB_GADGET
+#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
#else
#define gadget_is_musbhdrc(g) 0
#endif
diff --git a/drivers/usb/gadget/s3c_udc_otg.c b/drivers/usb/gadget/s3c_udc_otg.c
index 3fdfdf7af0..f9d24e3dfd 100644
--- a/drivers/usb/gadget/s3c_udc_otg.c
+++ b/drivers/usb/gadget/s3c_udc_otg.c
@@ -37,7 +37,6 @@
#include <malloc.h>
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <linux/usb/gadget.h>
#include <asm/byteorder.h>
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index 4dbe060d6f..95555cf96b 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -13,7 +13,6 @@
#include <common.h>
#include <asm/errno.h>
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <linux/usb/gadget.h>
#include <asm/unaligned.h>
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d90e94d810..7f98a6354a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -210,6 +210,18 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
return 0;
}
+static inline u8 ehci_encode_speed(enum usb_device_speed speed)
+{
+ #define QH_HIGH_SPEED 2
+ #define QH_FULL_SPEED 0
+ #define QH_LOW_SPEED 1
+ if (speed == USB_SPEED_HIGH)
+ return QH_HIGH_SPEED;
+ if (speed == USB_SPEED_LOW)
+ return QH_LOW_SPEED;
+ return QH_FULL_SPEED;
+}
+
static int
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
int length, struct devrequest *req)
@@ -318,12 +330,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
* - qh_overlay.qt_altnext
*/
qh->qh_link = cpu_to_hc32((uint32_t)&ctrl->qh_list | QH_LINK_TYPE_QH);
- c = usb_pipespeed(pipe) != USB_SPEED_HIGH && !usb_pipeendpoint(pipe);
+ c = (dev->speed != USB_SPEED_HIGH) && !usb_pipeendpoint(pipe);
maxpacket = usb_maxpacket(dev, pipe);
endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) |
QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) |
- QH_ENDPT1_EPS(usb_pipespeed(pipe)) |
+ QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) |
QH_ENDPT1_DEVADDR(usb_pipedevice(pipe));
qh->qh_endpt1 = cpu_to_hc32(endpt);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 19e16a4a80..289018c4f6 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -617,7 +617,7 @@ static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
int epnum = usb_pipeendpoint(pipe);
int max = usb_maxpacket(dev, pipe);
int dir_out = usb_pipeout(pipe);
- int speed_low = usb_pipeslow(pipe);
+ int speed_low = (dev->speed == USB_SPEED_LOW);
int i, done = 0, stat, timeout, cc;
/* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index c2106adbd3..bdbe250b01 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -803,7 +803,7 @@ static ed_t *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe,
| (usb_pipeisoc(pipe)? 0x8000: 0)
| (usb_pipecontrol(pipe)? 0: \
(usb_pipeout(pipe)? 0x800: 0x1000))
- | usb_pipeslow(pipe) << 13
+ | (usb_dev->speed == USB_SPEED_LOW) << 13
| usb_maxpacket(usb_dev, pipe) << 16);
if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) {
diff --git a/drivers/usb/host/ohci-s3c24xx.c b/drivers/usb/host/ohci-s3c24xx.c
index 03cd4c3d2a..dde0764034 100644
--- a/drivers/usb/host/ohci-s3c24xx.c
+++ b/drivers/usb/host/ohci-s3c24xx.c
@@ -620,7 +620,7 @@ static struct ed *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe)
| (usb_pipeisoc(pipe) ? 0x8000 : 0)
| (usb_pipecontrol(pipe) ? 0 :
(usb_pipeout(pipe) ? 0x800 : 0x1000))
- | usb_pipeslow(pipe) << 13 |
+ | (usb_dev->speed == USB_SPEED_LOW) << 13 |
usb_maxpacket(usb_dev, pipe) << 16);
return ed_ret;
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 2a4e7ff4b3..b503b356ce 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -31,9 +31,6 @@
#endif
static const char hcd_name[] = "r8a66597_hcd";
-static unsigned short clock = CONFIG_R8A66597_XTAL;
-static unsigned short vif = CONFIG_R8A66597_LDRV;
-static unsigned short endian = CONFIG_R8A66597_ENDIAN;
static struct r8a66597 gr8a66597;
static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport)
@@ -96,7 +93,7 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
}
} while ((tmp & USBE) != USBE);
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
- r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
+ r8a66597_mdfy(r8a66597, CONFIG_R8A66597_XTAL, XTAL, SYSCFG0);
i = 0;
r8a66597_bset(r8a66597, XCKE, SYSCFG0);
@@ -162,7 +159,7 @@ static int enable_controller(struct r8a66597 *r8a66597)
if (ret < 0)
return ret;
- r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+ r8a66597_bset(r8a66597, CONFIG_R8A66597_LDRV & LDRV, PINCFG);
r8a66597_bset(r8a66597, USBE, SYSCFG0);
r8a66597_bset(r8a66597, INTL, SOFCFG);
@@ -170,9 +167,9 @@ static int enable_controller(struct r8a66597 *r8a66597)
r8a66597_write(r8a66597, 0, INTENB1);
r8a66597_write(r8a66597, 0, INTENB2);
- r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
- r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
- r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+ r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, CFIFOSEL);
+ r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D0FIFOSEL);
+ r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D1FIFOSEL);
r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
@@ -673,7 +670,6 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
int stat = 0;
__u16 bmRType_bReq;
__u16 wValue;
- __u16 wIndex;
__u16 wLength;
unsigned char data[32];
@@ -686,7 +682,6 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
bmRType_bReq = cmd->requesttype | (cmd->request << 8);
wValue = cpu_to_le16 (cmd->value);
- wIndex = cpu_to_le16 (cmd->index);
wLength = cpu_to_le16 (cmd->length);
switch (bmRType_bReq) {
@@ -908,7 +903,7 @@ int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
return 0;
}
-int usb_lowlevel_init(int index, void **controller))
+int usb_lowlevel_init(int index, void **controller)
{
struct r8a66597 *r8a66597 = &gr8a66597;
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 2830616046..417f1a8aba 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -234,7 +234,7 @@ static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *b
__u16 status = 0;
int err = 0, time_start = get_timer(0);
int need_preamble = !(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) &&
- usb_pipeslow(pipe);
+ (dev->speed == USB_SPEED_LOW);
if (len > 239)
return -1;
diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile
new file mode 100644
index 0000000000..c23bef1cc2
--- /dev/null
+++ b/drivers/usb/musb-new/Makefile
@@ -0,0 +1,39 @@
+#
+# for USB OTG silicon based on Mentor Graphics INVENTRA designs
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libusb_musb-new.o
+
+COBJS-$(CONFIG_MUSB_GADGET) += musb_gadget.o musb_gadget_ep0.o musb_core.o
+COBJS-$(CONFIG_MUSB_GADGET) += musb_uboot.o
+COBJS-$(CONFIG_MUSB_HOST) += musb_host.o musb_core.o musb_uboot.o
+COBJS-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o
+COBJS-$(CONFIG_USB_MUSB_AM35X) += am35x.o
+COBJS-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o
+
+CFLAGS_NO_WARN := $(call cc-option,-Wno-unused-variable) \
+ $(call cc-option,-Wno-unused-but-set-variable) \
+ $(call cc-option,-Wno-unused-label)
+CFLAGS += $(CFLAGS_NO_WARN)
+
+COBJS := $(sort $(COBJS-y))
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+#$(LIB): $(OBJS)
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
diff --git a/drivers/usb/musb-new/am35x.c b/drivers/usb/musb-new/am35x.c
new file mode 100644
index 0000000000..57c9bd393b
--- /dev/null
+++ b/drivers/usb/musb-new/am35x.c
@@ -0,0 +1,709 @@
+/*
+ * Texas Instruments AM35x "glue layer"
+ *
+ * Copyright (c) 2010, by Texas Instruments
+ *
+ * Based on the DA8xx "glue layer" code.
+ * Copyright (c) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux 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.
+ *
+ * The Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <plat/usb.h>
+#else
+#include <common.h>
+#include <asm/omap_musb.h>
+#include "linux-compat.h"
+#endif
+
+#include "musb_core.h"
+
+/*
+ * AM35x specific definitions
+ */
+/* USB 2.0 OTG module registers */
+#define USB_REVISION_REG 0x00
+#define USB_CTRL_REG 0x04
+#define USB_STAT_REG 0x08
+#define USB_EMULATION_REG 0x0c
+/* 0x10 Reserved */
+#define USB_AUTOREQ_REG 0x14
+#define USB_SRP_FIX_TIME_REG 0x18
+#define USB_TEARDOWN_REG 0x1c
+#define EP_INTR_SRC_REG 0x20
+#define EP_INTR_SRC_SET_REG 0x24
+#define EP_INTR_SRC_CLEAR_REG 0x28
+#define EP_INTR_MASK_REG 0x2c
+#define EP_INTR_MASK_SET_REG 0x30
+#define EP_INTR_MASK_CLEAR_REG 0x34
+#define EP_INTR_SRC_MASKED_REG 0x38
+#define CORE_INTR_SRC_REG 0x40
+#define CORE_INTR_SRC_SET_REG 0x44
+#define CORE_INTR_SRC_CLEAR_REG 0x48
+#define CORE_INTR_MASK_REG 0x4c
+#define CORE_INTR_MASK_SET_REG 0x50
+#define CORE_INTR_MASK_CLEAR_REG 0x54
+#define CORE_INTR_SRC_MASKED_REG 0x58
+/* 0x5c Reserved */
+#define USB_END_OF_INTR_REG 0x60
+
+/* Control register bits */
+#define AM35X_SOFT_RESET_MASK 1
+
+/* USB interrupt register bits */
+#define AM35X_INTR_USB_SHIFT 16
+#define AM35X_INTR_USB_MASK (0x1ff << AM35X_INTR_USB_SHIFT)
+#define AM35X_INTR_DRVVBUS 0x100
+#define AM35X_INTR_RX_SHIFT 16
+#define AM35X_INTR_TX_SHIFT 0
+#define AM35X_TX_EP_MASK 0xffff /* EP0 + 15 Tx EPs */
+#define AM35X_RX_EP_MASK 0xfffe /* 15 Rx EPs */
+#define AM35X_TX_INTR_MASK (AM35X_TX_EP_MASK << AM35X_INTR_TX_SHIFT)
+#define AM35X_RX_INTR_MASK (AM35X_RX_EP_MASK << AM35X_INTR_RX_SHIFT)
+
+#define USB_MENTOR_CORE_OFFSET 0x400
+
+struct am35x_glue {
+ struct device *dev;
+ struct platform_device *musb;
+ struct clk *phy_clk;
+ struct clk *clk;
+};
+#define glue_to_musb(g) platform_get_drvdata(g->musb)
+
+/*
+ * am35x_musb_enable - enable interrupts
+ */
+static void am35x_musb_enable(struct musb *musb)
+{
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 epmask;
+
+ /* Workaround: setup IRQs through both register sets. */
+ epmask = ((musb->epmask & AM35X_TX_EP_MASK) << AM35X_INTR_TX_SHIFT) |
+ ((musb->epmask & AM35X_RX_EP_MASK) << AM35X_INTR_RX_SHIFT);
+
+ musb_writel(reg_base, EP_INTR_MASK_SET_REG, epmask);
+ musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK);
+
+ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
+ if (is_otg_enabled(musb))
+ musb_writel(reg_base, CORE_INTR_SRC_SET_REG,
+ AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT);
+}
+
+/*
+ * am35x_musb_disable - disable HDRC and flush interrupts
+ */
+static void am35x_musb_disable(struct musb *musb)
+{
+ void __iomem *reg_base = musb->ctrl_base;
+
+ musb_writel(reg_base, CORE_INTR_MASK_CLEAR_REG, AM35X_INTR_USB_MASK);
+ musb_writel(reg_base, EP_INTR_MASK_CLEAR_REG,
+ AM35X_TX_INTR_MASK | AM35X_RX_INTR_MASK);
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+}
+
+#ifndef __UBOOT__
+#define portstate(stmt) stmt
+
+static void am35x_musb_set_vbus(struct musb *musb, int is_on)
+{
+ WARN_ON(is_on && is_peripheral_active(musb));
+}
+
+#define POLL_SECONDS 2
+
+static struct timer_list otg_workaround;
+
+static void otg_timer(unsigned long _musb)
+{
+ struct musb *musb = (void *)_musb;
+ void __iomem *mregs = musb->mregs;
+ u8 devctl;
+ unsigned long flags;
+
+ /*
+ * We poll because AM35x's won't expose several OTG-critical
+ * status change events (from the transceiver) otherwise.
+ */
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
+ otg_state_string(musb->xceiv->state));
+
+ spin_lock_irqsave(&musb->lock, flags);
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ } else {
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ }
+ break;
+ case OTG_STATE_A_WAIT_VFALL:
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ musb_writel(musb->ctrl_base, CORE_INTR_SRC_SET_REG,
+ MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT);
+ break;
+ case OTG_STATE_B_IDLE:
+ if (!is_peripheral_enabled(musb))
+ break;
+
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE)
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ else
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
+{
+ static unsigned long last_timer;
+
+ if (!is_otg_enabled(musb))
+ return;
+
+ if (timeout == 0)
+ timeout = jiffies + msecs_to_jiffies(3);
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || (musb->a_wait_bcon == 0 &&
+ musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+ dev_dbg(musb->controller, "%s active, deleting timer\n",
+ otg_state_string(musb->xceiv->state));
+ del_timer(&otg_workaround);
+ last_timer = jiffies;
+ return;
+ }
+
+ if (time_after(last_timer, timeout) && timer_pending(&otg_workaround)) {
+ dev_dbg(musb->controller, "Longer idle timer already pending, ignoring...\n");
+ return;
+ }
+ last_timer = timeout;
+
+ dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
+ otg_state_string(musb->xceiv->state),
+ jiffies_to_msecs(timeout - jiffies));
+ mod_timer(&otg_workaround, timeout);
+}
+#endif
+
+static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
+{
+ struct musb *musb = hci;
+ void __iomem *reg_base = musb->ctrl_base;
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+ struct usb_otg *otg = musb->xceiv->otg;
+#else
+ struct omap_musb_board_data *data =
+ (struct omap_musb_board_data *)musb->controller;
+#endif
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+ u32 epintr, usbintr;
+
+#ifdef __UBOOT__
+ /*
+ * It seems that on AM35X interrupt registers can be updated
+ * before core registers. This confuses the code.
+ * As a workaround add a small delay here.
+ */
+ udelay(10);
+#endif
+ spin_lock_irqsave(&musb->lock, flags);
+
+ /* Get endpoint interrupts */
+ epintr = musb_readl(reg_base, EP_INTR_SRC_MASKED_REG);
+
+ if (epintr) {
+ musb_writel(reg_base, EP_INTR_SRC_CLEAR_REG, epintr);
+
+ musb->int_rx =
+ (epintr & AM35X_RX_INTR_MASK) >> AM35X_INTR_RX_SHIFT;
+ musb->int_tx =
+ (epintr & AM35X_TX_INTR_MASK) >> AM35X_INTR_TX_SHIFT;
+ }
+
+ /* Get usb core interrupts */
+ usbintr = musb_readl(reg_base, CORE_INTR_SRC_MASKED_REG);
+ if (!usbintr && !epintr)
+ goto eoi;
+
+ if (usbintr) {
+ musb_writel(reg_base, CORE_INTR_SRC_CLEAR_REG, usbintr);
+
+ musb->int_usb =
+ (usbintr & AM35X_INTR_USB_MASK) >> AM35X_INTR_USB_SHIFT;
+ }
+#ifndef __UBOOT__
+ /*
+ * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+ * AM35x's missing ID change IRQ. We need an ID change IRQ to
+ * switch appropriately between halves of the OTG state machine.
+ * Managing DEVCTL.SESSION per Mentor docs requires that we know its
+ * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
+ * Also, DRVVBUS pulses for SRP (but not at 5V) ...
+ */
+ if (usbintr & (AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT)) {
+ int drvvbus = musb_readl(reg_base, USB_STAT_REG);
+ void __iomem *mregs = musb->mregs;
+ u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+ int err;
+
+ err = is_host_enabled(musb) && (musb->int_usb &
+ MUSB_INTR_VBUSERROR);
+ if (err) {
+ /*
+ * The Mentor core doesn't debounce VBUS as needed
+ * to cope with device connect current spikes. This
+ * means it's not uncommon for bus-powered devices
+ * to get VBUS errors during enumeration.
+ *
+ * This is a workaround, but newer RTL from Mentor
+ * seems to allow a better one: "re"-starting sessions
+ * without waiting for VBUS to stop registering in
+ * devctl.
+ */
+ musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+ WARNING("VBUS error workaround (delay coming)\n");
+ } else if (is_host_enabled(musb) && drvvbus) {
+ MUSB_HST_MODE(musb);
+ otg->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ portstate(musb->port1_status |= USB_PORT_STAT_POWER);
+ del_timer(&otg_workaround);
+ } else {
+ musb->is_active = 0;
+ MUSB_DEV_MODE(musb);
+ otg->default_a = 0;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
+ }
+
+ /* NOTE: this must complete power-on within 100 ms. */
+ dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
+ drvvbus ? "on" : "off",
+ otg_state_string(musb->xceiv->state),
+ err ? " ERROR" : "",
+ devctl);
+ ret = IRQ_HANDLED;
+ }
+#endif
+
+ if (musb->int_tx || musb->int_rx || musb->int_usb)
+ ret |= musb_interrupt(musb);
+
+eoi:
+ /* EOI needs to be written for the IRQ to be re-asserted. */
+ if (ret == IRQ_HANDLED || epintr || usbintr) {
+ /* clear level interrupt */
+ if (data->clear_irq)
+ data->clear_irq();
+ /* write EOI */
+ musb_writel(reg_base, USB_END_OF_INTR_REG, 0);
+ }
+
+#ifndef __UBOOT__
+ /* Poll for ID change */
+ if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+ mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
+#endif
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return ret;
+}
+
+#ifndef __UBOOT__
+static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode)
+{
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+ int retval = 0;
+
+ if (data->set_mode)
+ data->set_mode(musb_mode);
+ else
+ retval = -EIO;
+
+ return retval;
+}
+#endif
+
+static int am35x_musb_init(struct musb *musb)
+{
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+#else
+ struct omap_musb_board_data *data =
+ (struct omap_musb_board_data *)musb->controller;
+#endif
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 rev;
+
+ musb->mregs += USB_MENTOR_CORE_OFFSET;
+
+ /* Returns zero if e.g. not clocked */
+ rev = musb_readl(reg_base, USB_REVISION_REG);
+ if (!rev)
+ return -ENODEV;
+
+#ifndef __UBOOT__
+ usb_nop_xceiv_register();
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
+ return -ENODEV;
+
+ if (is_host_enabled(musb))
+ setup_timer(&otg_workaround, otg_timer, (unsigned long) musb);
+#endif
+
+ /* Reset the musb */
+ if (data->reset)
+ data->reset();
+
+ /* Reset the controller */
+ musb_writel(reg_base, USB_CTRL_REG, AM35X_SOFT_RESET_MASK);
+
+ /* Start the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(1);
+
+ msleep(5);
+
+ musb->isr = am35x_musb_interrupt;
+
+ /* clear level interrupt */
+ if (data->clear_irq)
+ data->clear_irq();
+
+ return 0;
+}
+
+static int am35x_musb_exit(struct musb *musb)
+{
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+#else
+ struct omap_musb_board_data *data =
+ (struct omap_musb_board_data *)musb->controller;
+#endif
+
+#ifndef __UBOOT__
+ if (is_host_enabled(musb))
+ del_timer_sync(&otg_workaround);
+#endif
+
+ /* Shutdown the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(0);
+
+#ifndef __UBOOT__
+ usb_put_phy(musb->xceiv);
+ usb_nop_xceiv_unregister();
+#endif
+
+ return 0;
+}
+
+/* AM35x supports only 32bit read operation */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+ void __iomem *fifo = hw_ep->fifo;
+ u32 val;
+ int i;
+
+ /* Read for 32bit-aligned destination address */
+ if (likely((0x03 & (unsigned long) dst) == 0) && len >= 4) {
+ readsl(fifo, dst, len >> 2);
+ dst += len & ~0x03;
+ len &= 0x03;
+ }
+ /*
+ * Now read the remaining 1 to 3 byte or complete length if
+ * unaligned address.
+ */
+ if (len > 4) {
+ for (i = 0; i < (len >> 2); i++) {
+ *(u32 *) dst = musb_readl(fifo, 0);
+ dst += 4;
+ }
+ len &= 0x03;
+ }
+ if (len > 0) {
+ val = musb_readl(fifo, 0);
+ memcpy(dst, &val, len);
+ }
+}
+
+#ifndef __UBOOT__
+static const struct musb_platform_ops am35x_ops = {
+#else
+const struct musb_platform_ops am35x_ops = {
+#endif
+ .init = am35x_musb_init,
+ .exit = am35x_musb_exit,
+
+ .enable = am35x_musb_enable,
+ .disable = am35x_musb_disable,
+
+#ifndef __UBOOT__
+ .set_mode = am35x_musb_set_mode,
+ .try_idle = am35x_musb_try_idle,
+
+ .set_vbus = am35x_musb_set_vbus,
+#endif
+};
+
+#ifndef __UBOOT__
+static u64 am35x_dmamask = DMA_BIT_MASK(32);
+
+static int __devinit am35x_probe(struct platform_device *pdev)
+{
+ struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
+ struct platform_device *musb;
+ struct am35x_glue *glue;
+
+ struct clk *phy_clk;
+ struct clk *clk;
+
+ int ret = -ENOMEM;
+
+ glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+ if (!glue) {
+ dev_err(&pdev->dev, "failed to allocate glue context\n");
+ goto err0;
+ }
+
+ musb = platform_device_alloc("musb-hdrc", -1);
+ if (!musb) {
+ dev_err(&pdev->dev, "failed to allocate musb device\n");
+ goto err1;
+ }
+
+ phy_clk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR(phy_clk)) {
+ dev_err(&pdev->dev, "failed to get PHY clock\n");
+ ret = PTR_ERR(phy_clk);
+ goto err2;
+ }
+
+ clk = clk_get(&pdev->dev, "ick");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "failed to get clock\n");
+ ret = PTR_ERR(clk);
+ goto err3;
+ }
+
+ ret = clk_enable(phy_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable PHY clock\n");
+ goto err4;
+ }
+
+ ret = clk_enable(clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable clock\n");
+ goto err5;
+ }
+
+ musb->dev.parent = &pdev->dev;
+ musb->dev.dma_mask = &am35x_dmamask;
+ musb->dev.coherent_dma_mask = am35x_dmamask;
+
+ glue->dev = &pdev->dev;
+ glue->musb = musb;
+ glue->phy_clk = phy_clk;
+ glue->clk = clk;
+
+ pdata->platform_ops = &am35x_ops;
+
+ platform_set_drvdata(pdev, glue);
+
+ ret = platform_device_add_resources(musb, pdev->resource,
+ pdev->num_resources);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add resources\n");
+ goto err6;
+ }
+
+ ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add platform_data\n");
+ goto err6;
+ }
+
+ ret = platform_device_add(musb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register musb device\n");
+ goto err6;
+ }
+
+ return 0;
+
+err6:
+ clk_disable(clk);
+
+err5:
+ clk_disable(phy_clk);
+
+err4:
+ clk_put(clk);
+
+err3:
+ clk_put(phy_clk);
+
+err2:
+ platform_device_put(musb);
+
+err1:
+ kfree(glue);
+
+err0:
+ return ret;
+}
+
+static int __devexit am35x_remove(struct platform_device *pdev)
+{
+ struct am35x_glue *glue = platform_get_drvdata(pdev);
+
+ platform_device_del(glue->musb);
+ platform_device_put(glue->musb);
+ clk_disable(glue->clk);
+ clk_disable(glue->phy_clk);
+ clk_put(glue->clk);
+ clk_put(glue->phy_clk);
+ kfree(glue);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int am35x_suspend(struct device *dev)
+{
+ struct am35x_glue *glue = dev_get_drvdata(dev);
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+
+ /* Shutdown the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(0);
+
+ clk_disable(glue->phy_clk);
+ clk_disable(glue->clk);
+
+ return 0;
+}
+
+static int am35x_resume(struct device *dev)
+{
+ struct am35x_glue *glue = dev_get_drvdata(dev);
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+ int ret;
+
+ /* Start the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(1);
+
+ ret = clk_enable(glue->phy_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable PHY clock\n");
+ return ret;
+ }
+
+ ret = clk_enable(glue->clk);
+ if (ret) {
+ dev_err(dev, "failed to enable clock\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct dev_pm_ops am35x_pm_ops = {
+ .suspend = am35x_suspend,
+ .resume = am35x_resume,
+};
+
+#define DEV_PM_OPS &am35x_pm_ops
+#else
+#define DEV_PM_OPS NULL
+#endif
+
+static struct platform_driver am35x_driver = {
+ .probe = am35x_probe,
+ .remove = __devexit_p(am35x_remove),
+ .driver = {
+ .name = "musb-am35x",
+ .pm = DEV_PM_OPS,
+ },
+};
+
+MODULE_DESCRIPTION("AM35x MUSB Glue Layer");
+MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init am35x_init(void)
+{
+ return platform_driver_register(&am35x_driver);
+}
+module_init(am35x_init);
+
+static void __exit am35x_exit(void)
+{
+ platform_driver_unregister(&am35x_driver);
+}
+module_exit(am35x_exit);
+#endif
diff --git a/drivers/usb/musb-new/linux-compat.h b/drivers/usb/musb-new/linux-compat.h
new file mode 100644
index 0000000000..5c126ef9cf
--- /dev/null
+++ b/drivers/usb/musb-new/linux-compat.h
@@ -0,0 +1,116 @@
+#ifndef __LINUX_COMPAT_H__
+#define __LINUX_COMPAT_H__
+
+#include <malloc.h>
+#include <linux/list.h>
+#include <linux/compat.h>
+
+#define __init
+#define __devinit
+#define __devinitdata
+#define __devinitconst
+#define __iomem
+#define __deprecated
+
+typedef enum { false = 0, true = 1 } bool;
+
+struct unused {};
+typedef struct unused unused_t;
+
+typedef int irqreturn_t;
+typedef unused_t spinlock_t;
+
+struct work_struct {};
+
+struct timer_list {};
+struct notifier_block {};
+
+typedef unsigned long dmaaddr_t;
+
+#define spin_lock_init(lock) do {} while (0)
+#define spin_lock(lock) do {} while (0)
+#define spin_unlock(lock) do {} while (0)
+#define spin_lock_irqsave(lock, flags) do {} while (0)
+#define spin_unlock_irqrestore(lock, flags) do {} while (0)
+
+#define setup_timer(timer, func, data) do {} while (0)
+#define del_timer_sync(timer) do {} while (0)
+#define schedule_work(work) do {} while (0)
+#define INIT_WORK(work, fun) do {} while (0)
+
+#define cpu_relax() do {} while (0)
+
+#define pr_debug(fmt, args...) debug(fmt, ##args)
+#define dev_dbg(dev, fmt, args...) \
+ debug(fmt, ##args)
+#define dev_vdbg(dev, fmt, args...) \
+ debug(fmt, ##args)
+#define dev_info(dev, fmt, args...) \
+ printf(fmt, ##args)
+#define dev_err(dev, fmt, args...) \
+ printf(fmt, ##args)
+#define printk printf
+
+#define WARN(condition, fmt, args...) ({ \
+ int ret_warn = !!condition; \
+ if (ret_warn) \
+ printf(fmt, ##args); \
+ ret_warn; })
+
+#define KERN_DEBUG
+#define KERN_NOTICE
+#define KERN_WARNING
+#define KERN_ERR
+
+#define kfree(ptr) free(ptr)
+
+#define pm_runtime_get_sync(dev) do {} while (0)
+#define pm_runtime_put(dev) do {} while (0)
+#define pm_runtime_put_sync(dev) do {} while (0)
+#define pm_runtime_use_autosuspend(dev) do {} while (0)
+#define pm_runtime_set_autosuspend_delay(dev, delay) do {} while (0)
+#define pm_runtime_enable(dev) do {} while (0)
+
+#define MODULE_DESCRIPTION(desc)
+#define MODULE_AUTHOR(author)
+#define MODULE_LICENSE(license)
+#define MODULE_ALIAS(alias)
+#define module_param(name, type, perm)
+#define MODULE_PARM_DESC(name, desc)
+#define EXPORT_SYMBOL_GPL(name)
+
+#define writesl(a, d, s) __raw_writesl((unsigned long)a, d, s)
+#define readsl(a, d, s) __raw_readsl((unsigned long)a, d, s)
+#define writesw(a, d, s) __raw_writesw((unsigned long)a, d, s)
+#define readsw(a, d, s) __raw_readsw((unsigned long)a, d, s)
+#define writesb(a, d, s) __raw_writesb((unsigned long)a, d, s)
+#define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s)
+
+#define IRQ_NONE 0
+#define IRQ_HANDLED 0
+
+#define dev_set_drvdata(dev, data) do {} while (0)
+
+#define disable_irq_wake(irq) do {} while (0)
+#define enable_irq_wake(irq) -EINVAL
+#define free_irq(irq, data) do {} while (0)
+#define request_irq(nr, f, flags, nm, data) 0
+
+#define device_init_wakeup(dev, a) do {} while (0)
+
+#define platform_data device_data
+
+#ifndef wmb
+#define wmb() asm volatile ("" : : : "memory")
+#endif
+
+#define msleep(a) udelay(a * 1000)
+
+/*
+ * Map U-Boot config options to Linux ones
+ */
+#ifdef CONFIG_OMAP34XX
+#define CONFIG_SOC_OMAP3430
+#endif
+
+#endif /* __LINUX_COMPAT_H__ */
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
new file mode 100644
index 0000000000..040a5c0f0f
--- /dev/null
+++ b/drivers/usb/musb-new/musb_core.c
@@ -0,0 +1,2497 @@
+/*
+ * MUSB OTG driver core code
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Inventra (Multipoint) Dual-Role Controller Driver for Linux.
+ *
+ * This consists of a Host Controller Driver (HCD) and a peripheral
+ * controller driver implementing the "Gadget" API; OTG support is
+ * in the works. These are normal Linux-USB controller drivers which
+ * use IRQs and have no dedicated thread.
+ *
+ * This version of the driver has only been used with products from
+ * Texas Instruments. Those products integrate the Inventra logic
+ * with other DMA, IRQ, and bus modules, as well as other logic that
+ * needs to be reflected in this driver.
+ *
+ *
+ * NOTE: the original Mentor code here was pretty much a collection
+ * of mechanisms that don't seem to have been fully integrated/working
+ * for *any* Linux kernel version. This version aims at Linux 2.6.now,
+ * Key open issues include:
+ *
+ * - Lack of host-side transaction scheduling, for all transfer types.
+ * The hardware doesn't do it; instead, software must.
+ *
+ * This is not an issue for OTG devices that don't support external
+ * hubs, but for more "normal" USB hosts it's a user issue that the
+ * "multipoint" support doesn't scale in the expected ways. That
+ * includes DaVinci EVM in a common non-OTG mode.
+ *
+ * * Control and bulk use dedicated endpoints, and there's as
+ * yet no mechanism to either (a) reclaim the hardware when
+ * peripherals are NAKing, which gets complicated with bulk
+ * endpoints, or (b) use more than a single bulk endpoint in
+ * each direction.
+ *
+ * RESULT: one device may be perceived as blocking another one.
+ *
+ * * Interrupt and isochronous will dynamically allocate endpoint
+ * hardware, but (a) there's no record keeping for bandwidth;
+ * (b) in the common case that few endpoints are available, there
+ * is no mechanism to reuse endpoints to talk to multiple devices.
+ *
+ * RESULT: At one extreme, bandwidth can be overcommitted in
+ * some hardware configurations, no faults will be reported.
+ * At the other extreme, the bandwidth capabilities which do
+ * exist tend to be severely undercommitted. You can't yet hook
+ * up both a keyboard and a mouse to an external USB hub.
+ */
+
+/*
+ * This gets many kinds of configuration information:
+ * - Kconfig for everything user-configurable
+ * - platform_device for addressing, irq, and platform_data
+ * - platform_data is mostly for board-specific informarion
+ * (plus recentrly, SOC or family details)
+ *
+ * Most of the conditional compilation will (someday) vanish.
+ */
+
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/prefetch.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#else
+#include <common.h>
+#include <usb.h>
+#include <asm/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/musb.h>
+#include <asm/io.h>
+#include "linux-compat.h"
+#include "usb-compat.h"
+#endif
+
+#include "musb_core.h"
+
+#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON)
+
+
+#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
+#define DRIVER_DESC "Inventra Dual-Role USB Controller Driver"
+
+#define MUSB_VERSION "6.0"
+
+#define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION
+
+#define MUSB_DRIVER_NAME "musb-hdrc"
+const char musb_driver_name[] = MUSB_DRIVER_NAME;
+
+MODULE_DESCRIPTION(DRIVER_INFO);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
+
+
+#ifndef __UBOOT__
+/*-------------------------------------------------------------------------*/
+
+static inline struct musb *dev_to_musb(struct device *dev)
+{
+ return dev_get_drvdata(dev);
+}
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#ifndef __UBOOT__
+#ifndef CONFIG_BLACKFIN
+static int musb_ulpi_read(struct usb_phy *phy, u32 offset)
+{
+ void __iomem *addr = phy->io_priv;
+ int i = 0;
+ u8 r;
+ u8 power;
+ int ret;
+
+ pm_runtime_get_sync(phy->io_dev);
+
+ /* Make sure the transceiver is not in low power mode */
+ power = musb_readb(addr, MUSB_POWER);
+ power &= ~MUSB_POWER_SUSPENDM;
+ musb_writeb(addr, MUSB_POWER, power);
+
+ /* REVISIT: musbhdrc_ulpi_an.pdf recommends setting the
+ * ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM.
+ */
+
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL,
+ MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR);
+
+ while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
+ & MUSB_ULPI_REG_CMPLT)) {
+ i++;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+
+ }
+ r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
+ r &= ~MUSB_ULPI_REG_CMPLT;
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
+
+ ret = musb_readb(addr, MUSB_ULPI_REG_DATA);
+
+out:
+ pm_runtime_put(phy->io_dev);
+
+ return ret;
+}
+
+static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
+{
+ void __iomem *addr = phy->io_priv;
+ int i = 0;
+ u8 r = 0;
+ u8 power;
+ int ret = 0;
+
+ pm_runtime_get_sync(phy->io_dev);
+
+ /* Make sure the transceiver is not in low power mode */
+ power = musb_readb(addr, MUSB_POWER);
+ power &= ~MUSB_POWER_SUSPENDM;
+ musb_writeb(addr, MUSB_POWER, power);
+
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+ musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data);
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ);
+
+ while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
+ & MUSB_ULPI_REG_CMPLT)) {
+ i++;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ }
+
+ r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
+ r &= ~MUSB_ULPI_REG_CMPLT;
+ musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
+
+out:
+ pm_runtime_put(phy->io_dev);
+
+ return ret;
+}
+#else
+#define musb_ulpi_read NULL
+#define musb_ulpi_write NULL
+#endif
+
+static struct usb_phy_io_ops musb_ulpi_access = {
+ .read = musb_ulpi_read,
+ .write = musb_ulpi_write,
+};
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#if !defined(CONFIG_USB_MUSB_TUSB6010) && !defined(CONFIG_USB_MUSB_BLACKFIN)
+
+/*
+ * Load an endpoint's FIFO
+ */
+void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
+{
+ struct musb *musb = hw_ep->musb;
+ void __iomem *fifo = hw_ep->fifo;
+
+ prefetch((u8 *)src);
+
+ dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n",
+ 'T', hw_ep->epnum, fifo, len, src);
+
+ /* we can't assume unaligned reads work */
+ if (likely((0x01 & (unsigned long) src) == 0)) {
+ u16 index = 0;
+
+ /* best case is 32bit-aligned source address */
+ if ((0x02 & (unsigned long) src) == 0) {
+ if (len >= 4) {
+ writesl(fifo, src + index, len >> 2);
+ index += len & ~0x03;
+ }
+ if (len & 0x02) {
+ musb_writew(fifo, 0, *(u16 *)&src[index]);
+ index += 2;
+ }
+ } else {
+ if (len >= 2) {
+ writesw(fifo, src + index, len >> 1);
+ index += len & ~0x01;
+ }
+ }
+ if (len & 0x01)
+ musb_writeb(fifo, 0, src[index]);
+ } else {
+ /* byte aligned */
+ writesb(fifo, src, len);
+ }
+}
+
+#if !defined(CONFIG_USB_MUSB_AM35X)
+/*
+ * Unload an endpoint's FIFO
+ */
+void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
+{
+ struct musb *musb = hw_ep->musb;
+ void __iomem *fifo = hw_ep->fifo;
+
+ dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n",
+ 'R', hw_ep->epnum, fifo, len, dst);
+
+ /* we can't assume unaligned writes work */
+ if (likely((0x01 & (unsigned long) dst) == 0)) {
+ u16 index = 0;
+
+ /* best case is 32bit-aligned destination address */
+ if ((0x02 & (unsigned long) dst) == 0) {
+ if (len >= 4) {
+ readsl(fifo, dst, len >> 2);
+ index = len & ~0x03;
+ }
+ if (len & 0x02) {
+ *(u16 *)&dst[index] = musb_readw(fifo, 0);
+ index += 2;
+ }
+ } else {
+ if (len >= 2) {
+ readsw(fifo, dst, len >> 1);
+ index = len & ~0x01;
+ }
+ }
+ if (len & 0x01)
+ dst[index] = musb_readb(fifo, 0);
+ } else {
+ /* byte aligned */
+ readsb(fifo, dst, len);
+ }
+}
+#endif
+
+#endif /* normal PIO */
+
+
+/*-------------------------------------------------------------------------*/
+
+/* for high speed test mode; see USB 2.0 spec 7.1.20 */
+static const u8 musb_test_packet[53] = {
+ /* implicit SYNC then DATA0 to start */
+
+ /* JKJKJKJK x9 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* JJKKJJKK x8 */
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ /* JJJJKKKK x8 */
+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
+ /* JJJJJJJKKKKKKK x8 */
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* JJJJJJJK x8 */
+ 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd,
+ /* JKKKKKKK x10, JK */
+ 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e
+
+ /* implicit CRC16 then EOP to end */
+};
+
+void musb_load_testpacket(struct musb *musb)
+{
+ void __iomem *regs = musb->endpoints[0].regs;
+
+ musb_ep_select(musb->mregs, 0);
+ musb_write_fifo(musb->control_ep,
+ sizeof(musb_test_packet), musb_test_packet);
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY);
+}
+
+#ifndef __UBOOT__
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Handles OTG hnp timeouts, such as b_ase0_brst
+ */
+void musb_otg_timer_func(unsigned long data)
+{
+ struct musb *musb = (struct musb *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ switch (musb->xceiv->state) {
+ case OTG_STATE_B_WAIT_ACON:
+ dev_dbg(musb->controller, "HNP: b_wait_acon timeout; back to b_peripheral\n");
+ musb_g_disconnect(musb);
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->is_active = 0;
+ break;
+ case OTG_STATE_A_SUSPEND:
+ case OTG_STATE_A_WAIT_BCON:
+ dev_dbg(musb->controller, "HNP: %s timeout\n",
+ otg_state_string(musb->xceiv->state));
+ musb_platform_set_vbus(musb, 0);
+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ break;
+ default:
+ dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
+ otg_state_string(musb->xceiv->state));
+ }
+ musb->ignore_disconnect = 0;
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+/*
+ * Stops the HNP transition. Caller must take care of locking.
+ */
+void musb_hnp_stop(struct musb *musb)
+{
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+ void __iomem *mbase = musb->mregs;
+ u8 reg;
+
+ dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_PERIPHERAL:
+ musb_g_disconnect(musb);
+ dev_dbg(musb->controller, "HNP: back to %s\n",
+ otg_state_string(musb->xceiv->state));
+ break;
+ case OTG_STATE_B_HOST:
+ dev_dbg(musb->controller, "HNP: Disabling HR\n");
+ hcd->self.is_b_host = 0;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ MUSB_DEV_MODE(musb);
+ reg = musb_readb(mbase, MUSB_POWER);
+ reg |= MUSB_POWER_SUSPENDM;
+ musb_writeb(mbase, MUSB_POWER, reg);
+ /* REVISIT: Start SESSION_REQUEST here? */
+ break;
+ default:
+ dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
+ otg_state_string(musb->xceiv->state));
+ }
+
+ /*
+ * When returning to A state after HNP, avoid hub_port_rebounce(),
+ * which cause occasional OPT A "Did not receive reset after connect"
+ * errors.
+ */
+ musb->port1_status &= ~(USB_PORT_STAT_C_CONNECTION << 16);
+}
+#endif
+
+/*
+ * Interrupt Service Routine to record USB "global" interrupts.
+ * Since these do not happen often and signify things of
+ * paramount importance, it seems OK to check them individually;
+ * the order of the tests is specified in the manual
+ *
+ * @param musb instance pointer
+ * @param int_usb register contents
+ * @param devctl
+ * @param power
+ */
+
+static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
+ u8 devctl, u8 power)
+{
+#ifndef __UBOOT__
+ struct usb_otg *otg = musb->xceiv->otg;
+#endif
+ irqreturn_t handled = IRQ_NONE;
+
+ dev_dbg(musb->controller, "<== Power=%02x, DevCtl=%02x, int_usb=0x%x\n", power, devctl,
+ int_usb);
+
+#ifndef __UBOOT__
+ /* in host mode, the peripheral may issue remote wakeup.
+ * in peripheral mode, the host may resume the link.
+ * spurious RESUME irqs happen too, paired with SUSPEND.
+ */
+ if (int_usb & MUSB_INTR_RESUME) {
+ handled = IRQ_HANDLED;
+ dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
+
+ if (devctl & MUSB_DEVCTL_HM) {
+ void __iomem *mbase = musb->mregs;
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_SUSPEND:
+ /* remote wakeup? later, GetPortStatus
+ * will stop RESUME signaling
+ */
+
+ if (power & MUSB_POWER_SUSPENDM) {
+ /* spurious */
+ musb->int_usb &= ~MUSB_INTR_SUSPEND;
+ dev_dbg(musb->controller, "Spurious SUSPENDM\n");
+ break;
+ }
+
+ power &= ~MUSB_POWER_SUSPENDM;
+ musb_writeb(mbase, MUSB_POWER,
+ power | MUSB_POWER_RESUME);
+
+ musb->port1_status |=
+ (USB_PORT_STAT_C_SUSPEND << 16)
+ | MUSB_PORT_STAT_RESUME;
+ musb->rh_timer = jiffies
+ + msecs_to_jiffies(20);
+
+ musb->xceiv->state = OTG_STATE_A_HOST;
+ musb->is_active = 1;
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->is_active = 1;
+ MUSB_DEV_MODE(musb);
+ break;
+ default:
+ WARNING("bogus %s RESUME (%s)\n",
+ "host",
+ otg_state_string(musb->xceiv->state));
+ }
+ } else {
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_SUSPEND:
+ /* possibly DISCONNECT is upcoming */
+ musb->xceiv->state = OTG_STATE_A_HOST;
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_PERIPHERAL:
+ /* disconnect while suspended? we may
+ * not get a disconnect irq...
+ */
+ if ((devctl & MUSB_DEVCTL_VBUS)
+ != (3 << MUSB_DEVCTL_VBUS_SHIFT)
+ ) {
+ musb->int_usb |= MUSB_INTR_DISCONNECT;
+ musb->int_usb &= ~MUSB_INTR_SUSPEND;
+ break;
+ }
+ musb_g_resume(musb);
+ break;
+ case OTG_STATE_B_IDLE:
+ musb->int_usb &= ~MUSB_INTR_SUSPEND;
+ break;
+ default:
+ WARNING("bogus %s RESUME (%s)\n",
+ "peripheral",
+ otg_state_string(musb->xceiv->state));
+ }
+ }
+ }
+
+ /* see manual for the order of the tests */
+ if (int_usb & MUSB_INTR_SESSREQ) {
+ void __iomem *mbase = musb->mregs;
+
+ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS
+ && (devctl & MUSB_DEVCTL_BDEVICE)) {
+ dev_dbg(musb->controller, "SessReq while on B state\n");
+ return IRQ_HANDLED;
+ }
+
+ dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
+ otg_state_string(musb->xceiv->state));
+
+ /* IRQ arrives from ID pin sense or (later, if VBUS power
+ * is removed) SRP. responses are time critical:
+ * - turn on VBUS (with silicon-specific mechanism)
+ * - go through A_WAIT_VRISE
+ * - ... to A_WAIT_BCON.
+ * a_wait_vrise_tmout triggers VBUS_ERROR transitions
+ */
+ musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
+ musb->ep0_stage = MUSB_EP0_START;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ musb_platform_set_vbus(musb, 1);
+
+ handled = IRQ_HANDLED;
+ }
+
+ if (int_usb & MUSB_INTR_VBUSERROR) {
+ int ignore = 0;
+
+ /* During connection as an A-Device, we may see a short
+ * current spikes causing voltage drop, because of cable
+ * and peripheral capacitance combined with vbus draw.
+ * (So: less common with truly self-powered devices, where
+ * vbus doesn't act like a power supply.)
+ *
+ * Such spikes are short; usually less than ~500 usec, max
+ * of ~2 msec. That is, they're not sustained overcurrent
+ * errors, though they're reported using VBUSERROR irqs.
+ *
+ * Workarounds: (a) hardware: use self powered devices.
+ * (b) software: ignore non-repeated VBUS errors.
+ *
+ * REVISIT: do delays from lots of DEBUG_KERNEL checks
+ * make trouble here, keeping VBUS < 4.4V ?
+ */
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_HOST:
+ /* recovery is dicey once we've gotten past the
+ * initial stages of enumeration, but if VBUS
+ * stayed ok at the other end of the link, and
+ * another reset is due (at least for high speed,
+ * to redo the chirp etc), it might work OK...
+ */
+ case OTG_STATE_A_WAIT_BCON:
+ case OTG_STATE_A_WAIT_VRISE:
+ if (musb->vbuserr_retry) {
+ void __iomem *mbase = musb->mregs;
+
+ musb->vbuserr_retry--;
+ ignore = 1;
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(mbase, MUSB_DEVCTL, devctl);
+ } else {
+ musb->port1_status |=
+ USB_PORT_STAT_OVERCURRENT
+ | (USB_PORT_STAT_C_OVERCURRENT << 16);
+ }
+ break;
+ default:
+ break;
+ }
+
+ dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
+ otg_state_string(musb->xceiv->state),
+ devctl,
+ ({ char *s;
+ switch (devctl & MUSB_DEVCTL_VBUS) {
+ case 0 << MUSB_DEVCTL_VBUS_SHIFT:
+ s = "<SessEnd"; break;
+ case 1 << MUSB_DEVCTL_VBUS_SHIFT:
+ s = "<AValid"; break;
+ case 2 << MUSB_DEVCTL_VBUS_SHIFT:
+ s = "<VBusValid"; break;
+ /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */
+ default:
+ s = "VALID"; break;
+ }; s; }),
+ VBUSERR_RETRY_COUNT - musb->vbuserr_retry,
+ musb->port1_status);
+
+ /* go through A_WAIT_VFALL then start a new session */
+ if (!ignore)
+ musb_platform_set_vbus(musb, 0);
+ handled = IRQ_HANDLED;
+ }
+
+ if (int_usb & MUSB_INTR_SUSPEND) {
+ dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x power %02x\n",
+ otg_state_string(musb->xceiv->state), devctl, power);
+ handled = IRQ_HANDLED;
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_PERIPHERAL:
+ /* We also come here if the cable is removed, since
+ * this silicon doesn't report ID-no-longer-grounded.
+ *
+ * We depend on T(a_wait_bcon) to shut us down, and
+ * hope users don't do anything dicey during this
+ * undesired detour through A_WAIT_BCON.
+ */
+ musb_hnp_stop(musb);
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ musb_root_disconnect(musb);
+ musb_platform_try_idle(musb, jiffies
+ + msecs_to_jiffies(musb->a_wait_bcon
+ ? : OTG_TIME_A_WAIT_BCON));
+
+ break;
+ case OTG_STATE_B_IDLE:
+ if (!musb->is_active)
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ musb_g_suspend(musb);
+ musb->is_active = is_otg_enabled(musb)
+ && otg->gadget->b_hnp_enable;
+ if (musb->is_active) {
+ musb->xceiv->state = OTG_STATE_B_WAIT_ACON;
+ dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n");
+ mod_timer(&musb->otg_timer, jiffies
+ + msecs_to_jiffies(
+ OTG_TIME_B_ASE0_BRST));
+ }
+ break;
+ case OTG_STATE_A_WAIT_BCON:
+ if (musb->a_wait_bcon != 0)
+ musb_platform_try_idle(musb, jiffies
+ + msecs_to_jiffies(musb->a_wait_bcon));
+ break;
+ case OTG_STATE_A_HOST:
+ musb->xceiv->state = OTG_STATE_A_SUSPEND;
+ musb->is_active = is_otg_enabled(musb)
+ && otg->host->b_hnp_enable;
+ break;
+ case OTG_STATE_B_HOST:
+ /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */
+ dev_dbg(musb->controller, "REVISIT: SUSPEND as B_HOST\n");
+ break;
+ default:
+ /* "should not happen" */
+ musb->is_active = 0;
+ break;
+ }
+ }
+#endif
+
+ if (int_usb & MUSB_INTR_CONNECT) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+
+ handled = IRQ_HANDLED;
+ musb->is_active = 1;
+
+ musb->ep0_stage = MUSB_EP0_START;
+
+ /* flush endpoints when transitioning from Device Mode */
+ if (is_peripheral_active(musb)) {
+ /* REVISIT HNP; just force disconnect */
+ }
+ musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
+ musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+ musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
+#ifndef __UBOOT__
+ musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED
+ |USB_PORT_STAT_HIGH_SPEED
+ |USB_PORT_STAT_ENABLE
+ );
+ musb->port1_status |= USB_PORT_STAT_CONNECTION
+ |(USB_PORT_STAT_C_CONNECTION << 16);
+
+ /* high vs full speed is just a guess until after reset */
+ if (devctl & MUSB_DEVCTL_LSDEV)
+ musb->port1_status |= USB_PORT_STAT_LOW_SPEED;
+
+ /* indicate new connection to OTG machine */
+ switch (musb->xceiv->state) {
+ case OTG_STATE_B_PERIPHERAL:
+ if (int_usb & MUSB_INTR_SUSPEND) {
+ dev_dbg(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n");
+ int_usb &= ~MUSB_INTR_SUSPEND;
+ goto b_host;
+ } else
+ dev_dbg(musb->controller, "CONNECT as b_peripheral???\n");
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n");
+b_host:
+ musb->xceiv->state = OTG_STATE_B_HOST;
+ hcd->self.is_b_host = 1;
+ musb->ignore_disconnect = 0;
+ del_timer(&musb->otg_timer);
+ break;
+ default:
+ if ((devctl & MUSB_DEVCTL_VBUS)
+ == (3 << MUSB_DEVCTL_VBUS_SHIFT)) {
+ musb->xceiv->state = OTG_STATE_A_HOST;
+ hcd->self.is_b_host = 0;
+ }
+ break;
+ }
+
+ /* poke the root hub */
+ MUSB_HST_MODE(musb);
+ if (hcd->status_urb)
+ usb_hcd_poll_rh_status(hcd);
+ else
+ usb_hcd_resume_root_hub(hcd);
+
+ dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
+ otg_state_string(musb->xceiv->state), devctl);
+#endif
+ }
+
+#ifndef __UBOOT__
+ if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
+ dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
+ otg_state_string(musb->xceiv->state),
+ MUSB_MODE(musb), devctl);
+ handled = IRQ_HANDLED;
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_HOST:
+ case OTG_STATE_A_SUSPEND:
+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
+ musb_root_disconnect(musb);
+ if (musb->a_wait_bcon != 0 && is_otg_enabled(musb))
+ musb_platform_try_idle(musb, jiffies
+ + msecs_to_jiffies(musb->a_wait_bcon));
+ break;
+ case OTG_STATE_B_HOST:
+ /* REVISIT this behaves for "real disconnect"
+ * cases; make sure the other transitions from
+ * from B_HOST act right too. The B_HOST code
+ * in hnp_stop() is currently not used...
+ */
+ musb_root_disconnect(musb);
+ musb_to_hcd(musb)->self.is_b_host = 0;
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ MUSB_DEV_MODE(musb);
+ musb_g_disconnect(musb);
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ musb_hnp_stop(musb);
+ musb_root_disconnect(musb);
+ /* FALLTHROUGH */
+ case OTG_STATE_B_WAIT_ACON:
+ /* FALLTHROUGH */
+ case OTG_STATE_B_PERIPHERAL:
+ case OTG_STATE_B_IDLE:
+ musb_g_disconnect(musb);
+ break;
+ default:
+ WARNING("unhandled DISCONNECT transition (%s)\n",
+ otg_state_string(musb->xceiv->state));
+ break;
+ }
+ }
+
+ /* mentor saves a bit: bus reset and babble share the same irq.
+ * only host sees babble; only peripheral sees bus reset.
+ */
+ if (int_usb & MUSB_INTR_RESET) {
+ handled = IRQ_HANDLED;
+ if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) {
+ /*
+ * Looks like non-HS BABBLE can be ignored, but
+ * HS BABBLE is an error condition. For HS the solution
+ * is to avoid babble in the first place and fix what
+ * caused BABBLE. When HS BABBLE happens we can only
+ * stop the session.
+ */
+ if (devctl & (MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV))
+ dev_dbg(musb->controller, "BABBLE devctl: %02x\n", devctl);
+ else {
+ ERR("Stopping host session -- babble\n");
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ }
+ } else if (is_peripheral_capable()) {
+ dev_dbg(musb->controller, "BUS RESET as %s\n",
+ otg_state_string(musb->xceiv->state));
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_SUSPEND:
+ /* We need to ignore disconnect on suspend
+ * otherwise tusb 2.0 won't reconnect after a
+ * power cycle, which breaks otg compliance.
+ */
+ musb->ignore_disconnect = 1;
+ musb_g_reset(musb);
+ /* FALLTHROUGH */
+ case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */
+ /* never use invalid T(a_wait_bcon) */
+ dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
+ otg_state_string(musb->xceiv->state),
+ TA_WAIT_BCON(musb));
+ mod_timer(&musb->otg_timer, jiffies
+ + msecs_to_jiffies(TA_WAIT_BCON(musb)));
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ musb->ignore_disconnect = 0;
+ del_timer(&musb->otg_timer);
+ musb_g_reset(musb);
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
+ otg_state_string(musb->xceiv->state));
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb_g_reset(musb);
+ break;
+ case OTG_STATE_B_IDLE:
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ /* FALLTHROUGH */
+ case OTG_STATE_B_PERIPHERAL:
+ musb_g_reset(musb);
+ break;
+ default:
+ dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
+ otg_state_string(musb->xceiv->state));
+ }
+ }
+ }
+#endif
+
+#if 0
+/* REVISIT ... this would be for multiplexing periodic endpoints, or
+ * supporting transfer phasing to prevent exceeding ISO bandwidth
+ * limits of a given frame or microframe.
+ *
+ * It's not needed for peripheral side, which dedicates endpoints;
+ * though it _might_ use SOF irqs for other purposes.
+ *
+ * And it's not currently needed for host side, which also dedicates
+ * endpoints, relies on TX/RX interval registers, and isn't claimed
+ * to support ISO transfers yet.
+ */
+ if (int_usb & MUSB_INTR_SOF) {
+ void __iomem *mbase = musb->mregs;
+ struct musb_hw_ep *ep;
+ u8 epnum;
+ u16 frame;
+
+ dev_dbg(musb->controller, "START_OF_FRAME\n");
+ handled = IRQ_HANDLED;
+
+ /* start any periodic Tx transfers waiting for current frame */
+ frame = musb_readw(mbase, MUSB_FRAME);
+ ep = musb->endpoints;
+ for (epnum = 1; (epnum < musb->nr_endpoints)
+ && (musb->epmask >= (1 << epnum));
+ epnum++, ep++) {
+ /*
+ * FIXME handle framecounter wraps (12 bits)
+ * eliminate duplicated StartUrb logic
+ */
+ if (ep->dwWaitFrame >= frame) {
+ ep->dwWaitFrame = 0;
+ pr_debug("SOF --> periodic TX%s on %d\n",
+ ep->tx_channel ? " DMA" : "",
+ epnum);
+ if (!ep->tx_channel)
+ musb_h_tx_start(musb, epnum);
+ else
+ cppi_hostdma_start(musb, epnum);
+ }
+ } /* end of for loop */
+ }
+#endif
+
+ schedule_work(&musb->irq_work);
+
+ return handled;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+* Program the HDRC to start (enable interrupts, dma, etc.).
+*/
+void musb_start(struct musb *musb)
+{
+ void __iomem *regs = musb->mregs;
+ u8 devctl = musb_readb(regs, MUSB_DEVCTL);
+
+ dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
+
+ /* Set INT enable registers, enable interrupts */
+ musb_writew(regs, MUSB_INTRTXE, musb->epmask);
+ musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe);
+ musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
+
+ musb_writeb(regs, MUSB_TESTMODE, 0);
+
+ /* put into basic highspeed mode and start session */
+ musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
+ | MUSB_POWER_HSENAB
+ /* ENSUSPEND wedges tusb */
+ /* | MUSB_POWER_ENSUSPEND */
+ );
+
+ musb->is_active = 0;
+ devctl = musb_readb(regs, MUSB_DEVCTL);
+ devctl &= ~MUSB_DEVCTL_SESSION;
+
+ if (is_otg_enabled(musb)) {
+#ifndef __UBOOT__
+ /* session started after:
+ * (a) ID-grounded irq, host mode;
+ * (b) vbus present/connect IRQ, peripheral mode;
+ * (c) peripheral initiates, using SRP
+ */
+ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+ musb->is_active = 1;
+ else
+ devctl |= MUSB_DEVCTL_SESSION;
+#endif
+
+ } else if (is_host_enabled(musb)) {
+ /* assume ID pin is hard-wired to ground */
+ devctl |= MUSB_DEVCTL_SESSION;
+
+ } else /* peripheral is enabled */ {
+ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+ musb->is_active = 1;
+ }
+ musb_platform_enable(musb);
+ musb_writeb(regs, MUSB_DEVCTL, devctl);
+}
+
+
+static void musb_generic_disable(struct musb *musb)
+{
+ void __iomem *mbase = musb->mregs;
+ u16 temp;
+
+ /* disable interrupts */
+ musb_writeb(mbase, MUSB_INTRUSBE, 0);
+ musb_writew(mbase, MUSB_INTRTXE, 0);
+ musb_writew(mbase, MUSB_INTRRXE, 0);
+
+ /* off */
+ musb_writeb(mbase, MUSB_DEVCTL, 0);
+
+ /* flush pending interrupts */
+ temp = musb_readb(mbase, MUSB_INTRUSB);
+ temp = musb_readw(mbase, MUSB_INTRTX);
+ temp = musb_readw(mbase, MUSB_INTRRX);
+
+}
+
+/*
+ * Make the HDRC stop (disable interrupts, etc.);
+ * reversible by musb_start
+ * called on gadget driver unregister
+ * with controller locked, irqs blocked
+ * acts as a NOP unless some role activated the hardware
+ */
+void musb_stop(struct musb *musb)
+{
+ /* stop IRQs, timers, ... */
+ musb_platform_disable(musb);
+ musb_generic_disable(musb);
+ dev_dbg(musb->controller, "HDRC disabled\n");
+
+ /* FIXME
+ * - mark host and/or peripheral drivers unusable/inactive
+ * - disable DMA (and enable it in HdrcStart)
+ * - make sure we can musb_start() after musb_stop(); with
+ * OTG mode, gadget driver module rmmod/modprobe cycles that
+ * - ...
+ */
+ musb_platform_try_idle(musb, 0);
+}
+
+#ifndef __UBOOT__
+static void musb_shutdown(struct platform_device *pdev)
+{
+ struct musb *musb = dev_to_musb(&pdev->dev);
+ unsigned long flags;
+
+ pm_runtime_get_sync(musb->controller);
+
+ musb_gadget_cleanup(musb);
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb_platform_disable(musb);
+ musb_generic_disable(musb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ if (!is_otg_enabled(musb) && is_host_enabled(musb))
+ usb_remove_hcd(musb_to_hcd(musb));
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ musb_platform_exit(musb);
+
+ pm_runtime_put(musb->controller);
+ /* FIXME power down */
+}
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * The silicon either has hard-wired endpoint configurations, or else
+ * "dynamic fifo" sizing. The driver has support for both, though at this
+ * writing only the dynamic sizing is very well tested. Since we switched
+ * away from compile-time hardware parameters, we can no longer rely on
+ * dead code elimination to leave only the relevant one in the object file.
+ *
+ * We don't currently use dynamic fifo setup capability to do anything
+ * more than selecting one of a bunch of predefined configurations.
+ */
+#if defined(CONFIG_USB_MUSB_TUSB6010) \
+ || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) \
+ || defined(CONFIG_USB_MUSB_OMAP2PLUS) \
+ || defined(CONFIG_USB_MUSB_OMAP2PLUS_MODULE) \
+ || defined(CONFIG_USB_MUSB_AM35X) \
+ || defined(CONFIG_USB_MUSB_AM35X_MODULE) \
+ || defined(CONFIG_USB_MUSB_DSPS) \
+ || defined(CONFIG_USB_MUSB_DSPS_MODULE)
+static ushort __devinitdata fifo_mode = 4;
+#elif defined(CONFIG_USB_MUSB_UX500) \
+ || defined(CONFIG_USB_MUSB_UX500_MODULE)
+static ushort __devinitdata fifo_mode = 5;
+#else
+static ushort __devinitdata fifo_mode = 2;
+#endif
+
+/* "modprobe ... fifo_mode=1" etc */
+module_param(fifo_mode, ushort, 0);
+MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration");
+
+/*
+ * tables defining fifo_mode values. define more if you like.
+ * for host side, make sure both halves of ep1 are set up.
+ */
+
+/* mode 0 - fits in 2KB */
+static struct musb_fifo_cfg __devinitdata mode_0_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 1 - fits in 4KB */
+static struct musb_fifo_cfg __devinitdata mode_1_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 2, .style = FIFO_RXTX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 2 - fits in 4KB */
+static struct musb_fifo_cfg __devinitdata mode_2_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 3 - fits in 4KB */
+static struct musb_fifo_cfg __devinitdata mode_3_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, .mode = BUF_DOUBLE, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, },
+{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, },
+};
+
+/* mode 4 - fits in 16KB */
+static struct musb_fifo_cfg __devinitdata mode_4_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, },
+{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, },
+{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, },
+{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, },
+{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, },
+{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, },
+{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, },
+{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
+{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
+};
+
+/* mode 5 - fits in 8KB */
+static struct musb_fifo_cfg __devinitdata mode_5_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 6, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 6, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 7, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 7, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 8, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 32, },
+{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 32, },
+{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 512, },
+{ .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, },
+{ .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, },
+};
+
+/*
+ * configure a fifo; for non-shared endpoints, this may be called
+ * once for a tx fifo and once for an rx fifo.
+ *
+ * returns negative errno or offset for next fifo.
+ */
+static int __devinit
+fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
+ const struct musb_fifo_cfg *cfg, u16 offset)
+{
+ void __iomem *mbase = musb->mregs;
+ int size = 0;
+ u16 maxpacket = cfg->maxpacket;
+ u16 c_off = offset >> 3;
+ u8 c_size;
+
+ /* expect hw_ep has already been zero-initialized */
+
+ size = ffs(max(maxpacket, (u16) 8)) - 1;
+ maxpacket = 1 << size;
+
+ c_size = size - 3;
+ if (cfg->mode == BUF_DOUBLE) {
+ if ((offset + (maxpacket << 1)) >
+ (1 << (musb->config->ram_bits + 2)))
+ return -EMSGSIZE;
+ c_size |= MUSB_FIFOSZ_DPB;
+ } else {
+ if ((offset + maxpacket) > (1 << (musb->config->ram_bits + 2)))
+ return -EMSGSIZE;
+ }
+
+ /* configure the FIFO */
+ musb_writeb(mbase, MUSB_INDEX, hw_ep->epnum);
+
+ /* EP0 reserved endpoint for control, bidirectional;
+ * EP1 reserved for bulk, two unidirection halves.
+ */
+ if (hw_ep->epnum == 1)
+ musb->bulk_ep = hw_ep;
+ /* REVISIT error check: be sure ep0 can both rx and tx ... */
+ switch (cfg->style) {
+ case FIFO_TX:
+ musb_write_txfifosz(mbase, c_size);
+ musb_write_txfifoadd(mbase, c_off);
+ hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+ hw_ep->max_packet_sz_tx = maxpacket;
+ break;
+ case FIFO_RX:
+ musb_write_rxfifosz(mbase, c_size);
+ musb_write_rxfifoadd(mbase, c_off);
+ hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+ hw_ep->max_packet_sz_rx = maxpacket;
+ break;
+ case FIFO_RXTX:
+ musb_write_txfifosz(mbase, c_size);
+ musb_write_txfifoadd(mbase, c_off);
+ hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB);
+ hw_ep->max_packet_sz_rx = maxpacket;
+
+ musb_write_rxfifosz(mbase, c_size);
+ musb_write_rxfifoadd(mbase, c_off);
+ hw_ep->tx_double_buffered = hw_ep->rx_double_buffered;
+ hw_ep->max_packet_sz_tx = maxpacket;
+
+ hw_ep->is_shared_fifo = true;
+ break;
+ }
+
+ /* NOTE rx and tx endpoint irqs aren't managed separately,
+ * which happens to be ok
+ */
+ musb->epmask |= (1 << hw_ep->epnum);
+
+ return offset + (maxpacket << ((c_size & MUSB_FIFOSZ_DPB) ? 1 : 0));
+}
+
+static struct musb_fifo_cfg __devinitdata ep0_cfg = {
+ .style = FIFO_RXTX, .maxpacket = 64,
+};
+
+static int __devinit ep_config_from_table(struct musb *musb)
+{
+ const struct musb_fifo_cfg *cfg;
+ unsigned i, n;
+ int offset;
+ struct musb_hw_ep *hw_ep = musb->endpoints;
+
+ if (musb->config->fifo_cfg) {
+ cfg = musb->config->fifo_cfg;
+ n = musb->config->fifo_cfg_size;
+ goto done;
+ }
+
+ switch (fifo_mode) {
+ default:
+ fifo_mode = 0;
+ /* FALLTHROUGH */
+ case 0:
+ cfg = mode_0_cfg;
+ n = ARRAY_SIZE(mode_0_cfg);
+ break;
+ case 1:
+ cfg = mode_1_cfg;
+ n = ARRAY_SIZE(mode_1_cfg);
+ break;
+ case 2:
+ cfg = mode_2_cfg;
+ n = ARRAY_SIZE(mode_2_cfg);
+ break;
+ case 3:
+ cfg = mode_3_cfg;
+ n = ARRAY_SIZE(mode_3_cfg);
+ break;
+ case 4:
+ cfg = mode_4_cfg;
+ n = ARRAY_SIZE(mode_4_cfg);
+ break;
+ case 5:
+ cfg = mode_5_cfg;
+ n = ARRAY_SIZE(mode_5_cfg);
+ break;
+ }
+
+ printk(KERN_DEBUG "%s: setup fifo_mode %d\n",
+ musb_driver_name, fifo_mode);
+
+
+done:
+ offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);
+ /* assert(offset > 0) */
+
+ /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would
+ * be better than static musb->config->num_eps and DYN_FIFO_SIZE...
+ */
+
+ for (i = 0; i < n; i++) {
+ u8 epn = cfg->hw_ep_num;
+
+ if (epn >= musb->config->num_eps) {
+ pr_debug("%s: invalid ep %d\n",
+ musb_driver_name, epn);
+ return -EINVAL;
+ }
+ offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);
+ if (offset < 0) {
+ pr_debug("%s: mem overrun, ep %d\n",
+ musb_driver_name, epn);
+ return -EINVAL;
+ }
+ epn++;
+ musb->nr_endpoints = max(epn, musb->nr_endpoints);
+ }
+
+ printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n",
+ musb_driver_name,
+ n + 1, musb->config->num_eps * 2 - 1,
+ offset, (1 << (musb->config->ram_bits + 2)));
+
+ if (!musb->bulk_ep) {
+ pr_debug("%s: missing bulk\n", musb_driver_name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/*
+ * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false
+ * @param musb the controller
+ */
+static int __devinit ep_config_from_hw(struct musb *musb)
+{
+ u8 epnum = 0;
+ struct musb_hw_ep *hw_ep;
+ void *mbase = musb->mregs;
+ int ret = 0;
+
+ dev_dbg(musb->controller, "<== static silicon ep config\n");
+
+ /* FIXME pick up ep0 maxpacket size */
+
+ for (epnum = 1; epnum < musb->config->num_eps; epnum++) {
+ musb_ep_select(mbase, epnum);
+ hw_ep = musb->endpoints + epnum;
+
+ ret = musb_read_fifosize(musb, hw_ep, epnum);
+ if (ret < 0)
+ break;
+
+ /* FIXME set up hw_ep->{rx,tx}_double_buffered */
+
+ /* pick an RX/TX endpoint for bulk */
+ if (hw_ep->max_packet_sz_tx < 512
+ || hw_ep->max_packet_sz_rx < 512)
+ continue;
+
+ /* REVISIT: this algorithm is lazy, we should at least
+ * try to pick a double buffered endpoint.
+ */
+ if (musb->bulk_ep)
+ continue;
+ musb->bulk_ep = hw_ep;
+ }
+
+ if (!musb->bulk_ep) {
+ pr_debug("%s: missing bulk\n", musb_driver_name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };
+
+/* Initialize MUSB (M)HDRC part of the USB hardware subsystem;
+ * configure endpoints, or take their config from silicon
+ */
+static int __devinit musb_core_init(u16 musb_type, struct musb *musb)
+{
+ u8 reg;
+ char *type;
+ char aInfo[90], aRevision[32], aDate[12];
+ void __iomem *mbase = musb->mregs;
+ int status = 0;
+ int i;
+
+ /* log core options (read using indexed model) */
+ reg = musb_read_configdata(mbase);
+
+ strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");
+ if (reg & MUSB_CONFIGDATA_DYNFIFO) {
+ strcat(aInfo, ", dyn FIFOs");
+ musb->dyn_fifo = true;
+ }
+ if (reg & MUSB_CONFIGDATA_MPRXE) {
+ strcat(aInfo, ", bulk combine");
+ musb->bulk_combine = true;
+ }
+ if (reg & MUSB_CONFIGDATA_MPTXE) {
+ strcat(aInfo, ", bulk split");
+ musb->bulk_split = true;
+ }
+ if (reg & MUSB_CONFIGDATA_HBRXE) {
+ strcat(aInfo, ", HB-ISO Rx");
+ musb->hb_iso_rx = true;
+ }
+ if (reg & MUSB_CONFIGDATA_HBTXE) {
+ strcat(aInfo, ", HB-ISO Tx");
+ musb->hb_iso_tx = true;
+ }
+ if (reg & MUSB_CONFIGDATA_SOFTCONE)
+ strcat(aInfo, ", SoftConn");
+
+ printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n",
+ musb_driver_name, reg, aInfo);
+
+ aDate[0] = 0;
+ if (MUSB_CONTROLLER_MHDRC == musb_type) {
+ musb->is_multipoint = 1;
+ type = "M";
+ } else {
+ musb->is_multipoint = 0;
+ type = "";
+#ifndef CONFIG_USB_OTG_BLACKLIST_HUB
+ printk(KERN_ERR
+ "%s: kernel must blacklist external hubs\n",
+ musb_driver_name);
+#endif
+ }
+
+ /* log release info */
+ musb->hwvers = musb_read_hwvers(mbase);
+ snprintf(aRevision, 32, "%d.%d%s", MUSB_HWVERS_MAJOR(musb->hwvers),
+ MUSB_HWVERS_MINOR(musb->hwvers),
+ (musb->hwvers & MUSB_HWVERS_RC) ? "RC" : "");
+ printk(KERN_DEBUG "%s: %sHDRC RTL version %s %s\n",
+ musb_driver_name, type, aRevision, aDate);
+
+ /* configure ep0 */
+ musb_configure_ep0(musb);
+
+ /* discover endpoint configuration */
+ musb->nr_endpoints = 1;
+ musb->epmask = 1;
+
+ if (musb->dyn_fifo)
+ status = ep_config_from_table(musb);
+ else
+ status = ep_config_from_hw(musb);
+
+ if (status < 0)
+ return status;
+
+ /* finish init, and print endpoint config */
+ for (i = 0; i < musb->nr_endpoints; i++) {
+ struct musb_hw_ep *hw_ep = musb->endpoints + i;
+
+ hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase;
+#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE)
+ hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i);
+ hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i);
+ hw_ep->fifo_sync_va =
+ musb->sync_va + 0x400 + MUSB_FIFO_OFFSET(i);
+
+ if (i == 0)
+ hw_ep->conf = mbase - 0x400 + TUSB_EP0_CONF;
+ else
+ hw_ep->conf = mbase + 0x400 + (((i - 1) & 0xf) << 2);
+#endif
+
+ hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase;
+ hw_ep->target_regs = musb_read_target_reg_base(i, mbase);
+ hw_ep->rx_reinit = 1;
+ hw_ep->tx_reinit = 1;
+
+ if (hw_ep->max_packet_sz_tx) {
+ dev_dbg(musb->controller,
+ "%s: hw_ep %d%s, %smax %d\n",
+ musb_driver_name, i,
+ hw_ep->is_shared_fifo ? "shared" : "tx",
+ hw_ep->tx_double_buffered
+ ? "doublebuffer, " : "",
+ hw_ep->max_packet_sz_tx);
+ }
+ if (hw_ep->max_packet_sz_rx && !hw_ep->is_shared_fifo) {
+ dev_dbg(musb->controller,
+ "%s: hw_ep %d%s, %smax %d\n",
+ musb_driver_name, i,
+ "rx",
+ hw_ep->rx_double_buffered
+ ? "doublebuffer, " : "",
+ hw_ep->max_packet_sz_rx);
+ }
+ if (!(hw_ep->max_packet_sz_tx || hw_ep->max_packet_sz_rx))
+ dev_dbg(musb->controller, "hw_ep %d not configured\n", i);
+ }
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
+ defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
+
+static irqreturn_t generic_interrupt(int irq, void *__hci)
+{
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+ struct musb *musb = __hci;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+ if (musb->int_usb || musb->int_tx || musb->int_rx)
+ retval = musb_interrupt(musb);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return retval;
+}
+
+#else
+#define generic_interrupt NULL
+#endif
+
+/*
+ * handle all the irqs defined by the HDRC core. for now we expect: other
+ * irq sources (phy, dma, etc) will be handled first, musb->int_* values
+ * will be assigned, and the irq will already have been acked.
+ *
+ * called in irq context with spinlock held, irqs blocked
+ */
+irqreturn_t musb_interrupt(struct musb *musb)
+{
+ irqreturn_t retval = IRQ_NONE;
+ u8 devctl, power;
+ int ep_num;
+ u32 reg;
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ power = musb_readb(musb->mregs, MUSB_POWER);
+
+ dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n",
+ (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
+ musb->int_usb, musb->int_tx, musb->int_rx);
+
+ /* the core can interrupt us for multiple reasons; docs have
+ * a generic interrupt flowchart to follow
+ */
+ if (musb->int_usb)
+ retval |= musb_stage0_irq(musb, musb->int_usb,
+ devctl, power);
+
+ /* "stage 1" is handling endpoint irqs */
+
+ /* handle endpoint 0 first */
+ if (musb->int_tx & 1) {
+ if (devctl & MUSB_DEVCTL_HM) {
+ if (is_host_capable())
+ retval |= musb_h_ep0_irq(musb);
+ } else {
+ if (is_peripheral_capable())
+ retval |= musb_g_ep0_irq(musb);
+ }
+ }
+
+ /* RX on endpoints 1-15 */
+ reg = musb->int_rx >> 1;
+ ep_num = 1;
+ while (reg) {
+ if (reg & 1) {
+ /* musb_ep_select(musb->mregs, ep_num); */
+ /* REVISIT just retval = ep->rx_irq(...) */
+ retval = IRQ_HANDLED;
+ if (devctl & MUSB_DEVCTL_HM) {
+ if (is_host_capable())
+ musb_host_rx(musb, ep_num);
+ } else {
+ if (is_peripheral_capable())
+ musb_g_rx(musb, ep_num);
+ }
+ }
+
+ reg >>= 1;
+ ep_num++;
+ }
+
+ /* TX on endpoints 1-15 */
+ reg = musb->int_tx >> 1;
+ ep_num = 1;
+ while (reg) {
+ if (reg & 1) {
+ /* musb_ep_select(musb->mregs, ep_num); */
+ /* REVISIT just retval |= ep->tx_irq(...) */
+ retval = IRQ_HANDLED;
+ if (devctl & MUSB_DEVCTL_HM) {
+ if (is_host_capable())
+ musb_host_tx(musb, ep_num);
+ } else {
+ if (is_peripheral_capable())
+ musb_g_tx(musb, ep_num);
+ }
+ }
+ reg >>= 1;
+ ep_num++;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL_GPL(musb_interrupt);
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+static bool __devinitdata use_dma = 1;
+
+/* "modprobe ... use_dma=0" etc */
+module_param(use_dma, bool, 0);
+MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
+
+void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit)
+{
+ u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+ /* called with controller lock already held */
+
+ if (!epnum) {
+#ifndef CONFIG_USB_TUSB_OMAP_DMA
+ if (!is_cppi_enabled()) {
+ /* endpoint 0 */
+ if (devctl & MUSB_DEVCTL_HM)
+ musb_h_ep0_irq(musb);
+ else
+ musb_g_ep0_irq(musb);
+ }
+#endif
+ } else {
+ /* endpoints 1..15 */
+ if (transmit) {
+ if (devctl & MUSB_DEVCTL_HM) {
+ if (is_host_capable())
+ musb_host_tx(musb, epnum);
+ } else {
+ if (is_peripheral_capable())
+ musb_g_tx(musb, epnum);
+ }
+ } else {
+ /* receive */
+ if (devctl & MUSB_DEVCTL_HM) {
+ if (is_host_capable())
+ musb_host_rx(musb, epnum);
+ } else {
+ if (is_peripheral_capable())
+ musb_g_rx(musb, epnum);
+ }
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(musb_dma_completion);
+
+#else
+#define use_dma 0
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_SYSFS
+
+static ssize_t
+musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct musb *musb = dev_to_musb(dev);
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state));
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return ret;
+}
+
+static ssize_t
+musb_mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ struct musb *musb = dev_to_musb(dev);
+ unsigned long flags;
+ int status;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ if (sysfs_streq(buf, "host"))
+ status = musb_platform_set_mode(musb, MUSB_HOST);
+ else if (sysfs_streq(buf, "peripheral"))
+ status = musb_platform_set_mode(musb, MUSB_PERIPHERAL);
+ else if (sysfs_streq(buf, "otg"))
+ status = musb_platform_set_mode(musb, MUSB_OTG);
+ else
+ status = -EINVAL;
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return (status == 0) ? n : status;
+}
+static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store);
+
+static ssize_t
+musb_vbus_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ struct musb *musb = dev_to_musb(dev);
+ unsigned long flags;
+ unsigned long val;
+
+ if (sscanf(buf, "%lu", &val) < 1) {
+ dev_err(dev, "Invalid VBUS timeout ms value\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&musb->lock, flags);
+ /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */
+ musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ;
+ if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON)
+ musb->is_active = 0;
+ musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return n;
+}
+
+static ssize_t
+musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct musb *musb = dev_to_musb(dev);
+ unsigned long flags;
+ unsigned long val;
+ int vbus;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ val = musb->a_wait_bcon;
+ /* FIXME get_vbus_status() is normally #defined as false...
+ * and is effectively TUSB-specific.
+ */
+ vbus = musb_platform_get_vbus_status(musb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return sprintf(buf, "Vbus %s, timeout %lu msec\n",
+ vbus ? "on" : "off", val);
+}
+static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);
+
+/* Gadget drivers can't know that a host is connected so they might want
+ * to start SRP, but users can. This allows userspace to trigger SRP.
+ */
+static ssize_t
+musb_srp_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ struct musb *musb = dev_to_musb(dev);
+ unsigned short srp;
+
+ if (sscanf(buf, "%hu", &srp) != 1
+ || (srp != 1)) {
+ dev_err(dev, "SRP: Value must be 1\n");
+ return -EINVAL;
+ }
+
+ if (srp == 1)
+ musb_g_wakeup(musb);
+
+ return n;
+}
+static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store);
+
+static struct attribute *musb_attributes[] = {
+ &dev_attr_mode.attr,
+ &dev_attr_vbus.attr,
+ &dev_attr_srp.attr,
+ NULL
+};
+
+static const struct attribute_group musb_attr_group = {
+ .attrs = musb_attributes,
+};
+
+#endif /* sysfs */
+
+#ifndef __UBOOT__
+/* Only used to provide driver mode change events */
+static void musb_irq_work(struct work_struct *data)
+{
+ struct musb *musb = container_of(data, struct musb, irq_work);
+ static int old_state;
+
+ if (musb->xceiv->state != old_state) {
+ old_state = musb->xceiv->state;
+ sysfs_notify(&musb->controller->kobj, NULL, "mode");
+ }
+}
+#endif
+
+/* --------------------------------------------------------------------------
+ * Init support
+ */
+
+static struct musb *__devinit
+allocate_instance(struct device *dev,
+ struct musb_hdrc_config *config, void __iomem *mbase)
+{
+ struct musb *musb;
+ struct musb_hw_ep *ep;
+ int epnum;
+#ifndef __UBOOT__
+ struct usb_hcd *hcd;
+
+ hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev));
+ if (!hcd)
+ return NULL;
+ /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */
+
+ musb = hcd_to_musb(hcd);
+#else
+ musb = calloc(1, sizeof(*musb));
+ if (!musb)
+ return NULL;
+#endif
+ INIT_LIST_HEAD(&musb->control);
+ INIT_LIST_HEAD(&musb->in_bulk);
+ INIT_LIST_HEAD(&musb->out_bulk);
+
+#ifndef __UBOOT__
+ hcd->uses_new_polling = 1;
+ hcd->has_tt = 1;
+#endif
+
+ musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
+ musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON;
+ dev_set_drvdata(dev, musb);
+ musb->mregs = mbase;
+ musb->ctrl_base = mbase;
+ musb->nIrq = -ENODEV;
+ musb->config = config;
+ BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS);
+ for (epnum = 0, ep = musb->endpoints;
+ epnum < musb->config->num_eps;
+ epnum++, ep++) {
+ ep->musb = musb;
+ ep->epnum = epnum;
+ }
+
+ musb->controller = dev;
+
+ return musb;
+}
+
+static void musb_free(struct musb *musb)
+{
+ /* this has multiple entry modes. it handles fault cleanup after
+ * probe(), where things may be partially set up, as well as rmmod
+ * cleanup after everything's been de-activated.
+ */
+
+#ifdef CONFIG_SYSFS
+ sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
+#endif
+
+ if (musb->nIrq >= 0) {
+ if (musb->irq_wake)
+ disable_irq_wake(musb->nIrq);
+ free_irq(musb->nIrq, musb);
+ }
+ if (is_dma_capable() && musb->dma_controller) {
+ struct dma_controller *c = musb->dma_controller;
+
+ (void) c->stop(c);
+ dma_controller_destroy(c);
+ }
+
+ kfree(musb);
+}
+
+/*
+ * Perform generic per-controller initialization.
+ *
+ * @pDevice: the controller (already clocked, etc)
+ * @nIrq: irq
+ * @mregs: virtual address of controller registers,
+ * not yet corrected for platform-specific offsets
+ */
+#ifndef __UBOOT__
+static int __devinit
+musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
+#else
+struct musb *
+musb_init_controller(struct musb_hdrc_platform_data *plat, struct device *dev,
+ void *ctrl)
+#endif
+{
+ int status;
+ struct musb *musb;
+#ifndef __UBOOT__
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+#else
+ int nIrq = 0;
+#endif
+
+ /* The driver might handle more features than the board; OK.
+ * Fail when the board needs a feature that's not enabled.
+ */
+ if (!plat) {
+ dev_dbg(dev, "no platform_data?\n");
+ status = -ENODEV;
+ goto fail0;
+ }
+
+ /* allocate */
+ musb = allocate_instance(dev, plat->config, ctrl);
+ if (!musb) {
+ status = -ENOMEM;
+ goto fail0;
+ }
+
+ pm_runtime_use_autosuspend(musb->controller);
+ pm_runtime_set_autosuspend_delay(musb->controller, 200);
+ pm_runtime_enable(musb->controller);
+
+ spin_lock_init(&musb->lock);
+ musb->board_mode = plat->mode;
+ musb->board_set_power = plat->set_power;
+ musb->min_power = plat->min_power;
+ musb->ops = plat->platform_ops;
+
+ /* The musb_platform_init() call:
+ * - adjusts musb->mregs and musb->isr if needed,
+ * - may initialize an integrated tranceiver
+ * - initializes musb->xceiv, usually by otg_get_phy()
+ * - stops powering VBUS
+ *
+ * There are various transceiver configurations. Blackfin,
+ * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses
+ * external/discrete ones in various flavors (twl4030 family,
+ * isp1504, non-OTG, etc) mostly hooking up through ULPI.
+ */
+ musb->isr = generic_interrupt;
+ status = musb_platform_init(musb);
+ if (status < 0)
+ goto fail1;
+
+ if (!musb->isr) {
+ status = -ENODEV;
+ goto fail2;
+ }
+
+#ifndef __UBOOT__
+ if (!musb->xceiv->io_ops) {
+ musb->xceiv->io_dev = musb->controller;
+ musb->xceiv->io_priv = musb->mregs;
+ musb->xceiv->io_ops = &musb_ulpi_access;
+ }
+#endif
+
+ pm_runtime_get_sync(musb->controller);
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+ if (use_dma && dev->dma_mask) {
+ struct dma_controller *c;
+
+ c = dma_controller_create(musb, musb->mregs);
+ musb->dma_controller = c;
+ if (c)
+ (void) c->start(c);
+ }
+#endif
+#ifndef __UBOOT__
+ /* ideally this would be abstracted in platform setup */
+ if (!is_dma_capable() || !musb->dma_controller)
+ dev->dma_mask = NULL;
+#endif
+
+ /* be sure interrupts are disabled before connecting ISR */
+ musb_platform_disable(musb);
+ musb_generic_disable(musb);
+
+ /* setup musb parts of the core (especially endpoints) */
+ status = musb_core_init(plat->config->multipoint
+ ? MUSB_CONTROLLER_MHDRC
+ : MUSB_CONTROLLER_HDRC, musb);
+ if (status < 0)
+ goto fail3;
+
+ setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
+
+ /* Init IRQ workqueue before request_irq */
+ INIT_WORK(&musb->irq_work, musb_irq_work);
+
+ /* attach to the IRQ */
+ if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) {
+ dev_err(dev, "request_irq %d failed!\n", nIrq);
+ status = -ENODEV;
+ goto fail3;
+ }
+ musb->nIrq = nIrq;
+/* FIXME this handles wakeup irqs wrong */
+ if (enable_irq_wake(nIrq) == 0) {
+ musb->irq_wake = 1;
+ device_init_wakeup(dev, 1);
+ } else {
+ musb->irq_wake = 0;
+ }
+
+#ifndef __UBOOT__
+ /* host side needs more setup */
+ if (is_host_enabled(musb)) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+
+ otg_set_host(musb->xceiv->otg, &hcd->self);
+
+ if (is_otg_enabled(musb))
+ hcd->self.otg_port = 1;
+ musb->xceiv->otg->host = &hcd->self;
+ hcd->power_budget = 2 * (plat->power ? : 250);
+
+ /* program PHY to use external vBus if required */
+ if (plat->extvbus) {
+ u8 busctl = musb_read_ulpi_buscontrol(musb->mregs);
+ busctl |= MUSB_ULPI_USE_EXTVBUS;
+ musb_write_ulpi_buscontrol(musb->mregs, busctl);
+ }
+ }
+#endif
+
+ /* For the host-only role, we can activate right away.
+ * (We expect the ID pin to be forcibly grounded!!)
+ * Otherwise, wait till the gadget driver hooks up.
+ */
+ if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+
+ MUSB_HST_MODE(musb);
+#ifndef __UBOOT__
+ musb->xceiv->otg->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+
+ status = usb_add_hcd(musb_to_hcd(musb), 0, 0);
+
+ hcd->self.uses_pio_for_control = 1;
+ dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n",
+ "HOST", status,
+ musb_readb(musb->mregs, MUSB_DEVCTL),
+ (musb_readb(musb->mregs, MUSB_DEVCTL)
+ & MUSB_DEVCTL_BDEVICE
+ ? 'B' : 'A'));
+#endif
+
+ } else /* peripheral is enabled */ {
+ MUSB_DEV_MODE(musb);
+#ifndef __UBOOT__
+ musb->xceiv->otg->default_a = 0;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+#endif
+
+ if (is_peripheral_capable())
+ status = musb_gadget_setup(musb);
+
+#ifndef __UBOOT__
+ dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n",
+ is_otg_enabled(musb) ? "OTG" : "PERIPHERAL",
+ status,
+ musb_readb(musb->mregs, MUSB_DEVCTL));
+#endif
+
+ }
+ if (status < 0)
+ goto fail3;
+
+ status = musb_init_debugfs(musb);
+ if (status < 0)
+ goto fail4;
+
+#ifdef CONFIG_SYSFS
+ status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
+ if (status)
+ goto fail5;
+#endif
+
+ pm_runtime_put(musb->controller);
+
+ dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
+ ({char *s;
+ switch (musb->board_mode) {
+ case MUSB_HOST: s = "Host"; break;
+ case MUSB_PERIPHERAL: s = "Peripheral"; break;
+ default: s = "OTG"; break;
+ }; s; }),
+ ctrl,
+ (is_dma_capable() && musb->dma_controller)
+ ? "DMA" : "PIO",
+ musb->nIrq);
+
+#ifndef __UBOOT__
+ return 0;
+#else
+ return status == 0 ? musb : NULL;
+#endif
+
+fail5:
+ musb_exit_debugfs(musb);
+
+fail4:
+#ifndef __UBOOT__
+ if (!is_otg_enabled(musb) && is_host_enabled(musb))
+ usb_remove_hcd(musb_to_hcd(musb));
+ else
+#endif
+ musb_gadget_cleanup(musb);
+
+fail3:
+ pm_runtime_put_sync(musb->controller);
+
+fail2:
+ if (musb->irq_wake)
+ device_init_wakeup(dev, 0);
+ musb_platform_exit(musb);
+
+fail1:
+ dev_err(musb->controller,
+ "musb_init_controller failed with status %d\n", status);
+
+ musb_free(musb);
+
+fail0:
+
+#ifndef __UBOOT__
+ return status;
+#else
+ return status == 0 ? musb : NULL;
+#endif
+
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just
+ * bridge to a platform device; this driver then suffices.
+ */
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+static u64 *orig_dma_mask;
+#endif
+
+#ifndef __UBOOT__
+static int __devinit musb_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int irq = platform_get_irq_byname(pdev, "mc");
+ int status;
+ struct resource *iomem;
+ void __iomem *base;
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem || irq <= 0)
+ return -ENODEV;
+
+ base = ioremap(iomem->start, resource_size(iomem));
+ if (!base) {
+ dev_err(dev, "ioremap failed\n");
+ return -ENOMEM;
+ }
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+ /* clobbered by use_dma=n */
+ orig_dma_mask = dev->dma_mask;
+#endif
+ status = musb_init_controller(dev, irq, base);
+ if (status < 0)
+ iounmap(base);
+
+ return status;
+}
+
+static int __devexit musb_remove(struct platform_device *pdev)
+{
+ struct musb *musb = dev_to_musb(&pdev->dev);
+ void __iomem *ctrl_base = musb->ctrl_base;
+
+ /* this gets called on rmmod.
+ * - Host mode: host may still be active
+ * - Peripheral mode: peripheral is deactivated (or never-activated)
+ * - OTG mode: both roles are deactivated (or never-activated)
+ */
+ musb_exit_debugfs(musb);
+ musb_shutdown(pdev);
+
+ musb_free(musb);
+ iounmap(ctrl_base);
+ device_init_wakeup(&pdev->dev, 0);
+#ifndef CONFIG_MUSB_PIO_ONLY
+ pdev->dev.dma_mask = orig_dma_mask;
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static void musb_save_context(struct musb *musb)
+{
+ int i;
+ void __iomem *musb_base = musb->mregs;
+ void __iomem *epio;
+
+ if (is_host_enabled(musb)) {
+ musb->context.frame = musb_readw(musb_base, MUSB_FRAME);
+ musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
+ musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
+ }
+ musb->context.power = musb_readb(musb_base, MUSB_POWER);
+ musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
+ musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE);
+ musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
+ musb->context.index = musb_readb(musb_base, MUSB_INDEX);
+ musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
+
+ for (i = 0; i < musb->config->num_eps; ++i) {
+ struct musb_hw_ep *hw_ep;
+
+ hw_ep = &musb->endpoints[i];
+ if (!hw_ep)
+ continue;
+
+ epio = hw_ep->regs;
+ if (!epio)
+ continue;
+
+ musb_writeb(musb_base, MUSB_INDEX, i);
+ musb->context.index_regs[i].txmaxp =
+ musb_readw(epio, MUSB_TXMAXP);
+ musb->context.index_regs[i].txcsr =
+ musb_readw(epio, MUSB_TXCSR);
+ musb->context.index_regs[i].rxmaxp =
+ musb_readw(epio, MUSB_RXMAXP);
+ musb->context.index_regs[i].rxcsr =
+ musb_readw(epio, MUSB_RXCSR);
+
+ if (musb->dyn_fifo) {
+ musb->context.index_regs[i].txfifoadd =
+ musb_read_txfifoadd(musb_base);
+ musb->context.index_regs[i].rxfifoadd =
+ musb_read_rxfifoadd(musb_base);
+ musb->context.index_regs[i].txfifosz =
+ musb_read_txfifosz(musb_base);
+ musb->context.index_regs[i].rxfifosz =
+ musb_read_rxfifosz(musb_base);
+ }
+ if (is_host_enabled(musb)) {
+ musb->context.index_regs[i].txtype =
+ musb_readb(epio, MUSB_TXTYPE);
+ musb->context.index_regs[i].txinterval =
+ musb_readb(epio, MUSB_TXINTERVAL);
+ musb->context.index_regs[i].rxtype =
+ musb_readb(epio, MUSB_RXTYPE);
+ musb->context.index_regs[i].rxinterval =
+ musb_readb(epio, MUSB_RXINTERVAL);
+
+ musb->context.index_regs[i].txfunaddr =
+ musb_read_txfunaddr(musb_base, i);
+ musb->context.index_regs[i].txhubaddr =
+ musb_read_txhubaddr(musb_base, i);
+ musb->context.index_regs[i].txhubport =
+ musb_read_txhubport(musb_base, i);
+
+ musb->context.index_regs[i].rxfunaddr =
+ musb_read_rxfunaddr(musb_base, i);
+ musb->context.index_regs[i].rxhubaddr =
+ musb_read_rxhubaddr(musb_base, i);
+ musb->context.index_regs[i].rxhubport =
+ musb_read_rxhubport(musb_base, i);
+ }
+ }
+}
+
+static void musb_restore_context(struct musb *musb)
+{
+ int i;
+ void __iomem *musb_base = musb->mregs;
+ void __iomem *ep_target_regs;
+ void __iomem *epio;
+
+ if (is_host_enabled(musb)) {
+ musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
+ musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
+ musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
+ }
+ musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+ musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe);
+ musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe);
+ musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
+ musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
+
+ for (i = 0; i < musb->config->num_eps; ++i) {
+ struct musb_hw_ep *hw_ep;
+
+ hw_ep = &musb->endpoints[i];
+ if (!hw_ep)
+ continue;
+
+ epio = hw_ep->regs;
+ if (!epio)
+ continue;
+
+ musb_writeb(musb_base, MUSB_INDEX, i);
+ musb_writew(epio, MUSB_TXMAXP,
+ musb->context.index_regs[i].txmaxp);
+ musb_writew(epio, MUSB_TXCSR,
+ musb->context.index_regs[i].txcsr);
+ musb_writew(epio, MUSB_RXMAXP,
+ musb->context.index_regs[i].rxmaxp);
+ musb_writew(epio, MUSB_RXCSR,
+ musb->context.index_regs[i].rxcsr);
+
+ if (musb->dyn_fifo) {
+ musb_write_txfifosz(musb_base,
+ musb->context.index_regs[i].txfifosz);
+ musb_write_rxfifosz(musb_base,
+ musb->context.index_regs[i].rxfifosz);
+ musb_write_txfifoadd(musb_base,
+ musb->context.index_regs[i].txfifoadd);
+ musb_write_rxfifoadd(musb_base,
+ musb->context.index_regs[i].rxfifoadd);
+ }
+
+ if (is_host_enabled(musb)) {
+ musb_writeb(epio, MUSB_TXTYPE,
+ musb->context.index_regs[i].txtype);
+ musb_writeb(epio, MUSB_TXINTERVAL,
+ musb->context.index_regs[i].txinterval);
+ musb_writeb(epio, MUSB_RXTYPE,
+ musb->context.index_regs[i].rxtype);
+ musb_writeb(epio, MUSB_RXINTERVAL,
+
+ musb->context.index_regs[i].rxinterval);
+ musb_write_txfunaddr(musb_base, i,
+ musb->context.index_regs[i].txfunaddr);
+ musb_write_txhubaddr(musb_base, i,
+ musb->context.index_regs[i].txhubaddr);
+ musb_write_txhubport(musb_base, i,
+ musb->context.index_regs[i].txhubport);
+
+ ep_target_regs =
+ musb_read_target_reg_base(i, musb_base);
+
+ musb_write_rxfunaddr(ep_target_regs,
+ musb->context.index_regs[i].rxfunaddr);
+ musb_write_rxhubaddr(ep_target_regs,
+ musb->context.index_regs[i].rxhubaddr);
+ musb_write_rxhubport(ep_target_regs,
+ musb->context.index_regs[i].rxhubport);
+ }
+ }
+ musb_writeb(musb_base, MUSB_INDEX, musb->context.index);
+}
+
+static int musb_suspend(struct device *dev)
+{
+ struct musb *musb = dev_to_musb(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ if (is_peripheral_active(musb)) {
+ /* FIXME force disconnect unless we know USB will wake
+ * the system up quickly enough to respond ...
+ */
+ } else if (is_host_active(musb)) {
+ /* we know all the children are suspended; sometimes
+ * they will even be wakeup-enabled.
+ */
+ }
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return 0;
+}
+
+static int musb_resume_noirq(struct device *dev)
+{
+ /* for static cmos like DaVinci, register values were preserved
+ * unless for some reason the whole soc powered down or the USB
+ * module got reset through the PSC (vs just being disabled).
+ */
+ return 0;
+}
+
+static int musb_runtime_suspend(struct device *dev)
+{
+ struct musb *musb = dev_to_musb(dev);
+
+ musb_save_context(musb);
+
+ return 0;
+}
+
+static int musb_runtime_resume(struct device *dev)
+{
+ struct musb *musb = dev_to_musb(dev);
+ static int first = 1;
+
+ /*
+ * When pm_runtime_get_sync called for the first time in driver
+ * init, some of the structure is still not initialized which is
+ * used in restore function. But clock needs to be
+ * enabled before any register access, so
+ * pm_runtime_get_sync has to be called.
+ * Also context restore without save does not make
+ * any sense
+ */
+ if (!first)
+ musb_restore_context(musb);
+ first = 0;
+
+ return 0;
+}
+
+static const struct dev_pm_ops musb_dev_pm_ops = {
+ .suspend = musb_suspend,
+ .resume_noirq = musb_resume_noirq,
+ .runtime_suspend = musb_runtime_suspend,
+ .runtime_resume = musb_runtime_resume,
+};
+
+#define MUSB_DEV_PM_OPS (&musb_dev_pm_ops)
+#else
+#define MUSB_DEV_PM_OPS NULL
+#endif
+
+static struct platform_driver musb_driver = {
+ .driver = {
+ .name = (char *)musb_driver_name,
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ .pm = MUSB_DEV_PM_OPS,
+ },
+ .probe = musb_probe,
+ .remove = __devexit_p(musb_remove),
+ .shutdown = musb_shutdown,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int __init musb_init(void)
+{
+ if (usb_disabled())
+ return 0;
+
+ pr_info("%s: version " MUSB_VERSION ", "
+ "?dma?"
+ ", "
+ "otg (peripheral+host)",
+ musb_driver_name);
+ return platform_driver_register(&musb_driver);
+}
+module_init(musb_init);
+
+static void __exit musb_cleanup(void)
+{
+ platform_driver_unregister(&musb_driver);
+}
+module_exit(musb_cleanup);
+#endif
diff --git a/drivers/usb/musb-new/musb_core.h b/drivers/usb/musb-new/musb_core.h
new file mode 100644
index 0000000000..2695742098
--- /dev/null
+++ b/drivers/usb/musb-new/musb_core.h
@@ -0,0 +1,623 @@
+/*
+ * MUSB OTG driver defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_CORE_H__
+#define __MUSB_CORE_H__
+
+#ifndef __UBOOT__
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+#include <linux/usb/otg.h>
+#else
+#include <asm/errno.h>
+#endif
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/musb.h>
+
+struct musb;
+struct musb_hw_ep;
+struct musb_ep;
+
+/* Helper defines for struct musb->hwvers */
+#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f)
+#define MUSB_HWVERS_MINOR(x) (x & 0x3ff)
+#define MUSB_HWVERS_RC 0x8000
+#define MUSB_HWVERS_1300 0x52C
+#define MUSB_HWVERS_1400 0x590
+#define MUSB_HWVERS_1800 0x720
+#define MUSB_HWVERS_1900 0x784
+#define MUSB_HWVERS_2000 0x800
+
+#include "musb_debug.h"
+#include "musb_dma.h"
+
+#include "musb_io.h"
+#include "musb_regs.h"
+
+#include "musb_gadget.h"
+#ifndef __UBOOT__
+#include <linux/usb/hcd.h>
+#endif
+#include "musb_host.h"
+
+#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST)
+#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL)
+#define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG)
+
+/* NOTE: otg and peripheral-only state machines start at B_IDLE.
+ * OTG or host-only go to A_IDLE when ID is sensed.
+ */
+#define is_peripheral_active(m) (!(m)->is_host)
+#define is_host_active(m) ((m)->is_host)
+
+#ifdef CONFIG_PROC_FS
+#include <linux/fs.h>
+#define MUSB_CONFIG_PROC_FS
+#endif
+
+/****************************** PERIPHERAL ROLE *****************************/
+
+#ifndef __UBOOT__
+#define is_peripheral_capable() (1)
+#else
+#ifdef CONFIG_MUSB_GADGET
+#define is_peripheral_capable() (1)
+#else
+#define is_peripheral_capable() (0)
+#endif
+#endif
+
+extern irqreturn_t musb_g_ep0_irq(struct musb *);
+extern void musb_g_tx(struct musb *, u8);
+extern void musb_g_rx(struct musb *, u8);
+extern void musb_g_reset(struct musb *);
+extern void musb_g_suspend(struct musb *);
+extern void musb_g_resume(struct musb *);
+extern void musb_g_wakeup(struct musb *);
+extern void musb_g_disconnect(struct musb *);
+
+/****************************** HOST ROLE ***********************************/
+
+#ifndef __UBOOT__
+#define is_host_capable() (1)
+#else
+#ifdef CONFIG_MUSB_HOST
+#define is_host_capable() (1)
+#else
+#define is_host_capable() (0)
+#endif
+#endif
+
+extern irqreturn_t musb_h_ep0_irq(struct musb *);
+extern void musb_host_tx(struct musb *, u8);
+extern void musb_host_rx(struct musb *, u8);
+
+/****************************** CONSTANTS ********************************/
+
+#ifndef MUSB_C_NUM_EPS
+#define MUSB_C_NUM_EPS ((u8)16)
+#endif
+
+#ifndef MUSB_MAX_END0_PACKET
+#define MUSB_MAX_END0_PACKET ((u16)MUSB_EP0_FIFOSIZE)
+#endif
+
+/* host side ep0 states */
+enum musb_h_ep0_state {
+ MUSB_EP0_IDLE,
+ MUSB_EP0_START, /* expect ack of setup */
+ MUSB_EP0_IN, /* expect IN DATA */
+ MUSB_EP0_OUT, /* expect ack of OUT DATA */
+ MUSB_EP0_STATUS, /* expect ack of STATUS */
+} __attribute__ ((packed));
+
+/* peripheral side ep0 states */
+enum musb_g_ep0_state {
+ MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */
+ MUSB_EP0_STAGE_SETUP, /* received SETUP */
+ MUSB_EP0_STAGE_TX, /* IN data */
+ MUSB_EP0_STAGE_RX, /* OUT data */
+ MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */
+ MUSB_EP0_STAGE_STATUSOUT, /* (after IN data) */
+ MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */
+} __attribute__ ((packed));
+
+/*
+ * OTG protocol constants. See USB OTG 1.3 spec,
+ * sections 5.5 "Device Timings" and 6.6.5 "Timers".
+ */
+#define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */
+#define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */
+#define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */
+#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */
+
+
+/*************************** REGISTER ACCESS ********************************/
+
+/* Endpoint registers (other than dynfifo setup) can be accessed either
+ * directly with the "flat" model, or after setting up an index register.
+ */
+
+#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_SOC_OMAP2430) \
+ || defined(CONFIG_SOC_OMAP3430) || defined(CONFIG_BLACKFIN) \
+ || defined(CONFIG_ARCH_OMAP4)
+/* REVISIT indexed access seemed to
+ * misbehave (on DaVinci) for at least peripheral IN ...
+ */
+#define MUSB_FLAT_REG
+#endif
+
+/* TUSB mapping: "flat" plus ep0 special cases */
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+#define musb_ep_select(_mbase, _epnum) \
+ musb_writeb((_mbase), MUSB_INDEX, (_epnum))
+#define MUSB_EP_OFFSET MUSB_TUSB_OFFSET
+
+/* "flat" mapping: each endpoint has its own i/o address */
+#elif defined(MUSB_FLAT_REG)
+#define musb_ep_select(_mbase, _epnum) (((void)(_mbase)), ((void)(_epnum)))
+#define MUSB_EP_OFFSET MUSB_FLAT_OFFSET
+
+/* "indexed" mapping: INDEX register controls register bank select */
+#else
+#define musb_ep_select(_mbase, _epnum) \
+ musb_writeb((_mbase), MUSB_INDEX, (_epnum))
+#define MUSB_EP_OFFSET MUSB_INDEXED_OFFSET
+#endif
+
+/****************************** FUNCTIONS ********************************/
+
+#define MUSB_HST_MODE(_musb)\
+ { (_musb)->is_host = true; }
+#define MUSB_DEV_MODE(_musb) \
+ { (_musb)->is_host = false; }
+
+#define test_devctl_hst_mode(_x) \
+ (musb_readb((_x)->mregs, MUSB_DEVCTL)&MUSB_DEVCTL_HM)
+
+#define MUSB_MODE(musb) ((musb)->is_host ? "Host" : "Peripheral")
+
+/******************************** TYPES *************************************/
+
+/**
+ * struct musb_platform_ops - Operations passed to musb_core by HW glue layer
+ * @init: turns on clocks, sets up platform-specific registers, etc
+ * @exit: undoes @init
+ * @set_mode: forcefully changes operating mode
+ * @try_ilde: tries to idle the IP
+ * @vbus_status: returns vbus status if possible
+ * @set_vbus: forces vbus status
+ * @adjust_channel_params: pre check for standard dma channel_program func
+ */
+struct musb_platform_ops {
+ int (*init)(struct musb *musb);
+ int (*exit)(struct musb *musb);
+
+ void (*enable)(struct musb *musb);
+ void (*disable)(struct musb *musb);
+
+ int (*set_mode)(struct musb *musb, u8 mode);
+ void (*try_idle)(struct musb *musb, unsigned long timeout);
+
+ int (*vbus_status)(struct musb *musb);
+ void (*set_vbus)(struct musb *musb, int on);
+
+ int (*adjust_channel_params)(struct dma_channel *channel,
+ u16 packet_sz, u8 *mode,
+ dma_addr_t *dma_addr, u32 *len);
+};
+
+/*
+ * struct musb_hw_ep - endpoint hardware (bidirectional)
+ *
+ * Ordered slightly for better cacheline locality.
+ */
+struct musb_hw_ep {
+ struct musb *musb;
+ void __iomem *fifo;
+ void __iomem *regs;
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+ void __iomem *conf;
+#endif
+
+ /* index in musb->endpoints[] */
+ u8 epnum;
+
+ /* hardware configuration, possibly dynamic */
+ bool is_shared_fifo;
+ bool tx_double_buffered;
+ bool rx_double_buffered;
+ u16 max_packet_sz_tx;
+ u16 max_packet_sz_rx;
+
+ struct dma_channel *tx_channel;
+ struct dma_channel *rx_channel;
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+ /* TUSB has "asynchronous" and "synchronous" dma modes */
+ dma_addr_t fifo_async;
+ dma_addr_t fifo_sync;
+ void __iomem *fifo_sync_va;
+#endif
+
+ void __iomem *target_regs;
+
+ /* currently scheduled peripheral endpoint */
+ struct musb_qh *in_qh;
+ struct musb_qh *out_qh;
+
+ u8 rx_reinit;
+ u8 tx_reinit;
+
+ /* peripheral side */
+ struct musb_ep ep_in; /* TX */
+ struct musb_ep ep_out; /* RX */
+};
+
+static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep)
+{
+ return next_request(&hw_ep->ep_in);
+}
+
+static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep)
+{
+ return next_request(&hw_ep->ep_out);
+}
+
+struct musb_csr_regs {
+ /* FIFO registers */
+ u16 txmaxp, txcsr, rxmaxp, rxcsr;
+ u16 rxfifoadd, txfifoadd;
+ u8 txtype, txinterval, rxtype, rxinterval;
+ u8 rxfifosz, txfifosz;
+ u8 txfunaddr, txhubaddr, txhubport;
+ u8 rxfunaddr, rxhubaddr, rxhubport;
+};
+
+struct musb_context_registers {
+
+ u8 power;
+ u16 intrtxe, intrrxe;
+ u8 intrusbe;
+ u16 frame;
+ u8 index, testmode;
+
+ u8 devctl, busctl, misc;
+ u32 otg_interfsel;
+
+ struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
+};
+
+/*
+ * struct musb - Driver instance data.
+ */
+struct musb {
+ /* device lock */
+ spinlock_t lock;
+
+ const struct musb_platform_ops *ops;
+ struct musb_context_registers context;
+
+ irqreturn_t (*isr)(int, void *);
+ struct work_struct irq_work;
+ u16 hwvers;
+
+/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
+#define MUSB_PORT_STAT_RESUME (1 << 31)
+
+ u32 port1_status;
+
+ unsigned long rh_timer;
+
+ enum musb_h_ep0_state ep0_stage;
+
+ /* bulk traffic normally dedicates endpoint hardware, and each
+ * direction has its own ring of host side endpoints.
+ * we try to progress the transfer at the head of each endpoint's
+ * queue until it completes or NAKs too much; then we try the next
+ * endpoint.
+ */
+ struct musb_hw_ep *bulk_ep;
+
+ struct list_head control; /* of musb_qh */
+ struct list_head in_bulk; /* of musb_qh */
+ struct list_head out_bulk; /* of musb_qh */
+
+ struct timer_list otg_timer;
+ struct notifier_block nb;
+
+ struct dma_controller *dma_controller;
+
+ struct device *controller;
+ void __iomem *ctrl_base;
+ void __iomem *mregs;
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+ dma_addr_t async;
+ dma_addr_t sync;
+ void __iomem *sync_va;
+#endif
+
+ /* passed down from chip/board specific irq handlers */
+ u8 int_usb;
+ u16 int_rx;
+ u16 int_tx;
+
+ struct usb_phy *xceiv;
+
+ int nIrq;
+ unsigned irq_wake:1;
+
+ struct musb_hw_ep endpoints[MUSB_C_NUM_EPS];
+#define control_ep endpoints
+
+#define VBUSERR_RETRY_COUNT 3
+ u16 vbuserr_retry;
+ u16 epmask;
+ u8 nr_endpoints;
+
+ u8 board_mode; /* enum musb_mode */
+ int (*board_set_power)(int state);
+
+ u8 min_power; /* vbus for periph, in mA/2 */
+
+ bool is_host;
+
+ int a_wait_bcon; /* VBUS timeout in msecs */
+ unsigned long idle_timeout; /* Next timeout in jiffies */
+
+ /* active means connected and not suspended */
+ unsigned is_active:1;
+
+ unsigned is_multipoint:1;
+ unsigned ignore_disconnect:1; /* during bus resets */
+
+ unsigned hb_iso_rx:1; /* high bandwidth iso rx? */
+ unsigned hb_iso_tx:1; /* high bandwidth iso tx? */
+ unsigned dyn_fifo:1; /* dynamic FIFO supported? */
+
+ unsigned bulk_split:1;
+#define can_bulk_split(musb,type) \
+ (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_split)
+
+ unsigned bulk_combine:1;
+#define can_bulk_combine(musb,type) \
+ (((type) == USB_ENDPOINT_XFER_BULK) && (musb)->bulk_combine)
+
+ /* is_suspended means USB B_PERIPHERAL suspend */
+ unsigned is_suspended:1;
+
+ /* may_wakeup means remote wakeup is enabled */
+ unsigned may_wakeup:1;
+
+ /* is_self_powered is reported in device status and the
+ * config descriptor. is_bus_powered means B_PERIPHERAL
+ * draws some VBUS current; both can be true.
+ */
+ unsigned is_self_powered:1;
+ unsigned is_bus_powered:1;
+
+ unsigned set_address:1;
+ unsigned test_mode:1;
+ unsigned softconnect:1;
+
+ u8 address;
+ u8 test_mode_nr;
+ u16 ackpend; /* ep0 */
+ enum musb_g_ep0_state ep0_state;
+ struct usb_gadget g; /* the gadget */
+ struct usb_gadget_driver *gadget_driver; /* its driver */
+
+ /*
+ * FIXME: Remove this flag.
+ *
+ * This is only added to allow Blackfin to work
+ * with current driver. For some unknown reason
+ * Blackfin doesn't work with double buffering
+ * and that's enabled by default.
+ *
+ * We added this flag to forcefully disable double
+ * buffering until we get it working.
+ */
+ unsigned double_buffer_not_ok:1;
+
+ struct musb_hdrc_config *config;
+
+#ifdef MUSB_CONFIG_PROC_FS
+ struct proc_dir_entry *proc_entry;
+#endif
+};
+
+static inline struct musb *gadget_to_musb(struct usb_gadget *g)
+{
+ return container_of(g, struct musb, g);
+}
+
+#ifdef CONFIG_BLACKFIN
+static inline int musb_read_fifosize(struct musb *musb,
+ struct musb_hw_ep *hw_ep, u8 epnum)
+{
+ musb->nr_endpoints++;
+ musb->epmask |= (1 << epnum);
+
+ if (epnum < 5) {
+ hw_ep->max_packet_sz_tx = 128;
+ hw_ep->max_packet_sz_rx = 128;
+ } else {
+ hw_ep->max_packet_sz_tx = 1024;
+ hw_ep->max_packet_sz_rx = 1024;
+ }
+ hw_ep->is_shared_fifo = false;
+
+ return 0;
+}
+
+static inline void musb_configure_ep0(struct musb *musb)
+{
+ musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].is_shared_fifo = true;
+}
+
+#else
+
+static inline int musb_read_fifosize(struct musb *musb,
+ struct musb_hw_ep *hw_ep, u8 epnum)
+{
+ void *mbase = musb->mregs;
+ u8 reg = 0;
+
+ /* read from core using indexed model */
+ reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE));
+ /* 0's returned when no more endpoints */
+ if (!reg)
+ return -ENODEV;
+
+ musb->nr_endpoints++;
+ musb->epmask |= (1 << epnum);
+
+ hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f);
+
+ /* shared TX/RX FIFO? */
+ if ((reg & 0xf0) == 0xf0) {
+ hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx;
+ hw_ep->is_shared_fifo = true;
+ return 0;
+ } else {
+ hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4);
+ hw_ep->is_shared_fifo = false;
+ }
+
+ return 0;
+}
+
+static inline void musb_configure_ep0(struct musb *musb)
+{
+ musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].is_shared_fifo = true;
+}
+#endif /* CONFIG_BLACKFIN */
+
+
+/***************************** Glue it together *****************************/
+
+extern const char musb_driver_name[];
+
+extern void musb_start(struct musb *musb);
+extern void musb_stop(struct musb *musb);
+
+extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
+extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
+
+extern void musb_load_testpacket(struct musb *);
+
+extern irqreturn_t musb_interrupt(struct musb *);
+
+extern void musb_hnp_stop(struct musb *musb);
+
+static inline void musb_platform_set_vbus(struct musb *musb, int is_on)
+{
+ if (musb->ops->set_vbus)
+ musb->ops->set_vbus(musb, is_on);
+}
+
+static inline void musb_platform_enable(struct musb *musb)
+{
+ if (musb->ops->enable)
+ musb->ops->enable(musb);
+}
+
+static inline void musb_platform_disable(struct musb *musb)
+{
+ if (musb->ops->disable)
+ musb->ops->disable(musb);
+}
+
+static inline int musb_platform_set_mode(struct musb *musb, u8 mode)
+{
+ if (!musb->ops->set_mode)
+ return 0;
+
+ return musb->ops->set_mode(musb, mode);
+}
+
+static inline void musb_platform_try_idle(struct musb *musb,
+ unsigned long timeout)
+{
+ if (musb->ops->try_idle)
+ musb->ops->try_idle(musb, timeout);
+}
+
+static inline int musb_platform_get_vbus_status(struct musb *musb)
+{
+ if (!musb->ops->vbus_status)
+ return 0;
+
+ return musb->ops->vbus_status(musb);
+}
+
+static inline int musb_platform_init(struct musb *musb)
+{
+ if (!musb->ops->init)
+ return -EINVAL;
+
+ return musb->ops->init(musb);
+}
+
+static inline int musb_platform_exit(struct musb *musb)
+{
+ if (!musb->ops->exit)
+ return -EINVAL;
+
+ return musb->ops->exit(musb);
+}
+
+#ifdef __UBOOT__
+struct musb *
+musb_init_controller(struct musb_hdrc_platform_data *plat, struct device *dev,
+ void *ctrl);
+#endif
+#endif /* __MUSB_CORE_H__ */
diff --git a/drivers/usb/musb-new/musb_debug.h b/drivers/usb/musb-new/musb_debug.h
new file mode 100644
index 0000000000..27ba8f7994
--- /dev/null
+++ b/drivers/usb/musb-new/musb_debug.h
@@ -0,0 +1,58 @@
+/*
+ * MUSB OTG driver debug defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_LINUX_DEBUG_H__
+#define __MUSB_LINUX_DEBUG_H__
+
+#define yprintk(facility, format, args...) \
+ do { printk(facility "%s %d: " format , \
+ __func__, __LINE__ , ## args); } while (0)
+#define WARNING(fmt, args...) yprintk(KERN_WARNING, fmt, ## args)
+#define INFO(fmt, args...) yprintk(KERN_INFO, fmt, ## args)
+#define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args)
+
+#ifdef CONFIG_DEBUG_FS
+int musb_init_debugfs(struct musb *musb);
+void musb_exit_debugfs(struct musb *musb);
+#else
+static inline int musb_init_debugfs(struct musb *musb)
+{
+ return 0;
+}
+static inline void musb_exit_debugfs(struct musb *musb)
+{
+}
+#endif
+
+#endif /* __MUSB_LINUX_DEBUG_H__ */
diff --git a/drivers/usb/musb-new/musb_dma.h b/drivers/usb/musb-new/musb_dma.h
new file mode 100644
index 0000000000..3a97c4e2d4
--- /dev/null
+++ b/drivers/usb/musb-new/musb_dma.h
@@ -0,0 +1,186 @@
+/*
+ * MUSB OTG driver DMA controller abstraction
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_DMA_H__
+#define __MUSB_DMA_H__
+
+struct musb_hw_ep;
+
+/*
+ * DMA Controller Abstraction
+ *
+ * DMA Controllers are abstracted to allow use of a variety of different
+ * implementations of DMA, as allowed by the Inventra USB cores. On the
+ * host side, usbcore sets up the DMA mappings and flushes caches; on the
+ * peripheral side, the gadget controller driver does. Responsibilities
+ * of a DMA controller driver include:
+ *
+ * - Handling the details of moving multiple USB packets
+ * in cooperation with the Inventra USB core, including especially
+ * the correct RX side treatment of short packets and buffer-full
+ * states (both of which terminate transfers).
+ *
+ * - Knowing the correlation between dma channels and the
+ * Inventra core's local endpoint resources and data direction.
+ *
+ * - Maintaining a list of allocated/available channels.
+ *
+ * - Updating channel status on interrupts,
+ * whether shared with the Inventra core or separate.
+ */
+
+#define DMA_ADDR_INVALID (~(dma_addr_t)0)
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+#define is_dma_capable() (1)
+#else
+#define is_dma_capable() (0)
+#endif
+
+#ifdef CONFIG_USB_TI_CPPI_DMA
+#define is_cppi_enabled() 1
+#else
+#define is_cppi_enabled() 0
+#endif
+
+#ifdef CONFIG_USB_TUSB_OMAP_DMA
+#define tusb_dma_omap() 1
+#else
+#define tusb_dma_omap() 0
+#endif
+
+/* Anomaly 05000456 - USB Receive Interrupt Is Not Generated in DMA Mode 1
+ * Only allow DMA mode 1 to be used when the USB will actually generate the
+ * interrupts we expect.
+ */
+#ifdef CONFIG_BLACKFIN
+# undef USE_MODE1
+# if !ANOMALY_05000456
+# define USE_MODE1
+# endif
+#endif
+
+/*
+ * DMA channel status ... updated by the dma controller driver whenever that
+ * status changes, and protected by the overall controller spinlock.
+ */
+enum dma_channel_status {
+ /* unallocated */
+ MUSB_DMA_STATUS_UNKNOWN,
+ /* allocated ... but not busy, no errors */
+ MUSB_DMA_STATUS_FREE,
+ /* busy ... transactions are active */
+ MUSB_DMA_STATUS_BUSY,
+ /* transaction(s) aborted due to ... dma or memory bus error */
+ MUSB_DMA_STATUS_BUS_ABORT,
+ /* transaction(s) aborted due to ... core error or USB fault */
+ MUSB_DMA_STATUS_CORE_ABORT
+};
+
+struct dma_controller;
+
+/**
+ * struct dma_channel - A DMA channel.
+ * @private_data: channel-private data
+ * @max_len: the maximum number of bytes the channel can move in one
+ * transaction (typically representing many USB maximum-sized packets)
+ * @actual_len: how many bytes have been transferred
+ * @status: current channel status (updated e.g. on interrupt)
+ * @desired_mode: true if mode 1 is desired; false if mode 0 is desired
+ *
+ * channels are associated with an endpoint for the duration of at least
+ * one usb transfer.
+ */
+struct dma_channel {
+ void *private_data;
+ /* FIXME not void* private_data, but a dma_controller * */
+ size_t max_len;
+ size_t actual_len;
+ enum dma_channel_status status;
+ bool desired_mode;
+};
+
+/*
+ * dma_channel_status - return status of dma channel
+ * @c: the channel
+ *
+ * Returns the software's view of the channel status. If that status is BUSY
+ * then it's possible that the hardware has completed (or aborted) a transfer,
+ * so the driver needs to update that status.
+ */
+static inline enum dma_channel_status
+dma_channel_status(struct dma_channel *c)
+{
+ return (is_dma_capable() && c) ? c->status : MUSB_DMA_STATUS_UNKNOWN;
+}
+
+/**
+ * struct dma_controller - A DMA Controller.
+ * @start: call this to start a DMA controller;
+ * return 0 on success, else negative errno
+ * @stop: call this to stop a DMA controller
+ * return 0 on success, else negative errno
+ * @channel_alloc: call this to allocate a DMA channel
+ * @channel_release: call this to release a DMA channel
+ * @channel_abort: call this to abort a pending DMA transaction,
+ * returning it to FREE (but allocated) state
+ *
+ * Controllers manage dma channels.
+ */
+struct dma_controller {
+ int (*start)(struct dma_controller *);
+ int (*stop)(struct dma_controller *);
+ struct dma_channel *(*channel_alloc)(struct dma_controller *,
+ struct musb_hw_ep *, u8 is_tx);
+ void (*channel_release)(struct dma_channel *);
+ int (*channel_program)(struct dma_channel *channel,
+ u16 maxpacket, u8 mode,
+ dma_addr_t dma_addr,
+ u32 length);
+ int (*channel_abort)(struct dma_channel *);
+ int (*is_compatible)(struct dma_channel *channel,
+ u16 maxpacket,
+ void *buf, u32 length);
+};
+
+/* called after channel_program(), may indicate a fault */
+extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit);
+
+
+extern struct dma_controller *__init
+dma_controller_create(struct musb *, void __iomem *);
+
+extern void dma_controller_destroy(struct dma_controller *);
+
+#endif /* __MUSB_DMA_H__ */
diff --git a/drivers/usb/musb-new/musb_dsps.c b/drivers/usb/musb-new/musb_dsps.c
new file mode 100644
index 0000000000..9a03917e87
--- /dev/null
+++ b/drivers/usb/musb-new/musb_dsps.c
@@ -0,0 +1,771 @@
+/*
+ * Texas Instruments DSPS platforms "glue layer"
+ *
+ * Copyright (C) 2012, by Texas Instruments
+ *
+ * Based on the am35x "glue layer" code.
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux 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.
+ *
+ * The Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * musb_dsps.c will be a common file for all the TI DSPS platforms
+ * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x.
+ * For now only ti81x is using this and in future davinci.c, am35x.c
+ * da8xx.c would be merged to this file after testing.
+ */
+
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <linux/module.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+#include <plat/usb.h>
+#else
+#include <common.h>
+#include <asm/omap_musb.h>
+#include "linux-compat.h"
+#endif
+
+#include "musb_core.h"
+
+/**
+ * avoid using musb_readx()/musb_writex() as glue layer should not be
+ * dependent on musb core layer symbols.
+ */
+static inline u8 dsps_readb(const void __iomem *addr, unsigned offset)
+ { return __raw_readb(addr + offset); }
+
+static inline u32 dsps_readl(const void __iomem *addr, unsigned offset)
+ { return __raw_readl(addr + offset); }
+
+static inline void dsps_writeb(void __iomem *addr, unsigned offset, u8 data)
+ { __raw_writeb(data, addr + offset); }
+
+static inline void dsps_writel(void __iomem *addr, unsigned offset, u32 data)
+ { __raw_writel(data, addr + offset); }
+
+/**
+ * DSPS musb wrapper register offset.
+ * FIXME: This should be expanded to have all the wrapper registers from TI DSPS
+ * musb ips.
+ */
+struct dsps_musb_wrapper {
+ u16 revision;
+ u16 control;
+ u16 status;
+ u16 eoi;
+ u16 epintr_set;
+ u16 epintr_clear;
+ u16 epintr_status;
+ u16 coreintr_set;
+ u16 coreintr_clear;
+ u16 coreintr_status;
+ u16 phy_utmi;
+ u16 mode;
+
+ /* bit positions for control */
+ unsigned reset:5;
+
+ /* bit positions for interrupt */
+ unsigned usb_shift:5;
+ u32 usb_mask;
+ u32 usb_bitmap;
+ unsigned drvvbus:5;
+
+ unsigned txep_shift:5;
+ u32 txep_mask;
+ u32 txep_bitmap;
+
+ unsigned rxep_shift:5;
+ u32 rxep_mask;
+ u32 rxep_bitmap;
+
+ /* bit positions for phy_utmi */
+ unsigned otg_disable:5;
+
+ /* bit positions for mode */
+ unsigned iddig:5;
+ /* miscellaneous stuff */
+ u32 musb_core_offset;
+ u8 poll_seconds;
+};
+
+static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = {
+ .revision = 0x00,
+ .control = 0x14,
+ .status = 0x18,
+ .eoi = 0x24,
+ .epintr_set = 0x38,
+ .epintr_clear = 0x40,
+ .epintr_status = 0x30,
+ .coreintr_set = 0x3c,
+ .coreintr_clear = 0x44,
+ .coreintr_status = 0x34,
+ .phy_utmi = 0xe0,
+ .mode = 0xe8,
+ .reset = 0,
+ .otg_disable = 21,
+ .iddig = 8,
+ .usb_shift = 0,
+ .usb_mask = 0x1ff,
+ .usb_bitmap = (0x1ff << 0),
+ .drvvbus = 8,
+ .txep_shift = 0,
+ .txep_mask = 0xffff,
+ .txep_bitmap = (0xffff << 0),
+ .rxep_shift = 16,
+ .rxep_mask = 0xfffe,
+ .rxep_bitmap = (0xfffe << 16),
+ .musb_core_offset = 0x400,
+ .poll_seconds = 2,
+};
+
+/**
+ * DSPS glue structure.
+ */
+struct dsps_glue {
+ struct device *dev;
+ struct platform_device *musb; /* child musb pdev */
+ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */
+ struct timer_list timer; /* otg_workaround timer */
+};
+
+/**
+ * dsps_musb_enable - enable interrupts
+ */
+static void dsps_musb_enable(struct musb *musb)
+{
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+#else
+ const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data;
+#endif
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 epmask, coremask;
+
+ /* Workaround: setup IRQs through both register sets. */
+ epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) |
+ ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift);
+ coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF);
+
+ dsps_writel(reg_base, wrp->epintr_set, epmask);
+ dsps_writel(reg_base, wrp->coreintr_set, coremask);
+ /* Force the DRVVBUS IRQ so we can start polling for ID change. */
+#ifndef __UBOOT__
+ if (is_otg_enabled(musb))
+ dsps_writel(reg_base, wrp->coreintr_set,
+ (1 << wrp->drvvbus) << wrp->usb_shift);
+#endif
+}
+
+/**
+ * dsps_musb_disable - disable HDRC and flush interrupts
+ */
+static void dsps_musb_disable(struct musb *musb)
+{
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ void __iomem *reg_base = musb->ctrl_base;
+
+ dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap);
+ dsps_writel(reg_base, wrp->epintr_clear,
+ wrp->txep_bitmap | wrp->rxep_bitmap);
+ dsps_writeb(musb->mregs, MUSB_DEVCTL, 0);
+ dsps_writel(reg_base, wrp->eoi, 0);
+#endif
+}
+
+#ifndef __UBOOT__
+static void otg_timer(unsigned long _musb)
+{
+ struct musb *musb = (void *)_musb;
+ void __iomem *mregs = musb->mregs;
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ u8 devctl;
+ unsigned long flags;
+
+ /*
+ * We poll because DSPS IP's won't expose several OTG-critical
+ * status change events (from the transceiver) otherwise.
+ */
+ devctl = dsps_readb(mregs, MUSB_DEVCTL);
+ dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
+ otg_state_string(musb->xceiv->state));
+
+ spin_lock_irqsave(&musb->lock, flags);
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ devctl = dsps_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ } else {
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ }
+ break;
+ case OTG_STATE_A_WAIT_VFALL:
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ dsps_writel(musb->ctrl_base, wrp->coreintr_set,
+ MUSB_INTR_VBUSERROR << wrp->usb_shift);
+ break;
+ case OTG_STATE_B_IDLE:
+ if (!is_peripheral_enabled(musb))
+ break;
+
+ devctl = dsps_readb(mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE)
+ mod_timer(&glue->timer,
+ jiffies + wrp->poll_seconds * HZ);
+ else
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ break;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
+{
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ static unsigned long last_timer;
+
+ if (!is_otg_enabled(musb))
+ return;
+
+ if (timeout == 0)
+ timeout = jiffies + msecs_to_jiffies(3);
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || (musb->a_wait_bcon == 0 &&
+ musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
+ dev_dbg(musb->controller, "%s active, deleting timer\n",
+ otg_state_string(musb->xceiv->state));
+ del_timer(&glue->timer);
+ last_timer = jiffies;
+ return;
+ }
+
+ if (time_after(last_timer, timeout) && timer_pending(&glue->timer)) {
+ dev_dbg(musb->controller,
+ "Longer idle timer already pending, ignoring...\n");
+ return;
+ }
+ last_timer = timeout;
+
+ dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
+ otg_state_string(musb->xceiv->state),
+ jiffies_to_msecs(timeout - jiffies));
+ mod_timer(&glue->timer, timeout);
+}
+#endif
+
+static irqreturn_t dsps_interrupt(int irq, void *hci)
+{
+ struct musb *musb = hci;
+ void __iomem *reg_base = musb->ctrl_base;
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+#else
+ const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data;
+#endif
+ unsigned long flags;
+ irqreturn_t ret = IRQ_NONE;
+ u32 epintr, usbintr;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ /* Get endpoint interrupts */
+ epintr = dsps_readl(reg_base, wrp->epintr_status);
+ musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift;
+ musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift;
+
+ if (epintr)
+ dsps_writel(reg_base, wrp->epintr_status, epintr);
+
+ /* Get usb core interrupts */
+ usbintr = dsps_readl(reg_base, wrp->coreintr_status);
+ if (!usbintr && !epintr)
+ goto eoi;
+
+ musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift;
+ if (usbintr)
+ dsps_writel(reg_base, wrp->coreintr_status, usbintr);
+
+ dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n",
+ usbintr, epintr);
+#ifndef __UBOOT__
+ /*
+ * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
+ * DSPS IP's missing ID change IRQ. We need an ID change IRQ to
+ * switch appropriately between halves of the OTG state machine.
+ * Managing DEVCTL.SESSION per Mentor docs requires that we know its
+ * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
+ * Also, DRVVBUS pulses for SRP (but not at 5V) ...
+ */
+ if ((usbintr & MUSB_INTR_BABBLE) && is_host_enabled(musb))
+ pr_info("CAUTION: musb: Babble Interrupt Occured\n");
+
+ if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
+ int drvvbus = dsps_readl(reg_base, wrp->status);
+ void __iomem *mregs = musb->mregs;
+ u8 devctl = dsps_readb(mregs, MUSB_DEVCTL);
+ int err;
+
+ err = is_host_enabled(musb) && (musb->int_usb &
+ MUSB_INTR_VBUSERROR);
+ if (err) {
+ /*
+ * The Mentor core doesn't debounce VBUS as needed
+ * to cope with device connect current spikes. This
+ * means it's not uncommon for bus-powered devices
+ * to get VBUS errors during enumeration.
+ *
+ * This is a workaround, but newer RTL from Mentor
+ * seems to allow a better one: "re"-starting sessions
+ * without waiting for VBUS to stop registering in
+ * devctl.
+ */
+ musb->int_usb &= ~MUSB_INTR_VBUSERROR;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
+ mod_timer(&glue->timer,
+ jiffies + wrp->poll_seconds * HZ);
+ WARNING("VBUS error workaround (delay coming)\n");
+ } else if (is_host_enabled(musb) && drvvbus) {
+ musb->is_active = 1;
+ MUSB_HST_MODE(musb);
+ musb->xceiv->otg->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ del_timer(&glue->timer);
+ } else {
+ musb->is_active = 0;
+ MUSB_DEV_MODE(musb);
+ musb->xceiv->otg->default_a = 0;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ }
+
+ /* NOTE: this must complete power-on within 100 ms. */
+ dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
+ drvvbus ? "on" : "off",
+ otg_state_string(musb->xceiv->state),
+ err ? " ERROR" : "",
+ devctl);
+ ret = IRQ_HANDLED;
+ }
+#endif
+
+ if (musb->int_tx || musb->int_rx || musb->int_usb)
+ ret |= musb_interrupt(musb);
+
+ eoi:
+ /* EOI needs to be written for the IRQ to be re-asserted. */
+ if (ret == IRQ_HANDLED || epintr || usbintr)
+ dsps_writel(reg_base, wrp->eoi, 1);
+
+#ifndef __UBOOT__
+ /* Poll for ID change */
+ if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE)
+ mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
+#endif
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return ret;
+}
+
+static int dsps_musb_init(struct musb *musb)
+{
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+ const struct dsps_musb_wrapper *wrp = glue->wrp;
+ struct omap_musb_board_data *data = plat->board_data;
+#else
+ struct omap_musb_board_data *data =
+ (struct omap_musb_board_data *)musb->controller;
+ const struct dsps_musb_wrapper *wrp = &ti81xx_driver_data;
+#endif
+ void __iomem *reg_base = musb->ctrl_base;
+ u32 rev, val;
+ int status;
+
+ /* mentor core register starts at offset of 0x400 from musb base */
+ musb->mregs += wrp->musb_core_offset;
+
+#ifndef __UBOOT__
+ /* NOP driver needs change if supporting dual instance */
+ usb_nop_xceiv_register();
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv))
+ return -ENODEV;
+#endif
+
+ /* Returns zero if e.g. not clocked */
+ rev = dsps_readl(reg_base, wrp->revision);
+ if (!rev) {
+ status = -ENODEV;
+ goto err0;
+ }
+
+#ifndef __UBOOT__
+ if (is_host_enabled(musb))
+ setup_timer(&glue->timer, otg_timer, (unsigned long) musb);
+#endif
+
+ /* Reset the musb */
+ dsps_writel(reg_base, wrp->control, (1 << wrp->reset));
+
+ /* Start the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(1);
+
+ musb->isr = dsps_interrupt;
+
+ /* reset the otgdisable bit, needed for host mode to work */
+ val = dsps_readl(reg_base, wrp->phy_utmi);
+ val &= ~(1 << wrp->otg_disable);
+ dsps_writel(musb->ctrl_base, wrp->phy_utmi, val);
+
+ /* clear level interrupt */
+ dsps_writel(reg_base, wrp->eoi, 0);
+
+ return 0;
+err0:
+#ifndef __UBOOT__
+ usb_put_phy(musb->xceiv);
+ usb_nop_xceiv_unregister();
+#endif
+ return status;
+}
+
+static int dsps_musb_exit(struct musb *musb)
+{
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+ struct platform_device *pdev = to_platform_device(dev->parent);
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+#else
+ struct omap_musb_board_data *data =
+ (struct omap_musb_board_data *)musb->controller;
+#endif
+
+#ifndef __UBOOT__
+ if (is_host_enabled(musb))
+ del_timer_sync(&glue->timer);
+#endif
+
+ /* Shutdown the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(0);
+
+#ifndef __UBOOT__
+ /* NOP driver needs change if supporting dual instance */
+ usb_put_phy(musb->xceiv);
+ usb_nop_xceiv_unregister();
+#endif
+
+ return 0;
+}
+
+#ifndef __UBOOT__
+static struct musb_platform_ops dsps_ops = {
+#else
+struct musb_platform_ops musb_dsps_ops = {
+#endif
+ .init = dsps_musb_init,
+ .exit = dsps_musb_exit,
+
+ .enable = dsps_musb_enable,
+ .disable = dsps_musb_disable,
+
+#ifndef __UBOOT__
+ .try_idle = dsps_musb_try_idle,
+#endif
+};
+
+#ifndef __UBOOT__
+static u64 musb_dmamask = DMA_BIT_MASK(32);
+#endif
+
+#ifndef __UBOOT__
+static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
+{
+ struct device *dev = glue->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct musb_hdrc_platform_data *pdata = dev->platform_data;
+ struct platform_device *musb;
+ struct resource *res;
+ struct resource resources[2];
+ char res_name[10];
+ int ret;
+
+ /* get memory resource */
+ sprintf(res_name, "musb%d", id);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
+ if (!res) {
+ dev_err(dev, "%s get mem resource failed\n", res_name);
+ ret = -ENODEV;
+ goto err0;
+ }
+ res->parent = NULL;
+ resources[0] = *res;
+
+ /* get irq resource */
+ sprintf(res_name, "musb%d-irq", id);
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
+ if (!res) {
+ dev_err(dev, "%s get irq resource failed\n", res_name);
+ ret = -ENODEV;
+ goto err0;
+ }
+ res->parent = NULL;
+ resources[1] = *res;
+ resources[1].name = "mc";
+
+ /* allocate the child platform device */
+ musb = platform_device_alloc("musb-hdrc", -1);
+ if (!musb) {
+ dev_err(dev, "failed to allocate musb device\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ musb->dev.parent = dev;
+ musb->dev.dma_mask = &musb_dmamask;
+ musb->dev.coherent_dma_mask = musb_dmamask;
+
+ glue->musb = musb;
+
+ pdata->platform_ops = &dsps_ops;
+
+ ret = platform_device_add_resources(musb, resources, 2);
+ if (ret) {
+ dev_err(dev, "failed to add resources\n");
+ goto err1;
+ }
+
+ ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(dev, "failed to add platform_data\n");
+ goto err1;
+ }
+
+ ret = platform_device_add(musb);
+ if (ret) {
+ dev_err(dev, "failed to register musb device\n");
+ goto err1;
+ }
+
+ return 0;
+
+err1:
+ platform_device_put(musb);
+err0:
+ return ret;
+}
+
+static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue)
+{
+ platform_device_del(glue->musb);
+ platform_device_put(glue->musb);
+}
+
+static int __devinit dsps_probe(struct platform_device *pdev)
+{
+ const struct platform_device_id *id = platform_get_device_id(pdev);
+ const struct dsps_musb_wrapper *wrp =
+ (struct dsps_musb_wrapper *)id->driver_data;
+ struct dsps_glue *glue;
+ struct resource *iomem;
+ int ret;
+
+ /* allocate glue */
+ glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+ if (!glue) {
+ dev_err(&pdev->dev, "unable to allocate glue memory\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ /* get memory resource */
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iomem) {
+ dev_err(&pdev->dev, "failed to get usbss mem resourse\n");
+ ret = -ENODEV;
+ goto err1;
+ }
+
+ glue->dev = &pdev->dev;
+
+ glue->wrp = kmemdup(wrp, sizeof(*wrp), GFP_KERNEL);
+ if (!glue->wrp) {
+ dev_err(&pdev->dev, "failed to duplicate wrapper struct memory\n");
+ ret = -ENOMEM;
+ goto err1;
+ }
+ platform_set_drvdata(pdev, glue);
+
+ /* enable the usbss clocks */
+ pm_runtime_enable(&pdev->dev);
+
+ ret = pm_runtime_get_sync(&pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "pm_runtime_get_sync FAILED");
+ goto err2;
+ }
+
+ /* create the child platform device for first instances of musb */
+ ret = dsps_create_musb_pdev(glue, 0);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to create child pdev\n");
+ goto err3;
+ }
+
+ return 0;
+
+err3:
+ pm_runtime_put(&pdev->dev);
+err2:
+ pm_runtime_disable(&pdev->dev);
+ kfree(glue->wrp);
+err1:
+ kfree(glue);
+err0:
+ return ret;
+}
+static int __devexit dsps_remove(struct platform_device *pdev)
+{
+ struct dsps_glue *glue = platform_get_drvdata(pdev);
+
+ /* delete the child platform device */
+ dsps_delete_musb_pdev(glue);
+
+ /* disable usbss clocks */
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ kfree(glue->wrp);
+ kfree(glue);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int dsps_suspend(struct device *dev)
+{
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+
+ /* Shutdown the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(0);
+
+ return 0;
+}
+
+static int dsps_resume(struct device *dev)
+{
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+
+ /* Start the on-chip PHY and its PLL. */
+ if (data->set_phy_power)
+ data->set_phy_power(1);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
+#endif
+
+#ifndef __UBOOT__
+static const struct platform_device_id musb_dsps_id_table[] __devinitconst = {
+ {
+ .name = "musb-ti81xx",
+ .driver_data = (kernel_ulong_t) &ti81xx_driver_data,
+ },
+ { }, /* Terminating Entry */
+};
+MODULE_DEVICE_TABLE(platform, musb_dsps_id_table);
+
+static const struct of_device_id musb_dsps_of_match[] __devinitconst = {
+ { .compatible = "musb-ti81xx", },
+ { .compatible = "ti,ti81xx-musb", },
+ { .compatible = "ti,am335x-musb", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
+
+static struct platform_driver dsps_usbss_driver = {
+ .probe = dsps_probe,
+ .remove = __devexit_p(dsps_remove),
+ .driver = {
+ .name = "musb-dsps",
+ .pm = &dsps_pm_ops,
+ .of_match_table = musb_dsps_of_match,
+ },
+ .id_table = musb_dsps_id_table,
+};
+
+MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer");
+MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
+MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init dsps_init(void)
+{
+ return platform_driver_register(&dsps_usbss_driver);
+}
+subsys_initcall(dsps_init);
+
+static void __exit dsps_exit(void)
+{
+ platform_driver_unregister(&dsps_usbss_driver);
+}
+module_exit(dsps_exit);
+#endif
diff --git a/drivers/usb/musb-new/musb_gadget.c b/drivers/usb/musb-new/musb_gadget.c
new file mode 100644
index 0000000000..d2cb91a898
--- /dev/null
+++ b/drivers/usb/musb-new/musb_gadget.c
@@ -0,0 +1,2333 @@
+/*
+ * MUSB OTG driver peripheral support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#else
+#include <common.h>
+#include <linux/usb/ch9.h>
+#include "linux-compat.h"
+#endif
+
+#include "musb_core.h"
+
+
+/* MUSB PERIPHERAL status 3-mar-2006:
+ *
+ * - EP0 seems solid. It passes both USBCV and usbtest control cases.
+ * Minor glitches:
+ *
+ * + remote wakeup to Linux hosts work, but saw USBCV failures;
+ * in one test run (operator error?)
+ * + endpoint halt tests -- in both usbtest and usbcv -- seem
+ * to break when dma is enabled ... is something wrongly
+ * clearing SENDSTALL?
+ *
+ * - Mass storage behaved ok when last tested. Network traffic patterns
+ * (with lots of short transfers etc) need retesting; they turn up the
+ * worst cases of the DMA, since short packets are typical but are not
+ * required.
+ *
+ * - TX/IN
+ * + both pio and dma behave in with network and g_zero tests
+ * + no cppi throughput issues other than no-hw-queueing
+ * + failed with FLAT_REG (DaVinci)
+ * + seems to behave with double buffering, PIO -and- CPPI
+ * + with gadgetfs + AIO, requests got lost?
+ *
+ * - RX/OUT
+ * + both pio and dma behave in with network and g_zero tests
+ * + dma is slow in typical case (short_not_ok is clear)
+ * + double buffering ok with PIO
+ * + double buffering *FAILS* with CPPI, wrong data bytes sometimes
+ * + request lossage observed with gadgetfs
+ *
+ * - ISO not tested ... might work, but only weakly isochronous
+ *
+ * - Gadget driver disabling of softconnect during bind() is ignored; so
+ * drivers can't hold off host requests until userspace is ready.
+ * (Workaround: they can turn it off later.)
+ *
+ * - PORTABILITY (assumes PIO works):
+ * + DaVinci, basically works with cppi dma
+ * + OMAP 2430, ditto with mentor dma
+ * + TUSB 6010, platform-specific dma in the works
+ */
+
+/* ----------------------------------------------------------------------- */
+
+#define is_buffer_mapped(req) (is_dma_capable() && \
+ (req->map_state != UN_MAPPED))
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+/* Maps the buffer to dma */
+
+static inline void map_dma_buffer(struct musb_request *request,
+ struct musb *musb, struct musb_ep *musb_ep)
+{
+ int compatible = true;
+ struct dma_controller *dma = musb->dma_controller;
+
+ request->map_state = UN_MAPPED;
+
+ if (!is_dma_capable() || !musb_ep->dma)
+ return;
+
+ /* Check if DMA engine can handle this request.
+ * DMA code must reject the USB request explicitly.
+ * Default behaviour is to map the request.
+ */
+ if (dma->is_compatible)
+ compatible = dma->is_compatible(musb_ep->dma,
+ musb_ep->packet_sz, request->request.buf,
+ request->request.length);
+ if (!compatible)
+ return;
+
+ if (request->request.dma == DMA_ADDR_INVALID) {
+ request->request.dma = dma_map_single(
+ musb->controller,
+ request->request.buf,
+ request->request.length,
+ request->tx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ request->map_state = MUSB_MAPPED;
+ } else {
+ dma_sync_single_for_device(musb->controller,
+ request->request.dma,
+ request->request.length,
+ request->tx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ request->map_state = PRE_MAPPED;
+ }
+}
+
+/* Unmap the buffer from dma and maps it back to cpu */
+static inline void unmap_dma_buffer(struct musb_request *request,
+ struct musb *musb)
+{
+ if (!is_buffer_mapped(request))
+ return;
+
+ if (request->request.dma == DMA_ADDR_INVALID) {
+ dev_vdbg(musb->controller,
+ "not unmapping a never mapped buffer\n");
+ return;
+ }
+ if (request->map_state == MUSB_MAPPED) {
+ dma_unmap_single(musb->controller,
+ request->request.dma,
+ request->request.length,
+ request->tx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ request->request.dma = DMA_ADDR_INVALID;
+ } else { /* PRE_MAPPED */
+ dma_sync_single_for_cpu(musb->controller,
+ request->request.dma,
+ request->request.length,
+ request->tx
+ ? DMA_TO_DEVICE
+ : DMA_FROM_DEVICE);
+ }
+ request->map_state = UN_MAPPED;
+}
+#else
+static inline void map_dma_buffer(struct musb_request *request,
+ struct musb *musb, struct musb_ep *musb_ep)
+{
+}
+
+static inline void unmap_dma_buffer(struct musb_request *request,
+ struct musb *musb)
+{
+}
+#endif
+
+/*
+ * Immediately complete a request.
+ *
+ * @param request the request to complete
+ * @param status the status to complete the request with
+ * Context: controller locked, IRQs blocked.
+ */
+void musb_g_giveback(
+ struct musb_ep *ep,
+ struct usb_request *request,
+ int status)
+__releases(ep->musb->lock)
+__acquires(ep->musb->lock)
+{
+ struct musb_request *req;
+ struct musb *musb;
+ int busy = ep->busy;
+
+ req = to_musb_request(request);
+
+ list_del(&req->list);
+ if (req->request.status == -EINPROGRESS)
+ req->request.status = status;
+ musb = req->musb;
+
+ ep->busy = 1;
+ spin_unlock(&musb->lock);
+ unmap_dma_buffer(req, musb);
+ if (request->status == 0)
+ dev_dbg(musb->controller, "%s done request %p, %d/%d\n",
+ ep->end_point.name, request,
+ req->request.actual, req->request.length);
+ else
+ dev_dbg(musb->controller, "%s request %p, %d/%d fault %d\n",
+ ep->end_point.name, request,
+ req->request.actual, req->request.length,
+ request->status);
+ req->request.complete(&req->ep->end_point, &req->request);
+ spin_lock(&musb->lock);
+ ep->busy = busy;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Abort requests queued to an endpoint using the status. Synchronous.
+ * caller locked controller and blocked irqs, and selected this ep.
+ */
+static void nuke(struct musb_ep *ep, const int status)
+{
+ struct musb *musb = ep->musb;
+ struct musb_request *req = NULL;
+ void __iomem *epio = ep->musb->endpoints[ep->current_epnum].regs;
+
+ ep->busy = 1;
+
+ if (is_dma_capable() && ep->dma) {
+ struct dma_controller *c = ep->musb->dma_controller;
+ int value;
+
+ if (ep->is_in) {
+ /*
+ * The programming guide says that we must not clear
+ * the DMAMODE bit before DMAENAB, so we only
+ * clear it in the second write...
+ */
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO);
+ musb_writew(epio, MUSB_TXCSR,
+ 0 | MUSB_TXCSR_FLUSHFIFO);
+ } else {
+ musb_writew(epio, MUSB_RXCSR,
+ 0 | MUSB_RXCSR_FLUSHFIFO);
+ musb_writew(epio, MUSB_RXCSR,
+ 0 | MUSB_RXCSR_FLUSHFIFO);
+ }
+
+ value = c->channel_abort(ep->dma);
+ dev_dbg(musb->controller, "%s: abort DMA --> %d\n",
+ ep->name, value);
+ c->channel_release(ep->dma);
+ ep->dma = NULL;
+ }
+
+ while (!list_empty(&ep->req_list)) {
+ req = list_first_entry(&ep->req_list, struct musb_request, list);
+ musb_g_giveback(ep, &req->request, status);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* Data transfers - pure PIO, pure DMA, or mixed mode */
+
+/*
+ * This assumes the separate CPPI engine is responding to DMA requests
+ * from the usb core ... sequenced a bit differently from mentor dma.
+ */
+
+static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
+{
+ if (can_bulk_split(musb, ep->type))
+ return ep->hw_ep->max_packet_sz_tx;
+ else
+ return ep->packet_sz;
+}
+
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Peripheral tx (IN) using Mentor DMA works as follows:
+ Only mode 0 is used for transfers <= wPktSize,
+ mode 1 is used for larger transfers,
+
+ One of the following happens:
+ - Host sends IN token which causes an endpoint interrupt
+ -> TxAvail
+ -> if DMA is currently busy, exit.
+ -> if queue is non-empty, txstate().
+
+ - Request is queued by the gadget driver.
+ -> if queue was previously empty, txstate()
+
+ txstate()
+ -> start
+ /\ -> setup DMA
+ | (data is transferred to the FIFO, then sent out when
+ | IN token(s) are recd from Host.
+ | -> DMA interrupt on completion
+ | calls TxAvail.
+ | -> stop DMA, ~DMAENAB,
+ | -> set TxPktRdy for last short pkt or zlp
+ | -> Complete Request
+ | -> Continue next request (call txstate)
+ |___________________________________|
+
+ * Non-Mentor DMA engines can of course work differently, such as by
+ * upleveling from irq-per-packet to irq-per-buffer.
+ */
+
+#endif
+
+/*
+ * An endpoint is transmitting data. This can be called either from
+ * the IRQ routine or from ep.queue() to kickstart a request on an
+ * endpoint.
+ *
+ * Context: controller locked, IRQs blocked, endpoint selected
+ */
+static void txstate(struct musb *musb, struct musb_request *req)
+{
+ u8 epnum = req->epnum;
+ struct musb_ep *musb_ep;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ struct usb_request *request;
+ u16 fifo_count = 0, csr;
+ int use_dma = 0;
+
+ musb_ep = req->ep;
+
+ /* Check if EP is disabled */
+ if (!musb_ep->desc) {
+ dev_dbg(musb->controller, "ep:%s disabled - ignore request\n",
+ musb_ep->end_point.name);
+ return;
+ }
+
+ /* we shouldn't get here while DMA is active ... but we do ... */
+ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
+ dev_dbg(musb->controller, "dma pending...\n");
+ return;
+ }
+
+ /* read TXCSR before */
+ csr = musb_readw(epio, MUSB_TXCSR);
+
+ request = &req->request;
+ fifo_count = min(max_ep_writesize(musb, musb_ep),
+ (int)(request->length - request->actual));
+
+ if (csr & MUSB_TXCSR_TXPKTRDY) {
+ dev_dbg(musb->controller, "%s old packet still ready , txcsr %03x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
+
+ if (csr & MUSB_TXCSR_P_SENDSTALL) {
+ dev_dbg(musb->controller, "%s stalling, txcsr %03x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
+
+ dev_dbg(musb->controller, "hw_ep%d, maxpacket %d, fifo count %d, txcsr %03x\n",
+ epnum, musb_ep->packet_sz, fifo_count,
+ csr);
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+ if (is_buffer_mapped(req)) {
+ struct dma_controller *c = musb->dma_controller;
+ size_t request_size;
+
+ /* setup DMA, then program endpoint CSR */
+ request_size = min_t(size_t, request->length - request->actual,
+ musb_ep->dma->max_len);
+
+ use_dma = (request->dma != DMA_ADDR_INVALID);
+
+ /* MUSB_TXCSR_P_ISO is still set correctly */
+
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
+ {
+ if (request_size < musb_ep->packet_sz)
+ musb_ep->dma->desired_mode = 0;
+ else
+ musb_ep->dma->desired_mode = 1;
+
+ use_dma = use_dma && c->channel_program(
+ musb_ep->dma, musb_ep->packet_sz,
+ musb_ep->dma->desired_mode,
+ request->dma + request->actual, request_size);
+ if (use_dma) {
+ if (musb_ep->dma->desired_mode == 0) {
+ /*
+ * We must not clear the DMAMODE bit
+ * before the DMAENAB bit -- and the
+ * latter doesn't always get cleared
+ * before we get here...
+ */
+ csr &= ~(MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB);
+ musb_writew(epio, MUSB_TXCSR, csr
+ | MUSB_TXCSR_P_WZC_BITS);
+ csr &= ~MUSB_TXCSR_DMAMODE;
+ csr |= (MUSB_TXCSR_DMAENAB |
+ MUSB_TXCSR_MODE);
+ /* against programming guide */
+ } else {
+ csr |= (MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_DMAMODE
+ | MUSB_TXCSR_MODE);
+ if (!musb_ep->hb_mult)
+ csr |= MUSB_TXCSR_AUTOSET;
+ }
+ csr &= ~MUSB_TXCSR_P_UNDERRUN;
+
+ musb_writew(epio, MUSB_TXCSR, csr);
+ }
+ }
+
+#elif defined(CONFIG_USB_TI_CPPI_DMA)
+ /* program endpoint CSR first, then setup DMA */
+ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+ csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE |
+ MUSB_TXCSR_MODE;
+ musb_writew(epio, MUSB_TXCSR,
+ (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN)
+ | csr);
+
+ /* ensure writebuffer is empty */
+ csr = musb_readw(epio, MUSB_TXCSR);
+
+ /* NOTE host side sets DMAENAB later than this; both are
+ * OK since the transfer dma glue (between CPPI and Mentor
+ * fifos) just tells CPPI it could start. Data only moves
+ * to the USB TX fifo when both fifos are ready.
+ */
+
+ /* "mode" is irrelevant here; handle terminating ZLPs like
+ * PIO does, since the hardware RNDIS mode seems unreliable
+ * except for the last-packet-is-already-short case.
+ */
+ use_dma = use_dma && c->channel_program(
+ musb_ep->dma, musb_ep->packet_sz,
+ 0,
+ request->dma + request->actual,
+ request_size);
+ if (!use_dma) {
+ c->channel_release(musb_ep->dma);
+ musb_ep->dma = NULL;
+ csr &= ~MUSB_TXCSR_DMAENAB;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* invariant: prequest->buf is non-null */
+ }
+#elif defined(CONFIG_USB_TUSB_OMAP_DMA)
+ use_dma = use_dma && c->channel_program(
+ musb_ep->dma, musb_ep->packet_sz,
+ request->zero,
+ request->dma + request->actual,
+ request_size);
+#endif
+ }
+#endif
+
+ if (!use_dma) {
+ /*
+ * Unmap the dma buffer back to cpu if dma channel
+ * programming fails
+ */
+ unmap_dma_buffer(req, musb);
+
+ musb_write_fifo(musb_ep->hw_ep, fifo_count,
+ (u8 *) (request->buf + request->actual));
+ request->actual += fifo_count;
+ csr |= MUSB_TXCSR_TXPKTRDY;
+ csr &= ~MUSB_TXCSR_P_UNDERRUN;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ }
+
+ /* host may already have the data when this message shows... */
+ dev_dbg(musb->controller, "%s TX/IN %s len %d/%d, txcsr %04x, fifo %d/%d\n",
+ musb_ep->end_point.name, use_dma ? "dma" : "pio",
+ request->actual, request->length,
+ musb_readw(epio, MUSB_TXCSR),
+ fifo_count,
+ musb_readw(epio, MUSB_TXMAXP));
+}
+
+/*
+ * FIFO state update (e.g. data ready).
+ * Called from IRQ, with controller locked.
+ */
+void musb_g_tx(struct musb *musb, u8 epnum)
+{
+ u16 csr;
+ struct musb_request *req;
+ struct usb_request *request;
+ u8 __iomem *mbase = musb->mregs;
+ struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_in;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ struct dma_channel *dma;
+
+ musb_ep_select(mbase, epnum);
+ req = next_request(musb_ep);
+ request = &req->request;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ dev_dbg(musb->controller, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr);
+
+ dma = is_dma_capable() ? musb_ep->dma : NULL;
+
+ /*
+ * REVISIT: for high bandwidth, MUSB_TXCSR_P_INCOMPTX
+ * probably rates reporting as a host error.
+ */
+ if (csr & MUSB_TXCSR_P_SENTSTALL) {
+ csr |= MUSB_TXCSR_P_WZC_BITS;
+ csr &= ~MUSB_TXCSR_P_SENTSTALL;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ return;
+ }
+
+ if (csr & MUSB_TXCSR_P_UNDERRUN) {
+ /* We NAKed, no big deal... little reason to care. */
+ csr |= MUSB_TXCSR_P_WZC_BITS;
+ csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR, csr);
+ dev_vdbg(musb->controller, "underrun on ep%d, req %p\n",
+ epnum, request);
+ }
+
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ /*
+ * SHOULD NOT HAPPEN... has with CPPI though, after
+ * changing SENDSTALL (and other cases); harmless?
+ */
+ dev_dbg(musb->controller, "%s dma still busy?\n", musb_ep->end_point.name);
+ return;
+ }
+
+ if (request) {
+ u8 is_dma = 0;
+
+ if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
+ is_dma = 1;
+ csr |= MUSB_TXCSR_P_WZC_BITS;
+ csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
+ MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* Ensure writebuffer is empty. */
+ csr = musb_readw(epio, MUSB_TXCSR);
+ request->actual += musb_ep->dma->actual_len;
+ dev_dbg(musb->controller, "TXCSR%d %04x, DMA off, len %zu, req %p\n",
+ epnum, csr, musb_ep->dma->actual_len, request);
+ }
+
+ /*
+ * First, maybe a terminating short packet. Some DMA
+ * engines might handle this by themselves.
+ */
+ if ((request->zero && request->length
+ && (request->length % musb_ep->packet_sz == 0)
+ && (request->actual == request->length))
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
+ || (is_dma && (!dma->desired_mode ||
+ (request->actual &
+ (musb_ep->packet_sz - 1))))
+#endif
+ ) {
+ /*
+ * On DMA completion, FIFO may not be
+ * available yet...
+ */
+ if (csr & MUSB_TXCSR_TXPKTRDY)
+ return;
+
+ dev_dbg(musb->controller, "sending zero pkt\n");
+ musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE
+ | MUSB_TXCSR_TXPKTRDY);
+ request->zero = 0;
+ }
+
+ if (request->actual == request->length) {
+ musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by the gadget_queue function especially
+ * on SMP systems. Reselect the INDEX to be sure
+ * we are reading/modifying the right registers
+ */
+ musb_ep_select(mbase, epnum);
+ req = musb_ep->desc ? next_request(musb_ep) : NULL;
+ if (!req) {
+ dev_dbg(musb->controller, "%s idle now\n",
+ musb_ep->end_point.name);
+ return;
+ }
+ }
+
+ txstate(musb, req);
+ }
+}
+
+/* ------------------------------------------------------------ */
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Peripheral rx (OUT) using Mentor DMA works as follows:
+ - Only mode 0 is used.
+
+ - Request is queued by the gadget class driver.
+ -> if queue was previously empty, rxstate()
+
+ - Host sends OUT token which causes an endpoint interrupt
+ /\ -> RxReady
+ | -> if request queued, call rxstate
+ | /\ -> setup DMA
+ | | -> DMA interrupt on completion
+ | | -> RxReady
+ | | -> stop DMA
+ | | -> ack the read
+ | | -> if data recd = max expected
+ | | by the request, or host
+ | | sent a short packet,
+ | | complete the request,
+ | | and start the next one.
+ | |_____________________________________|
+ | else just wait for the host
+ | to send the next OUT token.
+ |__________________________________________________|
+
+ * Non-Mentor DMA engines can of course work differently.
+ */
+
+#endif
+
+/*
+ * Context: controller locked, IRQs blocked, endpoint selected
+ */
+static void rxstate(struct musb *musb, struct musb_request *req)
+{
+ const u8 epnum = req->epnum;
+ struct usb_request *request = &req->request;
+ struct musb_ep *musb_ep;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ unsigned fifo_count = 0;
+ u16 len;
+ u16 csr = musb_readw(epio, MUSB_RXCSR);
+ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
+ u8 use_mode_1;
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep = &hw_ep->ep_in;
+ else
+ musb_ep = &hw_ep->ep_out;
+
+ len = musb_ep->packet_sz;
+
+ /* Check if EP is disabled */
+ if (!musb_ep->desc) {
+ dev_dbg(musb->controller, "ep:%s disabled - ignore request\n",
+ musb_ep->end_point.name);
+ return;
+ }
+
+ /* We shouldn't get here while DMA is active, but we do... */
+ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
+ dev_dbg(musb->controller, "DMA pending...\n");
+ return;
+ }
+
+ if (csr & MUSB_RXCSR_P_SENDSTALL) {
+ dev_dbg(musb->controller, "%s stalling, RXCSR %04x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
+
+ if (is_cppi_enabled() && is_buffer_mapped(req)) {
+ struct dma_controller *c = musb->dma_controller;
+ struct dma_channel *channel = musb_ep->dma;
+
+ /* NOTE: CPPI won't actually stop advancing the DMA
+ * queue after short packet transfers, so this is almost
+ * always going to run as IRQ-per-packet DMA so that
+ * faults will be handled correctly.
+ */
+ if (c->channel_program(channel,
+ musb_ep->packet_sz,
+ !request->short_not_ok,
+ request->dma + request->actual,
+ request->length - request->actual)) {
+
+ /* make sure that if an rxpkt arrived after the irq,
+ * the cppi engine will be ready to take it as soon
+ * as DMA is enabled
+ */
+ csr &= ~(MUSB_RXCSR_AUTOCLEAR
+ | MUSB_RXCSR_DMAMODE);
+ csr |= MUSB_RXCSR_DMAENAB | MUSB_RXCSR_P_WZC_BITS;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ return;
+ }
+ }
+
+ if (csr & MUSB_RXCSR_RXPKTRDY) {
+ len = musb_readw(epio, MUSB_RXCOUNT);
+
+ /*
+ * Enable Mode 1 on RX transfers only when short_not_ok flag
+ * is set. Currently short_not_ok flag is set only from
+ * file_storage and f_mass_storage drivers
+ */
+
+ if (request->short_not_ok && len == musb_ep->packet_sz)
+ use_mode_1 = 1;
+ else
+ use_mode_1 = 0;
+
+ if (request->actual < request->length) {
+#ifdef CONFIG_USB_INVENTRA_DMA
+ if (is_buffer_mapped(req)) {
+ struct dma_controller *c;
+ struct dma_channel *channel;
+ int use_dma = 0;
+
+ c = musb->dma_controller;
+ channel = musb_ep->dma;
+
+ /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+ * mode 0 only. So we do not get endpoint interrupts due to DMA
+ * completion. We only get interrupts from DMA controller.
+ *
+ * We could operate in DMA mode 1 if we knew the size of the tranfer
+ * in advance. For mass storage class, request->length = what the host
+ * sends, so that'd work. But for pretty much everything else,
+ * request->length is routinely more than what the host sends. For
+ * most these gadgets, end of is signified either by a short packet,
+ * or filling the last byte of the buffer. (Sending extra data in
+ * that last pckate should trigger an overflow fault.) But in mode 1,
+ * we don't get DMA completion interrupt for short packets.
+ *
+ * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+ * to get endpoint interrupt on every DMA req, but that didn't seem
+ * to work reliably.
+ *
+ * REVISIT an updated g_file_storage can set req->short_not_ok, which
+ * then becomes usable as a runtime "use mode 1" hint...
+ */
+
+ /* Experimental: Mode1 works with mass storage use cases */
+ if (use_mode_1) {
+ csr |= MUSB_RXCSR_AUTOCLEAR;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ csr |= MUSB_RXCSR_DMAENAB;
+ musb_writew(epio, MUSB_RXCSR, csr);
+
+ /*
+ * this special sequence (enabling and then
+ * disabling MUSB_RXCSR_DMAMODE) is required
+ * to get DMAReq to activate
+ */
+ musb_writew(epio, MUSB_RXCSR,
+ csr | MUSB_RXCSR_DMAMODE);
+ musb_writew(epio, MUSB_RXCSR, csr);
+
+ } else {
+ if (!musb_ep->hb_mult &&
+ musb_ep->hw_ep->rx_double_buffered)
+ csr |= MUSB_RXCSR_AUTOCLEAR;
+ csr |= MUSB_RXCSR_DMAENAB;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ if (request->actual < request->length) {
+ int transfer_size = 0;
+ if (use_mode_1) {
+ transfer_size = min(request->length - request->actual,
+ channel->max_len);
+ musb_ep->dma->desired_mode = 1;
+ } else {
+ transfer_size = min(request->length - request->actual,
+ (unsigned)len);
+ musb_ep->dma->desired_mode = 0;
+ }
+
+ use_dma = c->channel_program(
+ channel,
+ musb_ep->packet_sz,
+ channel->desired_mode,
+ request->dma
+ + request->actual,
+ transfer_size);
+ }
+
+ if (use_dma)
+ return;
+ }
+#elif defined(CONFIG_USB_UX500_DMA)
+ if ((is_buffer_mapped(req)) &&
+ (request->actual < request->length)) {
+
+ struct dma_controller *c;
+ struct dma_channel *channel;
+ int transfer_size = 0;
+
+ c = musb->dma_controller;
+ channel = musb_ep->dma;
+
+ /* In case first packet is short */
+ if (len < musb_ep->packet_sz)
+ transfer_size = len;
+ else if (request->short_not_ok)
+ transfer_size = min(request->length -
+ request->actual,
+ channel->max_len);
+ else
+ transfer_size = min(request->length -
+ request->actual,
+ (unsigned)len);
+
+ csr &= ~MUSB_RXCSR_DMAMODE;
+ csr |= (MUSB_RXCSR_DMAENAB |
+ MUSB_RXCSR_AUTOCLEAR);
+
+ musb_writew(epio, MUSB_RXCSR, csr);
+
+ if (transfer_size <= musb_ep->packet_sz) {
+ musb_ep->dma->desired_mode = 0;
+ } else {
+ musb_ep->dma->desired_mode = 1;
+ /* Mode must be set after DMAENAB */
+ csr |= MUSB_RXCSR_DMAMODE;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ if (c->channel_program(channel,
+ musb_ep->packet_sz,
+ channel->desired_mode,
+ request->dma
+ + request->actual,
+ transfer_size))
+
+ return;
+ }
+#endif /* Mentor's DMA */
+
+ fifo_count = request->length - request->actual;
+ dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
+ musb_ep->end_point.name,
+ len, fifo_count,
+ musb_ep->packet_sz);
+
+ fifo_count = min_t(unsigned, len, fifo_count);
+
+#ifdef CONFIG_USB_TUSB_OMAP_DMA
+ if (tusb_dma_omap() && is_buffer_mapped(req)) {
+ struct dma_controller *c = musb->dma_controller;
+ struct dma_channel *channel = musb_ep->dma;
+ u32 dma_addr = request->dma + request->actual;
+ int ret;
+
+ ret = c->channel_program(channel,
+ musb_ep->packet_sz,
+ channel->desired_mode,
+ dma_addr,
+ fifo_count);
+ if (ret)
+ return;
+ }
+#endif
+ /*
+ * Unmap the dma buffer back to cpu if dma channel
+ * programming fails. This buffer is mapped if the
+ * channel allocation is successful
+ */
+ if (is_buffer_mapped(req)) {
+ unmap_dma_buffer(req, musb);
+
+ /*
+ * Clear DMAENAB and AUTOCLEAR for the
+ * PIO mode transfer
+ */
+ csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
+ (request->buf + request->actual));
+ request->actual += fifo_count;
+
+ /* REVISIT if we left anything in the fifo, flush
+ * it and report -EOVERFLOW
+ */
+
+ /* ack the read! */
+ csr |= MUSB_RXCSR_P_WZC_BITS;
+ csr &= ~MUSB_RXCSR_RXPKTRDY;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+ }
+
+ /* reach the end or short packet detected */
+ if (request->actual == request->length || len < musb_ep->packet_sz)
+ musb_g_giveback(musb_ep, request, 0);
+}
+
+/*
+ * Data ready for a request; called from IRQ
+ */
+void musb_g_rx(struct musb *musb, u8 epnum)
+{
+ u16 csr;
+ struct musb_request *req;
+ struct usb_request *request;
+ void __iomem *mbase = musb->mregs;
+ struct musb_ep *musb_ep;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ struct dma_channel *dma;
+ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep = &hw_ep->ep_in;
+ else
+ musb_ep = &hw_ep->ep_out;
+
+ musb_ep_select(mbase, epnum);
+
+ req = next_request(musb_ep);
+ if (!req)
+ return;
+
+ request = &req->request;
+
+ csr = musb_readw(epio, MUSB_RXCSR);
+ dma = is_dma_capable() ? musb_ep->dma : NULL;
+
+ dev_dbg(musb->controller, "<== %s, rxcsr %04x%s %p\n", musb_ep->end_point.name,
+ csr, dma ? " (dma)" : "", request);
+
+ if (csr & MUSB_RXCSR_P_SENTSTALL) {
+ csr |= MUSB_RXCSR_P_WZC_BITS;
+ csr &= ~MUSB_RXCSR_P_SENTSTALL;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ return;
+ }
+
+ if (csr & MUSB_RXCSR_P_OVERRUN) {
+ /* csr |= MUSB_RXCSR_P_WZC_BITS; */
+ csr &= ~MUSB_RXCSR_P_OVERRUN;
+ musb_writew(epio, MUSB_RXCSR, csr);
+
+ dev_dbg(musb->controller, "%s iso overrun on %p\n", musb_ep->name, request);
+ if (request->status == -EINPROGRESS)
+ request->status = -EOVERFLOW;
+ }
+ if (csr & MUSB_RXCSR_INCOMPRX) {
+ /* REVISIT not necessarily an error */
+ dev_dbg(musb->controller, "%s, incomprx\n", musb_ep->end_point.name);
+ }
+
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ /* "should not happen"; likely RXPKTRDY pending for DMA */
+ dev_dbg(musb->controller, "%s busy, csr %04x\n",
+ musb_ep->end_point.name, csr);
+ return;
+ }
+
+ if (dma && (csr & MUSB_RXCSR_DMAENAB)) {
+ csr &= ~(MUSB_RXCSR_AUTOCLEAR
+ | MUSB_RXCSR_DMAENAB
+ | MUSB_RXCSR_DMAMODE);
+ musb_writew(epio, MUSB_RXCSR,
+ MUSB_RXCSR_P_WZC_BITS | csr);
+
+ request->actual += musb_ep->dma->actual_len;
+
+ dev_dbg(musb->controller, "RXCSR%d %04x, dma off, %04x, len %zu, req %p\n",
+ epnum, csr,
+ musb_readw(epio, MUSB_RXCSR),
+ musb_ep->dma->actual_len, request);
+
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) || \
+ defined(CONFIG_USB_UX500_DMA)
+ /* Autoclear doesn't clear RxPktRdy for short packets */
+ if ((dma->desired_mode == 0 && !hw_ep->rx_double_buffered)
+ || (dma->actual_len
+ & (musb_ep->packet_sz - 1))) {
+ /* ack the read! */
+ csr &= ~MUSB_RXCSR_RXPKTRDY;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ /* incomplete, and not short? wait for next IN packet */
+ if ((request->actual < request->length)
+ && (musb_ep->dma->actual_len
+ == musb_ep->packet_sz)) {
+ /* In double buffer case, continue to unload fifo if
+ * there is Rx packet in FIFO.
+ **/
+ csr = musb_readw(epio, MUSB_RXCSR);
+ if ((csr & MUSB_RXCSR_RXPKTRDY) &&
+ hw_ep->rx_double_buffered)
+ goto exit;
+ return;
+ }
+#endif
+ musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by the gadget_queue function especially
+ * on SMP systems. Reselect the INDEX to be sure
+ * we are reading/modifying the right registers
+ */
+ musb_ep_select(mbase, epnum);
+
+ req = next_request(musb_ep);
+ if (!req)
+ return;
+ }
+#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) || \
+ defined(CONFIG_USB_UX500_DMA)
+exit:
+#endif
+ /* Analyze request */
+ rxstate(musb, req);
+}
+
+/* ------------------------------------------------------------ */
+
+static int musb_gadget_enable(struct usb_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ unsigned long flags;
+ struct musb_ep *musb_ep;
+ struct musb_hw_ep *hw_ep;
+ void __iomem *regs;
+ struct musb *musb;
+ void __iomem *mbase;
+ u8 epnum;
+ u16 csr;
+ unsigned tmp;
+ int status = -EINVAL;
+
+ if (!ep || !desc)
+ return -EINVAL;
+
+ musb_ep = to_musb_ep(ep);
+ hw_ep = musb_ep->hw_ep;
+ regs = hw_ep->regs;
+ musb = musb_ep->musb;
+ mbase = musb->mregs;
+ epnum = musb_ep->current_epnum;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ if (musb_ep->desc) {
+ status = -EBUSY;
+ goto fail;
+ }
+ musb_ep->type = usb_endpoint_type(desc);
+
+ /* check direction and (later) maxpacket size against endpoint */
+ if (usb_endpoint_num(desc) != epnum)
+ goto fail;
+
+ /* REVISIT this rules out high bandwidth periodic transfers */
+ tmp = usb_endpoint_maxp(desc);
+ if (tmp & ~0x07ff) {
+ int ok;
+
+ if (usb_endpoint_dir_in(desc))
+ ok = musb->hb_iso_tx;
+ else
+ ok = musb->hb_iso_rx;
+
+ if (!ok) {
+ dev_dbg(musb->controller, "no support for high bandwidth ISO\n");
+ goto fail;
+ }
+ musb_ep->hb_mult = (tmp >> 11) & 3;
+ } else {
+ musb_ep->hb_mult = 0;
+ }
+
+ musb_ep->packet_sz = tmp & 0x7ff;
+ tmp = musb_ep->packet_sz * (musb_ep->hb_mult + 1);
+
+ /* enable the interrupts for the endpoint, set the endpoint
+ * packet size (or fail), set the mode, clear the fifo
+ */
+ musb_ep_select(mbase, epnum);
+ if (usb_endpoint_dir_in(desc)) {
+ u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep->is_in = 1;
+ if (!musb_ep->is_in)
+ goto fail;
+
+ if (tmp > hw_ep->max_packet_sz_tx) {
+ dev_dbg(musb->controller, "packet size beyond hardware FIFO size\n");
+ goto fail;
+ }
+
+ int_txe |= (1 << epnum);
+ musb_writew(mbase, MUSB_INTRTXE, int_txe);
+
+ /* REVISIT if can_bulk_split(), use by updating "tmp";
+ * likewise high bandwidth periodic tx
+ */
+ /* Set TXMAXP with the FIFO size of the endpoint
+ * to disable double buffering mode.
+ */
+ if (musb->double_buffer_not_ok)
+ musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
+ else
+ musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz
+ | (musb_ep->hb_mult << 11));
+
+ csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
+ if (musb_readw(regs, MUSB_TXCSR)
+ & MUSB_TXCSR_FIFONOTEMPTY)
+ csr |= MUSB_TXCSR_FLUSHFIFO;
+ if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
+ csr |= MUSB_TXCSR_P_ISO;
+
+ /* set twice in case of double buffering */
+ musb_writew(regs, MUSB_TXCSR, csr);
+ /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+ musb_writew(regs, MUSB_TXCSR, csr);
+
+ } else {
+ u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE);
+
+ if (hw_ep->is_shared_fifo)
+ musb_ep->is_in = 0;
+ if (musb_ep->is_in)
+ goto fail;
+
+ if (tmp > hw_ep->max_packet_sz_rx) {
+ dev_dbg(musb->controller, "packet size beyond hardware FIFO size\n");
+ goto fail;
+ }
+
+ int_rxe |= (1 << epnum);
+ musb_writew(mbase, MUSB_INTRRXE, int_rxe);
+
+ /* REVISIT if can_bulk_combine() use by updating "tmp"
+ * likewise high bandwidth periodic rx
+ */
+ /* Set RXMAXP with the FIFO size of the endpoint
+ * to disable double buffering mode.
+ */
+ if (musb->double_buffer_not_ok)
+ musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_tx);
+ else
+ musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz
+ | (musb_ep->hb_mult << 11));
+
+ /* force shared fifo to OUT-only mode */
+ if (hw_ep->is_shared_fifo) {
+ csr = musb_readw(regs, MUSB_TXCSR);
+ csr &= ~(MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY);
+ musb_writew(regs, MUSB_TXCSR, csr);
+ }
+
+ csr = MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_CLRDATATOG;
+ if (musb_ep->type == USB_ENDPOINT_XFER_ISOC)
+ csr |= MUSB_RXCSR_P_ISO;
+ else if (musb_ep->type == USB_ENDPOINT_XFER_INT)
+ csr |= MUSB_RXCSR_DISNYET;
+
+ /* set twice in case of double buffering */
+ musb_writew(regs, MUSB_RXCSR, csr);
+ musb_writew(regs, MUSB_RXCSR, csr);
+ }
+
+ /* NOTE: all the I/O code _should_ work fine without DMA, in case
+ * for some reason you run out of channels here.
+ */
+ if (is_dma_capable() && musb->dma_controller) {
+ struct dma_controller *c = musb->dma_controller;
+
+ musb_ep->dma = c->channel_alloc(c, hw_ep,
+ (desc->bEndpointAddress & USB_DIR_IN));
+ } else
+ musb_ep->dma = NULL;
+
+ musb_ep->desc = desc;
+ musb_ep->busy = 0;
+ musb_ep->wedged = 0;
+ status = 0;
+
+ pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n",
+ musb_driver_name, musb_ep->end_point.name,
+ ({ char *s; switch (musb_ep->type) {
+ case USB_ENDPOINT_XFER_BULK: s = "bulk"; break;
+ case USB_ENDPOINT_XFER_INT: s = "int"; break;
+ default: s = "iso"; break;
+ }; s; }),
+ musb_ep->is_in ? "IN" : "OUT",
+ musb_ep->dma ? "dma, " : "",
+ musb_ep->packet_sz);
+
+ schedule_work(&musb->irq_work);
+
+fail:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+/*
+ * Disable an endpoint flushing all requests queued.
+ */
+static int musb_gadget_disable(struct usb_ep *ep)
+{
+ unsigned long flags;
+ struct musb *musb;
+ u8 epnum;
+ struct musb_ep *musb_ep;
+ void __iomem *epio;
+ int status = 0;
+
+ musb_ep = to_musb_ep(ep);
+ musb = musb_ep->musb;
+ epnum = musb_ep->current_epnum;
+ epio = musb->endpoints[epnum].regs;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb_ep_select(musb->mregs, epnum);
+
+ /* zero the endpoint sizes */
+ if (musb_ep->is_in) {
+ u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE);
+ int_txe &= ~(1 << epnum);
+ musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
+ musb_writew(epio, MUSB_TXMAXP, 0);
+ } else {
+ u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE);
+ int_rxe &= ~(1 << epnum);
+ musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe);
+ musb_writew(epio, MUSB_RXMAXP, 0);
+ }
+
+ musb_ep->desc = NULL;
+#ifndef __UBOOT__
+ musb_ep->end_point.desc = NULL;
+#endif
+
+ /* abort all pending DMA and requests */
+ nuke(musb_ep, -ESHUTDOWN);
+
+ schedule_work(&musb->irq_work);
+
+ spin_unlock_irqrestore(&(musb->lock), flags);
+
+ dev_dbg(musb->controller, "%s\n", musb_ep->end_point.name);
+
+ return status;
+}
+
+/*
+ * Allocate a request for an endpoint.
+ * Reused by ep0 code.
+ */
+struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ struct musb *musb = musb_ep->musb;
+ struct musb_request *request = NULL;
+
+ request = kzalloc(sizeof *request, gfp_flags);
+ if (!request) {
+ dev_dbg(musb->controller, "not enough memory\n");
+ return NULL;
+ }
+
+ request->request.dma = DMA_ADDR_INVALID;
+ request->epnum = musb_ep->current_epnum;
+ request->ep = musb_ep;
+
+ return &request->request;
+}
+
+/*
+ * Free a request
+ * Reused by ep0 code.
+ */
+void musb_free_request(struct usb_ep *ep, struct usb_request *req)
+{
+ kfree(to_musb_request(req));
+}
+
+static LIST_HEAD(buffers);
+
+struct free_record {
+ struct list_head list;
+ struct device *dev;
+ unsigned bytes;
+ dma_addr_t dma;
+};
+
+/*
+ * Context: controller locked, IRQs blocked.
+ */
+void musb_ep_restart(struct musb *musb, struct musb_request *req)
+{
+ dev_dbg(musb->controller, "<== %s request %p len %u on hw_ep%d\n",
+ req->tx ? "TX/IN" : "RX/OUT",
+ &req->request, req->request.length, req->epnum);
+
+ musb_ep_select(musb->mregs, req->epnum);
+ if (req->tx)
+ txstate(musb, req);
+ else
+ rxstate(musb, req);
+}
+
+static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
+ gfp_t gfp_flags)
+{
+ struct musb_ep *musb_ep;
+ struct musb_request *request;
+ struct musb *musb;
+ int status = 0;
+ unsigned long lockflags;
+
+ if (!ep || !req)
+ return -EINVAL;
+ if (!req->buf)
+ return -ENODATA;
+
+ musb_ep = to_musb_ep(ep);
+ musb = musb_ep->musb;
+
+ request = to_musb_request(req);
+ request->musb = musb;
+
+ if (request->ep != musb_ep)
+ return -EINVAL;
+
+ dev_dbg(musb->controller, "<== to %s request=%p\n", ep->name, req);
+
+ /* request is mine now... */
+ request->request.actual = 0;
+ request->request.status = -EINPROGRESS;
+ request->epnum = musb_ep->current_epnum;
+ request->tx = musb_ep->is_in;
+
+ map_dma_buffer(request, musb, musb_ep);
+
+ spin_lock_irqsave(&musb->lock, lockflags);
+
+ /* don't queue if the ep is down */
+ if (!musb_ep->desc) {
+ dev_dbg(musb->controller, "req %p queued to %s while ep %s\n",
+ req, ep->name, "disabled");
+ status = -ESHUTDOWN;
+ goto cleanup;
+ }
+
+ /* add request to the list */
+ list_add_tail(&request->list, &musb_ep->req_list);
+
+ /* it this is the head of the queue, start i/o ... */
+ if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
+ musb_ep_restart(musb, request);
+
+cleanup:
+ spin_unlock_irqrestore(&musb->lock, lockflags);
+ return status;
+}
+
+static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ struct musb_request *req = to_musb_request(request);
+ struct musb_request *r;
+ unsigned long flags;
+ int status = 0;
+ struct musb *musb = musb_ep->musb;
+
+ if (!ep || !request || to_musb_request(request)->ep != musb_ep)
+ return -EINVAL;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ list_for_each_entry(r, &musb_ep->req_list, list) {
+ if (r == req)
+ break;
+ }
+ if (r != req) {
+ dev_dbg(musb->controller, "request %p not queued to %s\n", request, ep->name);
+ status = -EINVAL;
+ goto done;
+ }
+
+ /* if the hardware doesn't have the request, easy ... */
+ if (musb_ep->req_list.next != &req->list || musb_ep->busy)
+ musb_g_giveback(musb_ep, request, -ECONNRESET);
+
+ /* ... else abort the dma transfer ... */
+ else if (is_dma_capable() && musb_ep->dma) {
+ struct dma_controller *c = musb->dma_controller;
+
+ musb_ep_select(musb->mregs, musb_ep->current_epnum);
+ if (c->channel_abort)
+ status = c->channel_abort(musb_ep->dma);
+ else
+ status = -EBUSY;
+ if (status == 0)
+ musb_g_giveback(musb_ep, request, -ECONNRESET);
+ } else {
+ /* NOTE: by sticking to easily tested hardware/driver states,
+ * we leave counting of in-flight packets imprecise.
+ */
+ musb_g_giveback(musb_ep, request, -ECONNRESET);
+ }
+
+done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+/*
+ * Set or clear the halt bit of an endpoint. A halted enpoint won't tx/rx any
+ * data but will queue requests.
+ *
+ * exported to ep0 code
+ */
+static int musb_gadget_set_halt(struct usb_ep *ep, int value)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ u8 epnum = musb_ep->current_epnum;
+ struct musb *musb = musb_ep->musb;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ void __iomem *mbase;
+ unsigned long flags;
+ u16 csr;
+ struct musb_request *request;
+ int status = 0;
+
+ if (!ep)
+ return -EINVAL;
+ mbase = musb->mregs;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ if ((USB_ENDPOINT_XFER_ISOC == musb_ep->type)) {
+ status = -EINVAL;
+ goto done;
+ }
+
+ musb_ep_select(mbase, epnum);
+
+ request = next_request(musb_ep);
+ if (value) {
+ if (request) {
+ dev_dbg(musb->controller, "request in progress, cannot halt %s\n",
+ ep->name);
+ status = -EAGAIN;
+ goto done;
+ }
+ /* Cannot portably stall with non-empty FIFO */
+ if (musb_ep->is_in) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+ dev_dbg(musb->controller, "FIFO busy, cannot halt %s\n", ep->name);
+ status = -EAGAIN;
+ goto done;
+ }
+ }
+ } else
+ musb_ep->wedged = 0;
+
+ /* set/clear the stall and toggle bits */
+ dev_dbg(musb->controller, "%s: %s stall\n", ep->name, value ? "set" : "clear");
+ if (musb_ep->is_in) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr |= MUSB_TXCSR_P_WZC_BITS
+ | MUSB_TXCSR_CLRDATATOG;
+ if (value)
+ csr |= MUSB_TXCSR_P_SENDSTALL;
+ else
+ csr &= ~(MUSB_TXCSR_P_SENDSTALL
+ | MUSB_TXCSR_P_SENTSTALL);
+ csr &= ~MUSB_TXCSR_TXPKTRDY;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ } else {
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_P_WZC_BITS
+ | MUSB_RXCSR_FLUSHFIFO
+ | MUSB_RXCSR_CLRDATATOG;
+ if (value)
+ csr |= MUSB_RXCSR_P_SENDSTALL;
+ else
+ csr &= ~(MUSB_RXCSR_P_SENDSTALL
+ | MUSB_RXCSR_P_SENTSTALL);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ /* maybe start the first request in the queue */
+ if (!musb_ep->busy && !value && request) {
+ dev_dbg(musb->controller, "restarting the request\n");
+ musb_ep_restart(musb, request);
+ }
+
+done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+#ifndef __UBOOT__
+/*
+ * Sets the halt feature with the clear requests ignored
+ */
+static int musb_gadget_set_wedge(struct usb_ep *ep)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+
+ if (!ep)
+ return -EINVAL;
+
+ musb_ep->wedged = 1;
+
+ return usb_ep_set_halt(ep);
+}
+#endif
+
+static int musb_gadget_fifo_status(struct usb_ep *ep)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ void __iomem *epio = musb_ep->hw_ep->regs;
+ int retval = -EINVAL;
+
+ if (musb_ep->desc && !musb_ep->is_in) {
+ struct musb *musb = musb_ep->musb;
+ int epnum = musb_ep->current_epnum;
+ void __iomem *mbase = musb->mregs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ musb_ep_select(mbase, epnum);
+ /* FIXME return zero unless RXPKTRDY is set */
+ retval = musb_readw(epio, MUSB_RXCOUNT);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+ }
+ return retval;
+}
+
+static void musb_gadget_fifo_flush(struct usb_ep *ep)
+{
+ struct musb_ep *musb_ep = to_musb_ep(ep);
+ struct musb *musb = musb_ep->musb;
+ u8 epnum = musb_ep->current_epnum;
+ void __iomem *epio = musb->endpoints[epnum].regs;
+ void __iomem *mbase;
+ unsigned long flags;
+ u16 csr, int_txe;
+
+ mbase = musb->mregs;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb_ep_select(mbase, (u8) epnum);
+
+ /* disable interrupts */
+ int_txe = musb_readw(mbase, MUSB_INTRTXE);
+ musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+
+ if (musb_ep->is_in) {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+ csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_P_WZC_BITS;
+ /*
+ * Setting both TXPKTRDY and FLUSHFIFO makes controller
+ * to interrupt current FIFO loading, but not flushing
+ * the already loaded ones.
+ */
+ csr &= ~MUSB_TXCSR_TXPKTRDY;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may be inappropriate w/o FIFONOTEMPTY ... */
+ musb_writew(epio, MUSB_TXCSR, csr);
+ }
+ } else {
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_P_WZC_BITS;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ /* re-enable interrupt */
+ musb_writew(mbase, MUSB_INTRTXE, int_txe);
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static const struct usb_ep_ops musb_ep_ops = {
+ .enable = musb_gadget_enable,
+ .disable = musb_gadget_disable,
+ .alloc_request = musb_alloc_request,
+ .free_request = musb_free_request,
+ .queue = musb_gadget_queue,
+ .dequeue = musb_gadget_dequeue,
+ .set_halt = musb_gadget_set_halt,
+#ifndef __UBOOT__
+ .set_wedge = musb_gadget_set_wedge,
+#endif
+ .fifo_status = musb_gadget_fifo_status,
+ .fifo_flush = musb_gadget_fifo_flush
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int musb_gadget_get_frame(struct usb_gadget *gadget)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+
+ return (int)musb_readw(musb->mregs, MUSB_FRAME);
+}
+
+static int musb_gadget_wakeup(struct usb_gadget *gadget)
+{
+#ifndef __UBOOT__
+ struct musb *musb = gadget_to_musb(gadget);
+ void __iomem *mregs = musb->mregs;
+ unsigned long flags;
+ int status = -EINVAL;
+ u8 power, devctl;
+ int retries;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_B_PERIPHERAL:
+ /* NOTE: OTG state machine doesn't include B_SUSPENDED;
+ * that's part of the standard usb 1.1 state machine, and
+ * doesn't affect OTG transitions.
+ */
+ if (musb->may_wakeup && musb->is_suspended)
+ break;
+ goto done;
+ case OTG_STATE_B_IDLE:
+ /* Start SRP ... OTG not required. */
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ dev_dbg(musb->controller, "Sending SRP: devctl: %02x\n", devctl);
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(mregs, MUSB_DEVCTL, devctl);
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ retries = 100;
+ while (!(devctl & MUSB_DEVCTL_SESSION)) {
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ if (retries-- < 1)
+ break;
+ }
+ retries = 10000;
+ while (devctl & MUSB_DEVCTL_SESSION) {
+ devctl = musb_readb(mregs, MUSB_DEVCTL);
+ if (retries-- < 1)
+ break;
+ }
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+ otg_start_srp(musb->xceiv->otg);
+ spin_lock_irqsave(&musb->lock, flags);
+
+ /* Block idling for at least 1s */
+ musb_platform_try_idle(musb,
+ jiffies + msecs_to_jiffies(1 * HZ));
+
+ status = 0;
+ goto done;
+ default:
+ dev_dbg(musb->controller, "Unhandled wake: %s\n",
+ otg_state_string(musb->xceiv->state));
+ goto done;
+ }
+
+ status = 0;
+
+ power = musb_readb(mregs, MUSB_POWER);
+ power |= MUSB_POWER_RESUME;
+ musb_writeb(mregs, MUSB_POWER, power);
+ dev_dbg(musb->controller, "issue wakeup\n");
+
+ /* FIXME do this next chunk in a timer callback, no udelay */
+ mdelay(2);
+
+ power = musb_readb(mregs, MUSB_POWER);
+ power &= ~MUSB_POWER_RESUME;
+ musb_writeb(mregs, MUSB_POWER, power);
+done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+#else
+ return 0;
+#endif
+}
+
+static int
+musb_gadget_set_self_powered(struct usb_gadget *gadget, int is_selfpowered)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+
+ musb->is_self_powered = !!is_selfpowered;
+ return 0;
+}
+
+static void musb_pullup(struct musb *musb, int is_on)
+{
+ u8 power;
+
+ power = musb_readb(musb->mregs, MUSB_POWER);
+ if (is_on)
+ power |= MUSB_POWER_SOFTCONN;
+ else
+ power &= ~MUSB_POWER_SOFTCONN;
+
+ /* FIXME if on, HdrcStart; if off, HdrcStop */
+
+ dev_dbg(musb->controller, "gadget D+ pullup %s\n",
+ is_on ? "on" : "off");
+ musb_writeb(musb->mregs, MUSB_POWER, power);
+}
+
+#if 0
+static int musb_gadget_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+ dev_dbg(musb->controller, "<= %s =>\n", __func__);
+
+ /*
+ * FIXME iff driver's softconnect flag is set (as it is during probe,
+ * though that can clear it), just musb_pullup().
+ */
+
+ return -EINVAL;
+}
+#endif
+
+static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+#ifndef __UBOOT__
+ struct musb *musb = gadget_to_musb(gadget);
+
+ if (!musb->xceiv->set_power)
+ return -EOPNOTSUPP;
+ return usb_phy_set_power(musb->xceiv, mA);
+#else
+ return 0;
+#endif
+}
+
+static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
+{
+ struct musb *musb = gadget_to_musb(gadget);
+ unsigned long flags;
+
+ is_on = !!is_on;
+
+ pm_runtime_get_sync(musb->controller);
+
+ /* NOTE: this assumes we are sensing vbus; we'd rather
+ * not pullup unless the B-session is active.
+ */
+ spin_lock_irqsave(&musb->lock, flags);
+ if (is_on != musb->softconnect) {
+ musb->softconnect = is_on;
+ musb_pullup(musb, is_on);
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ pm_runtime_put(musb->controller);
+
+ return 0;
+}
+
+#ifndef __UBOOT__
+static int musb_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver);
+static int musb_gadget_stop(struct usb_gadget *g,
+ struct usb_gadget_driver *driver);
+#endif
+
+static const struct usb_gadget_ops musb_gadget_operations = {
+ .get_frame = musb_gadget_get_frame,
+ .wakeup = musb_gadget_wakeup,
+ .set_selfpowered = musb_gadget_set_self_powered,
+ /* .vbus_session = musb_gadget_vbus_session, */
+ .vbus_draw = musb_gadget_vbus_draw,
+ .pullup = musb_gadget_pullup,
+#ifndef __UBOOT__
+ .udc_start = musb_gadget_start,
+ .udc_stop = musb_gadget_stop,
+#endif
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* Registration */
+
+/* Only this registration code "knows" the rule (from USB standards)
+ * about there being only one external upstream port. It assumes
+ * all peripheral ports are external...
+ */
+
+#ifndef __UBOOT__
+static void musb_gadget_release(struct device *dev)
+{
+ /* kref_put(WHAT) */
+ dev_dbg(dev, "%s\n", __func__);
+}
+#endif
+
+
+static void __devinit
+init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
+{
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+
+ memset(ep, 0, sizeof *ep);
+
+ ep->current_epnum = epnum;
+ ep->musb = musb;
+ ep->hw_ep = hw_ep;
+ ep->is_in = is_in;
+
+ INIT_LIST_HEAD(&ep->req_list);
+
+ sprintf(ep->name, "ep%d%s", epnum,
+ (!epnum || hw_ep->is_shared_fifo) ? "" : (
+ is_in ? "in" : "out"));
+ ep->end_point.name = ep->name;
+ INIT_LIST_HEAD(&ep->end_point.ep_list);
+ if (!epnum) {
+ ep->end_point.maxpacket = 64;
+ ep->end_point.ops = &musb_g_ep0_ops;
+ musb->g.ep0 = &ep->end_point;
+ } else {
+ if (is_in)
+ ep->end_point.maxpacket = hw_ep->max_packet_sz_tx;
+ else
+ ep->end_point.maxpacket = hw_ep->max_packet_sz_rx;
+ ep->end_point.ops = &musb_ep_ops;
+ list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
+ }
+}
+
+/*
+ * Initialize the endpoints exposed to peripheral drivers, with backlinks
+ * to the rest of the driver state.
+ */
+static inline void __devinit musb_g_init_endpoints(struct musb *musb)
+{
+ u8 epnum;
+ struct musb_hw_ep *hw_ep;
+ unsigned count = 0;
+
+ /* initialize endpoint list just once */
+ INIT_LIST_HEAD(&(musb->g.ep_list));
+
+ for (epnum = 0, hw_ep = musb->endpoints;
+ epnum < musb->nr_endpoints;
+ epnum++, hw_ep++) {
+ if (hw_ep->is_shared_fifo /* || !epnum */) {
+ init_peripheral_ep(musb, &hw_ep->ep_in, epnum, 0);
+ count++;
+ } else {
+ if (hw_ep->max_packet_sz_tx) {
+ init_peripheral_ep(musb, &hw_ep->ep_in,
+ epnum, 1);
+ count++;
+ }
+ if (hw_ep->max_packet_sz_rx) {
+ init_peripheral_ep(musb, &hw_ep->ep_out,
+ epnum, 0);
+ count++;
+ }
+ }
+ }
+}
+
+/* called once during driver setup to initialize and link into
+ * the driver model; memory is zeroed.
+ */
+int __devinit musb_gadget_setup(struct musb *musb)
+{
+ int status;
+
+ /* REVISIT minor race: if (erroneously) setting up two
+ * musb peripherals at the same time, only the bus lock
+ * is probably held.
+ */
+
+ musb->g.ops = &musb_gadget_operations;
+#ifndef __UBOOT__
+ musb->g.max_speed = USB_SPEED_HIGH;
+#endif
+ musb->g.speed = USB_SPEED_UNKNOWN;
+
+#ifndef __UBOOT__
+ /* this "gadget" abstracts/virtualizes the controller */
+ dev_set_name(&musb->g.dev, "gadget");
+ musb->g.dev.parent = musb->controller;
+ musb->g.dev.dma_mask = musb->controller->dma_mask;
+ musb->g.dev.release = musb_gadget_release;
+#endif
+ musb->g.name = musb_driver_name;
+
+#ifndef __UBOOT__
+ if (is_otg_enabled(musb))
+ musb->g.is_otg = 1;
+#endif
+
+ musb_g_init_endpoints(musb);
+
+ musb->is_active = 0;
+ musb_platform_try_idle(musb, 0);
+
+#ifndef __UBOOT__
+ status = device_register(&musb->g.dev);
+ if (status != 0) {
+ put_device(&musb->g.dev);
+ return status;
+ }
+ status = usb_add_gadget_udc(musb->controller, &musb->g);
+ if (status)
+ goto err;
+#endif
+
+ return 0;
+#ifndef __UBOOT__
+err:
+ musb->g.dev.parent = NULL;
+ device_unregister(&musb->g.dev);
+ return status;
+#endif
+}
+
+void musb_gadget_cleanup(struct musb *musb)
+{
+#ifndef __UBOOT__
+ usb_del_gadget_udc(&musb->g);
+ if (musb->g.dev.parent)
+ device_unregister(&musb->g.dev);
+#endif
+}
+
+/*
+ * Register the gadget driver. Used by gadget drivers when
+ * registering themselves with the controller.
+ *
+ * -EINVAL something went wrong (not driver)
+ * -EBUSY another gadget is already using the controller
+ * -ENOMEM no memory to perform the operation
+ *
+ * @param driver the gadget driver
+ * @return <0 if error, 0 if everything is fine
+ */
+#ifndef __UBOOT__
+static int musb_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
+#else
+int musb_gadget_start(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
+#endif
+{
+ struct musb *musb = gadget_to_musb(g);
+#ifndef __UBOOT__
+ struct usb_otg *otg = musb->xceiv->otg;
+#endif
+ unsigned long flags;
+ int retval = -EINVAL;
+
+#ifndef __UBOOT__
+ if (driver->max_speed < USB_SPEED_HIGH)
+ goto err0;
+#endif
+
+ pm_runtime_get_sync(musb->controller);
+
+#ifndef __UBOOT__
+ dev_dbg(musb->controller, "registering driver %s\n", driver->function);
+#endif
+
+ musb->softconnect = 0;
+ musb->gadget_driver = driver;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ musb->is_active = 1;
+
+#ifndef __UBOOT__
+ otg_set_peripheral(otg, &musb->g);
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+
+ /*
+ * FIXME this ignores the softconnect flag. Drivers are
+ * allowed hold the peripheral inactive until for example
+ * userspace hooks up printer hardware or DSP codecs, so
+ * hosts only see fully functional devices.
+ */
+
+ if (!is_otg_enabled(musb))
+#endif
+ musb_start(musb);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+#ifndef __UBOOT__
+ if (is_otg_enabled(musb)) {
+ struct usb_hcd *hcd = musb_to_hcd(musb);
+
+ dev_dbg(musb->controller, "OTG startup...\n");
+
+ /* REVISIT: funcall to other code, which also
+ * handles power budgeting ... this way also
+ * ensures HdrcStart is indirectly called.
+ */
+ retval = usb_add_hcd(musb_to_hcd(musb), 0, 0);
+ if (retval < 0) {
+ dev_dbg(musb->controller, "add_hcd failed, %d\n", retval);
+ goto err2;
+ }
+
+ if ((musb->xceiv->last_event == USB_EVENT_ID)
+ && otg->set_vbus)
+ otg_set_vbus(otg, 1);
+
+ hcd->self.uses_pio_for_control = 1;
+ }
+ if (musb->xceiv->last_event == USB_EVENT_NONE)
+ pm_runtime_put(musb->controller);
+#endif
+
+ return 0;
+
+#ifndef __UBOOT__
+err2:
+ if (!is_otg_enabled(musb))
+ musb_stop(musb);
+err0:
+ return retval;
+#endif
+}
+
+#ifndef __UBOOT__
+static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
+{
+ int i;
+ struct musb_hw_ep *hw_ep;
+
+ /* don't disconnect if it's not connected */
+ if (musb->g.speed == USB_SPEED_UNKNOWN)
+ driver = NULL;
+ else
+ musb->g.speed = USB_SPEED_UNKNOWN;
+
+ /* deactivate the hardware */
+ if (musb->softconnect) {
+ musb->softconnect = 0;
+ musb_pullup(musb, 0);
+ }
+ musb_stop(musb);
+
+ /* killing any outstanding requests will quiesce the driver;
+ * then report disconnect
+ */
+ if (driver) {
+ for (i = 0, hw_ep = musb->endpoints;
+ i < musb->nr_endpoints;
+ i++, hw_ep++) {
+ musb_ep_select(musb->mregs, i);
+ if (hw_ep->is_shared_fifo /* || !epnum */) {
+ nuke(&hw_ep->ep_in, -ESHUTDOWN);
+ } else {
+ if (hw_ep->max_packet_sz_tx)
+ nuke(&hw_ep->ep_in, -ESHUTDOWN);
+ if (hw_ep->max_packet_sz_rx)
+ nuke(&hw_ep->ep_out, -ESHUTDOWN);
+ }
+ }
+ }
+}
+
+/*
+ * Unregister the gadget driver. Used by gadget drivers when
+ * unregistering themselves from the controller.
+ *
+ * @param driver the gadget driver to unregister
+ */
+static int musb_gadget_stop(struct usb_gadget *g,
+ struct usb_gadget_driver *driver)
+{
+ struct musb *musb = gadget_to_musb(g);
+ unsigned long flags;
+
+ if (musb->xceiv->last_event == USB_EVENT_NONE)
+ pm_runtime_get_sync(musb->controller);
+
+ /*
+ * REVISIT always use otg_set_peripheral() here too;
+ * this needs to shut down the OTG engine.
+ */
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ musb_hnp_stop(musb);
+
+ (void) musb_gadget_vbus_draw(&musb->g, 0);
+
+ musb->xceiv->state = OTG_STATE_UNDEFINED;
+ stop_activity(musb, driver);
+ otg_set_peripheral(musb->xceiv->otg, NULL);
+
+ dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
+
+ musb->is_active = 0;
+ musb_platform_try_idle(musb, 0);
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ if (is_otg_enabled(musb)) {
+ usb_remove_hcd(musb_to_hcd(musb));
+ /* FIXME we need to be able to register another
+ * gadget driver here and have everything work;
+ * that currently misbehaves.
+ */
+ }
+
+ if (!is_otg_enabled(musb))
+ musb_stop(musb);
+
+ pm_runtime_put(musb->controller);
+
+ return 0;
+}
+#endif
+
+/* ----------------------------------------------------------------------- */
+
+/* lifecycle operations called through plat_uds.c */
+
+void musb_g_resume(struct musb *musb)
+{
+#ifndef __UBOOT__
+ musb->is_suspended = 0;
+ switch (musb->xceiv->state) {
+ case OTG_STATE_B_IDLE:
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_PERIPHERAL:
+ musb->is_active = 1;
+ if (musb->gadget_driver && musb->gadget_driver->resume) {
+ spin_unlock(&musb->lock);
+ musb->gadget_driver->resume(&musb->g);
+ spin_lock(&musb->lock);
+ }
+ break;
+ default:
+ WARNING("unhandled RESUME transition (%s)\n",
+ otg_state_string(musb->xceiv->state));
+ }
+#endif
+}
+
+/* called when SOF packets stop for 3+ msec */
+void musb_g_suspend(struct musb *musb)
+{
+#ifndef __UBOOT__
+ u8 devctl;
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ dev_dbg(musb->controller, "devctl %02x\n", devctl);
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_B_IDLE:
+ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ musb->is_suspended = 1;
+ if (musb->gadget_driver && musb->gadget_driver->suspend) {
+ spin_unlock(&musb->lock);
+ musb->gadget_driver->suspend(&musb->g);
+ spin_lock(&musb->lock);
+ }
+ break;
+ default:
+ /* REVISIT if B_HOST, clear DEVCTL.HOSTREQ;
+ * A_PERIPHERAL may need care too
+ */
+ WARNING("unhandled SUSPEND transition (%s)\n",
+ otg_state_string(musb->xceiv->state));
+ }
+#endif
+}
+
+/* Called during SRP */
+void musb_g_wakeup(struct musb *musb)
+{
+ musb_gadget_wakeup(&musb->g);
+}
+
+/* called when VBUS drops below session threshold, and in other cases */
+void musb_g_disconnect(struct musb *musb)
+{
+ void __iomem *mregs = musb->mregs;
+ u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
+
+ dev_dbg(musb->controller, "devctl %02x\n", devctl);
+
+ /* clear HR */
+ musb_writeb(mregs, MUSB_DEVCTL, devctl & MUSB_DEVCTL_SESSION);
+
+ /* don't draw vbus until new b-default session */
+ (void) musb_gadget_vbus_draw(&musb->g, 0);
+
+ musb->g.speed = USB_SPEED_UNKNOWN;
+ if (musb->gadget_driver && musb->gadget_driver->disconnect) {
+ spin_unlock(&musb->lock);
+ musb->gadget_driver->disconnect(&musb->g);
+ spin_lock(&musb->lock);
+ }
+
+#ifndef __UBOOT__
+ switch (musb->xceiv->state) {
+ default:
+ dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
+ otg_state_string(musb->xceiv->state));
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ MUSB_HST_MODE(musb);
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ case OTG_STATE_B_HOST:
+ case OTG_STATE_B_PERIPHERAL:
+ case OTG_STATE_B_IDLE:
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ break;
+ case OTG_STATE_B_SRP_INIT:
+ break;
+ }
+#endif
+
+ musb->is_active = 0;
+}
+
+void musb_g_reset(struct musb *musb)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+ void __iomem *mbase = musb->mregs;
+ u8 devctl = musb_readb(mbase, MUSB_DEVCTL);
+ u8 power;
+
+#ifndef __UBOOT__
+ dev_dbg(musb->controller, "<== %s addr=%x driver '%s'\n",
+ (devctl & MUSB_DEVCTL_BDEVICE)
+ ? "B-Device" : "A-Device",
+ musb_readb(mbase, MUSB_FADDR),
+ musb->gadget_driver
+ ? musb->gadget_driver->driver.name
+ : NULL
+ );
+#endif
+
+ /* report disconnect, if we didn't already (flushing EP state) */
+ if (musb->g.speed != USB_SPEED_UNKNOWN)
+ musb_g_disconnect(musb);
+
+ /* clear HR */
+ else if (devctl & MUSB_DEVCTL_HR)
+ musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION);
+
+
+ /* what speed did we negotiate? */
+ power = musb_readb(mbase, MUSB_POWER);
+ musb->g.speed = (power & MUSB_POWER_HSMODE)
+ ? USB_SPEED_HIGH : USB_SPEED_FULL;
+
+ /* start in USB_STATE_DEFAULT */
+ musb->is_active = 1;
+ musb->is_suspended = 0;
+ MUSB_DEV_MODE(musb);
+ musb->address = 0;
+ musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+
+ musb->may_wakeup = 0;
+ musb->g.b_hnp_enable = 0;
+ musb->g.a_alt_hnp_support = 0;
+ musb->g.a_hnp_support = 0;
+
+#ifndef __UBOOT__
+ /* Normal reset, as B-Device;
+ * or else after HNP, as A-Device
+ */
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
+ musb->g.is_a_peripheral = 0;
+ } else if (is_otg_enabled(musb)) {
+ musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
+ musb->g.is_a_peripheral = 1;
+ } else
+ WARN_ON(1);
+
+ /* start with default limits on VBUS power draw */
+ (void) musb_gadget_vbus_draw(&musb->g,
+ is_otg_enabled(musb) ? 8 : 100);
+#endif
+}
diff --git a/drivers/usb/musb-new/musb_gadget.h b/drivers/usb/musb-new/musb_gadget.h
new file mode 100644
index 0000000000..392f701a87
--- /dev/null
+++ b/drivers/usb/musb-new/musb_gadget.h
@@ -0,0 +1,130 @@
+/*
+ * MUSB OTG driver peripheral defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_GADGET_H
+#define __MUSB_GADGET_H
+
+#include <linux/list.h>
+#ifdef __UBOOT__
+#include <asm/byteorder.h>
+#include <asm/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#endif
+
+enum buffer_map_state {
+ UN_MAPPED = 0,
+ PRE_MAPPED,
+ MUSB_MAPPED
+};
+
+struct musb_request {
+ struct usb_request request;
+ struct list_head list;
+ struct musb_ep *ep;
+ struct musb *musb;
+ u8 tx; /* endpoint direction */
+ u8 epnum;
+ enum buffer_map_state map_state;
+};
+
+static inline struct musb_request *to_musb_request(struct usb_request *req)
+{
+ return req ? container_of(req, struct musb_request, request) : NULL;
+}
+
+extern struct usb_request *
+musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags);
+extern void musb_free_request(struct usb_ep *ep, struct usb_request *req);
+
+
+/*
+ * struct musb_ep - peripheral side view of endpoint rx or tx side
+ */
+struct musb_ep {
+ /* stuff towards the head is basically write-once. */
+ struct usb_ep end_point;
+ char name[12];
+ struct musb_hw_ep *hw_ep;
+ struct musb *musb;
+ u8 current_epnum;
+
+ /* ... when enabled/disabled ... */
+ u8 type;
+ u8 is_in;
+ u16 packet_sz;
+ const struct usb_endpoint_descriptor *desc;
+ struct dma_channel *dma;
+
+ /* later things are modified based on usage */
+ struct list_head req_list;
+
+ u8 wedged;
+
+ /* true if lock must be dropped but req_list may not be advanced */
+ u8 busy;
+
+ u8 hb_mult;
+};
+
+static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
+{
+ return ep ? container_of(ep, struct musb_ep, end_point) : NULL;
+}
+
+static inline struct musb_request *next_request(struct musb_ep *ep)
+{
+ struct list_head *queue = &ep->req_list;
+
+ if (list_empty(queue))
+ return NULL;
+ return container_of(queue->next, struct musb_request, list);
+}
+
+extern void musb_g_tx(struct musb *musb, u8 epnum);
+extern void musb_g_rx(struct musb *musb, u8 epnum);
+
+extern const struct usb_ep_ops musb_g_ep0_ops;
+
+extern int musb_gadget_setup(struct musb *);
+extern void musb_gadget_cleanup(struct musb *);
+
+extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int);
+
+extern void musb_ep_restart(struct musb *, struct musb_request *);
+
+#ifdef __UBOOT__
+int musb_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver);
+#endif
+#endif /* __MUSB_GADGET_H */
diff --git a/drivers/usb/musb-new/musb_gadget_ep0.c b/drivers/usb/musb-new/musb_gadget_ep0.c
new file mode 100644
index 0000000000..6599d386dc
--- /dev/null
+++ b/drivers/usb/musb-new/musb_gadget_ep0.c
@@ -0,0 +1,1089 @@
+/*
+ * MUSB OTG peripheral driver ep0 handling
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#else
+#include <common.h>
+#include "linux-compat.h"
+#endif
+
+#include "musb_core.h"
+
+/* ep0 is always musb->endpoints[0].ep_in */
+#define next_ep0_request(musb) next_in_request(&(musb)->endpoints[0])
+
+/*
+ * locking note: we use only the controller lock, for simpler correctness.
+ * It's always held with IRQs blocked.
+ *
+ * It protects the ep0 request queue as well as ep0_state, not just the
+ * controller and indexed registers. And that lock stays held unless it
+ * needs to be dropped to allow reentering this driver ... like upcalls to
+ * the gadget driver, or adjusting endpoint halt status.
+ */
+
+static char *decode_ep0stage(u8 stage)
+{
+ switch (stage) {
+ case MUSB_EP0_STAGE_IDLE: return "idle";
+ case MUSB_EP0_STAGE_SETUP: return "setup";
+ case MUSB_EP0_STAGE_TX: return "in";
+ case MUSB_EP0_STAGE_RX: return "out";
+ case MUSB_EP0_STAGE_ACKWAIT: return "wait";
+ case MUSB_EP0_STAGE_STATUSIN: return "in/status";
+ case MUSB_EP0_STAGE_STATUSOUT: return "out/status";
+ default: return "?";
+ }
+}
+
+/* handle a standard GET_STATUS request
+ * Context: caller holds controller lock
+ */
+static int service_tx_status_request(
+ struct musb *musb,
+ const struct usb_ctrlrequest *ctrlrequest)
+{
+ void __iomem *mbase = musb->mregs;
+ int handled = 1;
+ u8 result[2], epnum = 0;
+ const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK;
+
+ result[1] = 0;
+
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED;
+ result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+ if (musb->g.is_otg) {
+ result[0] |= musb->g.b_hnp_enable
+ << USB_DEVICE_B_HNP_ENABLE;
+ result[0] |= musb->g.a_alt_hnp_support
+ << USB_DEVICE_A_ALT_HNP_SUPPORT;
+ result[0] |= musb->g.a_hnp_support
+ << USB_DEVICE_A_HNP_SUPPORT;
+ }
+ break;
+
+ case USB_RECIP_INTERFACE:
+ result[0] = 0;
+ break;
+
+ case USB_RECIP_ENDPOINT: {
+ int is_in;
+ struct musb_ep *ep;
+ u16 tmp;
+ void __iomem *regs;
+
+ epnum = (u8) ctrlrequest->wIndex;
+ if (!epnum) {
+ result[0] = 0;
+ break;
+ }
+
+ is_in = epnum & USB_DIR_IN;
+ if (is_in) {
+ epnum &= 0x0f;
+ ep = &musb->endpoints[epnum].ep_in;
+ } else {
+ ep = &musb->endpoints[epnum].ep_out;
+ }
+ regs = musb->endpoints[epnum].regs;
+
+ if (epnum >= MUSB_C_NUM_EPS || !ep->desc) {
+ handled = -EINVAL;
+ break;
+ }
+
+ musb_ep_select(mbase, epnum);
+ if (is_in)
+ tmp = musb_readw(regs, MUSB_TXCSR)
+ & MUSB_TXCSR_P_SENDSTALL;
+ else
+ tmp = musb_readw(regs, MUSB_RXCSR)
+ & MUSB_RXCSR_P_SENDSTALL;
+ musb_ep_select(mbase, 0);
+
+ result[0] = tmp ? 1 : 0;
+ } break;
+
+ default:
+ /* class, vendor, etc ... delegate */
+ handled = 0;
+ break;
+ }
+
+ /* fill up the fifo; caller updates csr0 */
+ if (handled > 0) {
+ u16 len = le16_to_cpu(ctrlrequest->wLength);
+
+ if (len > 2)
+ len = 2;
+ musb_write_fifo(&musb->endpoints[0], len, result);
+ }
+
+ return handled;
+}
+
+/*
+ * handle a control-IN request, the end0 buffer contains the current request
+ * that is supposed to be a standard control request. Assumes the fifo to
+ * be at least 2 bytes long.
+ *
+ * @return 0 if the request was NOT HANDLED,
+ * < 0 when error
+ * > 0 when the request is processed
+ *
+ * Context: caller holds controller lock
+ */
+static int
+service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest)
+{
+ int handled = 0; /* not handled */
+
+ if ((ctrlrequest->bRequestType & USB_TYPE_MASK)
+ == USB_TYPE_STANDARD) {
+ switch (ctrlrequest->bRequest) {
+ case USB_REQ_GET_STATUS:
+ handled = service_tx_status_request(musb,
+ ctrlrequest);
+ break;
+
+ /* case USB_REQ_SYNC_FRAME: */
+
+ default:
+ break;
+ }
+ }
+ return handled;
+}
+
+/*
+ * Context: caller holds controller lock
+ */
+static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req)
+{
+ musb_g_giveback(&musb->endpoints[0].ep_in, req, 0);
+}
+
+/*
+ * Tries to start B-device HNP negotiation if enabled via sysfs
+ */
+static inline void musb_try_b_hnp_enable(struct musb *musb)
+{
+ void __iomem *mbase = musb->mregs;
+ u8 devctl;
+
+ dev_dbg(musb->controller, "HNP: Setting HR\n");
+ devctl = musb_readb(mbase, MUSB_DEVCTL);
+ musb_writeb(mbase, MUSB_DEVCTL, devctl | MUSB_DEVCTL_HR);
+}
+
+/*
+ * Handle all control requests with no DATA stage, including standard
+ * requests such as:
+ * USB_REQ_SET_CONFIGURATION, USB_REQ_SET_INTERFACE, unrecognized
+ * always delegated to the gadget driver
+ * USB_REQ_SET_ADDRESS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE
+ * always handled here, except for class/vendor/... features
+ *
+ * Context: caller holds controller lock
+ */
+static int
+service_zero_data_request(struct musb *musb,
+ struct usb_ctrlrequest *ctrlrequest)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+ int handled = -EINVAL;
+ void __iomem *mbase = musb->mregs;
+ const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK;
+
+ /* the gadget driver handles everything except what we MUST handle */
+ if ((ctrlrequest->bRequestType & USB_TYPE_MASK)
+ == USB_TYPE_STANDARD) {
+ switch (ctrlrequest->bRequest) {
+ case USB_REQ_SET_ADDRESS:
+ /* change it after the status stage */
+ musb->set_address = true;
+ musb->address = (u8) (ctrlrequest->wValue & 0x7f);
+ handled = 1;
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ if (ctrlrequest->wValue
+ != USB_DEVICE_REMOTE_WAKEUP)
+ break;
+ musb->may_wakeup = 0;
+ handled = 1;
+ break;
+ case USB_RECIP_INTERFACE:
+ break;
+ case USB_RECIP_ENDPOINT:{
+ const u8 epnum =
+ ctrlrequest->wIndex & 0x0f;
+ struct musb_ep *musb_ep;
+ struct musb_hw_ep *ep;
+ struct musb_request *request;
+ void __iomem *regs;
+ int is_in;
+ u16 csr;
+
+ if (epnum == 0 || epnum >= MUSB_C_NUM_EPS ||
+ ctrlrequest->wValue != USB_ENDPOINT_HALT)
+ break;
+
+ ep = musb->endpoints + epnum;
+ regs = ep->regs;
+ is_in = ctrlrequest->wIndex & USB_DIR_IN;
+ if (is_in)
+ musb_ep = &ep->ep_in;
+ else
+ musb_ep = &ep->ep_out;
+ if (!musb_ep->desc)
+ break;
+
+ handled = 1;
+ /* Ignore request if endpoint is wedged */
+ if (musb_ep->wedged)
+ break;
+
+ musb_ep_select(mbase, epnum);
+ if (is_in) {
+ csr = musb_readw(regs, MUSB_TXCSR);
+ csr |= MUSB_TXCSR_CLRDATATOG |
+ MUSB_TXCSR_P_WZC_BITS;
+ csr &= ~(MUSB_TXCSR_P_SENDSTALL |
+ MUSB_TXCSR_P_SENTSTALL |
+ MUSB_TXCSR_TXPKTRDY);
+ musb_writew(regs, MUSB_TXCSR, csr);
+ } else {
+ csr = musb_readw(regs, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_CLRDATATOG |
+ MUSB_RXCSR_P_WZC_BITS;
+ csr &= ~(MUSB_RXCSR_P_SENDSTALL |
+ MUSB_RXCSR_P_SENTSTALL);
+ musb_writew(regs, MUSB_RXCSR, csr);
+ }
+
+ /* Maybe start the first request in the queue */
+ request = next_request(musb_ep);
+ if (!musb_ep->busy && request) {
+ dev_dbg(musb->controller, "restarting the request\n");
+ musb_ep_restart(musb, request);
+ }
+
+ /* select ep0 again */
+ musb_ep_select(mbase, 0);
+ } break;
+ default:
+ /* class, vendor, etc ... delegate */
+ handled = 0;
+ break;
+ }
+ break;
+
+ case USB_REQ_SET_FEATURE:
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ handled = 1;
+ switch (ctrlrequest->wValue) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ musb->may_wakeup = 1;
+ break;
+ case USB_DEVICE_TEST_MODE:
+ if (musb->g.speed != USB_SPEED_HIGH)
+ goto stall;
+ if (ctrlrequest->wIndex & 0xff)
+ goto stall;
+
+ switch (ctrlrequest->wIndex >> 8) {
+ case 1:
+ pr_debug("TEST_J\n");
+ /* TEST_J */
+ musb->test_mode_nr =
+ MUSB_TEST_J;
+ break;
+ case 2:
+ /* TEST_K */
+ pr_debug("TEST_K\n");
+ musb->test_mode_nr =
+ MUSB_TEST_K;
+ break;
+ case 3:
+ /* TEST_SE0_NAK */
+ pr_debug("TEST_SE0_NAK\n");
+ musb->test_mode_nr =
+ MUSB_TEST_SE0_NAK;
+ break;
+ case 4:
+ /* TEST_PACKET */
+ pr_debug("TEST_PACKET\n");
+ musb->test_mode_nr =
+ MUSB_TEST_PACKET;
+ break;
+
+ case 0xc0:
+ /* TEST_FORCE_HS */
+ pr_debug("TEST_FORCE_HS\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FORCE_HS;
+ break;
+ case 0xc1:
+ /* TEST_FORCE_FS */
+ pr_debug("TEST_FORCE_FS\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FORCE_FS;
+ break;
+ case 0xc2:
+ /* TEST_FIFO_ACCESS */
+ pr_debug("TEST_FIFO_ACCESS\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FIFO_ACCESS;
+ break;
+ case 0xc3:
+ /* TEST_FORCE_HOST */
+ pr_debug("TEST_FORCE_HOST\n");
+ musb->test_mode_nr =
+ MUSB_TEST_FORCE_HOST;
+ break;
+ default:
+ goto stall;
+ }
+
+ /* enter test mode after irq */
+ if (handled > 0)
+ musb->test_mode = true;
+ break;
+ case USB_DEVICE_B_HNP_ENABLE:
+ if (!musb->g.is_otg)
+ goto stall;
+ musb->g.b_hnp_enable = 1;
+ musb_try_b_hnp_enable(musb);
+ break;
+ case USB_DEVICE_A_HNP_SUPPORT:
+ if (!musb->g.is_otg)
+ goto stall;
+ musb->g.a_hnp_support = 1;
+ break;
+ case USB_DEVICE_A_ALT_HNP_SUPPORT:
+ if (!musb->g.is_otg)
+ goto stall;
+ musb->g.a_alt_hnp_support = 1;
+ break;
+ case USB_DEVICE_DEBUG_MODE:
+ handled = 0;
+ break;
+stall:
+ default:
+ handled = -EINVAL;
+ break;
+ }
+ break;
+
+ case USB_RECIP_INTERFACE:
+ break;
+
+ case USB_RECIP_ENDPOINT:{
+ const u8 epnum =
+ ctrlrequest->wIndex & 0x0f;
+ struct musb_ep *musb_ep;
+ struct musb_hw_ep *ep;
+ void __iomem *regs;
+ int is_in;
+ u16 csr;
+
+ if (epnum == 0 || epnum >= MUSB_C_NUM_EPS ||
+ ctrlrequest->wValue != USB_ENDPOINT_HALT)
+ break;
+
+ ep = musb->endpoints + epnum;
+ regs = ep->regs;
+ is_in = ctrlrequest->wIndex & USB_DIR_IN;
+ if (is_in)
+ musb_ep = &ep->ep_in;
+ else
+ musb_ep = &ep->ep_out;
+ if (!musb_ep->desc)
+ break;
+
+ musb_ep_select(mbase, epnum);
+ if (is_in) {
+ csr = musb_readw(regs, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_FIFONOTEMPTY)
+ csr |= MUSB_TXCSR_FLUSHFIFO;
+ csr |= MUSB_TXCSR_P_SENDSTALL
+ | MUSB_TXCSR_CLRDATATOG
+ | MUSB_TXCSR_P_WZC_BITS;
+ musb_writew(regs, MUSB_TXCSR, csr);
+ } else {
+ csr = musb_readw(regs, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_P_SENDSTALL
+ | MUSB_RXCSR_FLUSHFIFO
+ | MUSB_RXCSR_CLRDATATOG
+ | MUSB_RXCSR_P_WZC_BITS;
+ musb_writew(regs, MUSB_RXCSR, csr);
+ }
+
+ /* select ep0 again */
+ musb_ep_select(mbase, 0);
+ handled = 1;
+ } break;
+
+ default:
+ /* class, vendor, etc ... delegate */
+ handled = 0;
+ break;
+ }
+ break;
+ default:
+ /* delegate SET_CONFIGURATION, etc */
+ handled = 0;
+ }
+ } else
+ handled = 0;
+ return handled;
+}
+
+/* we have an ep0out data packet
+ * Context: caller holds controller lock
+ */
+static void ep0_rxstate(struct musb *musb)
+{
+ void __iomem *regs = musb->control_ep->regs;
+ struct musb_request *request;
+ struct usb_request *req;
+ u16 count, csr;
+
+ request = next_ep0_request(musb);
+ req = &request->request;
+
+ /* read packet and ack; or stall because of gadget driver bug:
+ * should have provided the rx buffer before setup() returned.
+ */
+ if (req) {
+ void *buf = req->buf + req->actual;
+ unsigned len = req->length - req->actual;
+
+ /* read the buffer */
+ count = musb_readb(regs, MUSB_COUNT0);
+ if (count > len) {
+ req->status = -EOVERFLOW;
+ count = len;
+ }
+ musb_read_fifo(&musb->endpoints[0], count, buf);
+ req->actual += count;
+ csr = MUSB_CSR0_P_SVDRXPKTRDY;
+ if (count < 64 || req->actual == req->length) {
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+ csr |= MUSB_CSR0_P_DATAEND;
+ } else
+ req = NULL;
+ } else
+ csr = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL;
+
+
+ /* Completion handler may choose to stall, e.g. because the
+ * message just received holds invalid data.
+ */
+ if (req) {
+ musb->ackpend = csr;
+ musb_g_ep0_giveback(musb, req);
+ if (!musb->ackpend)
+ return;
+ musb->ackpend = 0;
+ }
+ musb_ep_select(musb->mregs, 0);
+ musb_writew(regs, MUSB_CSR0, csr);
+}
+
+/*
+ * transmitting to the host (IN), this code might be called from IRQ
+ * and from kernel thread.
+ *
+ * Context: caller holds controller lock
+ */
+static void ep0_txstate(struct musb *musb)
+{
+ void __iomem *regs = musb->control_ep->regs;
+ struct musb_request *req = next_ep0_request(musb);
+ struct usb_request *request;
+ u16 csr = MUSB_CSR0_TXPKTRDY;
+ u8 *fifo_src;
+ u8 fifo_count;
+
+ if (!req) {
+ /* WARN_ON(1); */
+ dev_dbg(musb->controller, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0));
+ return;
+ }
+
+ request = &req->request;
+
+ /* load the data */
+ fifo_src = (u8 *) request->buf + request->actual;
+ fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
+ request->length - request->actual);
+ musb_write_fifo(&musb->endpoints[0], fifo_count, fifo_src);
+ request->actual += fifo_count;
+
+ /* update the flags */
+ if (fifo_count < MUSB_MAX_END0_PACKET
+ || (request->actual == request->length
+ && !request->zero)) {
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT;
+ csr |= MUSB_CSR0_P_DATAEND;
+ } else
+ request = NULL;
+
+ /* report completions as soon as the fifo's loaded; there's no
+ * win in waiting till this last packet gets acked. (other than
+ * very precise fault reporting, needed by USB TMC; possible with
+ * this hardware, but not usable from portable gadget drivers.)
+ */
+ if (request) {
+ musb->ackpend = csr;
+ musb_g_ep0_giveback(musb, request);
+ if (!musb->ackpend)
+ return;
+ musb->ackpend = 0;
+ }
+
+ /* send it out, triggering a "txpktrdy cleared" irq */
+ musb_ep_select(musb->mregs, 0);
+ musb_writew(regs, MUSB_CSR0, csr);
+}
+
+/*
+ * Read a SETUP packet (struct usb_ctrlrequest) from the hardware.
+ * Fields are left in USB byte-order.
+ *
+ * Context: caller holds controller lock.
+ */
+static void
+musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
+{
+ struct musb_request *r;
+ void __iomem *regs = musb->control_ep->regs;
+
+ musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req);
+
+ /* NOTE: earlier 2.6 versions changed setup packets to host
+ * order, but now USB packets always stay in USB byte order.
+ */
+ dev_dbg(musb->controller, "SETUP req%02x.%02x v%04x i%04x l%d\n",
+ req->bRequestType,
+ req->bRequest,
+ le16_to_cpu(req->wValue),
+ le16_to_cpu(req->wIndex),
+ le16_to_cpu(req->wLength));
+
+ /* clean up any leftover transfers */
+ r = next_ep0_request(musb);
+ if (r)
+ musb_g_ep0_giveback(musb, &r->request);
+
+ /* For zero-data requests we want to delay the STATUS stage to
+ * avoid SETUPEND errors. If we read data (OUT), delay accepting
+ * packets until there's a buffer to store them in.
+ *
+ * If we write data, the controller acts happier if we enable
+ * the TX FIFO right away, and give the controller a moment
+ * to switch modes...
+ */
+ musb->set_address = false;
+ musb->ackpend = MUSB_CSR0_P_SVDRXPKTRDY;
+ if (req->wLength == 0) {
+ if (req->bRequestType & USB_DIR_IN)
+ musb->ackpend |= MUSB_CSR0_TXPKTRDY;
+ musb->ep0_state = MUSB_EP0_STAGE_ACKWAIT;
+ } else if (req->bRequestType & USB_DIR_IN) {
+ musb->ep0_state = MUSB_EP0_STAGE_TX;
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDRXPKTRDY);
+ while ((musb_readw(regs, MUSB_CSR0)
+ & MUSB_CSR0_RXPKTRDY) != 0)
+ cpu_relax();
+ musb->ackpend = 0;
+ } else
+ musb->ep0_state = MUSB_EP0_STAGE_RX;
+}
+
+static int
+forward_to_driver(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+ int retval;
+ if (!musb->gadget_driver)
+ return -EOPNOTSUPP;
+ spin_unlock(&musb->lock);
+ retval = musb->gadget_driver->setup(&musb->g, ctrlrequest);
+ spin_lock(&musb->lock);
+ return retval;
+}
+
+/*
+ * Handle peripheral ep0 interrupt
+ *
+ * Context: irq handler; we won't re-enter the driver that way.
+ */
+irqreturn_t musb_g_ep0_irq(struct musb *musb)
+{
+ u16 csr;
+ u16 len;
+ void __iomem *mbase = musb->mregs;
+ void __iomem *regs = musb->endpoints[0].regs;
+ irqreturn_t retval = IRQ_NONE;
+
+ musb_ep_select(mbase, 0); /* select ep0 */
+ csr = musb_readw(regs, MUSB_CSR0);
+ len = musb_readb(regs, MUSB_COUNT0);
+
+ dev_dbg(musb->controller, "csr %04x, count %d, myaddr %d, ep0stage %s\n",
+ csr, len,
+ musb_readb(mbase, MUSB_FADDR),
+ decode_ep0stage(musb->ep0_state));
+
+ if (csr & MUSB_CSR0_P_DATAEND) {
+ /*
+ * If DATAEND is set we should not call the callback,
+ * hence the status stage is not complete.
+ */
+ return IRQ_HANDLED;
+ }
+
+ /* I sent a stall.. need to acknowledge it now.. */
+ if (csr & MUSB_CSR0_P_SENTSTALL) {
+ musb_writew(regs, MUSB_CSR0,
+ csr & ~MUSB_CSR0_P_SENTSTALL);
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ csr = musb_readw(regs, MUSB_CSR0);
+ }
+
+ /* request ended "early" */
+ if (csr & MUSB_CSR0_P_SETUPEND) {
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND);
+ retval = IRQ_HANDLED;
+ /* Transition into the early status phase */
+ switch (musb->ep0_state) {
+ case MUSB_EP0_STAGE_TX:
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT;
+ break;
+ case MUSB_EP0_STAGE_RX:
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+ break;
+ default:
+ ERR("SetupEnd came in a wrong ep0stage %s\n",
+ decode_ep0stage(musb->ep0_state));
+ }
+ csr = musb_readw(regs, MUSB_CSR0);
+ /* NOTE: request may need completion */
+ }
+
+ /* docs from Mentor only describe tx, rx, and idle/setup states.
+ * we need to handle nuances around status stages, and also the
+ * case where status and setup stages come back-to-back ...
+ */
+ switch (musb->ep0_state) {
+
+ case MUSB_EP0_STAGE_TX:
+ /* irq on clearing txpktrdy */
+ if ((csr & MUSB_CSR0_TXPKTRDY) == 0) {
+ ep0_txstate(musb);
+ retval = IRQ_HANDLED;
+ }
+ break;
+
+ case MUSB_EP0_STAGE_RX:
+ /* irq on set rxpktrdy */
+ if (csr & MUSB_CSR0_RXPKTRDY) {
+ ep0_rxstate(musb);
+ retval = IRQ_HANDLED;
+ }
+ break;
+
+ case MUSB_EP0_STAGE_STATUSIN:
+ /* end of sequence #2 (OUT/RX state) or #3 (no data) */
+
+ /* update address (if needed) only @ the end of the
+ * status phase per usb spec, which also guarantees
+ * we get 10 msec to receive this irq... until this
+ * is done we won't see the next packet.
+ */
+ if (musb->set_address) {
+ musb->set_address = false;
+ musb_writeb(mbase, MUSB_FADDR, musb->address);
+ }
+
+ /* enter test mode if needed (exit by reset) */
+ else if (musb->test_mode) {
+ dev_dbg(musb->controller, "entering TESTMODE\n");
+
+ if (MUSB_TEST_PACKET == musb->test_mode_nr)
+ musb_load_testpacket(musb);
+
+ musb_writeb(mbase, MUSB_TESTMODE,
+ musb->test_mode_nr);
+ }
+ /* FALLTHROUGH */
+
+ case MUSB_EP0_STAGE_STATUSOUT:
+ /* end of sequence #1: write to host (TX state) */
+ {
+ struct musb_request *req;
+
+ req = next_ep0_request(musb);
+ if (req)
+ musb_g_ep0_giveback(musb, &req->request);
+ }
+
+ /*
+ * In case when several interrupts can get coalesced,
+ * check to see if we've already received a SETUP packet...
+ */
+ if (csr & MUSB_CSR0_RXPKTRDY)
+ goto setup;
+
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ break;
+
+ case MUSB_EP0_STAGE_IDLE:
+ /*
+ * This state is typically (but not always) indiscernible
+ * from the status states since the corresponding interrupts
+ * tend to happen within too little period of time (with only
+ * a zero-length packet in between) and so get coalesced...
+ */
+ retval = IRQ_HANDLED;
+ musb->ep0_state = MUSB_EP0_STAGE_SETUP;
+ /* FALLTHROUGH */
+
+ case MUSB_EP0_STAGE_SETUP:
+setup:
+ if (csr & MUSB_CSR0_RXPKTRDY) {
+ struct usb_ctrlrequest setup;
+ int handled = 0;
+
+ if (len != 8) {
+ ERR("SETUP packet len %d != 8 ?\n", len);
+ break;
+ }
+ musb_read_setup(musb, &setup);
+ retval = IRQ_HANDLED;
+
+ /* sometimes the RESET won't be reported */
+ if (unlikely(musb->g.speed == USB_SPEED_UNKNOWN)) {
+ u8 power;
+
+ printk(KERN_NOTICE "%s: peripheral reset "
+ "irq lost!\n",
+ musb_driver_name);
+ power = musb_readb(mbase, MUSB_POWER);
+ musb->g.speed = (power & MUSB_POWER_HSMODE)
+ ? USB_SPEED_HIGH : USB_SPEED_FULL;
+
+ }
+
+ switch (musb->ep0_state) {
+
+ /* sequence #3 (no data stage), includes requests
+ * we can't forward (notably SET_ADDRESS and the
+ * device/endpoint feature set/clear operations)
+ * plus SET_CONFIGURATION and others we must
+ */
+ case MUSB_EP0_STAGE_ACKWAIT:
+ handled = service_zero_data_request(
+ musb, &setup);
+
+ /*
+ * We're expecting no data in any case, so
+ * always set the DATAEND bit -- doing this
+ * here helps avoid SetupEnd interrupt coming
+ * in the idle stage when we're stalling...
+ */
+ musb->ackpend |= MUSB_CSR0_P_DATAEND;
+
+ /* status stage might be immediate */
+ if (handled > 0)
+ musb->ep0_state =
+ MUSB_EP0_STAGE_STATUSIN;
+ break;
+
+ /* sequence #1 (IN to host), includes GET_STATUS
+ * requests that we can't forward, GET_DESCRIPTOR
+ * and others that we must
+ */
+ case MUSB_EP0_STAGE_TX:
+ handled = service_in_request(musb, &setup);
+ if (handled > 0) {
+ musb->ackpend = MUSB_CSR0_TXPKTRDY
+ | MUSB_CSR0_P_DATAEND;
+ musb->ep0_state =
+ MUSB_EP0_STAGE_STATUSOUT;
+ }
+ break;
+
+ /* sequence #2 (OUT from host), always forward */
+ default: /* MUSB_EP0_STAGE_RX */
+ break;
+ }
+
+ dev_dbg(musb->controller, "handled %d, csr %04x, ep0stage %s\n",
+ handled, csr,
+ decode_ep0stage(musb->ep0_state));
+
+ /* unless we need to delegate this to the gadget
+ * driver, we know how to wrap this up: csr0 has
+ * not yet been written.
+ */
+ if (handled < 0)
+ goto stall;
+ else if (handled > 0)
+ goto finish;
+
+ handled = forward_to_driver(musb, &setup);
+ if (handled < 0) {
+ musb_ep_select(mbase, 0);
+stall:
+ dev_dbg(musb->controller, "stall (%d)\n", handled);
+ musb->ackpend |= MUSB_CSR0_P_SENDSTALL;
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+finish:
+ musb_writew(regs, MUSB_CSR0,
+ musb->ackpend);
+ musb->ackpend = 0;
+ }
+ }
+ break;
+
+ case MUSB_EP0_STAGE_ACKWAIT:
+ /* This should not happen. But happens with tusb6010 with
+ * g_file_storage and high speed. Do nothing.
+ */
+ retval = IRQ_HANDLED;
+ break;
+
+ default:
+ /* "can't happen" */
+ WARN_ON(1);
+ musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL);
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ break;
+ }
+
+ return retval;
+}
+
+
+static int
+musb_g_ep0_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc)
+{
+ /* always enabled */
+ return -EINVAL;
+}
+
+static int musb_g_ep0_disable(struct usb_ep *e)
+{
+ /* always enabled */
+ return -EINVAL;
+}
+
+static int
+musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags)
+{
+ struct musb_ep *ep;
+ struct musb_request *req;
+ struct musb *musb;
+ int status;
+ unsigned long lockflags;
+ void __iomem *regs;
+
+ if (!e || !r)
+ return -EINVAL;
+
+ ep = to_musb_ep(e);
+ musb = ep->musb;
+ regs = musb->control_ep->regs;
+
+ req = to_musb_request(r);
+ req->musb = musb;
+ req->request.actual = 0;
+ req->request.status = -EINPROGRESS;
+ req->tx = ep->is_in;
+
+ spin_lock_irqsave(&musb->lock, lockflags);
+
+ if (!list_empty(&ep->req_list)) {
+ status = -EBUSY;
+ goto cleanup;
+ }
+
+ switch (musb->ep0_state) {
+ case MUSB_EP0_STAGE_RX: /* control-OUT data */
+ case MUSB_EP0_STAGE_TX: /* control-IN data */
+ case MUSB_EP0_STAGE_ACKWAIT: /* zero-length data */
+ status = 0;
+ break;
+ default:
+ dev_dbg(musb->controller, "ep0 request queued in state %d\n",
+ musb->ep0_state);
+ status = -EINVAL;
+ goto cleanup;
+ }
+
+ /* add request to the list */
+ list_add_tail(&req->list, &ep->req_list);
+
+ dev_dbg(musb->controller, "queue to %s (%s), length=%d\n",
+ ep->name, ep->is_in ? "IN/TX" : "OUT/RX",
+ req->request.length);
+
+ musb_ep_select(musb->mregs, 0);
+
+ /* sequence #1, IN ... start writing the data */
+ if (musb->ep0_state == MUSB_EP0_STAGE_TX)
+ ep0_txstate(musb);
+
+ /* sequence #3, no-data ... issue IN status */
+ else if (musb->ep0_state == MUSB_EP0_STAGE_ACKWAIT) {
+ if (req->request.length)
+ status = -EINVAL;
+ else {
+ musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
+ musb_writew(regs, MUSB_CSR0,
+ musb->ackpend | MUSB_CSR0_P_DATAEND);
+ musb->ackpend = 0;
+ musb_g_ep0_giveback(ep->musb, r);
+ }
+
+ /* else for sequence #2 (OUT), caller provides a buffer
+ * before the next packet arrives. deferred responses
+ * (after SETUP is acked) are racey.
+ */
+ } else if (musb->ackpend) {
+ musb_writew(regs, MUSB_CSR0, musb->ackpend);
+ musb->ackpend = 0;
+ }
+
+cleanup:
+ spin_unlock_irqrestore(&musb->lock, lockflags);
+ return status;
+}
+
+static int musb_g_ep0_dequeue(struct usb_ep *ep, struct usb_request *req)
+{
+ /* we just won't support this */
+ return -EINVAL;
+}
+
+static int musb_g_ep0_halt(struct usb_ep *e, int value)
+{
+ struct musb_ep *ep;
+ struct musb *musb;
+ void __iomem *base, *regs;
+ unsigned long flags;
+ int status;
+ u16 csr;
+
+ if (!e || !value)
+ return -EINVAL;
+
+ ep = to_musb_ep(e);
+ musb = ep->musb;
+ base = musb->mregs;
+ regs = musb->control_ep->regs;
+ status = 0;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ if (!list_empty(&ep->req_list)) {
+ status = -EBUSY;
+ goto cleanup;
+ }
+
+ musb_ep_select(base, 0);
+ csr = musb->ackpend;
+
+ switch (musb->ep0_state) {
+
+ /* Stalls are usually issued after parsing SETUP packet, either
+ * directly in irq context from setup() or else later.
+ */
+ case MUSB_EP0_STAGE_TX: /* control-IN data */
+ case MUSB_EP0_STAGE_ACKWAIT: /* STALL for zero-length data */
+ case MUSB_EP0_STAGE_RX: /* control-OUT data */
+ csr = musb_readw(regs, MUSB_CSR0);
+ /* FALLTHROUGH */
+
+ /* It's also OK to issue stalls during callbacks when a non-empty
+ * DATA stage buffer has been read (or even written).
+ */
+ case MUSB_EP0_STAGE_STATUSIN: /* control-OUT status */
+ case MUSB_EP0_STAGE_STATUSOUT: /* control-IN status */
+
+ csr |= MUSB_CSR0_P_SENDSTALL;
+ musb_writew(regs, MUSB_CSR0, csr);
+ musb->ep0_state = MUSB_EP0_STAGE_IDLE;
+ musb->ackpend = 0;
+ break;
+ default:
+ dev_dbg(musb->controller, "ep0 can't halt in state %d\n", musb->ep0_state);
+ status = -EINVAL;
+ }
+
+cleanup:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return status;
+}
+
+const struct usb_ep_ops musb_g_ep0_ops = {
+ .enable = musb_g_ep0_enable,
+ .disable = musb_g_ep0_disable,
+ .alloc_request = musb_alloc_request,
+ .free_request = musb_free_request,
+ .queue = musb_g_ep0_queue,
+ .dequeue = musb_g_ep0_dequeue,
+ .set_halt = musb_g_ep0_halt,
+};
diff --git a/drivers/usb/musb-new/musb_host.c b/drivers/usb/musb-new/musb_host.c
new file mode 100644
index 0000000000..9a2cf59d92
--- /dev/null
+++ b/drivers/usb/musb-new/musb_host.c
@@ -0,0 +1,2400 @@
+/*
+ * MUSB OTG driver host support
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ * Copyright (C) 2008-2009 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/dma-mapping.h>
+#else
+#include <common.h>
+#include <usb.h>
+#include "linux-compat.h"
+#include "usb-compat.h"
+#endif
+
+#include "musb_core.h"
+#include "musb_host.h"
+
+
+/* MUSB HOST status 22-mar-2006
+ *
+ * - There's still lots of partial code duplication for fault paths, so
+ * they aren't handled as consistently as they need to be.
+ *
+ * - PIO mostly behaved when last tested.
+ * + including ep0, with all usbtest cases 9, 10
+ * + usbtest 14 (ep0out) doesn't seem to run at all
+ * + double buffered OUT/TX endpoints saw stalls(!) with certain usbtest
+ * configurations, but otherwise double buffering passes basic tests.
+ * + for 2.6.N, for N > ~10, needs API changes for hcd framework.
+ *
+ * - DMA (CPPI) ... partially behaves, not currently recommended
+ * + about 1/15 the speed of typical EHCI implementations (PCI)
+ * + RX, all too often reqpkt seems to misbehave after tx
+ * + TX, no known issues (other than evident silicon issue)
+ *
+ * - DMA (Mentor/OMAP) ...has at least toggle update problems
+ *
+ * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet
+ * starvation ... nothing yet for TX, interrupt, or bulk.
+ *
+ * - Not tested with HNP, but some SRP paths seem to behave.
+ *
+ * NOTE 24-August-2006:
+ *
+ * - Bulk traffic finally uses both sides of hardware ep1, freeing up an
+ * extra endpoint for periodic use enabling hub + keybd + mouse. That
+ * mostly works, except that with "usbnet" it's easy to trigger cases
+ * with "ping" where RX loses. (a) ping to davinci, even "ping -f",
+ * fine; but (b) ping _from_ davinci, even "ping -c 1", ICMP RX loses
+ * although ARP RX wins. (That test was done with a full speed link.)
+ */
+
+
+/*
+ * NOTE on endpoint usage:
+ *
+ * CONTROL transfers all go through ep0. BULK ones go through dedicated IN
+ * and OUT endpoints ... hardware is dedicated for those "async" queue(s).
+ * (Yes, bulk _could_ use more of the endpoints than that, and would even
+ * benefit from it.)
+ *
+ * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints.
+ * So far that scheduling is both dumb and optimistic: the endpoint will be
+ * "claimed" until its software queue is no longer refilled. No multiplexing
+ * of transfers between endpoints, or anything clever.
+ */
+
+
+static void musb_ep_program(struct musb *musb, u8 epnum,
+ struct urb *urb, int is_out,
+ u8 *buf, u32 offset, u32 len);
+
+/*
+ * Clear TX fifo. Needed to avoid BABBLE errors.
+ */
+static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep)
+{
+ struct musb *musb = ep->musb;
+ void __iomem *epio = ep->regs;
+ u16 csr;
+ u16 lastcsr = 0;
+ int retries = 1000;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ while (csr & MUSB_TXCSR_FIFONOTEMPTY) {
+ if (csr != lastcsr)
+ dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr);
+ lastcsr = csr;
+ csr |= MUSB_TXCSR_FLUSHFIFO;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (WARN(retries-- < 1,
+ "Could not flush host TX%d fifo: csr: %04x\n",
+ ep->epnum, csr))
+ return;
+ mdelay(1);
+ }
+}
+
+static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep)
+{
+ void __iomem *epio = ep->regs;
+ u16 csr;
+ int retries = 5;
+
+ /* scrub any data left in the fifo */
+ do {
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY)))
+ break;
+ musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ udelay(10);
+ } while (--retries);
+
+ WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n",
+ ep->epnum, csr);
+
+ /* and reset for the next transfer */
+ musb_writew(epio, MUSB_TXCSR, 0);
+}
+
+/*
+ * Start transmit. Caller is responsible for locking shared resources.
+ * musb must be locked.
+ */
+static inline void musb_h_tx_start(struct musb_hw_ep *ep)
+{
+ u16 txcsr;
+
+ /* NOTE: no locks here; caller should lock and select EP */
+ if (ep->epnum) {
+ txcsr = musb_readw(ep->regs, MUSB_TXCSR);
+ txcsr |= MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_H_WZC_BITS;
+ musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+ } else {
+ txcsr = MUSB_CSR0_H_SETUPPKT | MUSB_CSR0_TXPKTRDY;
+ musb_writew(ep->regs, MUSB_CSR0, txcsr);
+ }
+
+}
+
+static inline void musb_h_tx_dma_start(struct musb_hw_ep *ep)
+{
+ u16 txcsr;
+
+ /* NOTE: no locks here; caller should lock and select EP */
+ txcsr = musb_readw(ep->regs, MUSB_TXCSR);
+ txcsr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_H_WZC_BITS;
+ if (is_cppi_enabled())
+ txcsr |= MUSB_TXCSR_DMAMODE;
+ musb_writew(ep->regs, MUSB_TXCSR, txcsr);
+}
+
+static void musb_ep_set_qh(struct musb_hw_ep *ep, int is_in, struct musb_qh *qh)
+{
+ if (is_in != 0 || ep->is_shared_fifo)
+ ep->in_qh = qh;
+ if (is_in == 0 || ep->is_shared_fifo)
+ ep->out_qh = qh;
+}
+
+static struct musb_qh *musb_ep_get_qh(struct musb_hw_ep *ep, int is_in)
+{
+ return is_in ? ep->in_qh : ep->out_qh;
+}
+
+/*
+ * Start the URB at the front of an endpoint's queue
+ * end must be claimed from the caller.
+ *
+ * Context: controller locked, irqs blocked
+ */
+static void
+musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
+{
+ u16 frame;
+ u32 len;
+ void __iomem *mbase = musb->mregs;
+ struct urb *urb = next_urb(qh);
+ void *buf = urb->transfer_buffer;
+ u32 offset = 0;
+ struct musb_hw_ep *hw_ep = qh->hw_ep;
+ unsigned pipe = urb->pipe;
+ u8 address = usb_pipedevice(pipe);
+ int epnum = hw_ep->epnum;
+
+ /* initialize software qh state */
+ qh->offset = 0;
+ qh->segsize = 0;
+
+ /* gather right source of data */
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* control transfers always start with SETUP */
+ is_in = 0;
+ musb->ep0_stage = MUSB_EP0_START;
+ buf = urb->setup_packet;
+ len = 8;
+ break;
+#ifndef __UBOOT__
+ case USB_ENDPOINT_XFER_ISOC:
+ qh->iso_idx = 0;
+ qh->frame = 0;
+ offset = urb->iso_frame_desc[0].offset;
+ len = urb->iso_frame_desc[0].length;
+ break;
+#endif
+ default: /* bulk, interrupt */
+ /* actual_length may be nonzero on retry paths */
+ buf = urb->transfer_buffer + urb->actual_length;
+ len = urb->transfer_buffer_length - urb->actual_length;
+ }
+
+ dev_dbg(musb->controller, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n",
+ qh, urb, address, qh->epnum,
+ is_in ? "in" : "out",
+ ({char *s; switch (qh->type) {
+ case USB_ENDPOINT_XFER_CONTROL: s = ""; break;
+ case USB_ENDPOINT_XFER_BULK: s = "-bulk"; break;
+#ifndef __UBOOT__
+ case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break;
+#endif
+ default: s = "-intr"; break;
+ }; s; }),
+ epnum, buf + offset, len);
+
+ /* Configure endpoint */
+ musb_ep_set_qh(hw_ep, is_in, qh);
+ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
+
+ /* transmit may have more work: start it when it is time */
+ if (is_in)
+ return;
+
+ /* determine if the time is right for a periodic transfer */
+ switch (qh->type) {
+#ifndef __UBOOT__
+ case USB_ENDPOINT_XFER_ISOC:
+#endif
+ case USB_ENDPOINT_XFER_INT:
+ dev_dbg(musb->controller, "check whether there's still time for periodic Tx\n");
+ frame = musb_readw(mbase, MUSB_FRAME);
+ /* FIXME this doesn't implement that scheduling policy ...
+ * or handle framecounter wrapping
+ */
+#ifndef __UBOOT__
+ if ((urb->transfer_flags & URB_ISO_ASAP)
+ || (frame >= urb->start_frame)) {
+ /* REVISIT the SOF irq handler shouldn't duplicate
+ * this code; and we don't init urb->start_frame...
+ */
+ qh->frame = 0;
+ goto start;
+ } else {
+#endif
+ qh->frame = urb->start_frame;
+ /* enable SOF interrupt so we can count down */
+ dev_dbg(musb->controller, "SOF for %d\n", epnum);
+#if 1 /* ifndef CONFIG_ARCH_DAVINCI */
+ musb_writeb(mbase, MUSB_INTRUSBE, 0xff);
+#endif
+#ifndef __UBOOT__
+ }
+#endif
+ break;
+ default:
+start:
+ dev_dbg(musb->controller, "Start TX%d %s\n", epnum,
+ hw_ep->tx_channel ? "dma" : "pio");
+
+ if (!hw_ep->tx_channel)
+ musb_h_tx_start(hw_ep);
+ else if (is_cppi_enabled() || tusb_dma_omap())
+ musb_h_tx_dma_start(hw_ep);
+ }
+}
+
+/* Context: caller owns controller lock, IRQs are blocked */
+static void musb_giveback(struct musb *musb, struct urb *urb, int status)
+__releases(musb->lock)
+__acquires(musb->lock)
+{
+ dev_dbg(musb->controller,
+ "complete %p %pF (%d), dev%d ep%d%s, %d/%d\n",
+ urb, urb->complete, status,
+ usb_pipedevice(urb->pipe),
+ usb_pipeendpoint(urb->pipe),
+ usb_pipein(urb->pipe) ? "in" : "out",
+ urb->actual_length, urb->transfer_buffer_length
+ );
+
+ usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb);
+ spin_unlock(&musb->lock);
+ usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status);
+ spin_lock(&musb->lock);
+}
+
+/* For bulk/interrupt endpoints only */
+static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
+ struct urb *urb)
+{
+ void __iomem *epio = qh->hw_ep->regs;
+ u16 csr;
+
+ /*
+ * FIXME: the current Mentor DMA code seems to have
+ * problems getting toggle correct.
+ */
+
+ if (is_in)
+ csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
+ else
+ csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
+
+ usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
+}
+
+/*
+ * Advance this hardware endpoint's queue, completing the specified URB and
+ * advancing to either the next URB queued to that qh, or else invalidating
+ * that qh and advancing to the next qh scheduled after the current one.
+ *
+ * Context: caller owns controller lock, IRQs are blocked
+ */
+static void musb_advance_schedule(struct musb *musb, struct urb *urb,
+ struct musb_hw_ep *hw_ep, int is_in)
+{
+ struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in);
+ struct musb_hw_ep *ep = qh->hw_ep;
+ int ready = qh->is_ready;
+ int status;
+
+ status = (urb->status == -EINPROGRESS) ? 0 : urb->status;
+
+ /* save toggle eagerly, for paranoia */
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ musb_save_toggle(qh, is_in, urb);
+ break;
+#ifndef __UBOOT__
+ case USB_ENDPOINT_XFER_ISOC:
+ if (status == 0 && urb->error_count)
+ status = -EXDEV;
+ break;
+#endif
+ }
+
+ qh->is_ready = 0;
+ musb_giveback(musb, urb, status);
+ qh->is_ready = ready;
+
+ /* reclaim resources (and bandwidth) ASAP; deschedule it, and
+ * invalidate qh as soon as list_empty(&hep->urb_list)
+ */
+ if (list_empty(&qh->hep->urb_list)) {
+ struct list_head *head;
+ struct dma_controller *dma = musb->dma_controller;
+
+ if (is_in) {
+ ep->rx_reinit = 1;
+ if (ep->rx_channel) {
+ dma->channel_release(ep->rx_channel);
+ ep->rx_channel = NULL;
+ }
+ } else {
+ ep->tx_reinit = 1;
+ if (ep->tx_channel) {
+ dma->channel_release(ep->tx_channel);
+ ep->tx_channel = NULL;
+ }
+ }
+
+ /* Clobber old pointers to this qh */
+ musb_ep_set_qh(ep, is_in, NULL);
+ qh->hep->hcpriv = NULL;
+
+ switch (qh->type) {
+
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_BULK:
+ /* fifo policy for these lists, except that NAKing
+ * should rotate a qh to the end (for fairness).
+ */
+ if (qh->mux == 1) {
+ head = qh->ring.prev;
+ list_del(&qh->ring);
+ kfree(qh);
+ qh = first_qh(head);
+ break;
+ }
+
+ case USB_ENDPOINT_XFER_ISOC:
+ case USB_ENDPOINT_XFER_INT:
+ /* this is where periodic bandwidth should be
+ * de-allocated if it's tracked and allocated;
+ * and where we'd update the schedule tree...
+ */
+ kfree(qh);
+ qh = NULL;
+ break;
+ }
+ }
+
+ if (qh != NULL && qh->is_ready) {
+ dev_dbg(musb->controller, "... next ep%d %cX urb %p\n",
+ hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh));
+ musb_start_urb(musb, is_in, qh);
+ }
+}
+
+static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr)
+{
+ /* we don't want fifo to fill itself again;
+ * ignore dma (various models),
+ * leave toggle alone (may not have been saved yet)
+ */
+ csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_RXPKTRDY;
+ csr &= ~(MUSB_RXCSR_H_REQPKT
+ | MUSB_RXCSR_H_AUTOREQ
+ | MUSB_RXCSR_AUTOCLEAR);
+
+ /* write 2x to allow double buffering */
+ musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+ musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+
+ /* flush writebuffer */
+ return musb_readw(hw_ep->regs, MUSB_RXCSR);
+}
+
+/*
+ * PIO RX for a packet (or part of it).
+ */
+static bool
+musb_host_packet_rx(struct musb *musb, struct urb *urb, u8 epnum, u8 iso_err)
+{
+ u16 rx_count;
+ u8 *buf;
+ u16 csr;
+ bool done = false;
+ u32 length;
+ int do_flush = 0;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->in_qh;
+ int pipe = urb->pipe;
+ void *buffer = urb->transfer_buffer;
+
+ /* musb_ep_select(mbase, epnum); */
+ rx_count = musb_readw(epio, MUSB_RXCOUNT);
+ dev_dbg(musb->controller, "RX%d count %d, buffer %p len %d/%d\n", epnum, rx_count,
+ urb->transfer_buffer, qh->offset,
+ urb->transfer_buffer_length);
+
+ /* unload FIFO */
+#ifndef __UBOOT__
+ if (usb_pipeisoc(pipe)) {
+ int status = 0;
+ struct usb_iso_packet_descriptor *d;
+
+ if (iso_err) {
+ status = -EILSEQ;
+ urb->error_count++;
+ }
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+ buf = buffer + d->offset;
+ length = d->length;
+ if (rx_count > length) {
+ if (status == 0) {
+ status = -EOVERFLOW;
+ urb->error_count++;
+ }
+ dev_dbg(musb->controller, "** OVERFLOW %d into %d\n", rx_count, length);
+ do_flush = 1;
+ } else
+ length = rx_count;
+ urb->actual_length += length;
+ d->actual_length = length;
+
+ d->status = status;
+
+ /* see if we are done */
+ done = (++qh->iso_idx >= urb->number_of_packets);
+ } else {
+#endif
+ /* non-isoch */
+ buf = buffer + qh->offset;
+ length = urb->transfer_buffer_length - qh->offset;
+ if (rx_count > length) {
+ if (urb->status == -EINPROGRESS)
+ urb->status = -EOVERFLOW;
+ dev_dbg(musb->controller, "** OVERFLOW %d into %d\n", rx_count, length);
+ do_flush = 1;
+ } else
+ length = rx_count;
+ urb->actual_length += length;
+ qh->offset += length;
+
+ /* see if we are done */
+ done = (urb->actual_length == urb->transfer_buffer_length)
+ || (rx_count < qh->maxpacket)
+ || (urb->status != -EINPROGRESS);
+ if (done
+ && (urb->status == -EINPROGRESS)
+ && (urb->transfer_flags & URB_SHORT_NOT_OK)
+ && (urb->actual_length
+ < urb->transfer_buffer_length))
+ urb->status = -EREMOTEIO;
+#ifndef __UBOOT__
+ }
+#endif
+
+ musb_read_fifo(hw_ep, length, buf);
+
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_H_WZC_BITS;
+ if (unlikely(do_flush))
+ musb_h_flush_rxfifo(hw_ep, csr);
+ else {
+ /* REVISIT this assumes AUTOCLEAR is never set */
+ csr &= ~(MUSB_RXCSR_RXPKTRDY | MUSB_RXCSR_H_REQPKT);
+ if (!done)
+ csr |= MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
+
+ return done;
+}
+
+/* we don't always need to reinit a given side of an endpoint...
+ * when we do, use tx/rx reinit routine and then construct a new CSR
+ * to address data toggle, NYET, and DMA or PIO.
+ *
+ * it's possible that driver bugs (especially for DMA) or aborting a
+ * transfer might have left the endpoint busier than it should be.
+ * the busy/not-empty tests are basically paranoia.
+ */
+static void
+musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
+{
+ u16 csr;
+
+ /* NOTE: we know the "rx" fifo reinit never triggers for ep0.
+ * That always uses tx_reinit since ep0 repurposes TX register
+ * offsets; the initial SETUP packet is also a kind of OUT.
+ */
+
+ /* if programmed for Tx, put it in RX mode */
+ if (ep->is_shared_fifo) {
+ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ if (csr & MUSB_TXCSR_MODE) {
+ musb_h_tx_flush_fifo(ep);
+ csr = musb_readw(ep->regs, MUSB_TXCSR);
+ musb_writew(ep->regs, MUSB_TXCSR,
+ csr | MUSB_TXCSR_FRCDATATOG);
+ }
+
+ /*
+ * Clear the MODE bit (and everything else) to enable Rx.
+ * NOTE: we mustn't clear the DMAMODE bit before DMAENAB.
+ */
+ if (csr & MUSB_TXCSR_DMAMODE)
+ musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE);
+ musb_writew(ep->regs, MUSB_TXCSR, 0);
+
+ /* scrub all previous state, clearing toggle */
+ } else {
+ csr = musb_readw(ep->regs, MUSB_RXCSR);
+ if (csr & MUSB_RXCSR_RXPKTRDY)
+ WARNING("rx%d, packet/%d ready?\n", ep->epnum,
+ musb_readw(ep->regs, MUSB_RXCOUNT));
+
+ musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
+ }
+
+ /* target addr and (for multipoint) hub addr/port */
+ if (musb->is_multipoint) {
+ musb_write_rxfunaddr(ep->target_regs, qh->addr_reg);
+ musb_write_rxhubaddr(ep->target_regs, qh->h_addr_reg);
+ musb_write_rxhubport(ep->target_regs, qh->h_port_reg);
+
+ } else
+ musb_writeb(musb->mregs, MUSB_FADDR, qh->addr_reg);
+
+ /* protocol/endpoint, interval/NAKlimit, i/o size */
+ musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg);
+ musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg);
+ /* NOTE: bulk combining rewrites high bits of maxpacket */
+ /* Set RXMAXP with the FIFO size of the endpoint
+ * to disable double buffer mode.
+ */
+ if (musb->double_buffer_not_ok)
+ musb_writew(ep->regs, MUSB_RXMAXP, ep->max_packet_sz_rx);
+ else
+ musb_writew(ep->regs, MUSB_RXMAXP,
+ qh->maxpacket | ((qh->hb_mult - 1) << 11));
+
+ ep->rx_reinit = 0;
+}
+
+static bool musb_tx_dma_program(struct dma_controller *dma,
+ struct musb_hw_ep *hw_ep, struct musb_qh *qh,
+ struct urb *urb, u32 offset, u32 length)
+{
+ struct dma_channel *channel = hw_ep->tx_channel;
+ void __iomem *epio = hw_ep->regs;
+ u16 pkt_size = qh->maxpacket;
+ u16 csr;
+ u8 mode;
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+ if (length > channel->max_len)
+ length = channel->max_len;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ if (length > pkt_size) {
+ mode = 1;
+ csr |= MUSB_TXCSR_DMAMODE | MUSB_TXCSR_DMAENAB;
+ /* autoset shouldn't be set in high bandwidth */
+ if (qh->hb_mult == 1)
+ csr |= MUSB_TXCSR_AUTOSET;
+ } else {
+ mode = 0;
+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
+ csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
+ }
+ channel->desired_mode = mode;
+ musb_writew(epio, MUSB_TXCSR, csr);
+#else
+ if (!is_cppi_enabled() && !tusb_dma_omap())
+ return false;
+
+ channel->actual_len = 0;
+
+ /*
+ * TX uses "RNDIS" mode automatically but needs help
+ * to identify the zero-length-final-packet case.
+ */
+ mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
+#endif
+
+ qh->segsize = length;
+
+ /*
+ * Ensure the data reaches to main memory before starting
+ * DMA transfer
+ */
+ wmb();
+
+ if (!dma->channel_program(channel, pkt_size, mode,
+ urb->transfer_dma + offset, length)) {
+ dma->channel_release(channel);
+ hw_ep->tx_channel = NULL;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
+ musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS);
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Program an HDRC endpoint as per the given URB
+ * Context: irqs blocked, controller lock held
+ */
+static void musb_ep_program(struct musb *musb, u8 epnum,
+ struct urb *urb, int is_out,
+ u8 *buf, u32 offset, u32 len)
+{
+ struct dma_controller *dma_controller;
+ struct dma_channel *dma_channel;
+ u8 dma_ok;
+ void __iomem *mbase = musb->mregs;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = musb_ep_get_qh(hw_ep, !is_out);
+ u16 packet_sz = qh->maxpacket;
+
+ dev_dbg(musb->controller, "%s hw%d urb %p spd%d dev%d ep%d%s "
+ "h_addr%02x h_port%02x bytes %d\n",
+ is_out ? "-->" : "<--",
+ epnum, urb, urb->dev->speed,
+ qh->addr_reg, qh->epnum, is_out ? "out" : "in",
+ qh->h_addr_reg, qh->h_port_reg,
+ len);
+
+ musb_ep_select(mbase, epnum);
+
+ /* candidate for DMA? */
+ dma_controller = musb->dma_controller;
+ if (is_dma_capable() && epnum && dma_controller) {
+ dma_channel = is_out ? hw_ep->tx_channel : hw_ep->rx_channel;
+ if (!dma_channel) {
+ dma_channel = dma_controller->channel_alloc(
+ dma_controller, hw_ep, is_out);
+ if (is_out)
+ hw_ep->tx_channel = dma_channel;
+ else
+ hw_ep->rx_channel = dma_channel;
+ }
+ } else
+ dma_channel = NULL;
+
+ /* make sure we clear DMAEnab, autoSet bits from previous run */
+
+ /* OUT/transmit/EP0 or IN/receive? */
+ if (is_out) {
+ u16 csr;
+ u16 int_txe;
+ u16 load_count;
+
+ csr = musb_readw(epio, MUSB_TXCSR);
+
+ /* disable interrupt in case we flush */
+ int_txe = musb_readw(mbase, MUSB_INTRTXE);
+ musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+
+ /* general endpoint setup */
+ if (epnum) {
+ /* flush all old state, set default */
+ musb_h_tx_flush_fifo(hw_ep);
+
+ /*
+ * We must not clear the DMAMODE bit before or in
+ * the same cycle with the DMAENAB bit, so we clear
+ * the latter first...
+ */
+ csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT
+ | MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_FRCDATATOG
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_ERROR
+ | MUSB_TXCSR_TXPKTRDY
+ );
+ csr |= MUSB_TXCSR_MODE;
+
+ if (usb_gettoggle(urb->dev, qh->epnum, 1))
+ csr |= MUSB_TXCSR_H_WR_DATATOGGLE
+ | MUSB_TXCSR_H_DATATOGGLE;
+ else
+ csr |= MUSB_TXCSR_CLRDATATOG;
+
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
+ csr &= ~MUSB_TXCSR_DMAMODE;
+ musb_writew(epio, MUSB_TXCSR, csr);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+ /* endpoint 0: just flush */
+ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ /* target addr and (for multipoint) hub addr/port */
+ if (musb->is_multipoint) {
+ musb_write_txfunaddr(mbase, epnum, qh->addr_reg);
+ musb_write_txhubaddr(mbase, epnum, qh->h_addr_reg);
+ musb_write_txhubport(mbase, epnum, qh->h_port_reg);
+/* FIXME if !epnum, do the same for RX ... */
+ } else
+ musb_writeb(mbase, MUSB_FADDR, qh->addr_reg);
+
+ /* protocol/endpoint/interval/NAKlimit */
+ if (epnum) {
+ musb_writeb(epio, MUSB_TXTYPE, qh->type_reg);
+ if (musb->double_buffer_not_ok)
+ musb_writew(epio, MUSB_TXMAXP,
+ hw_ep->max_packet_sz_tx);
+ else if (can_bulk_split(musb, qh->type))
+ musb_writew(epio, MUSB_TXMAXP, packet_sz
+ | ((hw_ep->max_packet_sz_tx /
+ packet_sz) - 1) << 11);
+ else
+ musb_writew(epio, MUSB_TXMAXP,
+ qh->maxpacket |
+ ((qh->hb_mult - 1) << 11));
+ musb_writeb(epio, MUSB_TXINTERVAL, qh->intv_reg);
+ } else {
+ musb_writeb(epio, MUSB_NAKLIMIT0, qh->intv_reg);
+ if (musb->is_multipoint)
+ musb_writeb(epio, MUSB_TYPE0,
+ qh->type_reg);
+ }
+
+ if (can_bulk_split(musb, qh->type))
+ load_count = min((u32) hw_ep->max_packet_sz_tx,
+ len);
+ else
+ load_count = min((u32) packet_sz, len);
+
+ if (dma_channel && musb_tx_dma_program(dma_controller,
+ hw_ep, qh, urb, offset, len))
+ load_count = 0;
+
+ if (load_count) {
+ /* PIO to load FIFO */
+ qh->segsize = load_count;
+ musb_write_fifo(hw_ep, load_count, buf);
+ }
+
+ /* re-enable interrupt */
+ musb_writew(mbase, MUSB_INTRTXE, int_txe);
+
+ /* IN/receive */
+ } else {
+ u16 csr;
+
+ if (hw_ep->rx_reinit) {
+ musb_rx_reinit(musb, qh, hw_ep);
+
+ /* init new state: toggle and NYET, maybe DMA later */
+ if (usb_gettoggle(urb->dev, qh->epnum, 0))
+ csr = MUSB_RXCSR_H_WR_DATATOGGLE
+ | MUSB_RXCSR_H_DATATOGGLE;
+ else
+ csr = 0;
+ if (qh->type == USB_ENDPOINT_XFER_INT)
+ csr |= MUSB_RXCSR_DISNYET;
+
+ } else {
+ csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+
+ if (csr & (MUSB_RXCSR_RXPKTRDY
+ | MUSB_RXCSR_DMAENAB
+ | MUSB_RXCSR_H_REQPKT))
+ ERR("broken !rx_reinit, ep%d csr %04x\n",
+ hw_ep->epnum, csr);
+
+ /* scrub any stale state, leaving toggle alone */
+ csr &= MUSB_RXCSR_DISNYET;
+ }
+
+ /* kick things off */
+
+ if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
+ /* Candidate for DMA */
+ dma_channel->actual_len = 0L;
+ qh->segsize = len;
+
+ /* AUTOREQ is in a DMA register */
+ musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+ csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+
+ /*
+ * Unless caller treats short RX transfers as
+ * errors, we dare not queue multiple transfers.
+ */
+ dma_ok = dma_controller->channel_program(dma_channel,
+ packet_sz, !(urb->transfer_flags &
+ URB_SHORT_NOT_OK),
+ urb->transfer_dma + offset,
+ qh->segsize);
+ if (!dma_ok) {
+ dma_controller->channel_release(dma_channel);
+ hw_ep->rx_channel = dma_channel = NULL;
+ } else
+ csr |= MUSB_RXCSR_DMAENAB;
+ }
+
+ csr |= MUSB_RXCSR_H_REQPKT;
+ dev_dbg(musb->controller, "RXCSR%d := %04x\n", epnum, csr);
+ musb_writew(hw_ep->regs, MUSB_RXCSR, csr);
+ csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
+ }
+}
+
+
+/*
+ * Service the default endpoint (ep0) as host.
+ * Return true until it's time to start the status stage.
+ */
+static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
+{
+ bool more = false;
+ u8 *fifo_dest = NULL;
+ u16 fifo_count = 0;
+ struct musb_hw_ep *hw_ep = musb->control_ep;
+ struct musb_qh *qh = hw_ep->in_qh;
+ struct usb_ctrlrequest *request;
+
+ switch (musb->ep0_stage) {
+ case MUSB_EP0_IN:
+ fifo_dest = urb->transfer_buffer + urb->actual_length;
+ fifo_count = min_t(size_t, len, urb->transfer_buffer_length -
+ urb->actual_length);
+ if (fifo_count < len)
+ urb->status = -EOVERFLOW;
+
+ musb_read_fifo(hw_ep, fifo_count, fifo_dest);
+
+ urb->actual_length += fifo_count;
+ if (len < qh->maxpacket) {
+ /* always terminate on short read; it's
+ * rarely reported as an error.
+ */
+ } else if (urb->actual_length <
+ urb->transfer_buffer_length)
+ more = true;
+ break;
+ case MUSB_EP0_START:
+ request = (struct usb_ctrlrequest *) urb->setup_packet;
+
+ if (!request->wLength) {
+ dev_dbg(musb->controller, "start no-DATA\n");
+ break;
+ } else if (request->bRequestType & USB_DIR_IN) {
+ dev_dbg(musb->controller, "start IN-DATA\n");
+ musb->ep0_stage = MUSB_EP0_IN;
+ more = true;
+ break;
+ } else {
+ dev_dbg(musb->controller, "start OUT-DATA\n");
+ musb->ep0_stage = MUSB_EP0_OUT;
+ more = true;
+ }
+ /* FALLTHROUGH */
+ case MUSB_EP0_OUT:
+ fifo_count = min_t(size_t, qh->maxpacket,
+ urb->transfer_buffer_length -
+ urb->actual_length);
+ if (fifo_count) {
+ fifo_dest = (u8 *) (urb->transfer_buffer
+ + urb->actual_length);
+ dev_dbg(musb->controller, "Sending %d byte%s to ep0 fifo %p\n",
+ fifo_count,
+ (fifo_count == 1) ? "" : "s",
+ fifo_dest);
+ musb_write_fifo(hw_ep, fifo_count, fifo_dest);
+
+ urb->actual_length += fifo_count;
+ more = true;
+ }
+ break;
+ default:
+ ERR("bogus ep0 stage %d\n", musb->ep0_stage);
+ break;
+ }
+
+ return more;
+}
+
+/*
+ * Handle default endpoint interrupt as host. Only called in IRQ time
+ * from musb_interrupt().
+ *
+ * called with controller irqlocked
+ */
+irqreturn_t musb_h_ep0_irq(struct musb *musb)
+{
+ struct urb *urb;
+ u16 csr, len;
+ int status = 0;
+ void __iomem *mbase = musb->mregs;
+ struct musb_hw_ep *hw_ep = musb->control_ep;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->in_qh;
+ bool complete = false;
+ irqreturn_t retval = IRQ_NONE;
+
+ /* ep0 only has one queue, "in" */
+ urb = next_urb(qh);
+
+ musb_ep_select(mbase, 0);
+ csr = musb_readw(epio, MUSB_CSR0);
+ len = (csr & MUSB_CSR0_RXPKTRDY)
+ ? musb_readb(epio, MUSB_COUNT0)
+ : 0;
+
+ dev_dbg(musb->controller, "<== csr0 %04x, qh %p, count %d, urb %p, stage %d\n",
+ csr, qh, len, urb, musb->ep0_stage);
+
+ /* if we just did status stage, we are done */
+ if (MUSB_EP0_STATUS == musb->ep0_stage) {
+ retval = IRQ_HANDLED;
+ complete = true;
+ }
+
+ /* prepare status */
+ if (csr & MUSB_CSR0_H_RXSTALL) {
+ dev_dbg(musb->controller, "STALLING ENDPOINT\n");
+ status = -EPIPE;
+
+ } else if (csr & MUSB_CSR0_H_ERROR) {
+ dev_dbg(musb->controller, "no response, csr0 %04x\n", csr);
+ status = -EPROTO;
+
+ } else if (csr & MUSB_CSR0_H_NAKTIMEOUT) {
+ dev_dbg(musb->controller, "control NAK timeout\n");
+
+ /* NOTE: this code path would be a good place to PAUSE a
+ * control transfer, if another one is queued, so that
+ * ep0 is more likely to stay busy. That's already done
+ * for bulk RX transfers.
+ *
+ * if (qh->ring.next != &musb->control), then
+ * we have a candidate... NAKing is *NOT* an error
+ */
+ musb_writew(epio, MUSB_CSR0, 0);
+ retval = IRQ_HANDLED;
+ }
+
+ if (status) {
+ dev_dbg(musb->controller, "aborting\n");
+ retval = IRQ_HANDLED;
+ if (urb)
+ urb->status = status;
+ complete = true;
+
+ /* use the proper sequence to abort the transfer */
+ if (csr & MUSB_CSR0_H_REQPKT) {
+ csr &= ~MUSB_CSR0_H_REQPKT;
+ musb_writew(epio, MUSB_CSR0, csr);
+ csr &= ~MUSB_CSR0_H_NAKTIMEOUT;
+ musb_writew(epio, MUSB_CSR0, csr);
+ } else {
+ musb_h_ep0_flush_fifo(hw_ep);
+ }
+
+ musb_writeb(epio, MUSB_NAKLIMIT0, 0);
+
+ /* clear it */
+ musb_writew(epio, MUSB_CSR0, 0);
+ }
+
+ if (unlikely(!urb)) {
+ /* stop endpoint since we have no place for its data, this
+ * SHOULD NEVER HAPPEN! */
+ ERR("no URB for end 0\n");
+
+ musb_h_ep0_flush_fifo(hw_ep);
+ goto done;
+ }
+
+ if (!complete) {
+ /* call common logic and prepare response */
+ if (musb_h_ep0_continue(musb, len, urb)) {
+ /* more packets required */
+ csr = (MUSB_EP0_IN == musb->ep0_stage)
+ ? MUSB_CSR0_H_REQPKT : MUSB_CSR0_TXPKTRDY;
+ } else {
+ /* data transfer complete; perform status phase */
+ if (usb_pipeout(urb->pipe)
+ || !urb->transfer_buffer_length)
+ csr = MUSB_CSR0_H_STATUSPKT
+ | MUSB_CSR0_H_REQPKT;
+ else
+ csr = MUSB_CSR0_H_STATUSPKT
+ | MUSB_CSR0_TXPKTRDY;
+
+ /* flag status stage */
+ musb->ep0_stage = MUSB_EP0_STATUS;
+
+ dev_dbg(musb->controller, "ep0 STATUS, csr %04x\n", csr);
+
+ }
+ musb_writew(epio, MUSB_CSR0, csr);
+ retval = IRQ_HANDLED;
+ } else
+ musb->ep0_stage = MUSB_EP0_IDLE;
+
+ /* call completion handler if done */
+ if (complete)
+ musb_advance_schedule(musb, urb, hw_ep, 1);
+done:
+ return retval;
+}
+
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Host side TX (OUT) using Mentor DMA works as follows:
+ submit_urb ->
+ - if queue was empty, Program Endpoint
+ - ... which starts DMA to fifo in mode 1 or 0
+
+ DMA Isr (transfer complete) -> TxAvail()
+ - Stop DMA (~DmaEnab) (<--- Alert ... currently happens
+ only in musb_cleanup_urb)
+ - TxPktRdy has to be set in mode 0 or for
+ short packets in mode 1.
+*/
+
+#endif
+
+/* Service a Tx-Available or dma completion irq for the endpoint */
+void musb_host_tx(struct musb *musb, u8 epnum)
+{
+ int pipe;
+ bool done = false;
+ u16 tx_csr;
+ size_t length = 0;
+ size_t offset = 0;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->out_qh;
+ struct urb *urb = next_urb(qh);
+ u32 status = 0;
+ void __iomem *mbase = musb->mregs;
+ struct dma_channel *dma;
+ bool transfer_pending = false;
+
+ musb_ep_select(mbase, epnum);
+ tx_csr = musb_readw(epio, MUSB_TXCSR);
+
+ /* with CPPI, DMA sometimes triggers "extra" irqs */
+ if (!urb) {
+ dev_dbg(musb->controller, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+ return;
+ }
+
+ pipe = urb->pipe;
+ dma = is_dma_capable() ? hw_ep->tx_channel : NULL;
+ dev_dbg(musb->controller, "OUT/TX%d end, csr %04x%s\n", epnum, tx_csr,
+ dma ? ", dma" : "");
+
+ /* check for errors */
+ if (tx_csr & MUSB_TXCSR_H_RXSTALL) {
+ /* dma was disabled, fifo flushed */
+ dev_dbg(musb->controller, "TX end %d stall\n", epnum);
+
+ /* stall; record URB status */
+ status = -EPIPE;
+
+ } else if (tx_csr & MUSB_TXCSR_H_ERROR) {
+ /* (NON-ISO) dma was disabled, fifo flushed */
+ dev_dbg(musb->controller, "TX 3strikes on ep=%d\n", epnum);
+
+ status = -ETIMEDOUT;
+
+ } else if (tx_csr & MUSB_TXCSR_H_NAKTIMEOUT) {
+ dev_dbg(musb->controller, "TX end=%d device not responding\n", epnum);
+
+ /* NOTE: this code path would be a good place to PAUSE a
+ * transfer, if there's some other (nonperiodic) tx urb
+ * that could use this fifo. (dma complicates it...)
+ * That's already done for bulk RX transfers.
+ *
+ * if (bulk && qh->ring.next != &musb->out_bulk), then
+ * we have a candidate... NAKing is *NOT* an error
+ */
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_H_WZC_BITS
+ | MUSB_TXCSR_TXPKTRDY);
+ return;
+ }
+
+ if (status) {
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+ (void) musb->dma_controller->channel_abort(dma);
+ }
+
+ /* do the proper sequence to abort the transfer in the
+ * usb core; the dma engine should already be stopped.
+ */
+ musb_h_tx_flush_fifo(hw_ep);
+ tx_csr &= ~(MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_H_ERROR
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_NAKTIMEOUT
+ );
+
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_TXCSR, tx_csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
+ musb_writew(epio, MUSB_TXCSR, tx_csr);
+ musb_writeb(epio, MUSB_TXINTERVAL, 0);
+
+ done = true;
+ }
+
+ /* second cppi case */
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ dev_dbg(musb->controller, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
+ return;
+ }
+
+ if (is_dma_capable() && dma && !status) {
+ /*
+ * DMA has completed. But if we're using DMA mode 1 (multi
+ * packet DMA), we need a terminal TXPKTRDY interrupt before
+ * we can consider this transfer completed, lest we trash
+ * its last packet when writing the next URB's data. So we
+ * switch back to mode 0 to get that interrupt; we'll come
+ * back here once it happens.
+ */
+ if (tx_csr & MUSB_TXCSR_DMAMODE) {
+ /*
+ * We shouldn't clear DMAMODE with DMAENAB set; so
+ * clear them in a safe order. That should be OK
+ * once TXPKTRDY has been set (and I've never seen
+ * it being 0 at this moment -- DMA interrupt latency
+ * is significant) but if it hasn't been then we have
+ * no choice but to stop being polite and ignore the
+ * programmer's guide... :-)
+ *
+ * Note that we must write TXCSR with TXPKTRDY cleared
+ * in order not to re-trigger the packet send (this bit
+ * can't be cleared by CPU), and there's another caveat:
+ * TXPKTRDY may be set shortly and then cleared in the
+ * double-buffered FIFO mode, so we do an extra TXCSR
+ * read for debouncing...
+ */
+ tx_csr &= musb_readw(epio, MUSB_TXCSR);
+ if (tx_csr & MUSB_TXCSR_TXPKTRDY) {
+ tx_csr &= ~(MUSB_TXCSR_DMAENAB |
+ MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR,
+ tx_csr | MUSB_TXCSR_H_WZC_BITS);
+ }
+ tx_csr &= ~(MUSB_TXCSR_DMAMODE |
+ MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR,
+ tx_csr | MUSB_TXCSR_H_WZC_BITS);
+
+ /*
+ * There is no guarantee that we'll get an interrupt
+ * after clearing DMAMODE as we might have done this
+ * too late (after TXPKTRDY was cleared by controller).
+ * Re-read TXCSR as we have spoiled its previous value.
+ */
+ tx_csr = musb_readw(epio, MUSB_TXCSR);
+ }
+
+ /*
+ * We may get here from a DMA completion or TXPKTRDY interrupt.
+ * In any case, we must check the FIFO status here and bail out
+ * only if the FIFO still has data -- that should prevent the
+ * "missed" TXPKTRDY interrupts and deal with double-buffered
+ * FIFO mode too...
+ */
+ if (tx_csr & (MUSB_TXCSR_FIFONOTEMPTY | MUSB_TXCSR_TXPKTRDY)) {
+ dev_dbg(musb->controller, "DMA complete but packet still in FIFO, "
+ "CSR %04x\n", tx_csr);
+ return;
+ }
+ }
+
+ if (!status || dma || usb_pipeisoc(pipe)) {
+ if (dma)
+ length = dma->actual_len;
+ else
+ length = qh->segsize;
+ qh->offset += length;
+
+ if (usb_pipeisoc(pipe)) {
+#ifndef __UBOOT__
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+ d->actual_length = length;
+ d->status = status;
+ if (++qh->iso_idx >= urb->number_of_packets) {
+ done = true;
+ } else {
+ d++;
+ offset = d->offset;
+ length = d->length;
+ }
+#endif
+ } else if (dma && urb->transfer_buffer_length == qh->offset) {
+ done = true;
+ } else {
+ /* see if we need to send more data, or ZLP */
+ if (qh->segsize < qh->maxpacket)
+ done = true;
+ else if (qh->offset == urb->transfer_buffer_length
+ && !(urb->transfer_flags
+ & URB_ZERO_PACKET))
+ done = true;
+ if (!done) {
+ offset = qh->offset;
+ length = urb->transfer_buffer_length - offset;
+ transfer_pending = true;
+ }
+ }
+ }
+
+ /* urb->status != -EINPROGRESS means request has been faulted,
+ * so we must abort this transfer after cleanup
+ */
+ if (urb->status != -EINPROGRESS) {
+ done = true;
+ if (status == 0)
+ status = urb->status;
+ }
+
+ if (done) {
+ /* set status */
+ urb->status = status;
+ urb->actual_length = qh->offset;
+ musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
+ return;
+ } else if ((usb_pipeisoc(pipe) || transfer_pending) && dma) {
+ if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
+ offset, length)) {
+ if (is_cppi_enabled() || tusb_dma_omap())
+ musb_h_tx_dma_start(hw_ep);
+ return;
+ }
+ } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
+ dev_dbg(musb->controller, "not complete, but DMA enabled?\n");
+ return;
+ }
+
+ /*
+ * PIO: start next packet in this URB.
+ *
+ * REVISIT: some docs say that when hw_ep->tx_double_buffered,
+ * (and presumably, FIFO is not half-full) we should write *two*
+ * packets before updating TXCSR; other docs disagree...
+ */
+ if (length > qh->maxpacket)
+ length = qh->maxpacket;
+ /* Unmap the buffer so that CPU can use it */
+ usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb);
+ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
+ qh->segsize = length;
+
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_TXCSR,
+ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
+}
+
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+
+/* Host side RX (IN) using Mentor DMA works as follows:
+ submit_urb ->
+ - if queue was empty, ProgramEndpoint
+ - first IN token is sent out (by setting ReqPkt)
+ LinuxIsr -> RxReady()
+ /\ => first packet is received
+ | - Set in mode 0 (DmaEnab, ~ReqPkt)
+ | -> DMA Isr (transfer complete) -> RxReady()
+ | - Ack receive (~RxPktRdy), turn off DMA (~DmaEnab)
+ | - if urb not complete, send next IN token (ReqPkt)
+ | | else complete urb.
+ | |
+ ---------------------------
+ *
+ * Nuances of mode 1:
+ * For short packets, no ack (+RxPktRdy) is sent automatically
+ * (even if AutoClear is ON)
+ * For full packets, ack (~RxPktRdy) and next IN token (+ReqPkt) is sent
+ * automatically => major problem, as collecting the next packet becomes
+ * difficult. Hence mode 1 is not used.
+ *
+ * REVISIT
+ * All we care about at this driver level is that
+ * (a) all URBs terminate with REQPKT cleared and fifo(s) empty;
+ * (b) termination conditions are: short RX, or buffer full;
+ * (c) fault modes include
+ * - iff URB_SHORT_NOT_OK, short RX status is -EREMOTEIO.
+ * (and that endpoint's dma queue stops immediately)
+ * - overflow (full, PLUS more bytes in the terminal packet)
+ *
+ * So for example, usb-storage sets URB_SHORT_NOT_OK, and would
+ * thus be a great candidate for using mode 1 ... for all but the
+ * last packet of one URB's transfer.
+ */
+
+#endif
+
+/* Schedule next QH from musb->in_bulk and move the current qh to
+ * the end; avoids starvation for other endpoints.
+ */
+static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep)
+{
+ struct dma_channel *dma;
+ struct urb *urb;
+ void __iomem *mbase = musb->mregs;
+ void __iomem *epio = ep->regs;
+ struct musb_qh *cur_qh, *next_qh;
+ u16 rx_csr;
+
+ musb_ep_select(mbase, ep->epnum);
+ dma = is_dma_capable() ? ep->rx_channel : NULL;
+
+ /* clear nak timeout bit */
+ rx_csr = musb_readw(epio, MUSB_RXCSR);
+ rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+ rx_csr &= ~MUSB_RXCSR_DATAERROR;
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
+
+ cur_qh = first_qh(&musb->in_bulk);
+ if (cur_qh) {
+ urb = next_urb(cur_qh);
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+ musb->dma_controller->channel_abort(dma);
+ urb->actual_length += dma->actual_len;
+ dma->actual_len = 0L;
+ }
+ musb_save_toggle(cur_qh, 1, urb);
+
+ /* move cur_qh to end of queue */
+ list_move_tail(&cur_qh->ring, &musb->in_bulk);
+
+ /* get the next qh from musb->in_bulk */
+ next_qh = first_qh(&musb->in_bulk);
+
+ /* set rx_reinit and schedule the next qh */
+ ep->rx_reinit = 1;
+ musb_start_urb(musb, 1, next_qh);
+ }
+}
+
+/*
+ * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso,
+ * and high-bandwidth IN transfer cases.
+ */
+void musb_host_rx(struct musb *musb, u8 epnum)
+{
+ struct urb *urb;
+ struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
+ void __iomem *epio = hw_ep->regs;
+ struct musb_qh *qh = hw_ep->in_qh;
+ size_t xfer_len;
+ void __iomem *mbase = musb->mregs;
+ int pipe;
+ u16 rx_csr, val;
+ bool iso_err = false;
+ bool done = false;
+ u32 status;
+ struct dma_channel *dma;
+
+ musb_ep_select(mbase, epnum);
+
+ urb = next_urb(qh);
+ dma = is_dma_capable() ? hw_ep->rx_channel : NULL;
+ status = 0;
+ xfer_len = 0;
+
+ rx_csr = musb_readw(epio, MUSB_RXCSR);
+ val = rx_csr;
+
+ if (unlikely(!urb)) {
+ /* REVISIT -- THIS SHOULD NEVER HAPPEN ... but, at least
+ * usbtest #11 (unlinks) triggers it regularly, sometimes
+ * with fifo full. (Only with DMA??)
+ */
+ dev_dbg(musb->controller, "BOGUS RX%d ready, csr %04x, count %d\n", epnum, val,
+ musb_readw(epio, MUSB_RXCOUNT));
+ musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
+ return;
+ }
+
+ pipe = urb->pipe;
+
+ dev_dbg(musb->controller, "<== hw %d rxcsr %04x, urb actual %d (+dma %zu)\n",
+ epnum, rx_csr, urb->actual_length,
+ dma ? dma->actual_len : 0);
+
+ /* check for errors, concurrent stall & unlink is not really
+ * handled yet! */
+ if (rx_csr & MUSB_RXCSR_H_RXSTALL) {
+ dev_dbg(musb->controller, "RX end %d STALL\n", epnum);
+
+ /* stall; record URB status */
+ status = -EPIPE;
+
+ } else if (rx_csr & MUSB_RXCSR_H_ERROR) {
+ dev_dbg(musb->controller, "end %d RX proto error\n", epnum);
+
+ status = -EPROTO;
+ musb_writeb(epio, MUSB_RXINTERVAL, 0);
+
+ } else if (rx_csr & MUSB_RXCSR_DATAERROR) {
+
+ if (USB_ENDPOINT_XFER_ISOC != qh->type) {
+ dev_dbg(musb->controller, "RX end %d NAK timeout\n", epnum);
+
+ /* NOTE: NAKing is *NOT* an error, so we want to
+ * continue. Except ... if there's a request for
+ * another QH, use that instead of starving it.
+ *
+ * Devices like Ethernet and serial adapters keep
+ * reads posted at all times, which will starve
+ * other devices without this logic.
+ */
+ if (usb_pipebulk(urb->pipe)
+ && qh->mux == 1
+ && !list_is_singular(&musb->in_bulk)) {
+ musb_bulk_rx_nak_timeout(musb, hw_ep);
+ return;
+ }
+ musb_ep_select(mbase, epnum);
+ rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+ rx_csr &= ~MUSB_RXCSR_DATAERROR;
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
+
+ goto finish;
+ } else {
+ dev_dbg(musb->controller, "RX end %d ISO data error\n", epnum);
+ /* packet error reported later */
+ iso_err = true;
+ }
+ } else if (rx_csr & MUSB_RXCSR_INCOMPRX) {
+ dev_dbg(musb->controller, "end %d high bandwidth incomplete ISO packet RX\n",
+ epnum);
+ status = -EPROTO;
+ }
+
+ /* faults abort the transfer */
+ if (status) {
+ /* clean up dma and collect transfer count */
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+ (void) musb->dma_controller->channel_abort(dma);
+ xfer_len = dma->actual_len;
+ }
+ musb_h_flush_rxfifo(hw_ep, MUSB_RXCSR_CLRDATATOG);
+ musb_writeb(epio, MUSB_RXINTERVAL, 0);
+ done = true;
+ goto finish;
+ }
+
+ if (unlikely(dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY)) {
+ /* SHOULD NEVER HAPPEN ... but at least DaVinci has done it */
+ ERR("RX%d dma busy, csr %04x\n", epnum, rx_csr);
+ goto finish;
+ }
+
+ /* thorough shutdown for now ... given more precise fault handling
+ * and better queueing support, we might keep a DMA pipeline going
+ * while processing this irq for earlier completions.
+ */
+
+ /* FIXME this is _way_ too much in-line logic for Mentor DMA */
+
+#ifndef CONFIG_USB_INVENTRA_DMA
+ if (rx_csr & MUSB_RXCSR_H_REQPKT) {
+ /* REVISIT this happened for a while on some short reads...
+ * the cleanup still needs investigation... looks bad...
+ * and also duplicates dma cleanup code above ... plus,
+ * shouldn't this be the "half full" double buffer case?
+ */
+ if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
+ dma->status = MUSB_DMA_STATUS_CORE_ABORT;
+ (void) musb->dma_controller->channel_abort(dma);
+ xfer_len = dma->actual_len;
+ done = true;
+ }
+
+ dev_dbg(musb->controller, "RXCSR%d %04x, reqpkt, len %zu%s\n", epnum, rx_csr,
+ xfer_len, dma ? ", dma" : "");
+ rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+
+ musb_ep_select(mbase, epnum);
+ musb_writew(epio, MUSB_RXCSR,
+ MUSB_RXCSR_H_WZC_BITS | rx_csr);
+ }
+#endif
+ if (dma && (rx_csr & MUSB_RXCSR_DMAENAB)) {
+ xfer_len = dma->actual_len;
+
+ val &= ~(MUSB_RXCSR_DMAENAB
+ | MUSB_RXCSR_H_AUTOREQ
+ | MUSB_RXCSR_AUTOCLEAR
+ | MUSB_RXCSR_RXPKTRDY);
+ musb_writew(hw_ep->regs, MUSB_RXCSR, val);
+
+#ifdef CONFIG_USB_INVENTRA_DMA
+ if (usb_pipeisoc(pipe)) {
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+ d->actual_length = xfer_len;
+
+ /* even if there was an error, we did the dma
+ * for iso_frame_desc->length
+ */
+ if (d->status != -EILSEQ && d->status != -EOVERFLOW)
+ d->status = 0;
+
+ if (++qh->iso_idx >= urb->number_of_packets)
+ done = true;
+ else
+ done = false;
+
+ } else {
+ /* done if urb buffer is full or short packet is recd */
+ done = (urb->actual_length + xfer_len >=
+ urb->transfer_buffer_length
+ || dma->actual_len < qh->maxpacket);
+ }
+
+ /* send IN token for next packet, without AUTOREQ */
+ if (!done) {
+ val |= MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR,
+ MUSB_RXCSR_H_WZC_BITS | val);
+ }
+
+ dev_dbg(musb->controller, "ep %d dma %s, rxcsr %04x, rxcount %d\n", epnum,
+ done ? "off" : "reset",
+ musb_readw(epio, MUSB_RXCSR),
+ musb_readw(epio, MUSB_RXCOUNT));
+#else
+ done = true;
+#endif
+ } else if (urb->status == -EINPROGRESS) {
+ /* if no errors, be sure a packet is ready for unloading */
+ if (unlikely(!(rx_csr & MUSB_RXCSR_RXPKTRDY))) {
+ status = -EPROTO;
+ ERR("Rx interrupt with no errors or packet!\n");
+
+ /* FIXME this is another "SHOULD NEVER HAPPEN" */
+
+/* SCRUB (RX) */
+ /* do the proper sequence to abort the transfer */
+ musb_ep_select(mbase, epnum);
+ val &= ~MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, val);
+ goto finish;
+ }
+
+ /* we are expecting IN packets */
+#ifdef CONFIG_USB_INVENTRA_DMA
+ if (dma) {
+ struct dma_controller *c;
+ u16 rx_count;
+ int ret, length;
+ dma_addr_t buf;
+
+ rx_count = musb_readw(epio, MUSB_RXCOUNT);
+
+ dev_dbg(musb->controller, "RX%d count %d, buffer 0x%x len %d/%d\n",
+ epnum, rx_count,
+ urb->transfer_dma
+ + urb->actual_length,
+ qh->offset,
+ urb->transfer_buffer_length);
+
+ c = musb->dma_controller;
+
+ if (usb_pipeisoc(pipe)) {
+ int d_status = 0;
+ struct usb_iso_packet_descriptor *d;
+
+ d = urb->iso_frame_desc + qh->iso_idx;
+
+ if (iso_err) {
+ d_status = -EILSEQ;
+ urb->error_count++;
+ }
+ if (rx_count > d->length) {
+ if (d_status == 0) {
+ d_status = -EOVERFLOW;
+ urb->error_count++;
+ }
+ dev_dbg(musb->controller, "** OVERFLOW %d into %d\n",\
+ rx_count, d->length);
+
+ length = d->length;
+ } else
+ length = rx_count;
+ d->status = d_status;
+ buf = urb->transfer_dma + d->offset;
+ } else {
+ length = rx_count;
+ buf = urb->transfer_dma +
+ urb->actual_length;
+ }
+
+ dma->desired_mode = 0;
+#ifdef USE_MODE1
+ /* because of the issue below, mode 1 will
+ * only rarely behave with correct semantics.
+ */
+ if ((urb->transfer_flags &
+ URB_SHORT_NOT_OK)
+ && (urb->transfer_buffer_length -
+ urb->actual_length)
+ > qh->maxpacket)
+ dma->desired_mode = 1;
+ if (rx_count < hw_ep->max_packet_sz_rx) {
+ length = rx_count;
+ dma->desired_mode = 0;
+ } else {
+ length = urb->transfer_buffer_length;
+ }
+#endif
+
+/* Disadvantage of using mode 1:
+ * It's basically usable only for mass storage class; essentially all
+ * other protocols also terminate transfers on short packets.
+ *
+ * Details:
+ * An extra IN token is sent at the end of the transfer (due to AUTOREQ)
+ * If you try to use mode 1 for (transfer_buffer_length - 512), and try
+ * to use the extra IN token to grab the last packet using mode 0, then
+ * the problem is that you cannot be sure when the device will send the
+ * last packet and RxPktRdy set. Sometimes the packet is recd too soon
+ * such that it gets lost when RxCSR is re-set at the end of the mode 1
+ * transfer, while sometimes it is recd just a little late so that if you
+ * try to configure for mode 0 soon after the mode 1 transfer is
+ * completed, you will find rxcount 0. Okay, so you might think why not
+ * wait for an interrupt when the pkt is recd. Well, you won't get any!
+ */
+
+ val = musb_readw(epio, MUSB_RXCSR);
+ val &= ~MUSB_RXCSR_H_REQPKT;
+
+ if (dma->desired_mode == 0)
+ val &= ~MUSB_RXCSR_H_AUTOREQ;
+ else
+ val |= MUSB_RXCSR_H_AUTOREQ;
+ val |= MUSB_RXCSR_DMAENAB;
+
+ /* autoclear shouldn't be set in high bandwidth */
+ if (qh->hb_mult == 1)
+ val |= MUSB_RXCSR_AUTOCLEAR;
+
+ musb_writew(epio, MUSB_RXCSR,
+ MUSB_RXCSR_H_WZC_BITS | val);
+
+ /* REVISIT if when actual_length != 0,
+ * transfer_buffer_length needs to be
+ * adjusted first...
+ */
+ ret = c->channel_program(
+ dma, qh->maxpacket,
+ dma->desired_mode, buf, length);
+
+ if (!ret) {
+ c->channel_release(dma);
+ hw_ep->rx_channel = NULL;
+ dma = NULL;
+ val = musb_readw(epio, MUSB_RXCSR);
+ val &= ~(MUSB_RXCSR_DMAENAB
+ | MUSB_RXCSR_H_AUTOREQ
+ | MUSB_RXCSR_AUTOCLEAR);
+ musb_writew(epio, MUSB_RXCSR, val);
+ }
+ }
+#endif /* Mentor DMA */
+
+ if (!dma) {
+ /* Unmap the buffer so that CPU can use it */
+ usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb);
+ done = musb_host_packet_rx(musb, urb,
+ epnum, iso_err);
+ dev_dbg(musb->controller, "read %spacket\n", done ? "last " : "");
+ }
+ }
+
+finish:
+ urb->actual_length += xfer_len;
+ qh->offset += xfer_len;
+ if (done) {
+ if (urb->status == -EINPROGRESS)
+ urb->status = status;
+ musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN);
+ }
+}
+
+/* schedule nodes correspond to peripheral endpoints, like an OHCI QH.
+ * the software schedule associates multiple such nodes with a given
+ * host side hardware endpoint + direction; scheduling may activate
+ * that hardware endpoint.
+ */
+static int musb_schedule(
+ struct musb *musb,
+ struct musb_qh *qh,
+ int is_in)
+{
+ int idle;
+ int best_diff;
+ int best_end, epnum;
+ struct musb_hw_ep *hw_ep = NULL;
+ struct list_head *head = NULL;
+ u8 toggle;
+ u8 txtype;
+ struct urb *urb = next_urb(qh);
+
+ /* use fixed hardware for control and bulk */
+ if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+ head = &musb->control;
+ hw_ep = musb->control_ep;
+ goto success;
+ }
+
+ /* else, periodic transfers get muxed to other endpoints */
+
+ /*
+ * We know this qh hasn't been scheduled, so all we need to do
+ * is choose which hardware endpoint to put it on ...
+ *
+ * REVISIT what we really want here is a regular schedule tree
+ * like e.g. OHCI uses.
+ */
+ best_diff = 4096;
+ best_end = -1;
+
+ for (epnum = 1, hw_ep = musb->endpoints + 1;
+ epnum < musb->nr_endpoints;
+ epnum++, hw_ep++) {
+ int diff;
+
+ if (musb_ep_get_qh(hw_ep, is_in) != NULL)
+ continue;
+
+ if (hw_ep == musb->bulk_ep)
+ continue;
+
+ if (is_in)
+ diff = hw_ep->max_packet_sz_rx;
+ else
+ diff = hw_ep->max_packet_sz_tx;
+ diff -= (qh->maxpacket * qh->hb_mult);
+
+ if (diff >= 0 && best_diff > diff) {
+
+ /*
+ * Mentor controller has a bug in that if we schedule
+ * a BULK Tx transfer on an endpoint that had earlier
+ * handled ISOC then the BULK transfer has to start on
+ * a zero toggle. If the BULK transfer starts on a 1
+ * toggle then this transfer will fail as the mentor
+ * controller starts the Bulk transfer on a 0 toggle
+ * irrespective of the programming of the toggle bits
+ * in the TXCSR register. Check for this condition
+ * while allocating the EP for a Tx Bulk transfer. If
+ * so skip this EP.
+ */
+ hw_ep = musb->endpoints + epnum;
+ toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in);
+ txtype = (musb_readb(hw_ep->regs, MUSB_TXTYPE)
+ >> 4) & 0x3;
+ if (!is_in && (qh->type == USB_ENDPOINT_XFER_BULK) &&
+ toggle && (txtype == USB_ENDPOINT_XFER_ISOC))
+ continue;
+
+ best_diff = diff;
+ best_end = epnum;
+ }
+ }
+ /* use bulk reserved ep1 if no other ep is free */
+ if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
+ hw_ep = musb->bulk_ep;
+ if (is_in)
+ head = &musb->in_bulk;
+ else
+ head = &musb->out_bulk;
+
+ /* Enable bulk RX NAK timeout scheme when bulk requests are
+ * multiplexed. This scheme doen't work in high speed to full
+ * speed scenario as NAK interrupts are not coming from a
+ * full speed device connected to a high speed device.
+ * NAK timeout interval is 8 (128 uframe or 16ms) for HS and
+ * 4 (8 frame or 8ms) for FS device.
+ */
+ if (is_in && qh->dev)
+ qh->intv_reg =
+ (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
+ goto success;
+ } else if (best_end < 0) {
+ return -ENOSPC;
+ }
+
+ idle = 1;
+ qh->mux = 0;
+ hw_ep = musb->endpoints + best_end;
+ dev_dbg(musb->controller, "qh %p periodic slot %d\n", qh, best_end);
+success:
+ if (head) {
+ idle = list_empty(head);
+ list_add_tail(&qh->ring, head);
+ qh->mux = 1;
+ }
+ qh->hw_ep = hw_ep;
+ qh->hep->hcpriv = qh;
+ if (idle)
+ musb_start_urb(musb, is_in, qh);
+ return 0;
+}
+
+#ifdef __UBOOT__
+/* check if transaction translator is needed for device */
+static int tt_needed(struct musb *musb, struct usb_device *dev)
+{
+ if ((musb_readb(musb->mregs, MUSB_POWER) & MUSB_POWER_HSMODE) &&
+ (dev->speed < USB_SPEED_HIGH))
+ return 1;
+ return 0;
+}
+#endif
+
+#ifndef __UBOOT__
+static int musb_urb_enqueue(
+#else
+int musb_urb_enqueue(
+#endif
+ struct usb_hcd *hcd,
+ struct urb *urb,
+ gfp_t mem_flags)
+{
+ unsigned long flags;
+ struct musb *musb = hcd_to_musb(hcd);
+ struct usb_host_endpoint *hep = urb->ep;
+ struct musb_qh *qh;
+ struct usb_endpoint_descriptor *epd = &hep->desc;
+ int ret;
+ unsigned type_reg;
+ unsigned interval;
+
+ /* host role must be active */
+ if (!is_host_active(musb) || !musb->is_active)
+ return -ENODEV;
+
+ spin_lock_irqsave(&musb->lock, flags);
+ ret = usb_hcd_link_urb_to_ep(hcd, urb);
+ qh = ret ? NULL : hep->hcpriv;
+ if (qh)
+ urb->hcpriv = qh;
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ /* DMA mapping was already done, if needed, and this urb is on
+ * hep->urb_list now ... so we're done, unless hep wasn't yet
+ * scheduled onto a live qh.
+ *
+ * REVISIT best to keep hep->hcpriv valid until the endpoint gets
+ * disabled, testing for empty qh->ring and avoiding qh setup costs
+ * except for the first urb queued after a config change.
+ */
+ if (qh || ret)
+ return ret;
+
+ /* Allocate and initialize qh, minimizing the work done each time
+ * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it.
+ *
+ * REVISIT consider a dedicated qh kmem_cache, so it's harder
+ * for bugs in other kernel code to break this driver...
+ */
+ qh = kzalloc(sizeof *qh, mem_flags);
+ if (!qh) {
+ spin_lock_irqsave(&musb->lock, flags);
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return -ENOMEM;
+ }
+
+ qh->hep = hep;
+ qh->dev = urb->dev;
+ INIT_LIST_HEAD(&qh->ring);
+ qh->is_ready = 1;
+
+ qh->maxpacket = usb_endpoint_maxp(epd);
+ qh->type = usb_endpoint_type(epd);
+
+ /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier.
+ * Some musb cores don't support high bandwidth ISO transfers; and
+ * we don't (yet!) support high bandwidth interrupt transfers.
+ */
+ qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03);
+ if (qh->hb_mult > 1) {
+ int ok = (qh->type == USB_ENDPOINT_XFER_ISOC);
+
+ if (ok)
+ ok = (usb_pipein(urb->pipe) && musb->hb_iso_rx)
+ || (usb_pipeout(urb->pipe) && musb->hb_iso_tx);
+ if (!ok) {
+ ret = -EMSGSIZE;
+ goto done;
+ }
+ qh->maxpacket &= 0x7ff;
+ }
+
+ qh->epnum = usb_endpoint_num(epd);
+
+ /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */
+ qh->addr_reg = (u8) usb_pipedevice(urb->pipe);
+
+ /* precompute rxtype/txtype/type0 register */
+ type_reg = (qh->type << 4) | qh->epnum;
+ switch (urb->dev->speed) {
+ case USB_SPEED_LOW:
+ type_reg |= 0xc0;
+ break;
+ case USB_SPEED_FULL:
+ type_reg |= 0x80;
+ break;
+ default:
+ type_reg |= 0x40;
+ }
+ qh->type_reg = type_reg;
+
+ /* Precompute RXINTERVAL/TXINTERVAL register */
+ switch (qh->type) {
+ case USB_ENDPOINT_XFER_INT:
+ /*
+ * Full/low speeds use the linear encoding,
+ * high speed uses the logarithmic encoding.
+ */
+ if (urb->dev->speed <= USB_SPEED_FULL) {
+ interval = max_t(u8, epd->bInterval, 1);
+ break;
+ }
+ /* FALLTHROUGH */
+ case USB_ENDPOINT_XFER_ISOC:
+ /* ISO always uses logarithmic encoding */
+ interval = min_t(u8, epd->bInterval, 16);
+ break;
+ default:
+ /* REVISIT we actually want to use NAK limits, hinting to the
+ * transfer scheduling logic to try some other qh, e.g. try
+ * for 2 msec first:
+ *
+ * interval = (USB_SPEED_HIGH == urb->dev->speed) ? 16 : 2;
+ *
+ * The downside of disabling this is that transfer scheduling
+ * gets VERY unfair for nonperiodic transfers; a misbehaving
+ * peripheral could make that hurt. That's perfectly normal
+ * for reads from network or serial adapters ... so we have
+ * partial NAKlimit support for bulk RX.
+ *
+ * The upside of disabling it is simpler transfer scheduling.
+ */
+ interval = 0;
+ }
+ qh->intv_reg = interval;
+
+ /* precompute addressing for external hub/tt ports */
+ if (musb->is_multipoint) {
+ struct usb_device *parent = urb->dev->parent;
+
+#ifndef __UBOOT__
+ if (parent != hcd->self.root_hub) {
+#else
+ if (parent) {
+#endif
+ qh->h_addr_reg = (u8) parent->devnum;
+
+#ifndef __UBOOT__
+ /* set up tt info if needed */
+ if (urb->dev->tt) {
+ qh->h_port_reg = (u8) urb->dev->ttport;
+ if (urb->dev->tt->hub)
+ qh->h_addr_reg =
+ (u8) urb->dev->tt->hub->devnum;
+ if (urb->dev->tt->multi)
+ qh->h_addr_reg |= 0x80;
+ }
+#else
+ if (tt_needed(musb, urb->dev)) {
+ u16 hub_port = find_tt(urb->dev);
+ qh->h_addr_reg = (u8) (hub_port >> 8);
+ qh->h_port_reg = (u8) (hub_port & 0xff);
+ }
+#endif
+ }
+ }
+
+ /* invariant: hep->hcpriv is null OR the qh that's already scheduled.
+ * until we get real dma queues (with an entry for each urb/buffer),
+ * we only have work to do in the former case.
+ */
+ spin_lock_irqsave(&musb->lock, flags);
+ if (hep->hcpriv) {
+ /* some concurrent activity submitted another urb to hep...
+ * odd, rare, error prone, but legal.
+ */
+ kfree(qh);
+ qh = NULL;
+ ret = 0;
+ } else
+ ret = musb_schedule(musb, qh,
+ epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK);
+
+ if (ret == 0) {
+ urb->hcpriv = qh;
+ /* FIXME set urb->start_frame for iso/intr, it's tested in
+ * musb_start_urb(), but otherwise only konicawc cares ...
+ */
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+done:
+ if (ret != 0) {
+ spin_lock_irqsave(&musb->lock, flags);
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+ kfree(qh);
+ }
+ return ret;
+}
+
+
+#ifndef __UBOOT__
+/*
+ * abort a transfer that's at the head of a hardware queue.
+ * called with controller locked, irqs blocked
+ * that hardware queue advances to the next transfer, unless prevented
+ */
+static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh)
+{
+ struct musb_hw_ep *ep = qh->hw_ep;
+ struct musb *musb = ep->musb;
+ void __iomem *epio = ep->regs;
+ unsigned hw_end = ep->epnum;
+ void __iomem *regs = ep->musb->mregs;
+ int is_in = usb_pipein(urb->pipe);
+ int status = 0;
+ u16 csr;
+
+ musb_ep_select(regs, hw_end);
+
+ if (is_dma_capable()) {
+ struct dma_channel *dma;
+
+ dma = is_in ? ep->rx_channel : ep->tx_channel;
+ if (dma) {
+ status = ep->musb->dma_controller->channel_abort(dma);
+ dev_dbg(musb->controller,
+ "abort %cX%d DMA for urb %p --> %d\n",
+ is_in ? 'R' : 'T', ep->epnum,
+ urb, status);
+ urb->actual_length += dma->actual_len;
+ }
+ }
+
+ /* turn off DMA requests, discard state, stop polling ... */
+ if (ep->epnum && is_in) {
+ /* giveback saves bulk toggle */
+ csr = musb_h_flush_rxfifo(ep, 0);
+
+ /* REVISIT we still get an irq; should likely clear the
+ * endpoint's irq status here to avoid bogus irqs.
+ * clearing that status is platform-specific...
+ */
+ } else if (ep->epnum) {
+ musb_h_tx_flush_fifo(ep);
+ csr = musb_readw(epio, MUSB_TXCSR);
+ csr &= ~(MUSB_TXCSR_AUTOSET
+ | MUSB_TXCSR_DMAENAB
+ | MUSB_TXCSR_H_RXSTALL
+ | MUSB_TXCSR_H_NAKTIMEOUT
+ | MUSB_TXCSR_H_ERROR
+ | MUSB_TXCSR_TXPKTRDY);
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* REVISIT may need to clear FLUSHFIFO ... */
+ musb_writew(epio, MUSB_TXCSR, csr);
+ /* flush cpu writebuffer */
+ csr = musb_readw(epio, MUSB_TXCSR);
+ } else {
+ musb_h_ep0_flush_fifo(ep);
+ }
+ if (status == 0)
+ musb_advance_schedule(ep->musb, urb, ep, is_in);
+ return status;
+}
+
+static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+ struct musb *musb = hcd_to_musb(hcd);
+ struct musb_qh *qh;
+ unsigned long flags;
+ int is_in = usb_pipein(urb->pipe);
+ int ret;
+
+ dev_dbg(musb->controller, "urb=%p, dev%d ep%d%s\n", urb,
+ usb_pipedevice(urb->pipe),
+ usb_pipeendpoint(urb->pipe),
+ is_in ? "in" : "out");
+
+ spin_lock_irqsave(&musb->lock, flags);
+ ret = usb_hcd_check_unlink_urb(hcd, urb, status);
+ if (ret)
+ goto done;
+
+ qh = urb->hcpriv;
+ if (!qh)
+ goto done;
+
+ /*
+ * Any URB not actively programmed into endpoint hardware can be
+ * immediately given back; that's any URB not at the head of an
+ * endpoint queue, unless someday we get real DMA queues. And even
+ * if it's at the head, it might not be known to the hardware...
+ *
+ * Otherwise abort current transfer, pending DMA, etc.; urb->status
+ * has already been updated. This is a synchronous abort; it'd be
+ * OK to hold off until after some IRQ, though.
+ *
+ * NOTE: qh is invalid unless !list_empty(&hep->urb_list)
+ */
+ if (!qh->is_ready
+ || urb->urb_list.prev != &qh->hep->urb_list
+ || musb_ep_get_qh(qh->hw_ep, is_in) != qh) {
+ int ready = qh->is_ready;
+
+ qh->is_ready = 0;
+ musb_giveback(musb, urb, 0);
+ qh->is_ready = ready;
+
+ /* If nothing else (usually musb_giveback) is using it
+ * and its URB list has emptied, recycle this qh.
+ */
+ if (ready && list_empty(&qh->hep->urb_list)) {
+ qh->hep->hcpriv = NULL;
+ list_del(&qh->ring);
+ kfree(qh);
+ }
+ } else
+ ret = musb_cleanup_urb(urb, qh);
+done:
+ spin_unlock_irqrestore(&musb->lock, flags);
+ return ret;
+}
+
+/* disable an endpoint */
+static void
+musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
+{
+ u8 is_in = hep->desc.bEndpointAddress & USB_DIR_IN;
+ unsigned long flags;
+ struct musb *musb = hcd_to_musb(hcd);
+ struct musb_qh *qh;
+ struct urb *urb;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ qh = hep->hcpriv;
+ if (qh == NULL)
+ goto exit;
+
+ /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */
+
+ /* Kick the first URB off the hardware, if needed */
+ qh->is_ready = 0;
+ if (musb_ep_get_qh(qh->hw_ep, is_in) == qh) {
+ urb = next_urb(qh);
+
+ /* make software (then hardware) stop ASAP */
+ if (!urb->unlinked)
+ urb->status = -ESHUTDOWN;
+
+ /* cleanup */
+ musb_cleanup_urb(urb, qh);
+
+ /* Then nuke all the others ... and advance the
+ * queue on hw_ep (e.g. bulk ring) when we're done.
+ */
+ while (!list_empty(&hep->urb_list)) {
+ urb = next_urb(qh);
+ urb->status = -ESHUTDOWN;
+ musb_advance_schedule(musb, urb, qh->hw_ep, is_in);
+ }
+ } else {
+ /* Just empty the queue; the hardware is busy with
+ * other transfers, and since !qh->is_ready nothing
+ * will activate any of these as it advances.
+ */
+ while (!list_empty(&hep->urb_list))
+ musb_giveback(musb, next_urb(qh), -ESHUTDOWN);
+
+ hep->hcpriv = NULL;
+ list_del(&qh->ring);
+ kfree(qh);
+ }
+exit:
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+static int musb_h_get_frame_number(struct usb_hcd *hcd)
+{
+ struct musb *musb = hcd_to_musb(hcd);
+
+ return musb_readw(musb->mregs, MUSB_FRAME);
+}
+
+static int musb_h_start(struct usb_hcd *hcd)
+{
+ struct musb *musb = hcd_to_musb(hcd);
+
+ /* NOTE: musb_start() is called when the hub driver turns
+ * on port power, or when (OTG) peripheral starts.
+ */
+ hcd->state = HC_STATE_RUNNING;
+ musb->port1_status = 0;
+ return 0;
+}
+
+static void musb_h_stop(struct usb_hcd *hcd)
+{
+ musb_stop(hcd_to_musb(hcd));
+ hcd->state = HC_STATE_HALT;
+}
+
+static int musb_bus_suspend(struct usb_hcd *hcd)
+{
+ struct musb *musb = hcd_to_musb(hcd);
+ u8 devctl;
+
+ if (!is_host_active(musb))
+ return 0;
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_SUSPEND:
+ return 0;
+ case OTG_STATE_A_WAIT_VRISE:
+ /* ID could be grounded even if there's no device
+ * on the other end of the cable. NOTE that the
+ * A_WAIT_VRISE timers are messy with MUSB...
+ */
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ break;
+ default:
+ break;
+ }
+
+ if (musb->is_active) {
+ WARNING("trying to suspend as %s while active\n",
+ otg_state_string(musb->xceiv->state));
+ return -EBUSY;
+ } else
+ return 0;
+}
+
+static int musb_bus_resume(struct usb_hcd *hcd)
+{
+ /* resuming child port does the work */
+ return 0;
+}
+
+const struct hc_driver musb_hc_driver = {
+ .description = "musb-hcd",
+ .product_desc = "MUSB HDRC host driver",
+ .hcd_priv_size = sizeof(struct musb),
+ .flags = HCD_USB2 | HCD_MEMORY,
+
+ /* not using irq handler or reset hooks from usbcore, since
+ * those must be shared with peripheral code for OTG configs
+ */
+
+ .start = musb_h_start,
+ .stop = musb_h_stop,
+
+ .get_frame_number = musb_h_get_frame_number,
+
+ .urb_enqueue = musb_urb_enqueue,
+ .urb_dequeue = musb_urb_dequeue,
+ .endpoint_disable = musb_h_disable,
+
+ .hub_status_data = musb_hub_status_data,
+ .hub_control = musb_hub_control,
+ .bus_suspend = musb_bus_suspend,
+ .bus_resume = musb_bus_resume,
+ /* .start_port_reset = NULL, */
+ /* .hub_irq_enable = NULL, */
+};
+#endif
diff --git a/drivers/usb/musb-new/musb_host.h b/drivers/usb/musb-new/musb_host.h
new file mode 100644
index 0000000000..ebebe0c02a
--- /dev/null
+++ b/drivers/usb/musb-new/musb_host.h
@@ -0,0 +1,114 @@
+/*
+ * MUSB OTG driver host defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _MUSB_HOST_H
+#define _MUSB_HOST_H
+#ifdef __UBOOT__
+#include "usb-compat.h"
+#endif
+
+static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
+{
+ return container_of((void *) musb, struct usb_hcd, hcd_priv);
+}
+
+static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
+{
+ return (struct musb *) (hcd->hcd_priv);
+}
+
+/* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */
+struct musb_qh {
+ struct usb_host_endpoint *hep; /* usbcore info */
+ struct usb_device *dev;
+ struct musb_hw_ep *hw_ep; /* current binding */
+
+ struct list_head ring; /* of musb_qh */
+ /* struct musb_qh *next; */ /* for periodic tree */
+ u8 mux; /* qh multiplexed to hw_ep */
+
+ unsigned offset; /* in urb->transfer_buffer */
+ unsigned segsize; /* current xfer fragment */
+
+ u8 type_reg; /* {rx,tx} type register */
+ u8 intv_reg; /* {rx,tx} interval register */
+ u8 addr_reg; /* device address register */
+ u8 h_addr_reg; /* hub address register */
+ u8 h_port_reg; /* hub port register */
+
+ u8 is_ready; /* safe to modify hw_ep */
+ u8 type; /* XFERTYPE_* */
+ u8 epnum;
+ u8 hb_mult; /* high bandwidth pkts per uf */
+ u16 maxpacket;
+ u16 frame; /* for periodic schedule */
+ unsigned iso_idx; /* in urb->iso_frame_desc[] */
+};
+
+/* map from control or bulk queue head to the first qh on that ring */
+static inline struct musb_qh *first_qh(struct list_head *q)
+{
+ if (list_empty(q))
+ return NULL;
+ return list_entry(q->next, struct musb_qh, ring);
+}
+
+
+extern void musb_root_disconnect(struct musb *musb);
+
+struct usb_hcd;
+
+extern int musb_hub_status_data(struct usb_hcd *hcd, char *buf);
+extern int musb_hub_control(struct usb_hcd *hcd,
+ u16 typeReq, u16 wValue, u16 wIndex,
+ char *buf, u16 wLength);
+
+extern const struct hc_driver musb_hc_driver;
+
+static inline struct urb *next_urb(struct musb_qh *qh)
+{
+ struct list_head *queue;
+
+ if (!qh)
+ return NULL;
+ queue = &qh->hep->urb_list;
+ if (list_empty(queue))
+ return NULL;
+ return list_entry(queue->next, struct urb, urb_list);
+}
+
+#ifdef __UBOOT__
+int musb_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
+#endif
+#endif /* _MUSB_HOST_H */
diff --git a/drivers/usb/musb-new/musb_io.h b/drivers/usb/musb-new/musb_io.h
new file mode 100644
index 0000000000..51730aee52
--- /dev/null
+++ b/drivers/usb/musb-new/musb_io.h
@@ -0,0 +1,146 @@
+/*
+ * MUSB OTG driver register I/O
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_LINUX_PLATFORM_ARCH_H__
+#define __MUSB_LINUX_PLATFORM_ARCH_H__
+
+#ifndef __UBOOT__
+#include <linux/io.h>
+#else
+#include <asm/io.h>
+#endif
+
+#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \
+ && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \
+ && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \
+ && !defined(CONFIG_MIPS) && !defined(CONFIG_M68K)
+static inline void readsl(const void __iomem *addr, void *buf, int len)
+ { insl((unsigned long)addr, buf, len); }
+static inline void readsw(const void __iomem *addr, void *buf, int len)
+ { insw((unsigned long)addr, buf, len); }
+static inline void readsb(const void __iomem *addr, void *buf, int len)
+ { insb((unsigned long)addr, buf, len); }
+
+static inline void writesl(const void __iomem *addr, const void *buf, int len)
+ { outsl((unsigned long)addr, buf, len); }
+static inline void writesw(const void __iomem *addr, const void *buf, int len)
+ { outsw((unsigned long)addr, buf, len); }
+static inline void writesb(const void __iomem *addr, const void *buf, int len)
+ { outsb((unsigned long)addr, buf, len); }
+
+#endif
+
+#ifndef CONFIG_BLACKFIN
+
+/* NOTE: these offsets are all in bytes */
+
+static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
+ { return __raw_readw(addr + offset); }
+
+static inline u32 musb_readl(const void __iomem *addr, unsigned offset)
+ { return __raw_readl(addr + offset); }
+
+
+static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
+ { __raw_writew(data, addr + offset); }
+
+static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
+ { __raw_writel(data, addr + offset); }
+
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE)
+
+/*
+ * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum.
+ */
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+{
+ u16 tmp;
+ u8 val;
+
+ tmp = __raw_readw(addr + (offset & ~1));
+ if (offset & 1)
+ val = (tmp >> 8);
+ else
+ val = tmp & 0xff;
+
+ return val;
+}
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+{
+ u16 tmp;
+
+ tmp = __raw_readw(addr + (offset & ~1));
+ if (offset & 1)
+ tmp = (data << 8) | (tmp & 0xff);
+ else
+ tmp = (tmp & 0xff00) | data;
+
+ __raw_writew(tmp, addr + (offset & ~1));
+}
+
+#else
+
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+ { return __raw_readb(addr + offset); }
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+ { __raw_writeb(data, addr + offset); }
+
+#endif /* CONFIG_USB_MUSB_TUSB6010 */
+
+#else
+
+static inline u8 musb_readb(const void __iomem *addr, unsigned offset)
+ { return (u8) (bfin_read16(addr + offset)); }
+
+static inline u16 musb_readw(const void __iomem *addr, unsigned offset)
+ { return bfin_read16(addr + offset); }
+
+static inline u32 musb_readl(const void __iomem *addr, unsigned offset)
+ { return (u32) (bfin_read16(addr + offset)); }
+
+static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+ { bfin_write16(addr + offset, (u16) data); }
+
+static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data)
+ { bfin_write16(addr + offset, data); }
+
+static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data)
+ { bfin_write16(addr + offset, (u16) data); }
+
+#endif /* CONFIG_BLACKFIN */
+
+#endif
diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h
new file mode 100644
index 0000000000..03f2655af2
--- /dev/null
+++ b/drivers/usb/musb-new/musb_regs.h
@@ -0,0 +1,645 @@
+/*
+ * MUSB OTG driver register defines
+ *
+ * Copyright 2005 Mentor Graphics Corporation
+ * Copyright (C) 2005-2006 by Texas Instruments
+ * Copyright (C) 2006-2007 Nokia Corporation
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MUSB_REGS_H__
+#define __MUSB_REGS_H__
+
+#define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */
+
+/*
+ * MUSB Register bits
+ */
+
+/* POWER */
+#define MUSB_POWER_ISOUPDATE 0x80
+#define MUSB_POWER_SOFTCONN 0x40
+#define MUSB_POWER_HSENAB 0x20
+#define MUSB_POWER_HSMODE 0x10
+#define MUSB_POWER_RESET 0x08
+#define MUSB_POWER_RESUME 0x04
+#define MUSB_POWER_SUSPENDM 0x02
+#define MUSB_POWER_ENSUSPEND 0x01
+
+/* INTRUSB */
+#define MUSB_INTR_SUSPEND 0x01
+#define MUSB_INTR_RESUME 0x02
+#define MUSB_INTR_RESET 0x04
+#define MUSB_INTR_BABBLE 0x04
+#define MUSB_INTR_SOF 0x08
+#define MUSB_INTR_CONNECT 0x10
+#define MUSB_INTR_DISCONNECT 0x20
+#define MUSB_INTR_SESSREQ 0x40
+#define MUSB_INTR_VBUSERROR 0x80 /* For SESSION end */
+
+/* DEVCTL */
+#define MUSB_DEVCTL_BDEVICE 0x80
+#define MUSB_DEVCTL_FSDEV 0x40
+#define MUSB_DEVCTL_LSDEV 0x20
+#define MUSB_DEVCTL_VBUS 0x18
+#define MUSB_DEVCTL_VBUS_SHIFT 3
+#define MUSB_DEVCTL_HM 0x04
+#define MUSB_DEVCTL_HR 0x02
+#define MUSB_DEVCTL_SESSION 0x01
+
+/* MUSB ULPI VBUSCONTROL */
+#define MUSB_ULPI_USE_EXTVBUS 0x01
+#define MUSB_ULPI_USE_EXTVBUSIND 0x02
+/* ULPI_REG_CONTROL */
+#define MUSB_ULPI_REG_REQ (1 << 0)
+#define MUSB_ULPI_REG_CMPLT (1 << 1)
+#define MUSB_ULPI_RDN_WR (1 << 2)
+
+/* TESTMODE */
+#define MUSB_TEST_FORCE_HOST 0x80
+#define MUSB_TEST_FIFO_ACCESS 0x40
+#define MUSB_TEST_FORCE_FS 0x20
+#define MUSB_TEST_FORCE_HS 0x10
+#define MUSB_TEST_PACKET 0x08
+#define MUSB_TEST_K 0x04
+#define MUSB_TEST_J 0x02
+#define MUSB_TEST_SE0_NAK 0x01
+
+/* Allocate for double-packet buffering (effectively doubles assigned _SIZE) */
+#define MUSB_FIFOSZ_DPB 0x10
+/* Allocation size (8, 16, 32, ... 4096) */
+#define MUSB_FIFOSZ_SIZE 0x0f
+
+/* CSR0 */
+#define MUSB_CSR0_FLUSHFIFO 0x0100
+#define MUSB_CSR0_TXPKTRDY 0x0002
+#define MUSB_CSR0_RXPKTRDY 0x0001
+
+/* CSR0 in Peripheral mode */
+#define MUSB_CSR0_P_SVDSETUPEND 0x0080
+#define MUSB_CSR0_P_SVDRXPKTRDY 0x0040
+#define MUSB_CSR0_P_SENDSTALL 0x0020
+#define MUSB_CSR0_P_SETUPEND 0x0010
+#define MUSB_CSR0_P_DATAEND 0x0008
+#define MUSB_CSR0_P_SENTSTALL 0x0004
+
+/* CSR0 in Host mode */
+#define MUSB_CSR0_H_DIS_PING 0x0800
+#define MUSB_CSR0_H_WR_DATATOGGLE 0x0400 /* Set to allow setting: */
+#define MUSB_CSR0_H_DATATOGGLE 0x0200 /* Data toggle control */
+#define MUSB_CSR0_H_NAKTIMEOUT 0x0080
+#define MUSB_CSR0_H_STATUSPKT 0x0040
+#define MUSB_CSR0_H_REQPKT 0x0020
+#define MUSB_CSR0_H_ERROR 0x0010
+#define MUSB_CSR0_H_SETUPPKT 0x0008
+#define MUSB_CSR0_H_RXSTALL 0x0004
+
+/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_CSR0_P_WZC_BITS \
+ (MUSB_CSR0_P_SENTSTALL)
+#define MUSB_CSR0_H_WZC_BITS \
+ (MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL \
+ | MUSB_CSR0_RXPKTRDY)
+
+/* TxType/RxType */
+#define MUSB_TYPE_SPEED 0xc0
+#define MUSB_TYPE_SPEED_SHIFT 6
+#define MUSB_TYPE_PROTO 0x30 /* Implicitly zero for ep0 */
+#define MUSB_TYPE_PROTO_SHIFT 4
+#define MUSB_TYPE_REMOTE_END 0xf /* Implicitly zero for ep0 */
+
+/* CONFIGDATA */
+#define MUSB_CONFIGDATA_MPRXE 0x80 /* Auto bulk pkt combining */
+#define MUSB_CONFIGDATA_MPTXE 0x40 /* Auto bulk pkt splitting */
+#define MUSB_CONFIGDATA_BIGENDIAN 0x20
+#define MUSB_CONFIGDATA_HBRXE 0x10 /* HB-ISO for RX */
+#define MUSB_CONFIGDATA_HBTXE 0x08 /* HB-ISO for TX */
+#define MUSB_CONFIGDATA_DYNFIFO 0x04 /* Dynamic FIFO sizing */
+#define MUSB_CONFIGDATA_SOFTCONE 0x02 /* SoftConnect */
+#define MUSB_CONFIGDATA_UTMIDW 0x01 /* Data width 0/1 => 8/16bits */
+
+/* TXCSR in Peripheral and Host mode */
+#define MUSB_TXCSR_AUTOSET 0x8000
+#define MUSB_TXCSR_DMAENAB 0x1000
+#define MUSB_TXCSR_FRCDATATOG 0x0800
+#define MUSB_TXCSR_DMAMODE 0x0400
+#define MUSB_TXCSR_CLRDATATOG 0x0040
+#define MUSB_TXCSR_FLUSHFIFO 0x0008
+#define MUSB_TXCSR_FIFONOTEMPTY 0x0002
+#define MUSB_TXCSR_TXPKTRDY 0x0001
+
+/* TXCSR in Peripheral mode */
+#define MUSB_TXCSR_P_ISO 0x4000
+#define MUSB_TXCSR_P_INCOMPTX 0x0080
+#define MUSB_TXCSR_P_SENTSTALL 0x0020
+#define MUSB_TXCSR_P_SENDSTALL 0x0010
+#define MUSB_TXCSR_P_UNDERRUN 0x0004
+
+/* TXCSR in Host mode */
+#define MUSB_TXCSR_H_WR_DATATOGGLE 0x0200
+#define MUSB_TXCSR_H_DATATOGGLE 0x0100
+#define MUSB_TXCSR_H_NAKTIMEOUT 0x0080
+#define MUSB_TXCSR_H_RXSTALL 0x0020
+#define MUSB_TXCSR_H_ERROR 0x0004
+
+/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_TXCSR_P_WZC_BITS \
+ (MUSB_TXCSR_P_INCOMPTX | MUSB_TXCSR_P_SENTSTALL \
+ | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_FIFONOTEMPTY)
+#define MUSB_TXCSR_H_WZC_BITS \
+ (MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL \
+ | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)
+
+/* RXCSR in Peripheral and Host mode */
+#define MUSB_RXCSR_AUTOCLEAR 0x8000
+#define MUSB_RXCSR_DMAENAB 0x2000
+#define MUSB_RXCSR_DISNYET 0x1000
+#define MUSB_RXCSR_PID_ERR 0x1000
+#define MUSB_RXCSR_DMAMODE 0x0800
+#define MUSB_RXCSR_INCOMPRX 0x0100
+#define MUSB_RXCSR_CLRDATATOG 0x0080
+#define MUSB_RXCSR_FLUSHFIFO 0x0010
+#define MUSB_RXCSR_DATAERROR 0x0008
+#define MUSB_RXCSR_FIFOFULL 0x0002
+#define MUSB_RXCSR_RXPKTRDY 0x0001
+
+/* RXCSR in Peripheral mode */
+#define MUSB_RXCSR_P_ISO 0x4000
+#define MUSB_RXCSR_P_SENTSTALL 0x0040
+#define MUSB_RXCSR_P_SENDSTALL 0x0020
+#define MUSB_RXCSR_P_OVERRUN 0x0004
+
+/* RXCSR in Host mode */
+#define MUSB_RXCSR_H_AUTOREQ 0x4000
+#define MUSB_RXCSR_H_WR_DATATOGGLE 0x0400
+#define MUSB_RXCSR_H_DATATOGGLE 0x0200
+#define MUSB_RXCSR_H_RXSTALL 0x0040
+#define MUSB_RXCSR_H_REQPKT 0x0020
+#define MUSB_RXCSR_H_ERROR 0x0004
+
+/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
+#define MUSB_RXCSR_P_WZC_BITS \
+ (MUSB_RXCSR_P_SENTSTALL | MUSB_RXCSR_P_OVERRUN \
+ | MUSB_RXCSR_RXPKTRDY)
+#define MUSB_RXCSR_H_WZC_BITS \
+ (MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR \
+ | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY)
+
+/* HUBADDR */
+#define MUSB_HUBADDR_MULTI_TT 0x80
+
+
+#ifndef CONFIG_BLACKFIN
+
+/*
+ * Common USB registers
+ */
+
+#define MUSB_FADDR 0x00 /* 8-bit */
+#define MUSB_POWER 0x01 /* 8-bit */
+
+#define MUSB_INTRTX 0x02 /* 16-bit */
+#define MUSB_INTRRX 0x04
+#define MUSB_INTRTXE 0x06
+#define MUSB_INTRRXE 0x08
+#define MUSB_INTRUSB 0x0A /* 8 bit */
+#define MUSB_INTRUSBE 0x0B /* 8 bit */
+#define MUSB_FRAME 0x0C
+#define MUSB_INDEX 0x0E /* 8 bit */
+#define MUSB_TESTMODE 0x0F /* 8 bit */
+
+/* Get offset for a given FIFO from musb->mregs */
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+#define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20))
+#else
+#define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4))
+#endif
+
+/*
+ * Additional Control Registers
+ */
+
+#define MUSB_DEVCTL 0x60 /* 8 bit */
+
+/* These are always controlled through the INDEX register */
+#define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */
+#define MUSB_RXFIFOSZ 0x63 /* 8-bit (see masks) */
+#define MUSB_TXFIFOADD 0x64 /* 16-bit offset shifted right 3 */
+#define MUSB_RXFIFOADD 0x66 /* 16-bit offset shifted right 3 */
+
+/* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */
+#define MUSB_HWVERS 0x6C /* 8 bit */
+#define MUSB_ULPI_BUSCONTROL 0x70 /* 8 bit */
+#define MUSB_ULPI_INT_MASK 0x72 /* 8 bit */
+#define MUSB_ULPI_INT_SRC 0x73 /* 8 bit */
+#define MUSB_ULPI_REG_DATA 0x74 /* 8 bit */
+#define MUSB_ULPI_REG_ADDR 0x75 /* 8 bit */
+#define MUSB_ULPI_REG_CONTROL 0x76 /* 8 bit */
+#define MUSB_ULPI_RAW_DATA 0x77 /* 8 bit */
+
+#define MUSB_EPINFO 0x78 /* 8 bit */
+#define MUSB_RAMINFO 0x79 /* 8 bit */
+#define MUSB_LINKINFO 0x7a /* 8 bit */
+#define MUSB_VPLEN 0x7b /* 8 bit */
+#define MUSB_HS_EOF1 0x7c /* 8 bit */
+#define MUSB_FS_EOF1 0x7d /* 8 bit */
+#define MUSB_LS_EOF1 0x7e /* 8 bit */
+
+/* Offsets to endpoint registers */
+#define MUSB_TXMAXP 0x00
+#define MUSB_TXCSR 0x02
+#define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */
+#define MUSB_RXMAXP 0x04
+#define MUSB_RXCSR 0x06
+#define MUSB_RXCOUNT 0x08
+#define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */
+#define MUSB_TXTYPE 0x0A
+#define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */
+#define MUSB_TXINTERVAL 0x0B
+#define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */
+#define MUSB_RXTYPE 0x0C
+#define MUSB_RXINTERVAL 0x0D
+#define MUSB_FIFOSIZE 0x0F
+#define MUSB_CONFIGDATA MUSB_FIFOSIZE /* Re-used for EP0 */
+
+/* Offsets to endpoint registers in indexed model (using INDEX register) */
+#define MUSB_INDEXED_OFFSET(_epnum, _offset) \
+ (0x10 + (_offset))
+
+/* Offsets to endpoint registers in flat models */
+#define MUSB_FLAT_OFFSET(_epnum, _offset) \
+ (0x100 + (0x10*(_epnum)) + (_offset))
+
+#if defined(CONFIG_USB_MUSB_TUSB6010) || \
+ defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
+/* TUSB6010 EP0 configuration register is special */
+#define MUSB_TUSB_OFFSET(_epnum, _offset) \
+ (0x10 + _offset)
+#include "tusb6010.h" /* Needed "only" for TUSB_EP0_CONF */
+#endif
+
+#define MUSB_TXCSR_MODE 0x2000
+
+/* "bus control"/target registers, for host side multipoint (external hubs) */
+#define MUSB_TXFUNCADDR 0x00
+#define MUSB_TXHUBADDR 0x02
+#define MUSB_TXHUBPORT 0x03
+
+#define MUSB_RXFUNCADDR 0x04
+#define MUSB_RXHUBADDR 0x06
+#define MUSB_RXHUBPORT 0x07
+
+#define MUSB_BUSCTL_OFFSET(_epnum, _offset) \
+ (0x80 + (8*(_epnum)) + (_offset))
+
+static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
+{
+ musb_writeb(mbase, MUSB_TXFIFOSZ, c_size);
+}
+
+static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off)
+{
+ musb_writew(mbase, MUSB_TXFIFOADD, c_off);
+}
+
+static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size)
+{
+ musb_writeb(mbase, MUSB_RXFIFOSZ, c_size);
+}
+
+static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
+{
+ musb_writew(mbase, MUSB_RXFIFOADD, c_off);
+}
+
+static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val)
+{
+ musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val);
+}
+
+static inline u8 musb_read_txfifosz(void __iomem *mbase)
+{
+ return musb_readb(mbase, MUSB_TXFIFOSZ);
+}
+
+static inline u16 musb_read_txfifoadd(void __iomem *mbase)
+{
+ return musb_readw(mbase, MUSB_TXFIFOADD);
+}
+
+static inline u8 musb_read_rxfifosz(void __iomem *mbase)
+{
+ return musb_readb(mbase, MUSB_RXFIFOSZ);
+}
+
+static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
+{
+ return musb_readw(mbase, MUSB_RXFIFOADD);
+}
+
+static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
+{
+ return musb_readb(mbase, MUSB_ULPI_BUSCONTROL);
+}
+
+static inline u8 musb_read_configdata(void __iomem *mbase)
+{
+ musb_writeb(mbase, MUSB_INDEX, 0);
+ return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA);
+}
+
+static inline u16 musb_read_hwvers(void __iomem *mbase)
+{
+ return musb_readw(mbase, MUSB_HWVERS);
+}
+
+static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase)
+{
+ return (MUSB_BUSCTL_OFFSET(i, 0) + mbase);
+}
+
+static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs,
+ u8 qh_addr_reg)
+{
+ musb_writeb(ep_target_regs, MUSB_RXFUNCADDR, qh_addr_reg);
+}
+
+static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs,
+ u8 qh_h_addr_reg)
+{
+ musb_writeb(ep_target_regs, MUSB_RXHUBADDR, qh_h_addr_reg);
+}
+
+static inline void musb_write_rxhubport(void __iomem *ep_target_regs,
+ u8 qh_h_port_reg)
+{
+ musb_writeb(ep_target_regs, MUSB_RXHUBPORT, qh_h_port_reg);
+}
+
+static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+ musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR),
+ qh_addr_reg);
+}
+
+static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+ musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR),
+ qh_addr_reg);
+}
+
+static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
+ u8 qh_h_port_reg)
+{
+ musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT),
+ qh_h_port_reg);
+}
+
+static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXFUNCADDR));
+}
+
+static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBADDR));
+}
+
+static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_RXHUBPORT));
+}
+
+static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR));
+}
+
+static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR));
+}
+
+static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum)
+{
+ return musb_readb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT));
+}
+
+#else /* CONFIG_BLACKFIN */
+
+#define USB_BASE USB_FADDR
+#define USB_OFFSET(reg) (reg - USB_BASE)
+
+/*
+ * Common USB registers
+ */
+#define MUSB_FADDR USB_OFFSET(USB_FADDR) /* 8-bit */
+#define MUSB_POWER USB_OFFSET(USB_POWER) /* 8-bit */
+#define MUSB_INTRTX USB_OFFSET(USB_INTRTX) /* 16-bit */
+#define MUSB_INTRRX USB_OFFSET(USB_INTRRX)
+#define MUSB_INTRTXE USB_OFFSET(USB_INTRTXE)
+#define MUSB_INTRRXE USB_OFFSET(USB_INTRRXE)
+#define MUSB_INTRUSB USB_OFFSET(USB_INTRUSB) /* 8 bit */
+#define MUSB_INTRUSBE USB_OFFSET(USB_INTRUSBE)/* 8 bit */
+#define MUSB_FRAME USB_OFFSET(USB_FRAME)
+#define MUSB_INDEX USB_OFFSET(USB_INDEX) /* 8 bit */
+#define MUSB_TESTMODE USB_OFFSET(USB_TESTMODE)/* 8 bit */
+
+/* Get offset for a given FIFO from musb->mregs */
+#define MUSB_FIFO_OFFSET(epnum) \
+ (USB_OFFSET(USB_EP0_FIFO) + ((epnum) * 8))
+
+/*
+ * Additional Control Registers
+ */
+
+#define MUSB_DEVCTL USB_OFFSET(USB_OTG_DEV_CTL) /* 8 bit */
+
+#define MUSB_LINKINFO USB_OFFSET(USB_LINKINFO)/* 8 bit */
+#define MUSB_VPLEN USB_OFFSET(USB_VPLEN) /* 8 bit */
+#define MUSB_HS_EOF1 USB_OFFSET(USB_HS_EOF1) /* 8 bit */
+#define MUSB_FS_EOF1 USB_OFFSET(USB_FS_EOF1) /* 8 bit */
+#define MUSB_LS_EOF1 USB_OFFSET(USB_LS_EOF1) /* 8 bit */
+
+/* Offsets to endpoint registers */
+#define MUSB_TXMAXP 0x00
+#define MUSB_TXCSR 0x04
+#define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */
+#define MUSB_RXMAXP 0x08
+#define MUSB_RXCSR 0x0C
+#define MUSB_RXCOUNT 0x10
+#define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */
+#define MUSB_TXTYPE 0x14
+#define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */
+#define MUSB_TXINTERVAL 0x18
+#define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */
+#define MUSB_RXTYPE 0x1C
+#define MUSB_RXINTERVAL 0x20
+#define MUSB_TXCOUNT 0x28
+
+/* Offsets to endpoint registers in indexed model (using INDEX register) */
+#define MUSB_INDEXED_OFFSET(_epnum, _offset) \
+ (0x40 + (_offset))
+
+/* Offsets to endpoint registers in flat models */
+#define MUSB_FLAT_OFFSET(_epnum, _offset) \
+ (USB_OFFSET(USB_EP_NI0_TXMAXP) + (0x40 * (_epnum)) + (_offset))
+
+/* Not implemented - HW has separate Tx/Rx FIFO */
+#define MUSB_TXCSR_MODE 0x0000
+
+static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
+{
+}
+
+static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off)
+{
+}
+
+static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size)
+{
+}
+
+static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
+{
+}
+
+static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val)
+{
+}
+
+static inline u8 musb_read_txfifosz(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u16 musb_read_txfifoadd(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u8 musb_read_rxfifosz(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u16 musb_read_rxfifoadd(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u8 musb_read_configdata(void __iomem *mbase)
+{
+ return 0;
+}
+
+static inline u16 musb_read_hwvers(void __iomem *mbase)
+{
+ /*
+ * This register is invisible on Blackfin, actually the MUSB
+ * RTL version of Blackfin is 1.9, so just harcode its value.
+ */
+ return MUSB_HWVERS_1900;
+}
+
+static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase)
+{
+ return NULL;
+}
+
+static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs,
+ u8 qh_addr_req)
+{
+}
+
+static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs,
+ u8 qh_h_addr_reg)
+{
+}
+
+static inline void musb_write_rxhubport(void __iomem *ep_target_regs,
+ u8 qh_h_port_reg)
+{
+}
+
+static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+}
+
+static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum,
+ u8 qh_addr_reg)
+{
+}
+
+static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
+ u8 qh_h_port_reg)
+{
+}
+
+static inline u8 musb_read_rxfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_rxhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_rxhubport(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_txfunaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum)
+{
+ return 0;
+}
+
+#endif /* CONFIG_BLACKFIN */
+
+#endif /* __MUSB_REGS_H__ */
diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c
new file mode 100644
index 0000000000..762cbc11df
--- /dev/null
+++ b/drivers/usb/musb-new/musb_uboot.c
@@ -0,0 +1,237 @@
+#include <common.h>
+#include <asm/errno.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#define __UBOOT__
+#include <usb.h>
+#include "linux-compat.h"
+#include "usb-compat.h"
+#include "musb_core.h"
+#include "musb_host.h"
+#include "musb_gadget.h"
+
+#ifdef CONFIG_MUSB_HOST
+static struct musb *host;
+static struct usb_hcd hcd;
+static enum usb_device_speed host_speed;
+
+static void musb_host_complete_urb(struct urb *urb)
+{
+ urb->dev->status &= ~USB_ST_NOT_PROC;
+ urb->dev->act_len = urb->actual_length;
+}
+
+static struct usb_host_endpoint hep;
+static struct urb urb;
+
+static struct urb *construct_urb(struct usb_device *dev, int endpoint_type,
+ unsigned long pipe, void *buffer, int len,
+ struct devrequest *setup, int interval)
+{
+ int epnum = usb_pipeendpoint(pipe);
+ int is_in = usb_pipein(pipe);
+
+ memset(&urb, 0, sizeof(struct urb));
+ memset(&hep, 0, sizeof(struct usb_host_endpoint));
+ INIT_LIST_HEAD(&hep.urb_list);
+ INIT_LIST_HEAD(&urb.urb_list);
+ urb.ep = &hep;
+ urb.complete = musb_host_complete_urb;
+ urb.status = -EINPROGRESS;
+ urb.dev = dev;
+ urb.pipe = pipe;
+ urb.transfer_buffer = buffer;
+ urb.transfer_dma = (unsigned long)buffer;
+ urb.transfer_buffer_length = len;
+ urb.setup_packet = (unsigned char *)setup;
+
+ urb.ep->desc.wMaxPacketSize =
+ __cpu_to_le16(is_in ? dev->epmaxpacketin[epnum] :
+ dev->epmaxpacketout[epnum]);
+ urb.ep->desc.bmAttributes = endpoint_type;
+ urb.ep->desc.bEndpointAddress =
+ (is_in ? USB_DIR_IN : USB_DIR_OUT) | epnum;
+ urb.ep->desc.bInterval = interval;
+
+ return &urb;
+}
+
+#define MUSB_HOST_TIMEOUT 0x3ffffff
+
+static int submit_urb(struct usb_hcd *hcd, struct urb *urb)
+{
+ struct musb *host = hcd->hcd_priv;
+ int ret;
+ int timeout;
+
+ ret = musb_urb_enqueue(hcd, urb, 0);
+ if (ret < 0) {
+ printf("Failed to enqueue URB to controller\n");
+ return ret;
+ }
+
+ timeout = MUSB_HOST_TIMEOUT;
+ do {
+ if (ctrlc())
+ return -EIO;
+ host->isr(0, host);
+ } while ((urb->dev->status & USB_ST_NOT_PROC) && --timeout);
+
+ return urb->status;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int len, struct devrequest *setup)
+{
+ struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_CONTROL, pipe,
+ buffer, len, setup, 0);
+
+ /* Fix speed for non hub-attached devices */
+ if (!dev->parent)
+ dev->speed = host_speed;
+
+ return submit_urb(&hcd, urb);
+}
+
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int len)
+{
+ struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_BULK, pipe,
+ buffer, len, NULL, 0);
+ return submit_urb(&hcd, urb);
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int len, int interval)
+{
+ struct urb *urb = construct_urb(dev, USB_ENDPOINT_XFER_INT, pipe,
+ buffer, len, NULL, interval);
+ return submit_urb(&hcd, urb);
+}
+
+int usb_lowlevel_init(int index, void **controller)
+{
+ u8 power;
+ void *mbase;
+ int timeout = MUSB_HOST_TIMEOUT;
+
+ if (!host) {
+ printf("MUSB host is not registered\n");
+ return -ENODEV;
+ }
+
+ musb_start(host);
+ mbase = host->mregs;
+ do {
+ if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
+ break;
+ } while (--timeout);
+ if (!timeout)
+ return -ENODEV;
+
+ power = musb_readb(mbase, MUSB_POWER);
+ musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
+ udelay(30000);
+ power = musb_readb(mbase, MUSB_POWER);
+ musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power);
+ host->isr(0, host);
+ host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ?
+ USB_SPEED_HIGH :
+ (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_FSDEV) ?
+ USB_SPEED_FULL : USB_SPEED_LOW;
+ host->is_active = 1;
+ hcd.hcd_priv = host;
+
+ return 0;
+}
+
+int usb_lowlevel_stop(int index)
+{
+ if (!host) {
+ printf("MUSB host is not registered\n");
+ return -ENODEV;
+ }
+
+ musb_stop(host);
+ return 0;
+}
+#endif /* CONFIG_MUSB_HOST */
+
+#ifdef CONFIG_MUSB_GADGET
+static struct musb *gadget;
+
+int usb_gadget_handle_interrupts(void)
+{
+ if (!gadget || !gadget->isr)
+ return -EINVAL;
+
+ return gadget->isr(0, gadget);
+}
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+ int ret;
+
+ if (!driver || driver->speed < USB_SPEED_HIGH || !driver->bind ||
+ !driver->setup) {
+ printf("bad parameter.\n");
+ return -EINVAL;
+ }
+
+ if (!gadget) {
+ printf("Controller uninitialized\n");
+ return -ENXIO;
+ }
+
+ ret = musb_gadget_start(&gadget->g, driver);
+ if (ret < 0) {
+ printf("gadget_start failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = driver->bind(&gadget->g);
+ if (ret < 0) {
+ printf("bind failed with %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+ /* TODO: implement me */
+ return 0;
+}
+#endif /* CONFIG_MUSB_GADGET */
+
+int musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
+ void *ctl_regs)
+{
+ struct musb **musbp;
+
+ switch (plat->mode) {
+#ifdef CONFIG_MUSB_HOST
+ case MUSB_HOST:
+ musbp = &host;
+ break;
+#endif
+#ifdef CONFIG_MUSB_GADGET
+ case MUSB_PERIPHERAL:
+ musbp = &gadget;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ *musbp = musb_init_controller(plat, (struct device *)bdata, ctl_regs);
+ if (!musbp) {
+ printf("Failed to init the controller\n");
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c
new file mode 100644
index 0000000000..b1c4dc7828
--- /dev/null
+++ b/drivers/usb/musb-new/omap2430.c
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2005-2007 by Texas Instruments
+ * Some code has been taken from tusb6010.c
+ * Copyrights for that are attributable to:
+ * Copyright (C) 2006 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ *
+ * This file is part of the Inventra Controller Driver for Linux.
+ *
+ * The Inventra Controller Driver for Linux 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.
+ *
+ * The Inventra Controller Driver for Linux is distributed in
+ * the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Inventra Controller Driver for Linux ; if not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <linux/err.h>
+#include <linux/usb/musb-omap.h>
+#else
+#include <common.h>
+#include <asm/omap_musb.h>
+#include <twl4030.h>
+#include "linux-compat.h"
+#endif
+
+#include "musb_core.h"
+#include "omap2430.h"
+
+#ifndef __UBOOT__
+struct omap2430_glue {
+ struct device *dev;
+ struct platform_device *musb;
+ enum omap_musb_vbus_id_status status;
+ struct work_struct omap_musb_mailbox_work;
+};
+#define glue_to_musb(g) platform_get_drvdata(g->musb)
+
+struct omap2430_glue *_glue;
+
+static struct timer_list musb_idle_timer;
+
+static void musb_do_idle(unsigned long _musb)
+{
+ struct musb *musb = (void *)_musb;
+ unsigned long flags;
+ u8 power;
+ u8 devctl;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ switch (musb->xceiv->state) {
+ case OTG_STATE_A_WAIT_BCON:
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE) {
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ } else {
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ }
+ break;
+ case OTG_STATE_A_SUSPEND:
+ /* finish RESUME signaling? */
+ if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
+ power = musb_readb(musb->mregs, MUSB_POWER);
+ power &= ~MUSB_POWER_RESUME;
+ dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power);
+ musb_writeb(musb->mregs, MUSB_POWER, power);
+ musb->is_active = 1;
+ musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
+ | MUSB_PORT_STAT_RESUME);
+ musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
+ usb_hcd_poll_rh_status(musb_to_hcd(musb));
+ /* NOTE: it might really be A_WAIT_BCON ... */
+ musb->xceiv->state = OTG_STATE_A_HOST;
+ }
+ break;
+ case OTG_STATE_A_HOST:
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ if (devctl & MUSB_DEVCTL_BDEVICE)
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ else
+ musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+ default:
+ break;
+ }
+ spin_unlock_irqrestore(&musb->lock, flags);
+}
+
+
+static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
+{
+ unsigned long default_timeout = jiffies + msecs_to_jiffies(3);
+ static unsigned long last_timer;
+
+ if (timeout == 0)
+ timeout = default_timeout;
+
+ /* Never idle if active, or when VBUS timeout is not set as host */
+ if (musb->is_active || ((musb->a_wait_bcon == 0)
+ && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
+ dev_dbg(musb->controller, "%s active, deleting timer\n",
+ otg_state_string(musb->xceiv->state));
+ del_timer(&musb_idle_timer);
+ last_timer = jiffies;
+ return;
+ }
+
+ if (time_after(last_timer, timeout)) {
+ if (!timer_pending(&musb_idle_timer))
+ last_timer = timeout;
+ else {
+ dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n");
+ return;
+ }
+ }
+ last_timer = timeout;
+
+ dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
+ otg_state_string(musb->xceiv->state),
+ (unsigned long)jiffies_to_msecs(timeout - jiffies));
+ mod_timer(&musb_idle_timer, timeout);
+}
+
+static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
+{
+ struct usb_otg *otg = musb->xceiv->otg;
+ u8 devctl;
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+ int ret = 1;
+ /* HDRC controls CPEN, but beware current surges during device
+ * connect. They can trigger transient overcurrent conditions
+ * that must be ignored.
+ */
+
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+ if (is_on) {
+ if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+ /* start the session */
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+ /*
+ * Wait for the musb to set as A device to enable the
+ * VBUS
+ */
+ while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
+
+ cpu_relax();
+
+ if (time_after(jiffies, timeout)) {
+ dev_err(musb->controller,
+ "configured as A device timeout");
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ if (ret && otg->set_vbus)
+ otg_set_vbus(otg, 1);
+ } else {
+ musb->is_active = 1;
+ otg->default_a = 1;
+ musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+ devctl |= MUSB_DEVCTL_SESSION;
+ MUSB_HST_MODE(musb);
+ }
+ } else {
+ musb->is_active = 0;
+
+ /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and
+ * jumping right to B_IDLE...
+ */
+
+ otg->default_a = 0;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ devctl &= ~MUSB_DEVCTL_SESSION;
+
+ MUSB_DEV_MODE(musb);
+ }
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ dev_dbg(musb->controller, "VBUS %s, devctl %02x "
+ /* otg %3x conf %08x prcm %08x */ "\n",
+ otg_state_string(musb->xceiv->state),
+ musb_readb(musb->mregs, MUSB_DEVCTL));
+}
+
+static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
+{
+ u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+ return 0;
+}
+#endif
+
+static inline void omap2430_low_level_exit(struct musb *musb)
+{
+ u32 l;
+
+ /* in any role */
+ l = musb_readl(musb->mregs, OTG_FORCESTDBY);
+ l |= ENABLEFORCE; /* enable MSTANDBY */
+ musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+}
+
+static inline void omap2430_low_level_init(struct musb *musb)
+{
+ u32 l;
+
+ l = musb_readl(musb->mregs, OTG_FORCESTDBY);
+ l &= ~ENABLEFORCE; /* disable MSTANDBY */
+ musb_writel(musb->mregs, OTG_FORCESTDBY, l);
+}
+
+#ifndef __UBOOT__
+void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
+{
+ struct omap2430_glue *glue = _glue;
+ struct musb *musb = glue_to_musb(glue);
+
+ glue->status = status;
+ if (!musb) {
+ dev_err(glue->dev, "musb core is not yet ready\n");
+ return;
+ }
+
+ schedule_work(&glue->omap_musb_mailbox_work);
+}
+EXPORT_SYMBOL_GPL(omap_musb_mailbox);
+
+static void omap_musb_set_mailbox(struct omap2430_glue *glue)
+{
+ struct musb *musb = glue_to_musb(glue);
+ struct device *dev = musb->controller;
+ struct musb_hdrc_platform_data *pdata = dev->platform_data;
+ struct omap_musb_board_data *data = pdata->board_data;
+ struct usb_otg *otg = musb->xceiv->otg;
+
+ switch (glue->status) {
+ case OMAP_MUSB_ID_GROUND:
+ dev_dbg(dev, "ID GND\n");
+
+ otg->default_a = true;
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ musb->xceiv->last_event = USB_EVENT_ID;
+ if (!is_otg_enabled(musb) || musb->gadget_driver) {
+ pm_runtime_get_sync(dev);
+ usb_phy_init(musb->xceiv);
+ omap2430_musb_set_vbus(musb, 1);
+ }
+ break;
+
+ case OMAP_MUSB_VBUS_VALID:
+ dev_dbg(dev, "VBUS Connect\n");
+
+ otg->default_a = false;
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ musb->xceiv->last_event = USB_EVENT_VBUS;
+ if (musb->gadget_driver)
+ pm_runtime_get_sync(dev);
+ usb_phy_init(musb->xceiv);
+ break;
+
+ case OMAP_MUSB_ID_FLOAT:
+ case OMAP_MUSB_VBUS_OFF:
+ dev_dbg(dev, "VBUS Disconnect\n");
+
+ musb->xceiv->last_event = USB_EVENT_NONE;
+ if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
+ if (musb->gadget_driver) {
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+ }
+
+ if (data->interface_type == MUSB_INTERFACE_UTMI) {
+ if (musb->xceiv->otg->set_vbus)
+ otg_set_vbus(musb->xceiv->otg, 0);
+ }
+ usb_phy_shutdown(musb->xceiv);
+ break;
+ default:
+ dev_dbg(dev, "ID float\n");
+ }
+}
+
+
+static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
+{
+ struct omap2430_glue *glue = container_of(mailbox_work,
+ struct omap2430_glue, omap_musb_mailbox_work);
+ omap_musb_set_mailbox(glue);
+}
+#endif
+
+static int omap2430_musb_init(struct musb *musb)
+{
+ u32 l;
+ int status = 0;
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+ struct musb_hdrc_platform_data *plat = dev->platform_data;
+ struct omap_musb_board_data *data = plat->board_data;
+#else
+ struct omap_musb_board_data *data =
+ (struct omap_musb_board_data *)musb->controller;
+#endif
+
+
+#ifndef __UBOOT__
+ /* We require some kind of external transceiver, hooked
+ * up through ULPI. TWL4030-family PMICs include one,
+ * which needs a driver, drivers aren't always needed.
+ */
+ musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(musb->xceiv)) {
+ pr_err("HS USB OTG: no transceiver configured\n");
+ return -ENODEV;
+ }
+
+ status = pm_runtime_get_sync(dev);
+ if (status < 0) {
+ dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
+ goto err1;
+ }
+#endif
+
+ l = musb_readl(musb->mregs, OTG_INTERFSEL);
+
+ if (data->interface_type == MUSB_INTERFACE_UTMI) {
+ /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
+ l &= ~ULPI_12PIN; /* Disable ULPI */
+ l |= UTMI_8BIT; /* Enable UTMI */
+ } else {
+ l |= ULPI_12PIN;
+ }
+
+ musb_writel(musb->mregs, OTG_INTERFSEL, l);
+
+ pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
+ "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n",
+ musb_readl(musb->mregs, OTG_REVISION),
+ musb_readl(musb->mregs, OTG_SYSCONFIG),
+ musb_readl(musb->mregs, OTG_SYSSTATUS),
+ musb_readl(musb->mregs, OTG_INTERFSEL),
+ musb_readl(musb->mregs, OTG_SIMENABLE));
+
+#ifndef __UBOOT__
+ setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+
+ if (glue->status != OMAP_MUSB_UNKNOWN)
+ omap_musb_set_mailbox(glue);
+
+ pm_runtime_put_noidle(musb->controller);
+#endif
+ return 0;
+
+err1:
+ return status;
+}
+
+static void omap2430_musb_enable(struct musb *musb)
+{
+#ifndef __UBOOT__
+ u8 devctl;
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+ struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+ struct musb_hdrc_platform_data *pdata = dev->platform_data;
+ struct omap_musb_board_data *data = pdata->board_data;
+
+ switch (glue->status) {
+
+ case OMAP_MUSB_ID_GROUND:
+ usb_phy_init(musb->xceiv);
+ if (data->interface_type != MUSB_INTERFACE_UTMI)
+ break;
+ devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ /* start the session */
+ devctl |= MUSB_DEVCTL_SESSION;
+ musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+ while (musb_readb(musb->mregs, MUSB_DEVCTL) &
+ MUSB_DEVCTL_BDEVICE) {
+ cpu_relax();
+
+ if (time_after(jiffies, timeout)) {
+ dev_err(dev, "configured as A device timeout");
+ break;
+ }
+ }
+ break;
+
+ case OMAP_MUSB_VBUS_VALID:
+ usb_phy_init(musb->xceiv);
+ break;
+
+ default:
+ break;
+ }
+#else
+#ifdef CONFIG_TWL4030_USB
+ if (twl4030_usb_ulpi_init()) {
+ serial_printf("ERROR: %s Could not initialize PHY\n",
+ __PRETTY_FUNCTION__);
+ }
+#endif
+#endif
+}
+
+static void omap2430_musb_disable(struct musb *musb)
+{
+#ifndef __UBOOT__
+ struct device *dev = musb->controller;
+ struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+
+ if (glue->status != OMAP_MUSB_UNKNOWN)
+ usb_phy_shutdown(musb->xceiv);
+#endif
+}
+
+static int omap2430_musb_exit(struct musb *musb)
+{
+ del_timer_sync(&musb_idle_timer);
+
+ omap2430_low_level_exit(musb);
+
+ return 0;
+}
+
+#ifndef __UBOOT__
+static const struct musb_platform_ops omap2430_ops = {
+#else
+const struct musb_platform_ops omap2430_ops = {
+#endif
+ .init = omap2430_musb_init,
+ .exit = omap2430_musb_exit,
+
+#ifndef __UBOOT__
+ .set_mode = omap2430_musb_set_mode,
+ .try_idle = omap2430_musb_try_idle,
+
+ .set_vbus = omap2430_musb_set_vbus,
+#endif
+
+ .enable = omap2430_musb_enable,
+ .disable = omap2430_musb_disable,
+};
+
+#ifndef __UBOOT__
+static u64 omap2430_dmamask = DMA_BIT_MASK(32);
+
+static int __devinit omap2430_probe(struct platform_device *pdev)
+{
+ struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
+ struct platform_device *musb;
+ struct omap2430_glue *glue;
+ int ret = -ENOMEM;
+
+ glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+ if (!glue) {
+ dev_err(&pdev->dev, "failed to allocate glue context\n");
+ goto err0;
+ }
+
+ musb = platform_device_alloc("musb-hdrc", -1);
+ if (!musb) {
+ dev_err(&pdev->dev, "failed to allocate musb device\n");
+ goto err0;
+ }
+
+ musb->dev.parent = &pdev->dev;
+ musb->dev.dma_mask = &omap2430_dmamask;
+ musb->dev.coherent_dma_mask = omap2430_dmamask;
+
+ glue->dev = &pdev->dev;
+ glue->musb = musb;
+ glue->status = OMAP_MUSB_UNKNOWN;
+
+ pdata->platform_ops = &omap2430_ops;
+
+ platform_set_drvdata(pdev, glue);
+
+ /*
+ * REVISIT if we ever have two instances of the wrapper, we will be
+ * in big trouble
+ */
+ _glue = glue;
+
+ INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
+
+ ret = platform_device_add_resources(musb, pdev->resource,
+ pdev->num_resources);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add resources\n");
+ goto err1;
+ }
+
+ ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add platform_data\n");
+ goto err1;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+
+ ret = platform_device_add(musb);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register musb device\n");
+ goto err1;
+ }
+
+ return 0;
+
+err1:
+ platform_device_put(musb);
+
+err0:
+ return ret;
+}
+
+static int __devexit omap2430_remove(struct platform_device *pdev)
+{
+ struct omap2430_glue *glue = platform_get_drvdata(pdev);
+
+ cancel_work_sync(&glue->omap_musb_mailbox_work);
+ platform_device_del(glue->musb);
+ platform_device_put(glue->musb);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int omap2430_runtime_suspend(struct device *dev)
+{
+ struct omap2430_glue *glue = dev_get_drvdata(dev);
+ struct musb *musb = glue_to_musb(glue);
+
+ if (musb) {
+ musb->context.otg_interfsel = musb_readl(musb->mregs,
+ OTG_INTERFSEL);
+
+ omap2430_low_level_exit(musb);
+ usb_phy_set_suspend(musb->xceiv, 1);
+ }
+
+ return 0;
+}
+
+static int omap2430_runtime_resume(struct device *dev)
+{
+ struct omap2430_glue *glue = dev_get_drvdata(dev);
+ struct musb *musb = glue_to_musb(glue);
+
+ if (musb) {
+ omap2430_low_level_init(musb);
+ musb_writel(musb->mregs, OTG_INTERFSEL,
+ musb->context.otg_interfsel);
+
+ usb_phy_set_suspend(musb->xceiv, 0);
+ }
+
+ return 0;
+}
+
+static struct dev_pm_ops omap2430_pm_ops = {
+ .runtime_suspend = omap2430_runtime_suspend,
+ .runtime_resume = omap2430_runtime_resume,
+};
+
+#define DEV_PM_OPS (&omap2430_pm_ops)
+#else
+#define DEV_PM_OPS NULL
+#endif
+
+static struct platform_driver omap2430_driver = {
+ .probe = omap2430_probe,
+ .remove = __devexit_p(omap2430_remove),
+ .driver = {
+ .name = "musb-omap2430",
+ .pm = DEV_PM_OPS,
+ },
+};
+
+MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
+MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
+MODULE_LICENSE("GPL v2");
+
+static int __init omap2430_init(void)
+{
+ return platform_driver_register(&omap2430_driver);
+}
+subsys_initcall(omap2430_init);
+
+static void __exit omap2430_exit(void)
+{
+ platform_driver_unregister(&omap2430_driver);
+}
+module_exit(omap2430_exit);
+#endif
diff --git a/drivers/usb/musb-new/omap2430.h b/drivers/usb/musb-new/omap2430.h
new file mode 100644
index 0000000000..3b795c248d
--- /dev/null
+++ b/drivers/usb/musb-new/omap2430.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005-2006 by Texas Instruments
+ *
+ * The Inventra Controller Driver for Linux 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 __MUSB_OMAP243X_H__
+#define __MUSB_OMAP243X_H__
+
+#ifndef __UBOOT__
+#include <plat/usb.h>
+#else
+#undef RESETDONE
+#endif
+
+/*
+ * OMAP2430-specific definitions
+ */
+
+#define OTG_REVISION 0x400
+
+#define OTG_SYSCONFIG 0x404
+# define MIDLEMODE 12 /* bit position */
+# define FORCESTDBY (0 << MIDLEMODE)
+# define NOSTDBY (1 << MIDLEMODE)
+# define SMARTSTDBY (2 << MIDLEMODE)
+
+# define SIDLEMODE 3 /* bit position */
+# define FORCEIDLE (0 << SIDLEMODE)
+# define NOIDLE (1 << SIDLEMODE)
+# define SMARTIDLE (2 << SIDLEMODE)
+
+# define ENABLEWAKEUP (1 << 2)
+# define SOFTRST (1 << 1)
+# define AUTOIDLE (1 << 0)
+
+#define OTG_SYSSTATUS 0x408
+# define RESETDONE (1 << 0)
+
+#define OTG_INTERFSEL 0x40c
+# define EXTCP (1 << 2)
+# define PHYSEL 0 /* bit position */
+# define UTMI_8BIT (0 << PHYSEL)
+# define ULPI_12PIN (1 << PHYSEL)
+# define ULPI_8PIN (2 << PHYSEL)
+
+#define OTG_SIMENABLE 0x410
+# define TM1 (1 << 0)
+
+#define OTG_FORCESTDBY 0x414
+# define ENABLEFORCE (1 << 0)
+
+#endif /* __MUSB_OMAP243X_H__ */
diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h
new file mode 100644
index 0000000000..27f656f0ce
--- /dev/null
+++ b/drivers/usb/musb-new/usb-compat.h
@@ -0,0 +1,88 @@
+#ifndef __USB_COMPAT_H__
+#define __USB_COMPAT_H__
+
+#include "usb.h"
+
+struct usb_hcd {
+ void *hcd_priv;
+};
+
+struct usb_host_endpoint {
+ struct usb_endpoint_descriptor desc;
+ struct list_head urb_list;
+ void *hcpriv;
+};
+
+/*
+ * urb->transfer_flags:
+ *
+ * Note: URB_DIR_IN/OUT is automatically set in usb_submit_urb().
+ */
+#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
+#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
+
+struct urb;
+
+typedef void (*usb_complete_t)(struct urb *);
+
+struct urb {
+ void *hcpriv; /* private data for host controller */
+ struct list_head urb_list; /* list head for use by the urb's
+ * current owner */
+ struct usb_device *dev; /* (in) pointer to associated device */
+ struct usb_host_endpoint *ep; /* (internal) pointer to endpoint */
+ unsigned int pipe; /* (in) pipe information */
+ int status; /* (return) non-ISO status */
+ unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
+ void *transfer_buffer; /* (in) associated data buffer */
+ dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
+ u32 transfer_buffer_length; /* (in) data buffer length */
+ u32 actual_length; /* (return) actual transfer length */
+ unsigned char *setup_packet; /* (in) setup packet (control only) */
+ int start_frame; /* (modify) start frame (ISO) */
+ usb_complete_t complete; /* (in) completion routine */
+};
+
+#define usb_hcd_link_urb_to_ep(hcd, urb) ({ \
+ int ret = 0; \
+ list_add_tail(&urb->urb_list, &urb->ep->urb_list); \
+ ret; })
+#define usb_hcd_unlink_urb_from_ep(hcd, urb) list_del_init(&urb->urb_list)
+
+static inline void usb_hcd_giveback_urb(struct usb_hcd *hcd,
+ struct urb *urb,
+ int status)
+{
+ urb->status = status;
+ if (urb->complete)
+ urb->complete(urb);
+}
+
+static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
+ struct urb *urb)
+{
+ /* TODO: add cache invalidation here */
+ return 0;
+}
+
+static inline u16 find_tt(struct usb_device *dev)
+{
+ u8 chid;
+ u8 hub;
+
+ /* Find out the nearest parent which is high speed */
+ while (dev->parent->parent != NULL)
+ if (dev->parent->speed != USB_SPEED_HIGH)
+ dev = dev->parent;
+ else
+ break;
+
+ /* determine the port address at that hub */
+ hub = dev->parent->devnum;
+ for (chid = 0; chid < USB_MAXCHILDREN; chid++)
+ if (dev->parent->children[chid] == dev)
+ break;
+
+ return (hub << 8) | chid;
+}
+#endif /* __USB_COMPAT_H__ */
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index e914369297..ec8a038c74 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -34,7 +34,6 @@
#ifndef __MUSB_HDRC_DEFS_H__
#define __MUSB_HDRC_DEFS_H__
-#include <usb.h>
#include <usb_defs.h>
#include <asm/io.h>
@@ -145,7 +144,7 @@ struct musb_regs {
struct musb_epN_regs epN;
} ep[16];
-} __attribute__((packed, aligned(USB_DMA_MINALIGN)));
+} __attribute__((packed));
#endif
/*
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index 06be38d1cf..60e03a4bf7 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -22,6 +22,7 @@
*/
#include <common.h>
+#include <usb.h>
#include "musb_hcd.h"
/* MSC control transfers */
@@ -485,8 +486,8 @@ static int ctrlreq_in_status_phase(struct usb_device *dev)
*/
static u8 get_dev_speed(struct usb_device *dev)
{
- return (dev->speed & USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH :
- ((dev->speed & USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW :
+ return (dev->speed == USB_SPEED_HIGH) ? MUSB_TYPE_SPEED_HIGH :
+ ((dev->speed == USB_SPEED_LOW) ? MUSB_TYPE_SPEED_LOW :
MUSB_TYPE_SPEED_FULL);
}
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b3207c83c3..170a358b52 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -40,6 +40,7 @@ COBJS-$(CONFIG_S6E63D6) += s6e63d6.o
COBJS-$(CONFIG_LD9040) += ld9040.o
COBJS-$(CONFIG_SED156X) += sed156x.o
COBJS-$(CONFIG_VIDEO_AMBA) += amba.o
+COBJS-$(CONFIG_VIDEO_COREBOOT) += coreboot_fb.o
COBJS-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o
COBJS-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o
COBJS-$(CONFIG_VIDEO_MB862xx) += mb862xx.o videomodes.o
diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c
index beb7fa396e..b10ca4b677 100644
--- a/drivers/video/atmel_hlcdfb.c
+++ b/drivers/video/atmel_hlcdfb.c
@@ -51,6 +51,18 @@ short console_row;
#define lcdc_readl(reg) __raw_readl((reg))
#define lcdc_writel(reg, val) __raw_writel((val), (reg))
+/*
+ * the CLUT register map as following
+ * RCLUT(24 ~ 16), GCLUT(15 ~ 8), BCLUT(7 ~ 0)
+ */
+void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue)
+{
+ lcdc_writel(((red << LCDC_BASECLUT_RCLUT_Pos) & LCDC_BASECLUT_RCLUT_Msk)
+ | ((green << LCDC_BASECLUT_GCLUT_Pos) & LCDC_BASECLUT_GCLUT_Msk)
+ | ((blue << LCDC_BASECLUT_BCLUT_Pos) & LCDC_BASECLUT_BCLUT_Msk),
+ panel_info.mmio + ATMEL_LCDC_LUT(regno));
+}
+
void lcd_ctrl_init(void *lcdbase)
{
unsigned long value;
diff --git a/drivers/video/bus_vcxk.c b/drivers/video/bus_vcxk.c
index 9c4714d50a..a0607cf433 100644
--- a/drivers/video/bus_vcxk.c
+++ b/drivers/video/bus_vcxk.c
@@ -153,7 +153,7 @@ int vcxk_init(unsigned long width, unsigned long height)
#ifdef CONFIG_SYS_VCXK_DOUBLEBUFFERED
double_bws_word = (u_short *)double_bws;
double_bws_long = (u_long *)double_bws;
- debug("%lx %lx %lx \n", double_bws, double_bws_word, double_bws_long);
+ debug("%px %px %px\n", double_bws, double_bws_word, double_bws_long);
#endif
display_width = width;
display_height = height;
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
index 9c67b63bf4..26f673a96a 100644
--- a/drivers/video/cfb_console.c
+++ b/drivers/video/cfb_console.c
@@ -1515,6 +1515,13 @@ int video_display_bitmap(ulong bmp_image, int x, int y)
padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
+ /*
+ * Just ignore elements which are completely beyond screen
+ * dimensions.
+ */
+ if ((x >= VIDEO_VISIBLE_COLS) || (y >= VIDEO_VISIBLE_ROWS))
+ return 0;
+
#ifdef CONFIG_SPLASH_SCREEN_ALIGN
if (x == BMP_ALIGN_CENTER)
x = max(0, (VIDEO_VISIBLE_COLS - width) / 2);
@@ -2257,3 +2264,47 @@ int drv_video_init(void)
/* Return success */
return 1;
}
+
+void video_position_cursor(unsigned col, unsigned row)
+{
+ console_col = min(col, CONSOLE_COLS - 1);
+ console_row = min(row, CONSOLE_ROWS - 1);
+}
+
+int video_get_pixel_width(void)
+{
+ return VIDEO_VISIBLE_COLS;
+}
+
+int video_get_pixel_height(void)
+{
+ return VIDEO_VISIBLE_ROWS;
+}
+
+int video_get_screen_rows(void)
+{
+ return CONSOLE_ROWS;
+}
+
+int video_get_screen_columns(void)
+{
+ return CONSOLE_COLS;
+}
+
+void video_clear(void)
+{
+ if (!video_fb_address)
+ return;
+#ifdef VIDEO_HW_RECTFILL
+ video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
+ 0, /* dest pos x */
+ 0, /* dest pos y */
+ VIDEO_VISIBLE_COLS, /* frame width */
+ VIDEO_VISIBLE_ROWS, /* frame height */
+ bgx /* fill color */
+ );
+#else
+ memsetl(video_fb_address,
+ (VIDEO_VISIBLE_ROWS * VIDEO_LINE_LEN) / sizeof(int), bgx);
+#endif
+}
diff --git a/drivers/video/coreboot_fb.c b/drivers/video/coreboot_fb.c
new file mode 100644
index 0000000000..d93bd894a2
--- /dev/null
+++ b/drivers/video/coreboot_fb.c
@@ -0,0 +1,101 @@
+/*
+ * coreboot Framebuffer driver.
+ *
+ * Copyright (C) 2011 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
+ */
+
+#include <common.h>
+#include <asm/arch/tables.h>
+#include <asm/arch/sysinfo.h>
+#include <video_fb.h>
+#include "videomodes.h"
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+static int parse_coreboot_table_fb(GraphicDevice *gdev)
+{
+ struct cb_framebuffer *fb = lib_sysinfo.framebuffer;
+
+ /* If there is no framebuffer structure, bail out and keep
+ * running on the serial console.
+ */
+ if (!fb)
+ return 0;
+
+ gdev->winSizeX = fb->x_resolution;
+ gdev->winSizeY = fb->y_resolution;
+
+ gdev->plnSizeX = fb->x_resolution;
+ gdev->plnSizeY = fb->y_resolution;
+
+ gdev->gdfBytesPP = fb->bits_per_pixel / 8;
+
+ switch (fb->bits_per_pixel) {
+ case 24:
+ gdev->gdfIndex = GDF_32BIT_X888RGB;
+ break;
+ case 16:
+ gdev->gdfIndex = GDF_16BIT_565RGB;
+ break;
+ default:
+ gdev->gdfIndex = GDF__8BIT_INDEX;
+ break;
+ }
+
+ gdev->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS;
+ gdev->pciBase = (unsigned int)fb->physical_address;
+
+ gdev->frameAdrs = (unsigned int)fb->physical_address;
+ gdev->memSize = fb->bytes_per_line * fb->y_resolution;
+
+ gdev->vprBase = (unsigned int)fb->physical_address;
+ gdev->cprBase = (unsigned int)fb->physical_address;
+
+ return 1;
+}
+
+void *video_hw_init(void)
+{
+ GraphicDevice *gdev = &ctfb;
+ int bits_per_pixel;
+
+ printf("Video: ");
+
+ if (!parse_coreboot_table_fb(gdev)) {
+ printf("No video mode configured in coreboot!\n");
+ return NULL;
+ }
+
+ bits_per_pixel = gdev->gdfBytesPP * 8;
+
+ /* fill in Graphic device struct */
+ sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY,
+ bits_per_pixel);
+ printf("%s\n", gdev->modeIdent);
+
+ memset((void *)gdev->pciBase, 0,
+ gdev->winSizeX * gdev->winSizeY * gdev->gdfBytesPP);
+
+ return (void *)gdev;
+}
diff --git a/drivers/video/ipu_common.c b/drivers/video/ipu_common.c
index 0f2d113a6f..ad4af5283a 100644
--- a/drivers/video/ipu_common.c
+++ b/drivers/video/ipu_common.c
@@ -94,6 +94,7 @@ struct ipu_ch_param {
temp1; \
})
+#define IPU_SW_RST_TOUT_USEC (10000)
void clk_enable(struct clk *clk)
{
@@ -398,11 +399,20 @@ void ipu_reset(void)
{
u32 *reg;
u32 value;
+ int timeout = IPU_SW_RST_TOUT_USEC;
reg = (u32 *)SRC_BASE_ADDR;
value = __raw_readl(reg);
value = value | SW_IPU_RST;
__raw_writel(value, reg);
+
+ while (__raw_readl(reg) & SW_IPU_RST) {
+ udelay(1);
+ if (!(timeout--)) {
+ printf("ipu software reset timeout\n");
+ break;
+ }
+ };
}
/*
diff --git a/fs/cbfs/Makefile b/fs/cbfs/Makefile
index 2be8a6880b..e0e6de69fa 100644
--- a/fs/cbfs/Makefile
+++ b/fs/cbfs/Makefile
@@ -1,6 +1,4 @@
-#
-# See file CREDITS for list of people who contributed to this
-# project.
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c
index cae6d56db7..1b25a15e48 100644
--- a/fs/cbfs/cbfs.c
+++ b/fs/cbfs/cbfs.c
@@ -1,9 +1,6 @@
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
- * 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
diff --git a/fs/ext4/dev.c b/fs/ext4/dev.c
index 1596a92b9a..464a67d531 100644
--- a/fs/ext4/dev.c
+++ b/fs/ext4/dev.c
@@ -52,6 +52,7 @@ void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info)
part_info = info;
part_offset = info->start;
get_fs()->total_sect = (info->size * info->blksz) / SECTOR_SIZE;
+ get_fs()->dev_desc = rbdd;
}
int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf)
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 323875fa94..f12b8056cc 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -378,7 +378,6 @@ void ext4fs_update_parent_dentry(char *filename, int *p_ino, int file_type)
struct ext_filesystem *fs = get_fs();
/* directory entry */
struct ext2_dirent *dir;
- char *ptr = NULL;
char *temp_dir = NULL;
zero_buffer = zalloc(fs->blksz);
@@ -415,7 +414,6 @@ restart:
if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root))
goto fail;
dir = (struct ext2_dirent *)root_first_block_buffer;
- ptr = (char *)dir;
totalbytes = 0;
while (dir->direntlen > 0) {
/*
@@ -483,14 +481,12 @@ restart:
break;
dir = (struct ext2_dirent *)((char *)dir + templength);
- ptr = (char *)dir;
}
/* make a pointer ready for creating next directory entry */
templength = dir->direntlen;
totalbytes = totalbytes + templength;
dir = (struct ext2_dirent *)((char *)dir + templength);
- ptr = (char *)dir;
/* get the next available inode number */
inodeno = ext4fs_get_new_inode_no();
@@ -1200,6 +1196,11 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode,
status = ext4fs_devread(di_blockno_parent *
fs->sect_perblk, 0,
fs->blksz, (char *)di_parent_buffer);
+
+ if (!status) {
+ printf("%s: Device read error!\n", __func__);
+ goto fail;
+ }
memset(di_parent_buffer, '\0', fs->blksz);
/*
@@ -1227,6 +1228,11 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode,
fs->sect_perblk, 0,
fs->blksz,
(char *)di_child_buff);
+
+ if (!status) {
+ printf("%s: Device read error!\n", __func__);
+ goto fail;
+ }
memset(di_child_buff, '\0', fs->blksz);
/* filling of actual datablocks for each child */
for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c
index 8a252d66c3..9f017084f1 100644
--- a/fs/ext4/ext4_journal.c
+++ b/fs/ext4/ext4_journal.c
@@ -410,7 +410,7 @@ int ext4fs_check_journal_state(int recovery_flag)
int transaction_state = TRANSACTION_COMPLETE;
int prev_desc_logical_no = 0;
int curr_desc_logical_no = 0;
- int ofs, flags, block;
+ int ofs, flags;
struct ext2_inode inode_journal;
struct journal_superblock_t *jsb = NULL;
struct journal_header_t *jdb = NULL;
@@ -453,7 +453,6 @@ int ext4fs_check_journal_state(int recovery_flag)
i = be32_to_cpu(jsb->s_first);
while (1) {
- block = be32_to_cpu(jsb->s_first);
blknr = read_allocated_block(&inode_journal, i);
memset(temp_buff1, '\0', fs->blksz);
ext4fs_devread(blknr * fs->sect_perblk,
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 06536baf62..f02c215ccc 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -40,6 +40,7 @@
#include <linux/stat.h>
#include <linux/time.h>
#include <asm/byteorder.h>
+#include <div64.h>
#include "ext4_common.h"
int ext4fs_symlinknest;
@@ -930,7 +931,6 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
int previous_block_number = -1;
int delayed_start = 0;
int delayed_extent = 0;
- int delayed_skipfirst = 0;
int delayed_next = 0;
char *delayed_buf = NULL;
@@ -963,7 +963,6 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
previous_block_number = blknr;
delayed_start = blknr;
delayed_extent = blockend;
- delayed_skipfirst = skipfirst;
delayed_buf = buf;
delayed_next = blknr +
(blockend >> SECTOR_BITS);
@@ -972,7 +971,6 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
previous_block_number = blknr;
delayed_start = blknr;
delayed_extent = blockend;
- delayed_skipfirst = skipfirst;
delayed_buf = buf;
delayed_next = blknr +
(blockend >> SECTOR_BITS);
@@ -1013,8 +1011,6 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
unsigned int blks_reqd_for_file;
unsigned int blocks_remaining;
int existing_file_inodeno;
- char filename[256];
-
char *temp_ptr = NULL;
long int itable_blkno;
long int parent_itable_blkno;
@@ -1023,6 +1019,9 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
unsigned int inodes_per_block;
unsigned int ibmap_idx;
struct ext_filesystem *fs = get_fs();
+ ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256);
+ memset(filename, 0x00, sizeof(filename));
+
g_parent_inode = zalloc(sizeof(struct ext2_inode));
if (!g_parent_inode)
goto fail;
@@ -1051,8 +1050,8 @@ int ext4fs_write(const char *fname, unsigned char *buffer,
}
/* calucalate how many blocks required */
bytes_reqd_for_file = sizebytes;
- blks_reqd_for_file = bytes_reqd_for_file / fs->blksz;
- if (bytes_reqd_for_file % fs->blksz != 0) {
+ blks_reqd_for_file = lldiv(bytes_reqd_for_file, fs->blksz);
+ if (do_div(bytes_reqd_for_file, fs->blksz) != 0) {
blks_reqd_for_file++;
debug("total bytes for a file %u\n", blks_reqd_for_file);
}
diff --git a/fs/fs.c b/fs/fs.c
index ff360afd4b..023e7ef16a 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -257,6 +257,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
unsigned long pos;
int len_read;
char buf[12];
+ unsigned long time;
if (argc < 2)
return CMD_RET_USAGE;
@@ -293,11 +294,19 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
else
pos = 0;
+ time = get_timer(0);
len_read = fs_read(filename, addr, pos, bytes);
+ time = get_timer(time);
if (len_read <= 0)
return 1;
- printf("%d bytes read\n", len_read);
+ printf("%d bytes read in %lu ms", len_read, time);
+ if (time > 0) {
+ puts(" (");
+ print_size(len_read / time * 1000, "/s");
+ puts(")");
+ }
+ puts("\n");
sprintf(buf, "0x%x", len_read);
setenv("filesize", buf);
diff --git a/fs/zfs/zfs.c b/fs/zfs/zfs.c
index 2db45b1928..1b73244c00 100644
--- a/fs/zfs/zfs.c
+++ b/fs/zfs/zfs.c
@@ -30,6 +30,7 @@
#include <linux/ctype.h>
#include <asm/byteorder.h>
#include "zfs_common.h"
+#include "div64.h"
block_dev_desc_t *zfs_dev_desc;
@@ -2115,7 +2116,8 @@ zfs_read(zfs_file_t file, char *buf, uint64_t len)
/*
* Find requested blkid and the offset within that block.
*/
- uint64_t blkid = (file->offset + red) / blksz;
+ uint64_t blkid = file->offset + red;
+ blkid = do_div(blkid, blksz);
free(data->file_buf);
data->file_buf = 0;
diff --git a/include/atmel_hlcdc.h b/include/atmel_hlcdc.h
index 945b30acb0..fbd2f92457 100644
--- a/include/atmel_hlcdc.h
+++ b/include/atmel_hlcdc.h
@@ -217,6 +217,13 @@ struct atmel_hlcd_regs {
#define LCDC_BASECFG3_RDEF(value) \
((LCDC_BASECFG3_RDEF_Msk & ((value) << LCDC_BASECFG3_RDEF_Pos)))
+#define LCDC_BASECLUT_BCLUT_Pos 0
+#define LCDC_BASECLUT_BCLUT_Msk (0xff << LCDC_BASECLUT_BCLUT_Pos)
+#define LCDC_BASECLUT_GCLUT_Pos 8
+#define LCDC_BASECLUT_GCLUT_Msk (0xff << LCDC_BASECLUT_GCLUT_Pos)
+#define LCDC_BASECLUT_RCLUT_Pos 16
+#define LCDC_BASECLUT_RCLUT_Msk (0xff << LCDC_BASECLUT_RCLUT_Pos)
+
#define LCDC_BASECFG4_DMA (0x1 << 8)
#define LCDC_BASECFG4_REP (0x1 << 9)
diff --git a/include/bouncebuf.h b/include/bouncebuf.h
index 31021c5b85..707b588c73 100644
--- a/include/bouncebuf.h
+++ b/include/bouncebuf.h
@@ -25,6 +25,8 @@
#ifndef __INCLUDE_BOUNCEBUF_H__
#define __INCLUDE_BOUNCEBUF_H__
+#include <linux/types.h>
+
/*
* GEN_BB_READ -- Data are read from the buffer eg. by DMA hardware.
* The source buffer is copied into the bounce buffer (if unaligned, otherwise
@@ -51,37 +53,36 @@
*/
#define GEN_BB_RW (GEN_BB_READ | GEN_BB_WRITE)
-#ifdef CONFIG_BOUNCE_BUFFER
+struct bounce_buffer {
+ /* Copy of data parameter passed to start() */
+ void *user_buffer;
+ /*
+ * DMA-aligned buffer. This field is always set to the value that
+ * should be used for DMA; either equal to .user_buffer, or to a
+ * freshly allocated aligned buffer.
+ */
+ void *bounce_buffer;
+ /* Copy of len parameter passed to start() */
+ size_t len;
+ /* DMA-aligned buffer length */
+ size_t len_aligned;
+ /* Copy of flags parameter passed to start() */
+ unsigned int flags;
+};
+
/**
* bounce_buffer_start() -- Start the bounce buffer session
+ * state: stores state passed between bounce_buffer_{start,stop}
* data: pointer to buffer to be aligned
* len: length of the buffer
- * backup: pointer to backup buffer (the original value is stored here if
- * needed
* flags: flags describing the transaction, see above.
*/
-int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags);
+int bounce_buffer_start(struct bounce_buffer *state, void *data,
+ size_t len, unsigned int flags);
/**
* bounce_buffer_stop() -- Finish the bounce buffer session
- * data: pointer to buffer that was aligned
- * len: length of the buffer
- * backup: pointer to backup buffer (the original value is stored here if
- * needed
- * flags: flags describing the transaction, see above.
+ * state: stores state passed between bounce_buffer_{start,stop}
*/
-int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags);
-#else
-static inline int bounce_buffer_start(void **data, size_t len, void **backup,
- uint8_t flags)
-{
- return 0;
-}
-
-static inline int bounce_buffer_stop(void **data, size_t len, void **backup,
- uint8_t flags)
-{
- return 0;
-}
-#endif
+int bounce_buffer_stop(struct bounce_buffer *state);
#endif
diff --git a/include/cbfs.h b/include/cbfs.h
index 6ea3f35119..5bb12c355c 100644
--- a/include/cbfs.h
+++ b/include/cbfs.h
@@ -1,9 +1,6 @@
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
*
- * 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
@@ -77,46 +74,47 @@ struct cbfs_cachenode {
extern enum cbfs_result file_cbfs_result;
-/*
- * Return a string describing the most recent error condition.
+/**
+ * file_cbfs_error() - Return a string describing the most recent error
+ * condition.
*
* @return A pointer to the constant string.
*/
const char *file_cbfs_error(void);
-/*
- * Initialize the CBFS driver and load metadata into RAM.
+/**
+ * file_cbfs_init() - Initialize the CBFS driver and load metadata into RAM.
*
- * @param end_of_rom Points to the end of the ROM the CBFS should be read
+ * @end_of_rom: Points to the end of the ROM the CBFS should be read
* from.
*/
void file_cbfs_init(uintptr_t end_of_rom);
-/*
- * Get the header structure for the current CBFS.
+/**
+ * file_cbfs_get_header() - Get the header structure for the current CBFS.
*
* @return A pointer to the constant structure, or NULL if there is none.
*/
const struct cbfs_header *file_cbfs_get_header(void);
-/*
- * Get a handle for the first file in CBFS.
+/**
+ * file_cbfs_get_first() - Get a handle for the first file in CBFS.
*
* @return A handle for the first file in CBFS, NULL on error.
*/
const struct cbfs_cachenode *file_cbfs_get_first(void);
-/*
- * Get a handle to the file after this one in CBFS.
+/**
+ * file_cbfs_get_next() - Get a handle to the file after this one in CBFS.
*
- * @param file A pointer to the handle to advance.
+ * @file: A pointer to the handle to advance.
*/
void file_cbfs_get_next(const struct cbfs_cachenode **file);
-/*
- * Find a file with a particular name in CBFS.
+/**
+ * file_cbfs_find() - Find a file with a particular name in CBFS.
*
- * @param name The name to search for.
+ * @name: The name to search for.
*
* @return A handle to the file, or NULL on error.
*/
@@ -127,53 +125,55 @@ const struct cbfs_cachenode *file_cbfs_find(const char *name);
/* All of the functions below can be used without first initializing CBFS. */
/***************************************************************************/
-/*
- * Find a file with a particular name in CBFS without using the heap.
+/**
+ * file_cbfs_find_uncached() - Find a file with a particular name in CBFS
+ * without using the heap.
*
- * @param end_of_rom Points to the end of the ROM the CBFS should be read
+ * @end_of_rom: Points to the end of the ROM the CBFS should be read
* from.
- * @param name The name to search for.
+ * @name: The name to search for.
*
* @return A handle to the file, or NULL on error.
*/
const struct cbfs_cachenode *file_cbfs_find_uncached(uintptr_t end_of_rom,
const char *name);
-/*
- * Get the name of a file in CBFS.
+/**
+ * file_cbfs_name() - Get the name of a file in CBFS.
*
- * @param file The handle to the file.
+ * @file: The handle to the file.
*
* @return The name of the file, NULL on error.
*/
const char *file_cbfs_name(const struct cbfs_cachenode *file);
-/*
- * Get the size of a file in CBFS.
+/**
+ * file_cbfs_size() - Get the size of a file in CBFS.
*
- * @param file The handle to the file.
+ * @file: The handle to the file.
*
* @return The size of the file, zero on error.
*/
u32 file_cbfs_size(const struct cbfs_cachenode *file);
-/*
- * Get the type of a file in CBFS.
+/**
+ * file_cbfs_type() - Get the type of a file in CBFS.
*
- * @param file The handle to the file.
+ * @file: The handle to the file.
*
* @return The type of the file, zero on error.
*/
u32 file_cbfs_type(const struct cbfs_cachenode *file);
-/*
- * Read a file from CBFS into RAM
+/**
+ * file_cbfs_read() - Read a file from CBFS into RAM
*
- * @param file A handle to the file to read.
- * @param buffer Where to read it into memory.
+ * @file: A handle to the file to read.
+ * @buffer: Where to read it into memory.
+ * @maxsize: Maximum number of bytes to read
*
* @return If positive or zero, the number of characters read. If negative, an
- * error occurred.
+ * error occurred.
*/
long file_cbfs_read(const struct cbfs_cachenode *file, void *buffer,
unsigned long maxsize);
diff --git a/include/configs/CPCI405.h b/include/configs/CPCI405.h
index 9ecdad9c97..e3e5ebc53c 100644
--- a/include/configs/CPCI405.h
+++ b/include/configs/CPCI405.h
@@ -174,7 +174,7 @@
#define CONFIG_SYS_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */
#define CONFIG_SYS_PCI_PTM2LA 0xffc00000 /* point to flash */
#define CONFIG_SYS_PCI_PTM2MS 0xffc00001 /* 4MB, enable */
-#define CONFIG_SYS_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */
+#define CONFIG_SYS_PCI_PTM2PCI (bd->bi_memsize) /* host use this pci address */
#define CONFIG_PCI_4xx_PTM_OVERWRITE 1 /* overwrite PTMx settings by env */
diff --git a/include/configs/CPCI4052.h b/include/configs/CPCI4052.h
index efab11991d..c4fff486d8 100644
--- a/include/configs/CPCI4052.h
+++ b/include/configs/CPCI4052.h
@@ -195,7 +195,7 @@
#define CONFIG_SYS_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */
#define CONFIG_SYS_PCI_PTM2LA 0xffc00000 /* point to flash */
#define CONFIG_SYS_PCI_PTM2MS 0xffc00001 /* 4MB, enable */
-#define CONFIG_SYS_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */
+#define CONFIG_SYS_PCI_PTM2PCI (bd->bi_memsize) /* host use this pci address */
#define CONFIG_PCI_4xx_PTM_OVERWRITE 1 /* overwrite PTMx settings by env */
diff --git a/include/configs/CPCI405AB.h b/include/configs/CPCI405AB.h
index 83e9a046ad..9122cbd877 100644
--- a/include/configs/CPCI405AB.h
+++ b/include/configs/CPCI405AB.h
@@ -192,7 +192,7 @@
#define CONFIG_SYS_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */
#define CONFIG_SYS_PCI_PTM2LA 0xffc00000 /* point to flash */
#define CONFIG_SYS_PCI_PTM2MS 0xffc00001 /* 4MB, enable */
-#define CONFIG_SYS_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */
+#define CONFIG_SYS_PCI_PTM2PCI (bd->bi_memsize) /* host use this pci address */
#define CONFIG_PCI_4xx_PTM_OVERWRITE 1 /* overwrite PTMx settings by env */
diff --git a/include/configs/CPCI405DT.h b/include/configs/CPCI405DT.h
index 1944a071b4..f778af7e36 100644
--- a/include/configs/CPCI405DT.h
+++ b/include/configs/CPCI405DT.h
@@ -196,7 +196,7 @@
#define CONFIG_SYS_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */
#define CONFIG_SYS_PCI_PTM2LA 0xffc00000 /* point to flash */
#define CONFIG_SYS_PCI_PTM2MS 0xffc00001 /* 4MB, enable */
-#define CONFIG_SYS_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */
+#define CONFIG_SYS_PCI_PTM2PCI (bd->bi_memsize) /* host use this pci address */
#define CONFIG_PCI_4xx_PTM_OVERWRITE 1 /* overwrite PTMx settings by env */
diff --git a/include/configs/P1010RDB.h b/include/configs/P1010RDB.h
index 57aef21e96..437ee6ee6b 100644
--- a/include/configs/P1010RDB.h
+++ b/include/configs/P1010RDB.h
@@ -553,6 +553,7 @@ extern unsigned long get_sdram_size(void);
/* SATA */
#define CONFIG_FSL_SATA
+#define CONFIG_FSL_SATA_V2
#define CONFIG_LIBATA
#ifdef CONFIG_FSL_SATA
diff --git a/include/configs/P1022DS.h b/include/configs/P1022DS.h
index b3c850d584..14d597aad2 100644
--- a/include/configs/P1022DS.h
+++ b/include/configs/P1022DS.h
@@ -360,6 +360,7 @@
/* SATA */
#define CONFIG_LIBATA
#define CONFIG_FSL_SATA
+#define CONFIG_FSL_SATA_V2
#define CONFIG_SYS_SATA_MAX_DEVICE 2
#define CONFIG_SATA1
diff --git a/include/configs/P1023RDS.h b/include/configs/P1023RDS.h
index 800d666ab2..878bd5fa5e 100644
--- a/include/configs/P1023RDS.h
+++ b/include/configs/P1023RDS.h
@@ -524,7 +524,7 @@ extern unsigned long get_clock_freq(void);
/* Default address of microcode for the Linux Fman driver */
/* QE microcode/firmware address */
#define CONFIG_SYS_QE_FMAN_FW_IN_NOR
-#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xEF000000
+#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xEFF40000
#else
#define CONFIG_SYS_QE_FMAN_FW_IN_NAND
#define CONFIG_SYS_QE_FMAN_FW_ADDR 0x1f00000
diff --git a/include/configs/P2041RDB.h b/include/configs/P2041RDB.h
index 5cdb628ab1..8b9b0dbc22 100644
--- a/include/configs/P2041RDB.h
+++ b/include/configs/P2041RDB.h
@@ -202,15 +202,21 @@ unsigned long get_board_sys_clk(unsigned long dummy);
/* Set the local bus clock 1/8 of platform clock */
#define CONFIG_SYS_LBC_LCRR LCRR_CLKDIV_8
-#define CONFIG_SYS_FLASH_BASE 0xe8000000 /* Start of PromJet */
+/*
+ * This board doesn't have a promjet connector.
+ * However, it uses commone corenet board LAW and TLB.
+ * It is necessary to use the same start address with proper offset.
+ */
+#define CONFIG_SYS_FLASH_BASE 0xe0000000
#ifdef CONFIG_PHYS_64BIT
-#define CONFIG_SYS_FLASH_BASE_PHYS 0xfe8000000ull
+#define CONFIG_SYS_FLASH_BASE_PHYS 0xfe0000000ull
#else
#define CONFIG_SYS_FLASH_BASE_PHYS CONFIG_SYS_FLASH_BASE
#endif
#define CONFIG_SYS_FLASH_BR_PRELIM \
- (BR_PHYS_ADDR(CONFIG_SYS_FLASH_BASE_PHYS) | BR_PS_16 | BR_V)
+ (BR_PHYS_ADDR((CONFIG_SYS_FLASH_BASE_PHYS + 0x8000000)) | \
+ BR_PS_16 | BR_V)
#define CONFIG_SYS_FLASH_OR_PRELIM \
((0xf8000ff7 & ~OR_GPCM_SCY & ~OR_GPCM_EHTR) \
| OR_GPCM_SCY_8 | OR_GPCM_EHTR_CLEAR)
@@ -294,7 +300,7 @@ unsigned long get_board_sys_clk(unsigned long dummy);
#define CONFIG_SYS_FLASH_EMPTY_INFO
#define CONFIG_SYS_FLASH_AMD_CHECK_DQ7
-#define CONFIG_SYS_FLASH_BANKS_LIST {CONFIG_SYS_FLASH_BASE_PHYS}
+#define CONFIG_SYS_FLASH_BANKS_LIST {CONFIG_SYS_FLASH_BASE_PHYS + 0x8000000}
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_BOARD_EARLY_INIT_R /* call board_early_init_r function */
@@ -539,7 +545,7 @@ unsigned long get_board_sys_clk(unsigned long dummy);
#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xFFE00000
#else
#define CONFIG_SYS_QE_FMAN_FW_IN_NOR
-#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xEF000000
+#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xEFF40000
#endif
#define CONFIG_SYS_QE_FMAN_FW_LENGTH 0x10000
#define CONFIG_SYS_FDT_PAD (0x3000 + CONFIG_SYS_QE_FMAN_FW_LENGTH)
@@ -560,8 +566,10 @@ unsigned long get_board_sys_clk(unsigned long dummy);
#endif /* CONFIG_PCI */
/* SATA */
+#define CONFIG_FSL_SATA_V2
+
+#ifdef CONFIG_FSL_SATA_V2
#define CONFIG_FSL_SATA
-#ifdef CONFIG_FSL_SATA
#define CONFIG_LIBATA
#define CONFIG_SYS_SATA_MAX_DEVICE 2
diff --git a/include/configs/P3041DS.h b/include/configs/P3041DS.h
index cf184e74ab..ce8f9b0b2e 100644
--- a/include/configs/P3041DS.h
+++ b/include/configs/P3041DS.h
@@ -32,6 +32,7 @@
#define CONFIG_MMC
#define CONFIG_NAND_FSL_ELBC
+#define CONFIG_FSL_SATA_V2
#define CONFIG_PCIE3
#define CONFIG_PCIE4
#define CONFIG_SYS_DPAA_RMAN
diff --git a/include/configs/P5020DS.h b/include/configs/P5020DS.h
index 7018d7a322..778230d335 100644
--- a/include/configs/P5020DS.h
+++ b/include/configs/P5020DS.h
@@ -32,6 +32,7 @@
#define CONFIG_MMC
#define CONFIG_NAND_FSL_ELBC
+#define CONFIG_FSL_SATA_V2
#define CONFIG_PCIE3
#define CONFIG_PCIE4
#define CONFIG_SYS_FSL_RAID_ENGINE
diff --git a/include/configs/P5040DS.h b/include/configs/P5040DS.h
new file mode 100644
index 0000000000..50d9e541a8
--- /dev/null
+++ b/include/configs/P5040DS.h
@@ -0,0 +1,40 @@
+/*
+ * 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
+ */
+
+/*
+ * P5040 DS board configuration file
+ *
+ */
+#define CONFIG_P5040DS
+#define CONFIG_PHYS_64BIT
+#define CONFIG_PPC_P5040
+
+#define CONFIG_FSL_NGPIXIS /* use common ngPIXIS code */
+
+#define CONFIG_MMC
+#define CONFIG_NAND_FSL_ELBC
+#define CONFIG_PCIE3
+#define CONFIG_SYS_FSL_RAID_ENGINE
+
+#define CONFIG_ICS307_REFCLK_HZ 25000000 /* ICS307 ref clk freq */
+
+#include "corenet_ds.h"
diff --git a/include/configs/PK1C20.h b/include/configs/PK1C20.h
index 403fafa2f5..aced85b660 100644
--- a/include/configs/PK1C20.h
+++ b/include/configs/PK1C20.h
@@ -142,6 +142,7 @@
*----------------------------------------------------------------------*/
#define CONFIG_SYS_LEDPIO_ADDR 0x02120870 /* LED PIO base addr */
#define CONFIG_STATUS_LED /* Enable status driver */
+#define CONFIG_BOARD_SPECIFIC_LED
#define STATUS_LED_BIT 1 /* Bit-0 on PIO */
#define STATUS_LED_STATE 1 /* Blinking */
diff --git a/include/configs/a3m071.h b/include/configs/a3m071.h
new file mode 100644
index 0000000000..df3b4ae90a
--- /dev/null
+++ b/include/configs/a3m071.h
@@ -0,0 +1,380 @@
+/*
+ * 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.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC5200
+#define CONFIG_MPC5xxx 1 /* This is an MPC5xxx CPU */
+#define CONFIG_A3M071 /* ... on A3M071 board */
+#define CONFIG_MPC5200_DDR /* ... use DDR RAM */
+
+#define CONFIG_SYS_TEXT_BASE 0x01000000 /* boot low for 32 MiB boards */
+
+#define CONFIG_SYS_MPC5XXX_CLKIN 33000000 /* ... running at 33MHz */
+
+#define CONFIG_MISC_INIT_R
+#define CONFIG_SYS_LOWBOOT /* Enable lowboot */
+
+/*
+ * Serial console configuration
+ */
+#define CONFIG_PSC_CONSOLE 1 /* console is on PSC1 */
+#define CONFIG_BAUDRATE 115200 /* ... at 115200 bps */
+#define CONFIG_SYS_BAUDRATE_TABLE \
+ { 9600, 19200, 38400, 57600, 115200, 230400 }
+
+/*
+ * Command line configuration.
+ */
+#include <config_cmd_default.h>
+
+#define CONFIG_CMD_BSP
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_EEPROM
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_REGINFO
+
+/*
+ * IPB Bus clocking configuration.
+ */
+#define CONFIG_SYS_IPBCLK_EQUALS_XLBCLK /* define for 133MHz speed */
+/* define for 66MHz speed - undef for 33MHz PCI clock speed */
+#undef CONFIG_SYS_PCICLK_EQUALS_IPBCLK_DIV2
+
+/* pass open firmware flat tree */
+#define CONFIG_OF_LIBFDT
+#define CONFIG_OF_BOARD_SETUP
+
+/* maximum size of the flat tree (8K) */
+#define OF_FLAT_TREE_MAX_SIZE 8192
+
+#define OF_CPU "PowerPC,5200@0"
+#define OF_SOC "soc5200@f0000000"
+#define OF_TBCLK (bd->bi_busfreq / 4)
+#define OF_STDOUT_PATH "/soc5200@f0000000/serial@2000"
+
+/*
+ * I2C configuration
+ */
+#define CONFIG_HARD_I2C /* I2C with hardware support */
+#define CONFIG_SYS_I2C_MODULE 2 /* Select I2C module #1 or #2 */
+
+#define CONFIG_SYS_I2C_SPEED 100000 /* 100 kHz */
+#define CONFIG_SYS_I2C_SLAVE 0x7F
+
+/*
+ * EEPROM configuration
+ */
+#define CONFIG_SYS_I2C_EEPROM_ADDR 0x53
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 6
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10
+
+/*
+ * RTC configuration
+ */
+#define CONFIG_RTC_PCF8563
+#define CONFIG_SYS_I2C_RTC_ADDR 0x51
+
+/*
+ * NOR flash configuration
+ */
+#define CONFIG_SYS_FLASH_BASE 0xfc000000
+#define CONFIG_SYS_FLASH_SIZE 0x01000000
+#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x40000)
+
+#define CONFIG_SYS_MAX_FLASH_BANKS 1
+#define CONFIG_SYS_MAX_FLASH_SECT 256
+#define CONFIG_SYS_FLASH_ERASE_TOUT 240000
+#define CONFIG_SYS_FLASH_WRITE_TOUT 500
+#define CONFIG_SYS_FLASH_LOCK_TOUT 5
+#define CONFIG_SYS_FLASH_UNLOCK_TOUT 10000
+#define CONFIG_SYS_FLASH_PROTECTION
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_EMPTY_INFO
+#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
+
+/*
+ * Environment settings
+ */
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_ENV_SIZE 0x10000
+#define CONFIG_ENV_SECT_SIZE 0x20000
+#define CONFIG_ENV_OVERWRITE
+
+/*
+ * Memory map
+ */
+#define CONFIG_SYS_MBAR 0xf0000000
+#define CONFIG_SYS_SDRAM_BASE 0x00000000
+#define CONFIG_SYS_DEFAULT_MBAR 0x80000000
+
+/* Use SRAM until RAM will be available */
+#define CONFIG_SYS_INIT_RAM_ADDR MPC5XXX_SRAM
+#define CONFIG_SYS_INIT_RAM_END MPC5XXX_SRAM_SIZE
+
+
+#define CONFIG_SYS_GBL_DATA_SIZE 128
+#define CONFIG_SYS_GBL_DATA_OFFSET (CONFIG_SYS_INIT_RAM_END - \
+ CONFIG_SYS_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_GBL_DATA_OFFSET
+
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_MONITOR_LEN (256 << 10)
+#define CONFIG_SYS_MALLOC_LEN (1 << 20)
+#define CONFIG_SYS_BOOTMAPSZ (8 << 20)
+
+/*
+ * Ethernet configuration
+ */
+#define CONFIG_MPC5xxx_FEC
+#define CONFIG_MPC5xxx_FEC_MII100
+#define CONFIG_PHY_ADDR 0x00
+
+/*
+ * GPIO configuration
+ */
+
+/*
+ * GPIO-config depends on failsave-level
+ * failsave 0 means just MPX-config, no digiboard, no fpga
+ * 1 means digiboard ok
+ * 2 means fpga ok
+ */
+
+/* for failsave-level 0 - full failsave */
+#define CONFIG_SYS_GPS_PORT_CONFIG 0x1005C005
+/* for failsave-level 1 - only digiboard ok */
+#define CONFIG_SYS_GPS_PORT_CONFIG_1 0x1005C005
+/* for failsave-level 2 - all ok */
+#define CONFIG_SYS_GPS_PORT_CONFIG_2 0x1005C005
+
+/*
+ * Configuration matrix
+ * MSB LSB
+ * failsave 0 0x1005C005 00010000000001011100000001100101 ( full failsave )
+ * failsave 1 0x1005C005 00010000000001011100000001100101 ( digib.-ver ok )
+ * failsave 2 0x1005C005 00010000000001011100000001100101 ( all ok )
+ * || ||| || | ||| | | | |
+ * || ||| || | ||| | | | | bit rev name
+ * ++-+++-++--+---+++-+---+---+---+- 0 31 CS1
+ * +-+++-++--+---+++-+---+---+---+- 1 30 LPTZ
+ * ||| || | ||| | | | | 2 29 ALTs
+ * +++-++--+---+++-+---+---+---+- 3 28 ALTs
+ * ++-++--+---+++-+---+---+---+- 4 27 CS7
+ * +-++--+---+++-+---+---+---+- 5 26 CS6
+ * || | ||| | | | | 6 25 ATA
+ * ++--+---+++-+---+---+---+- 7 24 ATA
+ * +--+---+++-+---+---+---+- 8 23 IR_USB_CLK
+ * | ||| | | | | 9 22 IRDA
+ * | ||| | | | | 10 21 IRDA
+ * +---+++-+---+---+---+- 11 20 IRDA
+ * ||| | | | | 12 19 Ether
+ * ||| | | | | 13 18 Ether
+ * ||| | | | | 14 17 Ether
+ * +++-+---+---+---+- 15 16 Ether
+ * ++-+---+---+---+- 16 15 PCI_DIS
+ * +-+---+---+---+- 17 14 USB_SE
+ * | | | | 18 13 USB
+ * +---+---+---+- 19 12 USB
+ * | | | 20 11 PSC3
+ * | | | 21 10 PSC3
+ * | | | 22 9 PSC3
+ * +---+---+- 23 8 PSC3
+ * | | 24 7 -
+ * | | 25 6 PSC2
+ * | | 26 5 PSC2
+ * +---+- 27 4 PSC2
+ * | 28 3 -
+ * | 29 2 PSC1
+ * | 30 1 PSC1
+ * +- 31 0 PSC1
+ */
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_SYS_PROMPT "=> "
+
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
+
+#if defined(CONFIG_CMD_KGDB)
+#define CONFIG_SYS_CBSIZE 1024
+#else
+#define CONFIG_SYS_CBSIZE 256
+#endif
+#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16)
+#define CONFIG_SYS_MAXARGS 16
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+
+#define CONFIG_SYS_MEMTEST_START 0x00100000
+#define CONFIG_SYS_MEMTEST_END 0x00f00000
+
+#define CONFIG_SYS_LOAD_ADDR 0x00100000
+
+#define CONFIG_SYS_HZ 1000
+#define CONFIG_LOOPW
+#define CONFIG_SYS_CONSOLE_INFO_QUIET /* don't print console @ startup*/
+
+/*
+ * Various low-level settings
+ */
+#define CONFIG_SYS_HID0_INIT (HID0_ICE | HID0_ICFI)
+#define CONFIG_SYS_HID0_FINAL HID0_ICE
+
+#define CONFIG_SYS_BOOTCS_START CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_BOOTCS_SIZE CONFIG_SYS_FLASH_SIZE
+#define CONFIG_SYS_CS0_START CONFIG_SYS_FLASH_BASE
+#define CONFIG_SYS_CS0_SIZE CONFIG_SYS_FLASH_SIZE
+#define CONFIG_SYS_CS2_START 0xe0000000
+#define CONFIG_SYS_CS2_SIZE 0x00100000
+
+/* FPGA slave io (512kiB) - see ticket #66 */
+#define CONFIG_SYS_CS3_START 0xE9000000
+#define CONFIG_SYS_CS3_SIZE 0x00080000
+/* 00000000 00110010 1 0 1 1 10 01 00 00 0 0 0 0 = 0x0032B900 */
+#define CONFIG_SYS_CS3_CFG 0x0032B900
+
+/* Diagnosis Interface - see ticket #63 */
+#define CONFIG_SYS_CS4_START 0xEA000000
+#define CONFIG_SYS_CS4_SIZE 0x00000001
+/* 00000000 00000010 1 0 1 1 10 01 00 00 0 0 0 0 = 0x0002B900 */
+#define CONFIG_SYS_CS4_CFG 0x0002B900
+
+/* FPGA master io (64kiB) - see ticket #66 */
+#define CONFIG_SYS_CS5_START 0xE8000000
+#define CONFIG_SYS_CS5_SIZE 0x00010000
+/* 00000000 00110010 1 0 1 1 10 01 00 00 0 0 0 0 = 0x0032B900 */
+#define CONFIG_SYS_CS5_CFG 0x0032B900
+
+#ifdef CONFIG_SYS_PCICLK_EQUALS_IPBCLK_DIV2 /* for pci_clk = 66 MHz */
+#define CONFIG_SYS_BOOTCS_CFG 0x0006F900
+#define CONFIG_SYS_CS1_CFG 0x0004FB00
+#define CONFIG_SYS_CS2_CFG 0x0006F90C
+#else /* for pci_clk = 33 MHz */
+#define CONFIG_SYS_BOOTCS_CFG 0x0002F900
+#define CONFIG_SYS_CS1_CFG 0x0001FB00
+#define CONFIG_SYS_CS2_CFG 0x0002F90C
+#endif
+
+#define CONFIG_SYS_CS_BURST 0x00000000
+/* set DC for FPGA CS5 and CS3 to 0 - see ticket #66 */
+/* R 7 R 6 R 5 R 4 R 3 R 2 R 1 R 0 */
+/* 00 11 00 11 00 00 00 11 00 00 00 00 00 00 00 00 */
+#define CONFIG_SYS_CS_DEADCYCLE 0x33030000
+
+#define CONFIG_SYS_RESET_ADDRESS 0xff000000
+
+/*
+ * Environment Configuration
+ */
+
+#define CONFIG_BOOTDELAY 0 /* -1 disables auto-boot */
+#undef CONFIG_BOOTARGS
+#define CONFIG_ZERO_BOOTDELAY_CHECK
+
+#define CONFIG_PREBOOT "echo;" \
+ "echo Type \"run flash_mtd\" to boot from flash with mtd filesystem;" \
+ "echo Type \"run net_nfs\" to boot from tftp with nfs filesystem;" \
+ "echo"
+
+#undef CONFIG_BOOTARGS
+
+#define CONFIG_SYS_OS_BASE 0xfc080000
+#define CONFIG_SYS_FDT_BASE 0xfc060000
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "netdev=eth0\0" \
+ "verify=no\0" \
+ "consoledev=ttyPSC0\0" \
+ "nfsargs=setenv bootargs root=/dev/nfs rw " \
+ "nfsroot=${serverip}:${rootpath}\0" \
+ "ramargs=setenv bootargs root=/dev/ram rw\0" \
+ "mtdargs=setenv bootargs root=/dev/mtdblock4 rw rootfstype=jffs2\0"\
+ "addip=setenv bootargs ${bootargs} " \
+ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}" \
+ ":${hostname}:${netdev}:off panic=1\0" \
+ "addtty=setenv bootargs ${bootargs} " \
+ "console=${consoledev},${baudrate}\0" \
+ "flash_nfs=run nfsargs addip addtty;" \
+ "bootm ${kernel_addr} - ${fdtaddr}\0" \
+ "flash_mtd=run mtdargs addip addtty;" \
+ "bootm ${kernel_addr} - ${fdtaddr}\0" \
+ "flash_self=run ramargs addip addtty;" \
+ "bootm ${kernel_addr} ${ramdisk_addr} ${fdtaddr}\0" \
+ "net_nfs=sleep 2; tftp ${loadaddr} ${bootfile};" \
+ "tftp c00000 ${fdtfile};" \
+ "run nfsargs addip addtty;" \
+ "bootm ${loadaddr} - c00000\0" \
+ "load=tftp ${loadaddr} u-boot.bin\0" \
+ "update=protect off fc000000 fc03ffff; " \
+ "era fc000000 fc03ffff; cp.b ${loadaddr} fc000000 40000\0"\
+ "upd=run load;run update\0" \
+ "fdtaddr=" xstr(CONFIG_SYS_FDT_BASE) "\0" \
+ "fdtfile=dtbFile\0" \
+ "kernel_addr=" xstr(CONFIG_SYS_OS_BASE) "\0" \
+ ""
+
+#define CONFIG_BOOTCOMMAND "run flash_mtd"
+
+/*
+ * SPL related defines
+ */
+#define CONFIG_SPL
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_NOR_SUPPORT
+#define CONFIG_SPL_TEXT_BASE 0xfc000000
+#define CONFIG_SPL_START_S_PATH "arch/powerpc/cpu/mpc5xxx"
+#define CONFIG_SPL_LDSCRIPT "arch/powerpc/cpu/mpc5xxx/u-boot-spl.lds"
+#define CONFIG_SPL_LIBCOMMON_SUPPORT /* image.c */
+#define CONFIG_SPL_LIBGENERIC_SUPPORT /* string.c */
+#define CONFIG_SPL_SERIAL_SUPPORT
+
+/* Place BSS for SPL near end of SDRAM */
+#define CONFIG_SPL_BSS_START_ADDR ((128 - 1) << 20)
+#define CONFIG_SPL_BSS_MAX_SIZE (64 << 10)
+
+#define CONFIG_SPL_OS_BOOT
+/* Place patched DT blob (fdt) at this address */
+#define CONFIG_SYS_SPL_ARGS_ADDR 0x01800000
+
+/* Settings for real U-Boot to be loaded from NOR flash */
+#ifndef __ASSEMBLY__
+extern char __spl_flash_end[];
+#endif
+#define CONFIG_SYS_UBOOT_BASE __spl_flash_end
+#define CONFIG_SYS_SPL_MAX_LEN (32 << 10)
+#define CONFIG_SYS_UBOOT_START 0x1000100
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index b6e48f8a63..ab9549b93b 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -257,6 +257,33 @@
#define CONFIG_SKIP_LOWLEVEL_INIT
#endif
+/*
+ * USB configuration
+ */
+#define CONFIG_USB_MUSB_DSPS
+#define CONFIG_ARCH_MISC_INIT
+#define CONFIG_MUSB_GADGET
+#define CONFIG_MUSB_PIO_ONLY
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_MUSB_HOST
+#define CONFIG_AM335X_USB0
+#define CONFIG_AM335X_USB0_MODE MUSB_PERIPHERAL
+#define CONFIG_AM335X_USB1
+#define CONFIG_AM335X_USB1_MODE MUSB_HOST
+
+#ifdef CONFIG_MUSB_HOST
+#define CONFIG_CMD_USB
+#define CONFIG_USB_STORAGE
+#endif
+
+#ifdef CONFIG_MUSB_GADGET
+#define CONFIG_USB_ETHER
+#define CONFIG_USB_ETH_RNDIS
+#endif /* CONFIG_MUSB_GADGET */
+
+/* Unsupported features */
+#undef CONFIG_USE_IRQ
+
#define CONFIG_CMD_NET
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_PING
diff --git a/include/configs/am3517_crane.h b/include/configs/am3517_crane.h
index 20a3df5db2..e1ad1e58ff 100644
--- a/include/configs/am3517_crane.h
+++ b/include/configs/am3517_crane.h
@@ -337,6 +337,9 @@
#define CONFIG_SPL_FAT_SUPPORT
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
diff --git a/include/configs/am3517_evm.h b/include/configs/am3517_evm.h
index ce71d1335c..ba1532540e 100644
--- a/include/configs/am3517_evm.h
+++ b/include/configs/am3517_evm.h
@@ -97,15 +97,16 @@
/*
* USB configuration
- * Enable CONFIG_MUSB_HCD for Host functionalities MSC, keyboard
- * Enable CONFIG_MUSB_UDC for Device functionalities.
+ * Enable CONFIG_MUSB_HOST for Host functionalities MSC, keyboard
+ * Enable CONFIG_MUSB_GADGET for Device functionalities.
*/
-#define CONFIG_USB_AM35X 1
-#define CONFIG_MUSB_HCD 1
+#define CONFIG_USB_MUSB_AM35X
+#define CONFIG_MUSB_HOST
+#define CONFIG_MUSB_PIO_ONLY
-#ifdef CONFIG_USB_AM35X
+#ifdef CONFIG_USB_MUSB_AM35X
-#ifdef CONFIG_MUSB_HCD
+#ifdef CONFIG_MUSB_HOST
#define CONFIG_CMD_USB
#define CONFIG_USB_STORAGE
@@ -117,21 +118,15 @@
#define CONFIG_PREBOOT "usb start"
#endif /* CONFIG_USB_KEYBOARD */
-#endif /* CONFIG_MUSB_HCD */
+#endif /* CONFIG_MUSB_HOST */
-#ifdef CONFIG_MUSB_UDC
-/* USB device configuration */
-#define CONFIG_USB_DEVICE 1
-#define CONFIG_USB_TTY 1
-#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
-/* Change these to suit your needs */
-#define CONFIG_USBD_VENDORID 0x0451
-#define CONFIG_USBD_PRODUCTID 0x5678
-#define CONFIG_USBD_MANUFACTURER "Texas Instruments"
-#define CONFIG_USBD_PRODUCT_NAME "AM3517EVM"
-#endif /* CONFIG_MUSB_UDC */
+#ifdef CONFIG_MUSB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_ETHER
+#define CONFIG_USB_ETH_RNDIS
+#endif /* CONFIG_MUSB_GADGET */
-#endif /* CONFIG_USB_AM35X */
+#endif /* CONFIG_USB_MUSB_AM35X */
/* commands to include */
#include <config_cmd_default.h>
@@ -336,6 +331,9 @@
#define CONFIG_SPL_FAT_SUPPORT
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
diff --git a/include/configs/at91sam9x5ek.h b/include/configs/at91sam9x5ek.h
index 71f765b494..131758279c 100644
--- a/include/configs/at91sam9x5ek.h
+++ b/include/configs/at91sam9x5ek.h
@@ -168,8 +168,7 @@
#define CONFIG_BOOTCOMMAND "nand read " \
"0x22000000 0x200000 0x300000; " \
"bootm 0x22000000"
-#else
-#ifdef CONFIG_SYS_USE_SPIFLASH
+#elif defined(CONFIG_SYS_USE_SPIFLASH)
/* bootstrap + u-boot + env + linux in spi flash */
#define CONFIG_ENV_IS_IN_SPI_FLASH
#define CONFIG_ENV_OFFSET 0x5000
@@ -179,14 +178,28 @@
#define CONFIG_BOOTCOMMAND "sf probe 0; " \
"sf read 0x22000000 0x100000 0x300000; " \
"bootm 0x22000000"
-#endif
+#else /* CONFIG_SYS_USE_MMC */
+/* bootstrap + u-boot + env + linux in mmc */
+#define CONFIG_ENV_IS_IN_MMC
+/* For FAT system, most cases it should be in the reserved sector */
+#define CONFIG_ENV_OFFSET 0x2000
+#define CONFIG_ENV_SIZE 0x1000
+#define CONFIG_SYS_MMC_ENV_DEV 0
#endif
+#ifdef CONFIG_SYS_USE_MMC
+#define CONFIG_BOOTARGS "mem=128M console=ttyS0,115200 " \
+ "mtdparts=atmel_nand:" \
+ "8M(bootstrap/uboot/kernel)ro,-(rootfs) " \
+ "root=/dev/mmcblk0p2 " \
+ "rw rootfstype=ext4 rootwait"
+#else
#define CONFIG_BOOTARGS "mem=128M console=ttyS0,115200 " \
"mtdparts=atmel_nand:" \
"8M(bootstrap/uboot/kernel)ro,-(rootfs) " \
"root=/dev/mtdblock1 rw " \
"rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs"
+#endif
#define CONFIG_BAUDRATE 115200
diff --git a/include/configs/cam_enc_4xx.h b/include/configs/cam_enc_4xx.h
index 56dc1cbbd5..a7a698c0ca 100644
--- a/include/configs/cam_enc_4xx.h
+++ b/include/configs/cam_enc_4xx.h
@@ -219,6 +219,9 @@
#define CONFIG_SPL_BOARD_INIT
#define CONFIG_SPL_LIBGENERIC_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_NAND_SIMPLE
#define CONFIG_SYS_NAND_HW_ECC_OOBFIRST
#define CONFIG_SPL_SERIAL_SUPPORT
diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h
index cc95e2be98..adeace0cf2 100644
--- a/include/configs/coreboot.h
+++ b/include/configs/coreboot.h
@@ -35,9 +35,13 @@
* (easy to change)
*/
#define CONFIG_SYS_COREBOOT
-#undef CONFIG_SHOW_BOOT_PROGRESS
+#define CONFIG_SHOW_BOOT_PROGRESS
#define CONFIG_LAST_STAGE_INIT
-
+#define CONFIG_X86_NO_RESET_VECTOR
+#define CONFIG_SYS_VSNPRINTF
+#define CONFIG_INTEL_CORE_ARCH /* Sandy bridge and ivy bridge chipsets. */
+#define CONFIG_ZBOOT_32
+#define CONFIG_PHYSMEM
/*-----------------------------------------------------------------------
* Watchdog Configuration
@@ -67,11 +71,16 @@
CONFIG_SYS_SCSI_MAX_LUN)
#endif
+/* Generic TPM interfaced through LPC bus */
+#define CONFIG_GENERIC_LPC_TPM
+#define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000
+
/*-----------------------------------------------------------------------
* Real Time Clock Configuration
*/
#define CONFIG_RTC_MC146818
#define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0
+#define CONFIG_SYS_ISA_IO CONFIG_SYS_ISA_IO_BASE_ADDRESS
/*-----------------------------------------------------------------------
* Serial Configuration
@@ -88,18 +97,18 @@
#define CONFIG_SYS_NS16550_COM2 UART1_BASE
#define CONFIG_SYS_NS16550_PORT_MAPPED
-/* max. 1 IDE bus */
-#define CONFIG_SYS_IDE_MAXBUS 1
-/* max. 1 drive per IDE bus */
-#define CONFIG_SYS_IDE_MAXDEVICE (CONFIG_SYS_IDE_MAXBUS * 1)
+#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,eserial0\0" \
+ "stdout=vga,eserial0,cbmem\0" \
+ "stderr=vga,eserial0,cbmem\0"
-#define CONFIG_SYS_ATA_BASE_ADDR CONFIG_SYS_ISA_IO_BASE_ADDRESS
-#define CONFIG_SYS_ATA_IDE0_OFFSET 0x01f0
-#define CONFIG_SYS_ATA_IDE1_OFFSET 0x0170
-#define CONFIG_SYS_ATA_DATA_OFFSET 0
-#define CONFIG_SYS_ATA_REG_OFFSET 0
-#define CONFIG_SYS_ATA_ALT_OFFSET 0x200
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
+#define CONFIG_SYS_STDIO_DEREGISTER
+#define CONFIG_CBMEM_CONSOLE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_COMMAND_HISTORY
+#define CONFIG_AUTOCOMPLETE
#define CONFIG_SUPPORT_VFAT
/************************************************************
@@ -110,19 +119,30 @@
/************************************************************
* DISK Partition support
************************************************************/
+#define CONFIG_EFI_PARTITION
#define CONFIG_DOS_PARTITION
#define CONFIG_MAC_PARTITION
#define CONFIG_ISO_PARTITION /* Experimental */
+#define CONFIG_CMD_PART
#define CONFIG_CMD_CBFS
#define CONFIG_CMD_EXT4
#define CONFIG_CMD_EXT4_WRITE
+#define CONFIG_PARTITION_UUIDS
/*-----------------------------------------------------------------------
* Video Configuration
*/
-#undef CONFIG_VIDEO
-#undef CONFIG_CFB_CONSOLE
+#define CONFIG_VIDEO
+#define CONFIG_VIDEO_COREBOOT
+#define CONFIG_VIDEO_SW_CURSOR
+#define VIDEO_FB_16BPP_WORD_SWAP
+#define CONFIG_I8042_KBD
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_SYS_CONSOLE_INFO_QUIET
+
+/* x86 GPIOs are accessed through a PCI device */
+#define CONFIG_INTEL_ICH6_GPIO
/*-----------------------------------------------------------------------
* Command line configuration.
@@ -136,6 +156,7 @@
#define CONFIG_CMD_ECHO
#undef CONFIG_CMD_FLASH
#define CONFIG_CMD_FPGA
+#define CONFIG_CMD_GPIO
#define CONFIG_CMD_IMI
#undef CONFIG_CMD_IMLS
#define CONFIG_CMD_IRQ
@@ -153,12 +174,19 @@
#define CONFIG_CMD_SETGETDCR
#define CONFIG_CMD_SOURCE
#define CONFIG_CMD_XIMG
-#define CONFIG_CMD_IDE
+#define CONFIG_CMD_SCSI
+
#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_ZBOOT
+
#define CONFIG_BOOTDELAY 2
-#define CONFIG_BOOTARGS "root=/dev/mtdblock0 console=ttyS0,9600"
+#define CONFIG_BOOTARGS \
+ "root=/dev/sdb3 init=/sbin/init rootwait ro"
+#define CONFIG_BOOTCOMMAND \
+ "ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000"
+
#if defined(CONFIG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200
@@ -210,12 +238,11 @@
* (128kB + Environment Sector Size) malloc pool
*/
#define CONFIG_SYS_STACK_SIZE (32 * 1024)
-#define CONFIG_SYS_INIT_SP_ADDR (256 * 1024 + 16 * 1024)
+#define CONFIG_SYS_CAR_ADDR 0x19200000
+#define CONFIG_SYS_CAR_SIZE (16 * 1024)
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_MONITOR_LEN (256 * 1024)
#define CONFIG_SYS_MALLOC_LEN (0x20000 + 128 * 1024)
-/* Address of temporary Global Data */
-#define CONFIG_SYS_INIT_GD_ADDR (256 * 1024)
/* allow to overwrite serial and ethaddr */
@@ -240,4 +267,7 @@
*/
#define CONFIG_PCI
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ CONFIG_STD_DEVICES_SETTINGS
+
#endif /* __CONFIG_H */
diff --git a/include/configs/corenet_ds.h b/include/configs/corenet_ds.h
index c41b039996..3f42cd9a38 100644
--- a/include/configs/corenet_ds.h
+++ b/include/configs/corenet_ds.h
@@ -549,7 +549,7 @@
#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xFFE00000
#else
#define CONFIG_SYS_QE_FMAN_FW_IN_NOR
-#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xEF000000
+#define CONFIG_SYS_QE_FMAN_FW_ADDR 0xEFF40000
#endif
#define CONFIG_SYS_QE_FMAN_FW_LENGTH 0x10000
#define CONFIG_SYS_FDT_PAD (0x3000 + CONFIG_SYS_QE_FMAN_FW_LENGTH)
diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h
index ddd615509f..99b4de7288 100644
--- a/include/configs/da850evm.h
+++ b/include/configs/da850evm.h
@@ -227,6 +227,9 @@
#define CONFIG_SYS_NAND_ECCBYTES 10
#define CONFIG_SYS_NAND_OOBSIZE 64
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_NAND_SIMPLE
#define CONFIG_SPL_NAND_LOAD
#endif
diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h
index da3263f4f5..83a8b5d59f 100644
--- a/include/configs/devkit8000.h
+++ b/include/configs/devkit8000.h
@@ -316,6 +316,9 @@
#define CONFIG_SPL_GPIO_SUPPORT
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_MMC_SUPPORT
#define CONFIG_SPL_FAT_SUPPORT
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
diff --git a/include/configs/eNET.h b/include/configs/eNET.h
index 4b1c21904c..28cf95b778 100644
--- a/include/configs/eNET.h
+++ b/include/configs/eNET.h
@@ -168,16 +168,10 @@
#define CONFIG_SYS_STACK_SIZE (32 * 1024)
#define CONFIG_SYS_CAR_ADDR 0x19200000
#define CONFIG_SYS_CAR_SIZE (16 * 1024)
-#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_CAR_ADDR + \
- CONFIG_SYS_CAR_SIZE)
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_MONITOR_LEN (256 * 1024)
#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SECT_SIZE + \
128*1024)
-/* Address of temporary Global Data */
-#define CONFIG_SYS_INIT_GD_ADDR CONFIG_SYS_CAR_ADDR
-
-
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
diff --git a/include/configs/eb_cpu5282.h b/include/configs/eb_cpu5282.h
index 9ecc10bd1b..5a0d321f73 100644
--- a/include/configs/eb_cpu5282.h
+++ b/include/configs/eb_cpu5282.h
@@ -38,7 +38,7 @@
#define CONFIG_MCFUART
#define CONFIG_SYS_UART_PORT (0)
-#define CONFIG_BAUDRATE 9600
+#define CONFIG_BAUDRATE 115200
#undef CONFIG_MONITOR_IS_IN_RAM /* starts uboot direct */
@@ -52,20 +52,24 @@
#define CONFIG_RESET_TO_RETRY
#define CONFIG_SPLASH_SCREEN
+#define CONFIG_HW_WATCHDOG
+
+#define CONFIG_STATUS_LED
+#define CONFIG_BOARD_SPECIFIC_LED
+#define STATUS_LED_ACTIVE 0
+#define STATUS_LED_BIT 0x0008 /* Timer7 GPIO */
+#define STATUS_LED_BOOT 0
+#define STATUS_LED_PERIOD (CONFIG_SYS_HZ / 2)
+#define STATUS_LED_STATE STATUS_LED_OFF
+
/*----------------------------------------------------------------------*
* Configuration for environment *
* Environment is in the second sector of the first 256k of flash *
*----------------------------------------------------------------------*/
-#ifndef CONFIG_MONITOR_IS_IN_RAM
-#define CONFIG_ENV_ADDR 0xF003C000 /* End of 256K */
-#define CONFIG_ENV_SECT_SIZE 0x4000
-#define CONFIG_ENV_IS_IN_FLASH 1
-#else
-#define CONFIG_ENV_ADDR 0xFFE04000
-#define CONFIG_ENV_SECT_SIZE 0x2000
+#define CONFIG_ENV_ADDR 0xFF040000
+#define CONFIG_ENV_SECT_SIZE 0x00020000
#define CONFIG_ENV_IS_IN_FLASH 1
-#endif
/*
* BOOTP options
@@ -78,26 +82,24 @@
/*
* Command line configuration.
*/
+#define CONFIG_CMDLINE_EDITING
#include <config_cmd_default.h>
#undef CONFIG_CMD_LOADB
+#define CONFIG_CMD_DATE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_LED
#define CONFIG_CMD_MII
#define CONFIG_CMD_NET
#define CONFIG_MCFTMR
-
#define CONFIG_BOOTDELAY 5
-#define CONFIG_SYS_HUSH_PARSER
-#define CONFIG_SYS_PROMPT_HUSH_PS2 "> "
#define CONFIG_SYS_PROMPT "\nEB+CPU5282> "
#define CONFIG_SYS_LONGHELP 1
-#if defined(CONFIG_CMD_KGDB)
#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */
-#else
-#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
-#endif
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16)
#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
@@ -112,12 +114,12 @@
/*----------------------------------------------------------------------*
* Clock and PLL Configuration *
*----------------------------------------------------------------------*/
-#define CONFIG_SYS_HZ 10000000
-#define CONFIG_SYS_CLK 58982400 /* 9,8304MHz * 6 */
+#define CONFIG_SYS_HZ 1000
+#define CONFIG_SYS_CLK 80000000 /* 8MHz * 8 */
-/* PLL Configuration: Ext Clock * 6 (see table 9-4 of MCF user manual) */
+/* PLL Configuration: Ext Clock * 8 (see table 9-4 of MCF user manual) */
-#define CONFIG_SYS_MFD 0x01 /* PLL Multiplication Factor Devider */
+#define CONFIG_SYS_MFD 0x02 /* PLL Multiplication Factor Devider */
#define CONFIG_SYS_RFD 0x00 /* PLL Reduce Frecuency Devider */
/*----------------------------------------------------------------------*
@@ -135,7 +137,6 @@
#define CONFIG_SYS_FEC0_MIIBASE CONFIG_SYS_FEC0_IOBASE
#define MCFFEC_TOUT_LOOP 50000
-#define CONFIG_ETHADDR 00:CF:52:82:EB:01
#define CONFIG_OVERWRITE_ETHADDR_ONCE
/*-------------------------------------------------------------------------
@@ -151,7 +152,7 @@
*-----------------------------------------------------------------------*/
#define CONFIG_SYS_INIT_RAM_ADDR 0x20000000
-#define CONFIG_SYS_INIT_RAM_SIZE 0x10000
+#define CONFIG_SYS_INIT_RAM_SIZE 0x10000
#define CONFIG_SYS_GBL_DATA_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_GBL_DATA_OFFSET
@@ -161,12 +162,11 @@
* (Set up by the startup code)
* Please note that CONFIG_SYS_SDRAM_BASE _must_ start at 0
*/
-#define CONFIG_SYS_SDRAM_BASE1 0x00000000
-#define CONFIG_SYS_SDRAM_SIZE1 16 /* SDRAM size in MB */
-
-#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_SDRAM_BASE1
-#define CONFIG_SYS_SDRAM_SIZE CONFIG_SYS_SDRAM_SIZE1
+#define CONFIG_SYS_SDRAM_BASE0 0x00000000
+#define CONFIG_SYS_SDRAM_SIZE0 16 /* SDRAM size in MB */
+#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_SDRAM_BASE0
+#define CONFIG_SYS_SDRAM_SIZE CONFIG_SYS_SDRAM_SIZE0
/* If M5282 port is fully implemented the monitor base will be behind
* the vector table. */
@@ -190,16 +190,24 @@
/*-----------------------------------------------------------------------
* FLASH organization
*/
+#define CONFIG_FLASH_SHOW_PROGRESS 45
#define CONFIG_SYS_FLASH_BASE CONFIG_SYS_CS0_BASE
#define CONFIG_SYS_INT_FLASH_BASE 0xF0000000
#define CONFIG_SYS_INT_FLASH_ENABLE 0x21
-#define CONFIG_SYS_MAX_FLASH_SECT 35
-#define CONFIG_SYS_MAX_FLASH_BANKS 2
+#define CONFIG_SYS_MAX_FLASH_SECT 128
+#define CONFIG_SYS_MAX_FLASH_BANKS 1
#define CONFIG_SYS_FLASH_ERASE_TOUT 10000000
#define CONFIG_SYS_FLASH_PROTECTION
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_SIZE 16*1024*1024
+#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
+
+#define CONFIG_SYS_FLASH_BANKS_LIST { CONFIG_SYS_FLASH_BASE }
+
/*-----------------------------------------------------------------------
* Cache Configuration
*/
@@ -221,12 +229,16 @@
* Memory bank definitions
*/
-#define CONFIG_SYS_CS0_BASE 0xFFE00000
+#define CONFIG_SYS_CS0_BASE 0xFF000000
#define CONFIG_SYS_CS0_CTRL 0x00001980
-#define CONFIG_SYS_CS0_MASK 0x001F0001
+#define CONFIG_SYS_CS0_MASK 0x00FF0001
-#define CONFIG_SYS_CS3_BASE 0xE0000000
-#define CONFIG_SYS_CS0_CTRL 0x00001980
+#define CONFIG_SYS_CS2_BASE 0xE0000000
+#define CONFIG_SYS_CS2_CTRL 0x00001980
+#define CONFIG_SYS_CS2_MASK 0x000F0001
+
+#define CONFIG_SYS_CS3_BASE 0xE0100000
+#define CONFIG_SYS_CS3_CTRL 0x00001980
#define CONFIG_SYS_CS3_MASK 0x000F0001
/*-----------------------------------------------------------------------
@@ -248,24 +260,42 @@
#define CONFIG_SYS_PCDDR 0x0000000
#define CONFIG_SYS_PCDAT 0x0000000
+#define CONFIG_SYS_PASPAR 0x0F0F
#define CONFIG_SYS_PEHLPAR 0xC0
#define CONFIG_SYS_PUAPAR 0x0F
#define CONFIG_SYS_DDRUA 0x05
#define CONFIG_SYS_PJPAR 0xFF
/*-----------------------------------------------------------------------
+ * I2C
+ */
+
+#define CONFIG_HARD_I2C
+#define CONFIG_FSL_I2C
+
+#define CONFIG_SYS_I2C_OFFSET 0x00000300
+#define CONFIG_SYS_IMMR CONFIG_SYS_MBAR
+
+#define CONFIG_SYS_I2C_SPEED 100000
+#define CONFIG_SYS_I2C_SLAVE 0
+
+#ifdef CONFIG_CMD_DATE
+#define CONFIG_RTC_DS1338
+#define CONFIG_I2C_RTC_ADDR 0x68
+#endif
+
+/*-----------------------------------------------------------------------
* VIDEO configuration
*/
#define CONFIG_VIDEO
#ifdef CONFIG_VIDEO
-#define CONFIG_VIDEO_VCXK 1
+#define CONFIG_VIDEO_VCXK 1
#define CONFIG_SYS_VCXK_DEFAULT_LINEALIGN 2
#define CONFIG_SYS_VCXK_DOUBLEBUFFERED 1
-#define CONFIG_SYS_VCXK_BASE CONFIG_SYS_CS3_BASE
-#define CONFIG_SYS_VCXK_AUTODETECT 1
+#define CONFIG_SYS_VCXK_BASE CONFIG_SYS_CS2_BASE
#define CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT MCFGPTB_GPTPORT
#define CONFIG_SYS_VCXK_ACKNOWLEDGE_DDR MCFGPTB_GPTDDR
diff --git a/include/configs/hawkboard.h b/include/configs/hawkboard.h
index c0e3ed3efc..8d27590278 100644
--- a/include/configs/hawkboard.h
+++ b/include/configs/hawkboard.h
@@ -63,6 +63,9 @@
#define CONFIG_SPL_FRAMEWORK
#define CONFIG_SPL_BOARD_INIT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_NAND_SIMPLE
#define CONFIG_SPL_LIBGENERIC_SUPPORT /* for udelay and __div64_32 for NAND */
#define CONFIG_SPL_SERIAL_SUPPORT
diff --git a/include/configs/ib62x0.h b/include/configs/ib62x0.h
index 85856f290e..f646ae5776 100644
--- a/include/configs/ib62x0.h
+++ b/include/configs/ib62x0.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2011-2012
* Gerald Kerma <dreagle@doukki.net>
- * Luka Perkov <uboot@lukaperkov.net>
+ * Luka Perkov <luka@openwrt.org>
*
* See file CREDITS for list of people who contributed to this
* project.
diff --git a/include/configs/iconnect.h b/include/configs/iconnect.h
index 2b523c9fc9..ba57849a60 100644
--- a/include/configs/iconnect.h
+++ b/include/configs/iconnect.h
@@ -1,7 +1,7 @@
/*
* (C) Copyright 2009-2012
* Wojciech Dubowik <wojciech.dubowik@neratec.com>
- * Luka Perkov <uboot@lukaperkov.net>
+ * Luka Perkov <luka@openwrt.org>
*
* See file CREDITS for list of people who contributed to this
* project.
diff --git a/include/configs/igep00x0.h b/include/configs/igep00x0.h
index c81ab7622e..be7937d70e 100644
--- a/include/configs/igep00x0.h
+++ b/include/configs/igep00x0.h
@@ -338,6 +338,9 @@
#ifdef CONFIG_BOOT_NAND
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
/* NAND boot config */
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
diff --git a/include/configs/imx31_litekit.h b/include/configs/imx31_litekit.h
index 6ae764a2d4..8fc3942450 100644
--- a/include/configs/imx31_litekit.h
+++ b/include/configs/imx31_litekit.h
@@ -72,9 +72,9 @@
#define CONFIG_DEFAULT_SPI_MODE (SPI_MODE_0 | SPI_CS_HIGH)
/* PMIC Controller */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 1000000
diff --git a/include/configs/lwmon5.h b/include/configs/lwmon5.h
index 2d33ebcd71..2ebcd1615f 100644
--- a/include/configs/lwmon5.h
+++ b/include/configs/lwmon5.h
@@ -401,7 +401,6 @@
#define CONFIG_USB_EHCI /* Enable EHCI USB support */
#define CONFIG_USB_EHCI_PPC4XX /* on PPC4xx platform */
#define CONFIG_SYS_PPC4XX_USB_ADDR 0xe0000300
-#define CONFIG_EHCI_DCACHE /* with dcache handling support */
#define CONFIG_EHCI_MMIO_BIG_ENDIAN
#define CONFIG_EHCI_DESC_BIG_ENDIAN
#define CONFIG_EHCI_HCD_INIT_AFTER_RESET /* re-init HCD after CMD_RESET */
diff --git a/include/configs/mcx.h b/include/configs/mcx.h
index bf49cc1381..e304c99417 100644
--- a/include/configs/mcx.h
+++ b/include/configs/mcx.h
@@ -114,7 +114,6 @@
#define CONFIG_USB_EHCI_OMAP
#define CONFIG_USB_ULPI
#define CONFIG_USB_ULPI_VIEWPORT_OMAP
-/*#define CONFIG_EHCI_DCACHE*/ /* leave it disabled for now */
#define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 57
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3
@@ -379,6 +378,9 @@
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
#define CONFIG_SPL_TEXT_BASE 0x40200000 /*CONFIG_SYS_SRAM_START*/
diff --git a/include/configs/mx31ads.h b/include/configs/mx31ads.h
index 9d9f4a7822..9e4006b441 100644
--- a/include/configs/mx31ads.h
+++ b/include/configs/mx31ads.h
@@ -68,9 +68,9 @@
#define CONFIG_MXC_GPIO
/* PMIC Controller */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 1000000
diff --git a/include/configs/mx31pdk.h b/include/configs/mx31pdk.h
index 6572676970..138a941373 100644
--- a/include/configs/mx31pdk.h
+++ b/include/configs/mx31pdk.h
@@ -69,9 +69,9 @@
#define CONFIG_DEFAULT_SPI_MODE (SPI_MODE_0 | SPI_CS_HIGH)
/* PMIC Controller */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 2
#define CONFIG_FSL_PMIC_CLK 1000000
diff --git a/include/configs/mx35pdk.h b/include/configs/mx35pdk.h
index 1c2f5993d8..88b2bd6ed4 100644
--- a/include/configs/mx35pdk.h
+++ b/include/configs/mx35pdk.h
@@ -65,9 +65,9 @@
/*
* PMIC Configs
*/
-#define CONFIG_PMIC
-#define CONFIG_PMIC_I2C
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_FSL
#define CONFIG_PMIC_FSL_MC13892
#define CONFIG_SYS_FSL_PMIC_I2C_ADDR 0x08
#define CONFIG_RTC_MC13XXX
diff --git a/include/configs/mx51_efikamx.h b/include/configs/mx51_efikamx.h
index a056566efc..a74a0a71f1 100644
--- a/include/configs/mx51_efikamx.h
+++ b/include/configs/mx51_efikamx.h
@@ -127,9 +127,9 @@
#endif
/* SPI PMIC */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 0
#define CONFIG_FSL_PMIC_CS (0 | 120 << 8)
#define CONFIG_FSL_PMIC_CLK 25000000
diff --git a/include/configs/mx51evk.h b/include/configs/mx51evk.h
index 4e82355334..fa0db3824b 100644
--- a/include/configs/mx51evk.h
+++ b/include/configs/mx51evk.h
@@ -69,9 +69,9 @@
#define CONFIG_MXC_SPI
/* PMIC Controller */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 0
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 2500000
diff --git a/include/configs/mx53evk.h b/include/configs/mx53evk.h
index c472075c9a..a0af3eeb26 100644
--- a/include/configs/mx53evk.h
+++ b/include/configs/mx53evk.h
@@ -55,9 +55,9 @@
#define CONFIG_SYS_I2C_SPEED 100000
/* PMIC Configs */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_I2C
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_FSL
#define CONFIG_SYS_FSL_PMIC_I2C_ADDR 8
#define CONFIG_PMIC_FSL_MC13892
#define CONFIG_RTC_MC13XXX
diff --git a/include/configs/mx53loco.h b/include/configs/mx53loco.h
index 37f9d69e26..e30502b4e2 100644
--- a/include/configs/mx53loco.h
+++ b/include/configs/mx53loco.h
@@ -89,10 +89,10 @@
#define CONFIG_SYS_I2C_SPEED 100000
/* PMIC Controller */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_I2C
-#define CONFIG_DIALOG_PMIC
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_DIALOG_POWER
+#define CONFIG_POWER_FSL
#define CONFIG_PMIC_FSL_MC13892
#define CONFIG_SYS_DIALOG_PMIC_I2C_ADDR 0x48
#define CONFIG_SYS_FSL_PMIC_I2C_ADDR 0x8
diff --git a/include/configs/mx6qarm2.h b/include/configs/mx6qarm2.h
index 6ebdaa8768..138e460180 100644
--- a/include/configs/mx6qarm2.h
+++ b/include/configs/mx6qarm2.h
@@ -51,7 +51,7 @@
#define CONFIG_MMC
#define CONFIG_CMD_MMC
#define CONFIG_GENERIC_MMC
-#define CONFIG_MMC_BOUNCE_BUFFER
+#define CONFIG_BOUNCE_BUFFER
#define CONFIG_CMD_FAT
#define CONFIG_DOS_PARTITION
diff --git a/include/configs/mx6qsabre_common.h b/include/configs/mx6qsabre_common.h
index b8621b8e1c..0f226f790e 100644
--- a/include/configs/mx6qsabre_common.h
+++ b/include/configs/mx6qsabre_common.h
@@ -46,7 +46,7 @@
#define CONFIG_MMC
#define CONFIG_CMD_MMC
#define CONFIG_GENERIC_MMC
-#define CONFIG_MMC_BOUNCE_BUFFER
+#define CONFIG_BOUNCE_BUFFER
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_FAT
#define CONFIG_DOS_PARTITION
diff --git a/include/configs/mx6qsabrelite.h b/include/configs/mx6qsabrelite.h
index 759275a03a..4ce4d4c086 100644
--- a/include/configs/mx6qsabrelite.h
+++ b/include/configs/mx6qsabrelite.h
@@ -73,7 +73,7 @@
#define CONFIG_MMC
#define CONFIG_CMD_MMC
#define CONFIG_GENERIC_MMC
-#define CONFIG_MMC_BOUNCE_BUFFER
+#define CONFIG_BOUNCE_BUFFER
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_FAT
#define CONFIG_DOS_PARTITION
diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h
index 69ff3efb50..624bd5c7ee 100644
--- a/include/configs/nios2-generic.h
+++ b/include/configs/nios2-generic.h
@@ -68,6 +68,7 @@
#define CONFIG_SYS_ALTERA_PIO_GPIO_NUM LED_PIO_WIDTH
#define CONFIG_STATUS_LED /* Enable status driver */
+#define CONFIG_BOARD_SPECIFIC_LED
#define CONFIG_GPIO_LED /* Enable GPIO LED driver */
#define CONFIG_GPIO /* Enable GPIO driver */
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index 7a3cc16a09..12d65f2c4e 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -117,21 +117,19 @@
#define CONFIG_SYS_I2C_NOPROBES {{0x0, 0x0}}
/* USB */
-#define CONFIG_MUSB_UDC 1
-#define CONFIG_USB_OMAP3 1
+#define CONFIG_MUSB_GADGET
+#define CONFIG_USB_MUSB_OMAP2PLUS
+#define CONFIG_MUSB_PIO_ONLY
+#define CONFIG_USB_GADGET_DUALSPEED
#define CONFIG_TWL4030_USB 1
-
-/* USB device configuration */
-#define CONFIG_USB_DEVICE 1
-#define CONFIG_USB_TTY 1
-#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
+#define CONFIG_USB_ETHER
+#define CONFIG_USB_ETHER_RNDIS
/* USB EHCI */
#define CONFIG_CMD_USB
#define CONFIG_USB_EHCI
#define CONFIG_USB_EHCI_OMAP
-/*#define CONFIG_EHCI_DCACHE*/ /* leave it disabled for now */
#define CONFIG_OMAP_EHCI_PHY1_RESET_GPIO 147
#define CONFIG_USB_ULPI
@@ -414,6 +412,9 @@
#define CONFIG_SPL_FAT_SUPPORT
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_GPIO_SUPPORT
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_OMAP3_ID_NAND
diff --git a/include/configs/omap3_evm.h b/include/configs/omap3_evm.h
index f6e4236998..b4d925ed90 100644
--- a/include/configs/omap3_evm.h
+++ b/include/configs/omap3_evm.h
@@ -113,6 +113,9 @@
/* NAND SPL */
#define CONFIG_SPL_NAND_SIMPLE
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048
diff --git a/include/configs/omap3_evm_quick_nand.h b/include/configs/omap3_evm_quick_nand.h
index 362fa1d720..8f0258491e 100644
--- a/include/configs/omap3_evm_quick_nand.h
+++ b/include/configs/omap3_evm_quick_nand.h
@@ -81,6 +81,9 @@
*/
#define CONFIG_SPL_NAND_SIMPLE
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
#define CONFIG_SYS_NAND_PAGE_COUNT 64
#define CONFIG_SYS_NAND_PAGE_SIZE 2048
diff --git a/include/configs/omap3_overo.h b/include/configs/omap3_overo.h
index 626cf7afd5..fd31c73964 100644
--- a/include/configs/omap3_overo.h
+++ b/include/configs/omap3_overo.h
@@ -319,6 +319,9 @@
#define CONFIG_SPL_FAT_SUPPORT
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_GPIO_SUPPORT
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
diff --git a/include/configs/p1_p2_rdb_pc.h b/include/configs/p1_p2_rdb_pc.h
index 350150b115..964bfcd440 100644
--- a/include/configs/p1_p2_rdb_pc.h
+++ b/include/configs/p1_p2_rdb_pc.h
@@ -38,6 +38,7 @@
#define __SW_BOOT_MASK 0x03
#define __SW_BOOT_NOR 0xe4
#define __SW_BOOT_SD 0x54
+#define CONFIG_SYS_L2_SIZE (256 << 10)
#endif
#if defined(CONFIG_P1020UTM)
@@ -46,6 +47,7 @@
#define __SW_BOOT_MASK 0x03
#define __SW_BOOT_NOR 0xe0
#define __SW_BOOT_SD 0x50
+#define CONFIG_SYS_L2_SIZE (256 << 10)
#endif
#if defined(CONFIG_P1020RDB)
@@ -61,6 +63,7 @@
#define __SW_BOOT_SD 0x9c
#define __SW_BOOT_NAND 0xec
#define __SW_BOOT_PCIE 0x6c
+#define CONFIG_SYS_L2_SIZE (256 << 10)
#endif
#if defined(CONFIG_P1021RDB)
@@ -78,6 +81,7 @@
#define __SW_BOOT_SD 0x9c
#define __SW_BOOT_NAND 0xec
#define __SW_BOOT_PCIE 0x6c
+#define CONFIG_SYS_L2_SIZE (256 << 10)
#endif
#if defined(CONFIG_P1024RDB)
@@ -91,6 +95,7 @@
#define __SW_BOOT_SPI 0x08
#define __SW_BOOT_SD 0x04
#define __SW_BOOT_NAND 0x0c
+#define CONFIG_SYS_L2_SIZE (256 << 10)
#endif
#if defined(CONFIG_P1025RDB)
@@ -108,6 +113,7 @@
#define __SW_BOOT_SPI 0x08
#define __SW_BOOT_SD 0x04
#define __SW_BOOT_NAND 0x0c
+#define CONFIG_SYS_L2_SIZE (256 << 10)
#endif
#if defined(CONFIG_P2020RDB)
@@ -122,6 +128,14 @@
#define __SW_BOOT_SD 0x68 /* or 0x18 */
#define __SW_BOOT_NAND 0xe8
#define __SW_BOOT_PCIE 0xa8
+#define CONFIG_SYS_L2_SIZE (512 << 10)
+#endif
+
+#if CONFIG_SYS_L2_SIZE >= (512 << 10)
+/* must be 32-bit */
+#define CONFIG_SYS_INIT_L2_ADDR 0xf8f80000
+#define CONFIG_SYS_INIT_L2_ADDR_PHYS CONFIG_SYS_INIT_L2_ADDR
+#define CONFIG_SYS_INIT_L2_END (CONFIG_SYS_INIT_L2_ADDR + CONFIG_SYS_L2_SIZE)
#endif
#ifdef CONFIG_SDCARD
@@ -140,16 +154,39 @@
#define CONFIG_RESET_VECTOR_ADDRESS 0x1107fffc
#endif
-#if defined(CONFIG_NAND) && defined(CONFIG_NAND_FSL_ELBC)
-#define CONFIG_NAND_U_BOOT
-#define CONFIG_SYS_EXTRA_ENV_RELOC
-#define CONFIG_SYS_RAMBOOT
-#define CONFIG_SYS_TEXT_BASE_SPL 0xff800000
-#ifdef CONFIG_NAND_SPL
-#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE_SPL
+#ifdef CONFIG_NAND
+#define CONFIG_SPL
+#define CONFIG_SPL_INIT_MINIMAL
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_MINIMAL
+#define CONFIG_SPL_FLUSH_IMAGE
+#define CONFIG_SPL_TARGET "u-boot-with-spl.bin"
+
+#define CONFIG_SPL_TEXT_BASE 0xfffff000
+#define CONFIG_SPL_MAX_SIZE (4 * 1024)
+
+#ifdef CONFIG_SYS_INIT_L2_ADDR
+/* We multiply CONFIG_SPL_MAX_SIZE by two to leave some room for BSS. */
+#define CONFIG_SYS_TEXT_BASE 0xf8f82000
+#define CONFIG_SPL_RELOC_TEXT_BASE \
+ (CONFIG_SYS_INIT_L2_END - CONFIG_SPL_MAX_SIZE * 2)
+#define CONFIG_SPL_RELOC_STACK \
+ (CONFIG_SYS_INIT_L2_END - CONFIG_SPL_MAX_SIZE * 2)
+#define CONFIG_SYS_NAND_U_BOOT_DST (CONFIG_SYS_INIT_L2_ADDR)
+#define CONFIG_SYS_NAND_U_BOOT_START \
+ (CONFIG_SYS_INIT_L2_ADDR + CONFIG_SPL_MAX_SIZE)
#else
-#define CONFIG_SYS_TEXT_BASE 0x11001000
-#endif /* CONFIG_NAND_SPL */
+#define CONFIG_SYS_TEXT_BASE 0x00201000
+#define CONFIG_SPL_RELOC_TEXT_BASE 0x00100000
+#define CONFIG_SPL_RELOC_STACK 0x00100000
+#define CONFIG_SYS_NAND_U_BOOT_DST (0x00200000 - CONFIG_SPL_MAX_SIZE)
+#define CONFIG_SYS_NAND_U_BOOT_START 0x00200000
+#endif
+
+#define CONFIG_SYS_NAND_U_BOOT_SIZE ((512 << 10) - 0x2000)
+#define CONFIG_SYS_NAND_U_BOOT_OFFS 0
+#define CONFIG_SYS_LDSCRIPT "arch/powerpc/cpu/mpc85xx/u-boot-nand.lds"
#endif
#ifndef CONFIG_SYS_TEXT_BASE
@@ -161,8 +198,12 @@
#endif
#ifndef CONFIG_SYS_MONITOR_BASE
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MONITOR_BASE CONFIG_SPL_TEXT_BASE
+#else
#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE /* start of monitor */
#endif
+#endif
/* High Level Configuration Options */
#define CONFIG_BOOKE
@@ -221,7 +262,7 @@
/* IN case of NAND bootloader relocate CCSRBAR in RAMboot code not in the 4k
SPL code*/
-#if defined(CONFIG_NAND_SPL)
+#ifdef CONFIG_SPL_BUILD
#define CONFIG_SYS_CCSR_DO_NOT_RELOCATE
#endif
@@ -248,39 +289,7 @@
#define CONFIG_DIMM_SLOTS_PER_CTLR 1
/* Default settings for DDR3 */
-#ifdef CONFIG_P2020RDB
-#define CONFIG_SYS_DDR_CS0_BNDS 0x0000003f
-#define CONFIG_SYS_DDR_CS0_CONFIG 0x80014202
-#define CONFIG_SYS_DDR_CS0_CONFIG_2 0x00000000
-#define CONFIG_SYS_DDR_CS1_BNDS 0x00000000
-#define CONFIG_SYS_DDR_CS1_CONFIG 0x00000000
-#define CONFIG_SYS_DDR_CS1_CONFIG_2 0x00000000
-
-#define CONFIG_SYS_DDR_DATA_INIT 0xdeadbeef
-#define CONFIG_SYS_DDR_INIT_ADDR 0x00000000
-#define CONFIG_SYS_DDR_INIT_EXT_ADDR 0x00000000
-#define CONFIG_SYS_DDR_MODE_CONTROL 0x00000000
-
-#define CONFIG_SYS_DDR_ZQ_CONTROL 0x89080600
-#define CONFIG_SYS_DDR_WRLVL_CONTROL 0x8645F607
-#define CONFIG_SYS_DDR_SR_CNTR 0x00000000
-#define CONFIG_SYS_DDR_RCW_1 0x00000000
-#define CONFIG_SYS_DDR_RCW_2 0x00000000
-#define CONFIG_SYS_DDR_CONTROL 0xC7000000 /* Type = DDR3 */
-#define CONFIG_SYS_DDR_CONTROL_2 0x24401000
-#define CONFIG_SYS_DDR_TIMING_4 0x00220001
-#define CONFIG_SYS_DDR_TIMING_5 0x02401400
-
-#define CONFIG_SYS_DDR_TIMING_3 0x00020000
-#define CONFIG_SYS_DDR_TIMING_0 0x00330104
-#define CONFIG_SYS_DDR_TIMING_1 0x6f6B4644
-#define CONFIG_SYS_DDR_TIMING_2 0x0FA88CCF
-#define CONFIG_SYS_DDR_CLK_CTRL 0x02000000
-#define CONFIG_SYS_DDR_MODE_1 0x00421422
-#define CONFIG_SYS_DDR_MODE_2 0x04000000
-#define CONFIG_SYS_DDR_INTERVAL 0x0C300100
-
-#else
+#ifndef CONFIG_P2020RDB
#define CONFIG_SYS_DDR_CS0_BNDS 0x0000003f
#define CONFIG_SYS_DDR_CS0_CONFIG 0x80014302
#define CONFIG_SYS_DDR_CS0_CONFIG_2 0x00000000
@@ -318,21 +327,18 @@
/*
* Memory map
*
- * 0x0000_0000 0x7fff_ffff DDR Up to 2GB cacheable
+ * 0x0000_0000 0x7fff_ffff DDR Up to 2GB cacheable
* 0x8000_0000 0xdfff_ffff PCI Express Mem 1.5G non-cacheable(PCIe * 3)
+ * 0xec00_0000 0xefff_ffff NOR flash Up to 64M non-cacheable CS0/1
+ * 0xf8f8_0000 0xf8ff_ffff L2 SRAM Up to 512K cacheable
+ * (early boot only)
+ * 0xff80_0000 0xff80_7fff NAND flash 32K non-cacheable CS1/0
+ * 0xff98_0000 0xff98_ffff PMC 64K non-cacheable CS2
+ * 0xffa0_0000 0xffaf_ffff CPLD 1M non-cacheable CS3
+ * 0xffb0_0000 0xffbf_ffff VSC7385 switch 1M non-cacheable CS2
* 0xffc0_0000 0xffc3_ffff PCI IO range 256k non-cacheable
- *
- * Localbus cacheable (TBD)
- * 0xXXXX_XXXX 0xXXXX_XXXX SRAM YZ M Cacheable
- *
- * Localbus non-cacheable
- * 0xec00_0000 0xefff_ffff FLASH Up to 64M non-cacheable
- * 0xff80_0000 0xff8f_ffff NAND flash 1M non-cacheable
- * 0xff90_0000 0xff97_ffff L2 SDRAM(REV.) 512K cacheable(optional)
- * 0xffa0_0000 0xffaf_ffff CPLD 1M non-cacheable
- * 0xffb0_0000 0xffbf_ffff VSC7385 switch 1M non-cacheable
- * 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0
- * 0xffe0_0000 0xffef_ffff CCSR 1M non-cacheable
+ * 0xffd0_0000 0xffd0_3fff L1 for stack 16K cacheable
+ * 0xffe0_0000 0xffef_ffff CCSR 1M non-cacheable
*/
@@ -392,15 +398,6 @@
#define CONFIG_CMD_NAND
#define CONFIG_SYS_NAND_BLOCK_SIZE (16 * 1024)
-/* NAND boot: 4K NAND loader config */
-#define CONFIG_SYS_NAND_SPL_SIZE 0x1000
-#define CONFIG_SYS_NAND_U_BOOT_SIZE ((512 << 10) + CONFIG_SYS_NAND_SPL_SIZE)
-#define CONFIG_SYS_NAND_U_BOOT_DST (0x11000000 - CONFIG_SYS_NAND_SPL_SIZE)
-#define CONFIG_SYS_NAND_U_BOOT_START 0x11000000
-#define CONFIG_SYS_NAND_U_BOOT_OFFS (0)
-#define CONFIG_SYS_NAND_U_BOOT_RELOC 0x00010000
-#define CONFIG_SYS_NAND_U_BOOT_RELOC_SP (CONFIG_SYS_NAND_U_BOOT_RELOC + 0x10000)
-
#define CONFIG_SYS_NAND_BR_PRELIM (BR_PHYS_ADDR(CONFIG_SYS_NAND_BASE_PHYS) \
| (2<<BR_DECC_SHIFT) /* Use HW ECC */ \
| BR_PS_8 /* Port Size = 8 bit */ \
@@ -461,7 +458,7 @@
OR_GPCM_SCY | OR_GPCM_TRLX | OR_GPCM_EHTR | \
OR_GPCM_EAD)
-#ifdef CONFIG_NAND_U_BOOT
+#ifdef CONFIG_NAND
#define CONFIG_SYS_BR0_PRELIM CONFIG_SYS_NAND_BR_PRELIM /* NAND Base Addr */
#define CONFIG_SYS_OR0_PRELIM CONFIG_SYS_NAND_OR_PRELIM /* NAND Options */
#define CONFIG_SYS_BR1_PRELIM CONFIG_FLASH_BR_PRELIM /* NOR Base Address */
@@ -511,7 +508,7 @@
#define CONFIG_SYS_NS16550_SERIAL
#define CONFIG_SYS_NS16550_REG_SIZE 1
#define CONFIG_SYS_NS16550_CLK get_bus_freq(0)
-#ifdef CONFIG_NAND_SPL
+#ifdef CONFIG_SPL_BUILD
#define CONFIG_NS16550_MIN_FUNCTIONS
#endif
@@ -709,7 +706,6 @@
/*
* Environment
*/
-#ifdef CONFIG_SYS_RAMBOOT
#ifdef CONFIG_RAMBOOT_SPIFLASH
#define CONFIG_ENV_IS_IN_SPI_FLASH
#define CONFIG_ENV_SPI_BUS 0
@@ -724,16 +720,15 @@
#define CONFIG_FSL_FIXED_MMC_LOCATION
#define CONFIG_ENV_SIZE 0x2000
#define CONFIG_SYS_MMC_ENV_DEV 0
-#elif defined(CONFIG_NAND_U_BOOT)
+#elif defined(CONFIG_NAND)
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_SIZE CONFIG_SYS_NAND_BLOCK_SIZE
#define CONFIG_ENV_OFFSET ((512 * 1024) + CONFIG_SYS_NAND_BLOCK_SIZE)
#define CONFIG_ENV_RANGE (3 * CONFIG_ENV_SIZE)
-#else
+#elif defined(CONFIG_SYS_RAMBOOT)
#define CONFIG_ENV_IS_NOWHERE /* Store ENV in memory only */
#define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE - 0x1000)
#define CONFIG_ENV_SIZE 0x2000
-#endif
#else
#define CONFIG_ENV_IS_IN_FLASH
#if CONFIG_SYS_MONITOR_BASE > 0xfff80000
diff --git a/include/configs/qong.h b/include/configs/qong.h
index e43a02110e..d9bf2010b8 100644
--- a/include/configs/qong.h
+++ b/include/configs/qong.h
@@ -58,9 +58,9 @@
#define CONFIG_DEFAULT_SPI_MODE (SPI_MODE_0 | SPI_CS_HIGH)
#define CONFIG_RTC_MC13XXX
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 100000
diff --git a/include/configs/s5p_goni.h b/include/configs/s5p_goni.h
index 7e0b302935..56e83478f8 100644
--- a/include/configs/s5p_goni.h
+++ b/include/configs/s5p_goni.h
@@ -215,9 +215,9 @@
#define CONFIG_SYS_CACHELINE_SIZE 64
-#define CONFIG_PMIC
-#define CONFIG_PMIC_I2C
-#define CONFIG_PMIC_MAX8998
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_MAX8998
#include <asm/arch/gpio.h>
/*
diff --git a/include/configs/s5pc210_universal.h b/include/configs/s5pc210_universal.h
index 035c27fe94..eb13bb3a67 100644
--- a/include/configs/s5pc210_universal.h
+++ b/include/configs/s5pc210_universal.h
@@ -256,9 +256,9 @@
#define CONFIG_I2C_MULTI_BUS
#define CONFIG_SYS_MAX_I2C_BUS 7
-#define CONFIG_PMIC
-#define CONFIG_PMIC_I2C
-#define CONFIG_PMIC_MAX8998
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_MAX8998
#define CONFIG_USB_GADGET
#define CONFIG_USB_GADGET_S3C_UDC_OTG
diff --git a/include/configs/sc_sps_1.h b/include/configs/sc_sps_1.h
index f5dc393020..cb99d58644 100644
--- a/include/configs/sc_sps_1.h
+++ b/include/configs/sc_sps_1.h
@@ -140,7 +140,7 @@
#ifdef CONFIG_CMD_MMC
#define CONFIG_APBH_DMA
#define CONFIG_MMC
-#define CONFIG_MMC_BOUNCE_BUFFER
+#define CONFIG_BOUNCE_BUFFER
#define CONFIG_GENERIC_MMC
#define CONFIG_MXS_MMC
#endif
diff --git a/include/configs/seaboard.h b/include/configs/seaboard.h
index c2d1c66215..94116f116a 100644
--- a/include/configs/seaboard.h
+++ b/include/configs/seaboard.h
@@ -103,6 +103,9 @@
#define CONFIG_TEGRA_KEYBOARD
#define CONFIG_KEYBOARD
+/* USB keyboard */
+#define CONFIG_USB_KEYBOARD
+
#undef TEGRA_DEVICE_SETTINGS
#define TEGRA_DEVICE_SETTINGS "stdin=serial,tegra-kbc\0" \
"stdout=serial,lcd\0" \
diff --git a/include/configs/sequoia.h b/include/configs/sequoia.h
index 8e6954e3aa..dd5d7cd260 100644
--- a/include/configs/sequoia.h
+++ b/include/configs/sequoia.h
@@ -288,9 +288,6 @@
#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
#define CONFIG_EHCI_MMIO_BIG_ENDIAN
#define CONFIG_EHCI_DESC_BIG_ENDIAN
-#ifdef CONFIG_4xx_DCACHE
-#define CONFIG_EHCI_DCACHE
-#endif
#else /* CONFIG_USB_EHCI */
#define CONFIG_USB_OHCI_NEW
#define CONFIG_SYS_OHCI_BE_CONTROLLER
diff --git a/include/configs/tam3517-common.h b/include/configs/tam3517-common.h
index dd7757cb97..ee73c277b9 100644
--- a/include/configs/tam3517-common.h
+++ b/include/configs/tam3517-common.h
@@ -106,8 +106,6 @@
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3
#define CONFIG_USB_STORAGE
-/* #define CONFIG_EHCI_DCACHE */
-
/* commands to include */
#include <config_cmd_default.h>
@@ -254,6 +252,9 @@
#define CONFIG_SPL_GPIO_SUPPORT
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
#define CONFIG_SPL_TEXT_BASE 0x40200000 /*CONFIG_SYS_SRAM_START*/
diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h
index 2d0d61dc9d..ab62e7127d 100644
--- a/include/configs/tegra-common-post.h
+++ b/include/configs/tegra-common-post.h
@@ -146,6 +146,25 @@
"fdt_addr_r=0x02000000\0" \
"ramdisk_addr_r=0x02100000\0" \
+#ifdef CONFIG_TEGRA_KEYBOARD
+#define STDIN_KBD_KBC ",tegra-kbc"
+#else
+#define STDIN_KBD_KBC ""
+#endif
+
+#ifdef CONFIG_USB_KEYBOARD
+#define STDIN_KBD_USB ",usbkbd"
+#define CONFIG_SYS_USB_EVENT_POLL
+#define CONFIG_PREBOOT "usb start"
+#else
+#define STDIN_KBD_USB ""
+#endif
+
+#define TEGRA_DEVICE_SETTINGS \
+ "stdin=serial" STDIN_KBD_KBC STDIN_KBD_USB "\0" \
+ "stdout=serial\0" \
+ "stderr=serial\0" \
+
#define CONFIG_EXTRA_ENV_SETTINGS \
TEGRA_DEVICE_SETTINGS \
MEM_LAYOUT_ENV_SETTINGS \
diff --git a/include/configs/tegra20-common.h b/include/configs/tegra20-common.h
index 72b661a895..fe07f72260 100644
--- a/include/configs/tegra20-common.h
+++ b/include/configs/tegra20-common.h
@@ -103,7 +103,6 @@
*/
#define CONFIG_USB_EHCI_TXFIFO_THRESH 10
#define CONFIG_EHCI_IS_TDI
-#define CONFIG_EHCI_DCACHE
/* Total I2C ports on Tegra20 */
#define TEGRA_I2C_NUM_CONTROLLERS 4
@@ -128,12 +127,8 @@
#define CONFIG_SYS_NO_FLASH
-/* Environment information, boards can override if required */
#define CONFIG_CONSOLE_MUX
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
-#define TEGRA_DEVICE_SETTINGS "stdin=serial\0" \
- "stdout=serial\0" \
- "stderr=serial\0"
#define CONFIG_LOADADDR 0x408000 /* def. location for kernel */
#define CONFIG_BOOTDELAY 2 /* -1 to disable auto boot */
@@ -210,4 +205,7 @@
#define CONFIG_SYS_NAND_SELF_INIT
#define CONFIG_SYS_NAND_ONFI_DETECTION
+/* Misc utility code */
+#define CONFIG_BOUNCE_BUFFER
+
#endif /* __TEGRA20_COMMON_H */
diff --git a/include/configs/trats.h b/include/configs/trats.h
index a24e945313..78d7ea3e7e 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -239,10 +239,16 @@
#define CONFIG_SOFT_I2C_GPIO_SDA get_multi_sda_pin()
#define I2C_INIT multi_i2c_init()
-#define CONFIG_PMIC
-#define CONFIG_PMIC_I2C
-#define CONFIG_PMIC_MAX8997
-
+#define CONFIG_POWER
+#define CONFIG_POWER_I2C
+#define CONFIG_POWER_MAX8997
+
+#define CONFIG_POWER_FG
+#define CONFIG_POWER_FG_MAX17042
+#define CONFIG_POWER_MUIC
+#define CONFIG_POWER_MUIC_MAX8997
+#define CONFIG_POWER_BATTERY
+#define CONFIG_POWER_BATTERY_TRATS
#define CONFIG_USB_GADGET
#define CONFIG_USB_GADGET_S3C_UDC_OTG
#define CONFIG_USB_GADGET_DUALSPEED
diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h
index 5859a7337b..be0d2ec3c7 100644
--- a/include/configs/tricorder.h
+++ b/include/configs/tricorder.h
@@ -282,6 +282,9 @@
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_POWER_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_NAND_BASE
+#define CONFIG_SPL_NAND_DRIVERS
+#define CONFIG_SPL_NAND_ECC
#define CONFIG_SPL_MMC_SUPPORT
#define CONFIG_SPL_FAT_SUPPORT
#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/omap-common/u-boot-spl.lds"
diff --git a/include/configs/tt01.h b/include/configs/tt01.h
index f46efa55f1..9f8f240f82 100644
--- a/include/configs/tt01.h
+++ b/include/configs/tt01.h
@@ -149,9 +149,9 @@
#define CONFIG_MXC_GPIO
/* MC13783 connected to CSPI3 and SS0 */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 2
#define CONFIG_FSL_PMIC_CS 0
diff --git a/include/configs/vct.h b/include/configs/vct.h
index b4b0949522..7aeb66801e 100644
--- a/include/configs/vct.h
+++ b/include/configs/vct.h
@@ -136,7 +136,6 @@
*/
#define CONFIG_USB_EHCI /* Enable EHCI USB support */
#define CONFIG_USB_EHCI_VCT /* on VCT platform */
-#define CONFIG_EHCI_DCACHE /* with dcache handling support */
#define CONFIG_EHCI_MMIO_BIG_ENDIAN
#define CONFIG_EHCI_DESC_BIG_ENDIAN
#define CONFIG_EHCI_IS_TDI
diff --git a/include/configs/ventana.h b/include/configs/ventana.h
index 8f455221c9..b55ebc9bfc 100644
--- a/include/configs/ventana.h
+++ b/include/configs/ventana.h
@@ -78,6 +78,9 @@
#define CONFIG_CMD_NET
#define CONFIG_CMD_DHCP
+/* USB keyboard */
+#define CONFIG_USB_KEYBOARD
+
#include "tegra-common-post.h"
#endif /* __CONFIG_H */
diff --git a/include/configs/vision2.h b/include/configs/vision2.h
index 13c570299f..226d04901f 100644
--- a/include/configs/vision2.h
+++ b/include/configs/vision2.h
@@ -87,9 +87,9 @@
#define CONFIG_ENV_IS_IN_SPI_FLASH
/* PMIC Controller */
-#define CONFIG_PMIC
-#define CONFIG_PMIC_SPI
-#define CONFIG_PMIC_FSL
+#define CONFIG_POWER
+#define CONFIG_POWER_SPI
+#define CONFIG_POWER_FSL
#define CONFIG_FSL_PMIC_BUS 0
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 2500000
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 64e5cffe80..70d0e979d1 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -40,10 +40,12 @@
typedef u64 fdt_addr_t;
#define FDT_ADDR_T_NONE (-1ULL)
#define fdt_addr_to_cpu(reg) be64_to_cpu(reg)
+#define fdt_size_to_cpu(reg) be64_to_cpu(reg)
#else
typedef u32 fdt_addr_t;
#define FDT_ADDR_T_NONE (-1U)
#define fdt_addr_to_cpu(reg) be32_to_cpu(reg)
+#define fdt_size_to_cpu(reg) be32_to_cpu(reg)
#endif
/* Information obtained about memory from the FDT */
@@ -90,6 +92,22 @@ struct fdt_gpio_state {
#define fdt_gpio_isvalid(x) ((x)->gpio != FDT_GPIO_NONE)
/**
+ * Read the GPIO taking into account the polarity of the pin.
+ *
+ * @param gpio pointer to the decoded gpio
+ * @return value of the gpio if successful, < 0 if unsuccessful
+ */
+int fdtdec_get_gpio(struct fdt_gpio_state *gpio);
+
+/**
+ * Write the GPIO taking into account the polarity of the pin.
+ *
+ * @param gpio pointer to the decoded gpio
+ * @return 0 if successful
+ */
+int fdtdec_set_gpio(struct fdt_gpio_state *gpio, int val);
+
+/**
* Find the next numbered alias for a peripheral. This is used to enumerate
* all the peripherals of a certain type.
*
@@ -110,6 +128,19 @@ int fdtdec_next_alias(const void *blob, const char *name,
enum fdt_compat_id id, int *upto);
/**
+ * Find the compatible ID for a given node.
+ *
+ * Generally each node has at least one compatible string attached to it.
+ * This function looks through our list of known compatible strings and
+ * returns the corresponding ID which matches the compatible string.
+ *
+ * @param blob FDT blob to use
+ * @param node Node containing compatible string to find
+ * @return compatible ID, or COMPAT_UNKNOWN if we cannot find a match
+ */
+enum fdt_compat_id fdtdec_lookup(const void *blob, int node);
+
+/**
* Find the next compatible node for a peripheral.
*
* Do the first call with node = 0. This function will return a pointer to
@@ -169,6 +200,21 @@ s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
s32 default_val);
/**
+ * Look up a 64-bit integer property in a node and return it. The property
+ * must have at least 8 bytes of data (2 cells). The first two cells are
+ * concatenated to form a 8 bytes value, where the first cell is top half and
+ * the second cell is bottom half.
+ *
+ * @param blob FDT blob
+ * @param node node to examine
+ * @param prop_name name of property to find
+ * @param default_val default value to return if the property is not found
+ * @return integer value, if found, or default_val if not
+ */
+uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
+ uint64_t default_val);
+
+/**
* Checks whether a node is enabled.
* This looks for a 'status' property. If this exists, then returns 1 if
* the status is 'ok' and 0 otherwise. If there is no status property,
@@ -345,6 +391,22 @@ int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name,
struct fdt_gpio_state *gpio);
/**
+ * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with no
+ * terminating item.
+ *
+ * @param blob FDT blob to use
+ * @param node Node to look at
+ * @param prop_name Node property name
+ * @param gpio Array of gpio elements to fill from FDT. This will be
+ * untouched if either 0 or an error is returned
+ * @param max_count Maximum number of elements allowed
+ * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
+ * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing.
+ */
+int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name,
+ struct fdt_gpio_state *gpio, int max_count);
+
+/**
* Set up a GPIO pin according to the provided gpio information. At present this
* just requests the GPIO.
*
@@ -356,6 +418,39 @@ int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name,
*/
int fdtdec_setup_gpio(struct fdt_gpio_state *gpio);
+/**
+ * Look in the FDT for a config item with the given name and return its value
+ * as a 32-bit integer. The property must have at least 4 bytes of data. The
+ * value of the first cell is returned.
+ *
+ * @param blob FDT blob to use
+ * @param prop_name Node property name
+ * @param default_val default value to return if the property is not found
+ * @return integer value, if found, or default_val if not
+ */
+int fdtdec_get_config_int(const void *blob, const char *prop_name,
+ int default_val);
+
+/**
+ * Look in the FDT for a config item with the given name
+ * and return whether it exists.
+ *
+ * @param blob FDT blob
+ * @param prop_name property name to look up
+ * @return 1, if it exists, or 0 if not
+ */
+int fdtdec_get_config_bool(const void *blob, const char *prop_name);
+
+/**
+ * Look in the FDT for a config item with the given name and return its value
+ * as a string.
+ *
+ * @param blob FDT blob
+ * @param prop_name property name to look up
+ * @returns property string, NULL on error.
+ */
+char *fdtdec_get_config_string(const void *blob, const char *prop_name);
+
/*
* Look up a property in a node and return its contents in a byte
* array of given length. The property must have at least enough data for
@@ -387,4 +482,21 @@ int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
*/
const u8 *fdtdec_locate_byte_array(const void *blob, int node,
const char *prop_name, int count);
+
+/**
+ * Look up a property in a node which contains a memory region address and
+ * size. Then return a pointer to this address.
+ *
+ * The property must hold one address with a length. This is only tested on
+ * 32-bit machines.
+ *
+ * @param blob FDT blob
+ * @param node node to examine
+ * @param prop_name name of property to find
+ * @param ptrp returns pointer to region, or NULL if no address
+ * @param size returns size of region
+ * @return 0 if ok, -1 on error (propery not found)
+ */
+int fdtdec_decode_region(const void *blob, int node,
+ const char *prop_name, void **ptrp, size_t *size);
#endif
diff --git a/include/g_dnl.h b/include/g_dnl.h
index 0ec7440306..f47395f35d 100644
--- a/include/g_dnl.h
+++ b/include/g_dnl.h
@@ -22,7 +22,6 @@
#define __G_DOWNLOAD_H_
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <linux/usb/gadget.h>
int g_dnl_register(const char *s);
diff --git a/include/image.h b/include/image.h
index 0a895f2044..f54d983306 100644
--- a/include/image.h
+++ b/include/image.h
@@ -615,6 +615,7 @@ int fit_image_check_type(const void *fit, int noffset, uint8_t type);
int fit_image_check_comp(const void *fit, int noffset, uint8_t comp);
int fit_check_format(const void *fit);
+int fit_conf_find_compat(const void *fit, const void *fdt);
int fit_conf_get_node(const void *fit, const char *conf_uname);
int fit_conf_get_kernel_node(const void *fit, int noffset);
int fit_conf_get_ramdisk_node(const void *fit, int noffset);
diff --git a/include/lcd.h b/include/lcd.h
index 8f84741961..c24164a9de 100644
--- a/include/lcd.h
+++ b/include/lcd.h
@@ -302,6 +302,42 @@ void lcd_printf (const char *fmt, ...);
void lcd_clear(void);
int lcd_display_bitmap(ulong bmp_image, int x, int y);
+/**
+ * Get the width of the LCD in pixels
+ *
+ * @return width of LCD in pixels
+ */
+int lcd_get_pixel_width(void);
+
+/**
+ * Get the height of the LCD in pixels
+ *
+ * @return height of LCD in pixels
+ */
+int lcd_get_pixel_height(void);
+
+/**
+ * Get the number of text lines/rows on the LCD
+ *
+ * @return number of rows
+ */
+int lcd_get_screen_rows(void);
+
+/**
+ * Get the number of text columns on the LCD
+ *
+ * @return number of columns
+ */
+int lcd_get_screen_columns(void);
+
+/**
+ * Set the position of the text cursor
+ *
+ * @param col Column to place cursor (0 = left side)
+ * @param row Row to place cursor (0 = top line)
+ */
+void lcd_position_cursor(unsigned col, unsigned row);
+
/* Allow boards to customize the information displayed */
void lcd_show_board_info(void);
diff --git a/include/linux/byteorder/swab.h b/include/linux/byteorder/swab.h
index bb4a046937..4334fa77e3 100644
--- a/include/linux/byteorder/swab.h
+++ b/include/linux/byteorder/swab.h
@@ -122,7 +122,6 @@ static __inline__ void __swab32s(__u32 *addr)
__arch__swab32s(addr);
}
-#ifdef __BYTEORDER_HAS_U64__
static __inline__ __attribute__((const)) __u64 __fswab64(__u64 x)
{
# ifdef __SWAB_64_THRU_32__
@@ -141,7 +140,6 @@ static __inline__ void __swab64s(__u64 *addr)
{
__arch__swab64s(addr);
}
-#endif /* __BYTEORDER_HAS_U64__ */
#if defined(__KERNEL__)
#define swab16 __swab16
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index f63e04b634..e9e904523a 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -194,6 +194,9 @@ typedef enum {
/* Device behaves just like nand, but is readonly */
#define NAND_ROM 0x00000800
+/* Device supports subpage reads */
+#define NAND_SUBPAGE_READ 0x00001000
+
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS \
(NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
@@ -203,9 +206,7 @@ typedef enum {
#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
-/* Large page NAND with SOFT_ECC should support subpage reads */
-#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
- && (chip->page_shift > 9))
+#define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
/* Non chip related options */
/*
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index ce1d1e10ba..d1d732c283 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -28,15 +28,13 @@
* [c] for consistency, removing all doubt even when it appears to
* someone that the two other points are non-issues for that
* particular descriptor type.
- *
- * Ported to U-boot by: Thomas Smits <ts.smits@gmail.com> and
- * Remy Bohmer <linux@bohmer.net>
*/
#ifndef __LINUX_USB_CH9_H
#define __LINUX_USB_CH9_H
#include <linux/types.h> /* __u8 etc */
+#include <asm/byteorder.h> /* le16_to_cpu */
/*-------------------------------------------------------------------------*/
@@ -70,7 +68,7 @@
#define USB_RECIP_OTHER 0x03
/* From Wireless USB 1.0 */
#define USB_RECIP_PORT 0x04
-#define USB_RECIP_RPIPE 0x05
+#define USB_RECIP_RPIPE 0x05
/*
* Standard requests, for the bRequest field of a SETUP packet.
@@ -90,6 +88,8 @@
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
+#define USB_REQ_SET_SEL 0x30
+#define USB_REQ_SET_ISOCH_DELAY 0x31
#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */
#define USB_REQ_GET_ENCRYPTION 0x0E
@@ -105,10 +105,16 @@
#define USB_REQ_LOOPBACK_DATA_READ 0x16
#define USB_REQ_SET_INTERFACE_DS 0x17
+/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
+ * used by hubs to put ports into a new L1 suspend state, except that it
+ * forgot to define its number ...
+ */
+
/*
* USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
* are read as a bit array returned by USB_REQ_GET_STATUS. (So there
- * are at most sixteen features of each type.)
+ * are at most sixteen features of each type.) Hubs may also support a
+ * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
*/
#define USB_DEVICE_SELF_POWERED 0 /* (read only) */
#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */
@@ -120,8 +126,38 @@
#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */
#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */
+/*
+ * Test Mode Selectors
+ * See USB 2.0 spec Table 9-7
+ */
+#define TEST_J 1
+#define TEST_K 2
+#define TEST_SE0_NAK 3
+#define TEST_PACKET 4
+#define TEST_FORCE_EN 5
+
+/*
+ * New Feature Selectors as added by USB 3.0
+ * See USB 3.0 spec Table 9-6
+ */
+#define USB_DEVICE_U1_ENABLE 48 /* dev may initiate U1 transition */
+#define USB_DEVICE_U2_ENABLE 49 /* dev may initiate U2 transition */
+#define USB_DEVICE_LTM_ENABLE 50 /* dev may send LTM */
+#define USB_INTRF_FUNC_SUSPEND 0 /* function suspend */
+
+#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00
+/*
+ * Suspend Options, Table 9-7 USB 3.0 spec
+ */
+#define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0))
+#define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1))
+
#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */
+/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
+#define USB_DEV_STAT_U1_ENABLED 2 /* transition into U1 state */
+#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */
+#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */
/**
* struct usb_ctrlrequest - SETUP data for a USB device control request
@@ -140,10 +176,6 @@
* For most devices, interfaces don't coordinate with each other, so
* such requests may be made at any time.
*/
-#if defined(__BIG_ENDIAN) || defined(__ARMEB__)
-#error (functionality not verified for big endian targets, todo...)
-#endif
-
struct usb_ctrlrequest {
__u8 bRequestType;
__u8 bRequest;
@@ -159,8 +191,12 @@ struct usb_ctrlrequest {
* (rarely) accepted by SET_DESCRIPTOR.
*
* Note that all multi-byte values here are encoded in little endian
- * byte order "on the wire". But when exposed through Linux-USB APIs,
- * they've been converted to cpu byte order.
+ * byte order "on the wire". Within the kernel and when exposed
+ * through the Linux-USB APIs, they are not converted to cpu byte
+ * order; it is the responsibility of the client code to do this.
+ * The single exception is when device and configuration descriptors (but
+ * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD);
+ * in this case the fields are converted to host endianness by the kernel.
*/
/*
@@ -187,6 +223,11 @@ struct usb_ctrlrequest {
#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11
#define USB_DT_WIRE_ADAPTER 0x21
#define USB_DT_RPIPE 0x22
+#define USB_DT_CS_RADIO_CONTROL 0x23
+/* From the T10 UAS specification */
+#define USB_DT_PIPE_USAGE 0x24
+/* From the USB 3.0 spec */
+#define USB_DT_SS_ENDPOINT_COMP 0x30
/* Conventional codes for class-specific descriptors. The convention is
* defined in the USB "Common Class" Spec (3.11). Individual class specs
@@ -204,6 +245,28 @@ struct usb_descriptor_header {
__u8 bDescriptorType;
} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE: Device descriptor */
+struct usb_device_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __le16 bcdUSB;
+ __u8 bDeviceClass;
+ __u8 bDeviceSubClass;
+ __u8 bDeviceProtocol;
+ __u8 bMaxPacketSize0;
+ __le16 idVendor;
+ __le16 idProduct;
+ __le16 bcdDevice;
+ __u8 iManufacturer;
+ __u8 iProduct;
+ __u8 iSerialNumber;
+ __u8 bNumConfigurations;
+} __attribute__ ((packed));
+
#define USB_DT_DEVICE_SIZE 18
@@ -230,6 +293,8 @@ struct usb_descriptor_header {
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
+#define USB_SUBCLASS_VENDOR_SPEC 0xff
+
/*-------------------------------------------------------------------------*/
/* USB_DT_CONFIG: Configuration descriptor information.
@@ -260,11 +325,56 @@ struct usb_config_descriptor {
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_STRING: String descriptor */
+struct usb_string_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __le16 wData[1]; /* UTF-16LE encoded */
+} __attribute__ ((packed));
+
/* note that "string" zero is special, it holds language codes that
* the device supports, not Unicode characters.
*/
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE: Interface descriptor */
+struct usb_interface_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bInterfaceNumber;
+ __u8 bAlternateSetting;
+ __u8 bNumEndpoints;
+ __u8 bInterfaceClass;
+ __u8 bInterfaceSubClass;
+ __u8 bInterfaceProtocol;
+ __u8 iInterface;
+} __attribute__ ((packed));
+
#define USB_DT_INTERFACE_SIZE 9
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENDPOINT: Endpoint descriptor */
+struct usb_endpoint_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bEndpointAddress;
+ __u8 bmAttributes;
+ __le16 wMaxPacketSize;
+ __u8 bInterval;
+
+ /* NOTE: these two are _only_ in audio endpoints. */
+ /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
+ __u8 bRefresh;
+ __u8 bSynchAddress;
+} __attribute__ ((packed));
+
#define USB_DT_ENDPOINT_SIZE 7
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
@@ -282,6 +392,254 @@ struct usb_config_descriptor {
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
+/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
+#define USB_ENDPOINT_INTRTYPE 0x30
+#define USB_ENDPOINT_INTR_PERIODIC (0 << 4)
+#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
+
+#define USB_ENDPOINT_SYNCTYPE 0x0c
+#define USB_ENDPOINT_SYNC_NONE (0 << 2)
+#define USB_ENDPOINT_SYNC_ASYNC (1 << 2)
+#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2)
+#define USB_ENDPOINT_SYNC_SYNC (3 << 2)
+
+#define USB_ENDPOINT_USAGE_MASK 0x30
+#define USB_ENDPOINT_USAGE_DATA 0x00
+#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
+#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20 /* Implicit feedback Data endpoint */
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_endpoint_num - get the endpoint's number
+ * @epd: endpoint to be checked
+ *
+ * Returns @epd's number: 0 to 15.
+ */
+static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
+{
+ return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+}
+
+/**
+ * usb_endpoint_type - get the endpoint's transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
+ * to @epd's transfer type.
+ */
+static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
+{
+ return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+}
+
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_out(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_bulk(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_control - check if the endpoint has control transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type control, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_control(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_CONTROL);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_int(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_isoc(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_in(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_out(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_in(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_out(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_in(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_out(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_maxp - get endpoint's max packet size
+ * @epd: endpoint to be checked
+ *
+ * Returns @epd's max packet
+ */
+static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
+{
+ return __le16_to_cpu(epd->wMaxPacketSize);
+}
+
+static inline int usb_endpoint_interrupt_type(
+ const struct usb_endpoint_descriptor *epd)
+{
+ return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
+struct usb_ss_ep_comp_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bMaxBurst;
+ __u8 bmAttributes;
+ __le16 wBytesPerInterval;
+} __attribute__ ((packed));
+
+#define USB_DT_SS_EP_COMP_SIZE 6
+
+/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
+static inline int
+usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp)
+{
+ int max_streams;
+
+ if (!comp)
+ return 0;
+
+ max_streams = comp->bmAttributes & 0x1f;
+
+ if (!max_streams)
+ return 0;
+
+ max_streams = 1 << max_streams;
+
+ return max_streams;
+}
+
+/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
+#define USB_SS_MULT(p) (1 + ((p) & 0x3))
/*-------------------------------------------------------------------------*/
@@ -388,7 +746,7 @@ struct usb_encryption_descriptor {
/*-------------------------------------------------------------------------*/
-/* USB_DT_BOS: group of wireless capabilities */
+/* USB_DT_BOS: group of device-level capabilities */
struct usb_bos_descriptor {
__u8 bLength;
__u8 bDescriptorType;
@@ -397,6 +755,7 @@ struct usb_bos_descriptor {
__u8 bNumDeviceCaps;
} __attribute__((packed));
+#define USB_DT_BOS_SIZE 5
/*-------------------------------------------------------------------------*/
/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */
@@ -434,6 +793,61 @@ struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
__u8 bReserved;
} __attribute__((packed));
+/* USB 2.0 Extension descriptor */
+#define USB_CAP_TYPE_EXT 2
+
+struct usb_ext_cap_descriptor { /* Link Power Management */
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+ __le32 bmAttributes;
+#define USB_LPM_SUPPORT (1 << 1) /* supports LPM */
+#define USB_BESL_SUPPORT (1 << 2) /* supports BESL */
+#define USB_BESL_BASELINE_VALID (1 << 3) /* Baseline BESL valid*/
+#define USB_BESL_DEEP_VALID (1 << 4) /* Deep BESL valid */
+#define USB_GET_BESL_BASELINE(p) (((p) & (0xf << 8)) >> 8)
+#define USB_GET_BESL_DEEP(p) (((p) & (0xf << 12)) >> 12)
+} __attribute__((packed));
+
+#define USB_DT_USB_EXT_CAP_SIZE 7
+
+/*
+ * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
+ * specific device level capabilities
+ */
+#define USB_SS_CAP_TYPE 3
+struct usb_ss_cap_descriptor { /* Link Power Management */
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+ __u8 bmAttributes;
+#define USB_LTM_SUPPORT (1 << 1) /* supports LTM */
+ __le16 wSpeedSupported;
+#define USB_LOW_SPEED_OPERATION (1) /* Low speed operation */
+#define USB_FULL_SPEED_OPERATION (1 << 1) /* Full speed operation */
+#define USB_HIGH_SPEED_OPERATION (1 << 2) /* High speed operation */
+#define USB_5GBPS_OPERATION (1 << 3) /* Operation at 5Gbps */
+ __u8 bFunctionalitySupport;
+ __u8 bU1devExitLat;
+ __le16 bU2DevExitLat;
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CAP_SIZE 10
+
+/*
+ * Container ID Capability descriptor: Defines the instance unique ID used to
+ * identify the instance across all operating modes
+ */
+#define CONTAINER_ID_TYPE 4
+struct usb_ss_container_id_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDevCapabilityType;
+ __u8 bReserved;
+ __u8 ContainerID[16]; /* 128-bit number */
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CONTN_ID_SIZE 20
/*-------------------------------------------------------------------------*/
/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with
@@ -491,9 +905,22 @@ enum usb_device_speed {
USB_SPEED_UNKNOWN = 0, /* enumerating */
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
USB_SPEED_HIGH, /* usb 2.0 */
- USB_SPEED_VARIABLE, /* wireless (usb 2.5) */
+ USB_SPEED_WIRELESS, /* wireless (usb 2.5) */
+ USB_SPEED_SUPER, /* usb 3.0 */
};
+#ifdef __KERNEL__
+
+/**
+ * usb_speed_string() - Returns human readable-name of the speed.
+ * @speed: The speed to return human-readable name for. If it's not
+ * any of the speeds defined in usb_device_speed enum, string for
+ * USB_SPEED_UNKNOWN will be returned.
+ */
+extern const char *usb_speed_string(enum usb_device_speed speed);
+
+#endif
+
enum usb_device_state {
/* NOTATTACHED isn't in the USB spec, and this state acts
* the same as ATTACHED ... but it's clearer this way.
@@ -503,8 +930,8 @@ enum usb_device_state {
/* chapter 9 and authentication (wireless) device states */
USB_STATE_ATTACHED,
USB_STATE_POWERED, /* wired */
- USB_STATE_UNAUTHENTICATED, /* auth */
USB_STATE_RECONNECTING, /* auth */
+ USB_STATE_UNAUTHENTICATED, /* auth */
USB_STATE_DEFAULT, /* limited function */
USB_STATE_ADDRESS,
USB_STATE_CONFIGURED, /* most functions */
@@ -514,7 +941,64 @@ enum usb_device_state {
/* NOTE: there are actually four different SUSPENDED
* states, returning to POWERED, DEFAULT, ADDRESS, or
* CONFIGURED respectively when SOF tokens flow again.
+ * At this level there's no difference between L1 and L2
+ * suspend states. (L2 being original USB 1.1 suspend.)
*/
};
-#endif /* __LINUX_USB_CH9_H */
+enum usb3_link_state {
+ USB3_LPM_U0 = 0,
+ USB3_LPM_U1,
+ USB3_LPM_U2,
+ USB3_LPM_U3
+};
+
+/*
+ * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
+ * 0xff means the parent hub will accept transitions to U1, but will not
+ * initiate a transition.
+ *
+ * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
+ * U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved
+ * values.
+ *
+ * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
+ * 0xff means the parent hub will accept transitions to U2, but will not
+ * initiate a transition.
+ *
+ * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
+ * U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2
+ * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
+ * 65.024ms.
+ */
+#define USB3_LPM_DISABLED 0x0
+#define USB3_LPM_U1_MAX_TIMEOUT 0x7F
+#define USB3_LPM_U2_MAX_TIMEOUT 0xFE
+#define USB3_LPM_DEVICE_INITIATED 0xFF
+
+struct usb_set_sel_req {
+ __u8 u1_sel;
+ __u8 u1_pel;
+ __le16 u2_sel;
+ __le16 u2_pel;
+} __attribute__ ((packed));
+
+/*
+ * The Set System Exit Latency control transfer provides one byte each for
+ * U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each
+ * are two bytes long.
+ */
+#define USB3_LPM_MAX_U1_SEL_PEL 0xFF
+#define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * As per USB compliance update, a device that is actively drawing
+ * more than 100mA from USB must report itself as bus-powered in
+ * the GetStatus(DEVICE) call.
+ * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
+ */
+#define USB_SELF_POWER_VBUS_MAX_DRAW 100
+
+#endif /* __LINUX_USB_CH9_H */
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
new file mode 100644
index 0000000000..9f65ef96ac
--- /dev/null
+++ b/include/linux/usb/musb.h
@@ -0,0 +1,162 @@
+/*
+ * This is used to for host and peripheral modes of the driver for
+ * Inventra (Multidrop) Highspeed Dual-Role Controllers: (M)HDRC.
+ *
+ * Board initialization should put one of these into dev->platform_data,
+ * probably on some platform_device named "musb-hdrc". It encapsulates
+ * key configuration differences between boards.
+ */
+
+#ifndef __LINUX_USB_MUSB_H
+#define __LINUX_USB_MUSB_H
+
+#ifndef __deprecated
+#define __deprecated
+#endif
+
+/* The USB role is defined by the connector used on the board, so long as
+ * standards are being followed. (Developer boards sometimes won't.)
+ */
+enum musb_mode {
+ MUSB_UNDEFINED = 0,
+ MUSB_HOST, /* A or Mini-A connector */
+ MUSB_PERIPHERAL, /* B or Mini-B connector */
+ MUSB_OTG /* Mini-AB connector */
+};
+
+struct clk;
+
+enum musb_fifo_style {
+ FIFO_RXTX,
+ FIFO_TX,
+ FIFO_RX
+} __attribute__ ((packed));
+
+enum musb_buf_mode {
+ BUF_SINGLE,
+ BUF_DOUBLE
+} __attribute__ ((packed));
+
+struct musb_fifo_cfg {
+ u8 hw_ep_num;
+ enum musb_fifo_style style;
+ enum musb_buf_mode mode;
+ u16 maxpacket;
+};
+
+#define MUSB_EP_FIFO(ep, st, m, pkt) \
+{ \
+ .hw_ep_num = ep, \
+ .style = st, \
+ .mode = m, \
+ .maxpacket = pkt, \
+}
+
+#define MUSB_EP_FIFO_SINGLE(ep, st, pkt) \
+ MUSB_EP_FIFO(ep, st, BUF_SINGLE, pkt)
+
+#define MUSB_EP_FIFO_DOUBLE(ep, st, pkt) \
+ MUSB_EP_FIFO(ep, st, BUF_DOUBLE, pkt)
+
+struct musb_hdrc_eps_bits {
+ const char name[16];
+ u8 bits;
+};
+
+struct musb_hdrc_config {
+ struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */
+ unsigned fifo_cfg_size; /* size of the fifo configuration */
+
+ /* MUSB configuration-specific details */
+ unsigned multipoint:1; /* multipoint device */
+ unsigned dyn_fifo:1 __deprecated; /* supports dynamic fifo sizing */
+ unsigned soft_con:1 __deprecated; /* soft connect required */
+ unsigned utm_16:1 __deprecated; /* utm data witdh is 16 bits */
+ unsigned big_endian:1; /* true if CPU uses big-endian */
+ unsigned mult_bulk_tx:1; /* Tx ep required for multbulk pkts */
+ unsigned mult_bulk_rx:1; /* Rx ep required for multbulk pkts */
+ unsigned high_iso_tx:1; /* Tx ep required for HB iso */
+ unsigned high_iso_rx:1; /* Rx ep required for HD iso */
+ unsigned dma:1 __deprecated; /* supports DMA */
+ unsigned vendor_req:1 __deprecated; /* vendor registers required */
+
+ u8 num_eps; /* number of endpoints _with_ ep0 */
+ u8 dma_channels __deprecated; /* number of dma channels */
+ u8 dyn_fifo_size; /* dynamic size in bytes */
+ u8 vendor_ctrl __deprecated; /* vendor control reg width */
+ u8 vendor_stat __deprecated; /* vendor status reg witdh */
+ u8 dma_req_chan __deprecated; /* bitmask for required dma channels */
+ u8 ram_bits; /* ram address size */
+
+ struct musb_hdrc_eps_bits *eps_bits __deprecated;
+#ifdef CONFIG_BLACKFIN
+ /* A GPIO controlling VRSEL in Blackfin */
+ unsigned int gpio_vrsel;
+ unsigned int gpio_vrsel_active;
+ /* musb CLKIN in Blackfin in MHZ */
+ unsigned char clkin;
+#endif
+
+};
+
+struct musb_hdrc_platform_data {
+ /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */
+ u8 mode;
+
+ /* for clk_get() */
+ const char *clock;
+
+ /* (HOST or OTG) switch VBUS on/off */
+ int (*set_vbus)(struct device *dev, int is_on);
+
+ /* (HOST or OTG) mA/2 power supplied on (default = 8mA) */
+ u8 power;
+
+ /* (PERIPHERAL) mA/2 max power consumed (default = 100mA) */
+ u8 min_power;
+
+ /* (HOST or OTG) msec/2 after VBUS on till power good */
+ u8 potpgt;
+
+ /* (HOST or OTG) program PHY for external Vbus */
+ unsigned extvbus:1;
+
+ /* Power the device on or off */
+ int (*set_power)(int state);
+
+ /* MUSB configuration-specific details */
+ struct musb_hdrc_config *config;
+
+ /* Architecture specific board data */
+ void *board_data;
+
+ /* Platform specific struct musb_ops pointer */
+ const void *platform_ops;
+};
+
+
+/* TUSB 6010 support */
+
+#define TUSB6010_OSCCLK_60 16667 /* psec/clk @ 60.0 MHz */
+#define TUSB6010_REFCLK_24 41667 /* psec/clk @ 24.0 MHz XI */
+#define TUSB6010_REFCLK_19 52083 /* psec/clk @ 19.2 MHz CLKIN */
+
+#ifdef CONFIG_ARCH_OMAP2
+
+extern int __init tusb6010_setup_interface(
+ struct musb_hdrc_platform_data *data,
+ unsigned ps_refclk, unsigned waitpin,
+ unsigned async_cs, unsigned sync_cs,
+ unsigned irq, unsigned dmachan);
+
+extern int tusb6010_platform_retime(unsigned is_refclk);
+
+#endif /* OMAP2 */
+
+/*
+ * U-Boot specfic stuff
+ */
+int musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
+ void *ctl_regs);
+
+#endif /* __LINUX_USB_MUSB_H */
diff --git a/include/nand.h b/include/nand.h
index bbe28b20bb..dded4e27f0 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -139,6 +139,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
u_char *buffer, int flags);
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
+int nand_torture(nand_info_t *nand, loff_t offset);
#define NAND_LOCK_STATUS_TIGHT 0x01
#define NAND_LOCK_STATUS_UNLOCK 0x04
diff --git a/include/nios2.h b/include/nios2.h
index df8126a66e..cbca0dc01f 100644
--- a/include/nios2.h
+++ b/include/nios2.h
@@ -24,8 +24,6 @@
#ifndef __NIOS2_H__
#define __NIOS2_H__
-#include <linux/stringify.h>
-
/*------------------------------------------------------------------------
* Control registers -- use with wrctl() & rdctl()
*----------------------------------------------------------------------*/
@@ -39,14 +37,8 @@
* Access to control regs
*----------------------------------------------------------------------*/
-#define rdctl(reg)\
- ({unsigned int val;\
- asm volatile("rdctl %0, ctl" __stringify(reg) \
- : "=r" (val) ); val;})
-
-#define wrctl(reg,val)\
- asm volatile( "wrctl ctl" _str_(reg) ",%0"\
- : : "r" (val))
+#define rdctl(reg) __builtin_rdctl(reg)
+#define wrctl(reg, val) __builtin_wrctl(reg, val)
/*------------------------------------------------------------------------
* Control reg bit masks
diff --git a/include/pci.h b/include/pci.h
index eba122f8c0..15f583f069 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -67,7 +67,130 @@
#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
#define PCI_CLASS_DEVICE 0x0a /* Device class */
#define PCI_CLASS_CODE 0x0b /* Device class code */
+#define PCI_CLASS_CODE_TOO_OLD 0x00
+#define PCI_CLASS_CODE_STORAGE 0x01
+#define PCI_CLASS_CODE_NETWORK 0x02
+#define PCI_CLASS_CODE_DISPLAY 0x03
+#define PCI_CLASS_CODE_MULTIMEDIA 0x04
+#define PCI_CLASS_CODE_MEMORY 0x05
+#define PCI_CLASS_CODE_BRIDGE 0x06
+#define PCI_CLASS_CODE_COMM 0x07
+#define PCI_CLASS_CODE_PERIPHERAL 0x08
+#define PCI_CLASS_CODE_INPUT 0x09
+#define PCI_CLASS_CODE_DOCKING 0x0A
+#define PCI_CLASS_CODE_PROCESSOR 0x0B
+#define PCI_CLASS_CODE_SERIAL 0x0C
+#define PCI_CLASS_CODE_WIRELESS 0x0D
+#define PCI_CLASS_CODE_I2O 0x0E
+#define PCI_CLASS_CODE_SATELLITE 0x0F
+#define PCI_CLASS_CODE_CRYPTO 0x10
+#define PCI_CLASS_CODE_DATA 0x11
+/* Base Class 0x12 - 0xFE is reserved */
+#define PCI_CLASS_CODE_OTHER 0xFF
+
#define PCI_CLASS_SUB_CODE 0x0a /* Device sub-class code */
+#define PCI_CLASS_SUB_CODE_TOO_OLD_NOTVGA 0x00
+#define PCI_CLASS_SUB_CODE_TOO_OLD_VGA 0x01
+#define PCI_CLASS_SUB_CODE_STORAGE_SCSI 0x00
+#define PCI_CLASS_SUB_CODE_STORAGE_IDE 0x01
+#define PCI_CLASS_SUB_CODE_STORAGE_FLOPPY 0x02
+#define PCI_CLASS_SUB_CODE_STORAGE_IPIBUS 0x03
+#define PCI_CLASS_SUB_CODE_STORAGE_RAID 0x04
+#define PCI_CLASS_SUB_CODE_STORAGE_ATA 0x05
+#define PCI_CLASS_SUB_CODE_STORAGE_SATA 0x06
+#define PCI_CLASS_SUB_CODE_STORAGE_SAS 0x07
+#define PCI_CLASS_SUB_CODE_STORAGE_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_NETWORK_ETHERNET 0x00
+#define PCI_CLASS_SUB_CODE_NETWORK_TOKENRING 0x01
+#define PCI_CLASS_SUB_CODE_NETWORK_FDDI 0x02
+#define PCI_CLASS_SUB_CODE_NETWORK_ATM 0x03
+#define PCI_CLASS_SUB_CODE_NETWORK_ISDN 0x04
+#define PCI_CLASS_SUB_CODE_NETWORK_WORLDFIP 0x05
+#define PCI_CLASS_SUB_CODE_NETWORK_PICMG 0x06
+#define PCI_CLASS_SUB_CODE_NETWORK_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_DISPLAY_VGA 0x00
+#define PCI_CLASS_SUB_CODE_DISPLAY_XGA 0x01
+#define PCI_CLASS_SUB_CODE_DISPLAY_3D 0x02
+#define PCI_CLASS_SUB_CODE_DISPLAY_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_MULTIMEDIA_VIDEO 0x00
+#define PCI_CLASS_SUB_CODE_MULTIMEDIA_AUDIO 0x01
+#define PCI_CLASS_SUB_CODE_MULTIMEDIA_PHONE 0x02
+#define PCI_CLASS_SUB_CODE_MULTIMEDIA_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_MEMORY_RAM 0x00
+#define PCI_CLASS_SUB_CODE_MEMORY_FLASH 0x01
+#define PCI_CLASS_SUB_CODE_MEMORY_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_BRIDGE_HOST 0x00
+#define PCI_CLASS_SUB_CODE_BRIDGE_ISA 0x01
+#define PCI_CLASS_SUB_CODE_BRIDGE_EISA 0x02
+#define PCI_CLASS_SUB_CODE_BRIDGE_MCA 0x03
+#define PCI_CLASS_SUB_CODE_BRIDGE_PCI 0x04
+#define PCI_CLASS_SUB_CODE_BRIDGE_PCMCIA 0x05
+#define PCI_CLASS_SUB_CODE_BRIDGE_NUBUS 0x06
+#define PCI_CLASS_SUB_CODE_BRIDGE_CARDBUS 0x07
+#define PCI_CLASS_SUB_CODE_BRIDGE_RACEWAY 0x08
+#define PCI_CLASS_SUB_CODE_BRIDGE_SEMI_PCI 0x09
+#define PCI_CLASS_SUB_CODE_BRIDGE_INFINIBAND 0x0A
+#define PCI_CLASS_SUB_CODE_BRIDGE_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_COMM_SERIAL 0x00
+#define PCI_CLASS_SUB_CODE_COMM_PARALLEL 0x01
+#define PCI_CLASS_SUB_CODE_COMM_MULTIPORT 0x02
+#define PCI_CLASS_SUB_CODE_COMM_MODEM 0x03
+#define PCI_CLASS_SUB_CODE_COMM_GPIB 0x04
+#define PCI_CLASS_SUB_CODE_COMM_SMARTCARD 0x05
+#define PCI_CLASS_SUB_CODE_COMM_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_PERIPHERAL_PIC 0x00
+#define PCI_CLASS_SUB_CODE_PERIPHERAL_DMA 0x01
+#define PCI_CLASS_SUB_CODE_PERIPHERAL_TIMER 0x02
+#define PCI_CLASS_SUB_CODE_PERIPHERAL_RTC 0x03
+#define PCI_CLASS_SUB_CODE_PERIPHERAL_HOTPLUG 0x04
+#define PCI_CLASS_SUB_CODE_PERIPHERAL_SD 0x05
+#define PCI_CLASS_SUB_CODE_PERIPHERAL_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_INPUT_KEYBOARD 0x00
+#define PCI_CLASS_SUB_CODE_INPUT_DIGITIZER 0x01
+#define PCI_CLASS_SUB_CODE_INPUT_MOUSE 0x02
+#define PCI_CLASS_SUB_CODE_INPUT_SCANNER 0x03
+#define PCI_CLASS_SUB_CODE_INPUT_GAMEPORT 0x04
+#define PCI_CLASS_SUB_CODE_INPUT_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_DOCKING_GENERIC 0x00
+#define PCI_CLASS_SUB_CODE_DOCKING_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_PROCESSOR_386 0x00
+#define PCI_CLASS_SUB_CODE_PROCESSOR_486 0x01
+#define PCI_CLASS_SUB_CODE_PROCESSOR_PENTIUM 0x02
+#define PCI_CLASS_SUB_CODE_PROCESSOR_ALPHA 0x10
+#define PCI_CLASS_SUB_CODE_PROCESSOR_POWERPC 0x20
+#define PCI_CLASS_SUB_CODE_PROCESSOR_MIPS 0x30
+#define PCI_CLASS_SUB_CODE_PROCESSOR_COPROC 0x40
+#define PCI_CLASS_SUB_CODE_SERIAL_1394 0x00
+#define PCI_CLASS_SUB_CODE_SERIAL_ACCESSBUS 0x01
+#define PCI_CLASS_SUB_CODE_SERIAL_SSA 0x02
+#define PCI_CLASS_SUB_CODE_SERIAL_USB 0x03
+#define PCI_CLASS_SUB_CODE_SERIAL_FIBRECHAN 0x04
+#define PCI_CLASS_SUB_CODE_SERIAL_SMBUS 0x05
+#define PCI_CLASS_SUB_CODE_SERIAL_INFINIBAND 0x06
+#define PCI_CLASS_SUB_CODE_SERIAL_IPMI 0x07
+#define PCI_CLASS_SUB_CODE_SERIAL_SERCOS 0x08
+#define PCI_CLASS_SUB_CODE_SERIAL_CANBUS 0x09
+#define PCI_CLASS_SUB_CODE_WIRELESS_IRDA 0x00
+#define PCI_CLASS_SUB_CODE_WIRELESS_IR 0x01
+#define PCI_CLASS_SUB_CODE_WIRELESS_RF 0x10
+#define PCI_CLASS_SUB_CODE_WIRELESS_BLUETOOTH 0x11
+#define PCI_CLASS_SUB_CODE_WIRELESS_BROADBAND 0x12
+#define PCI_CLASS_SUB_CODE_WIRELESS_80211A 0x20
+#define PCI_CLASS_SUB_CODE_WIRELESS_80211B 0x21
+#define PCI_CLASS_SUB_CODE_WIRELESS_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_I2O_V1_0 0x00
+#define PCI_CLASS_SUB_CODE_SATELLITE_TV 0x01
+#define PCI_CLASS_SUB_CODE_SATELLITE_AUDIO 0x02
+#define PCI_CLASS_SUB_CODE_SATELLITE_VOICE 0x03
+#define PCI_CLASS_SUB_CODE_SATELLITE_DATA 0x04
+#define PCI_CLASS_SUB_CODE_CRYPTO_NETWORK 0x00
+#define PCI_CLASS_SUB_CODE_CRYPTO_ENTERTAINMENT 0x10
+#define PCI_CLASS_SUB_CODE_CRYPTO_OTHER 0x80
+#define PCI_CLASS_SUB_CODE_DATA_DPIO 0x00
+#define PCI_CLASS_SUB_CODE_DATA_PERFCNTR 0x01
+#define PCI_CLASS_SUB_CODE_DATA_COMMSYNC 0x10
+#define PCI_CLASS_SUB_CODE_DATA_MGMT 0x20
+#define PCI_CLASS_SUB_CODE_DATA_OTHER 0x80
#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
diff --git a/include/physmem.h b/include/physmem.h
new file mode 100644
index 0000000000..03d3a78b74
--- /dev/null
+++ b/include/physmem.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+/*
+ * These functions work like memset but operate on physical memory which may
+ * not be accessible directly.
+ *
+ * @param s The physical address to start setting memory at.
+ * @param c The character to set each byte of the region to.
+ * @param n The number of bytes to set.
+ *
+ * @return The physical address of the memory which was set.
+ */
+phys_addr_t arch_phys_memset(phys_addr_t s, int c, phys_size_t n);
diff --git a/drivers/misc/pmic_max8997.c b/include/power/battery.h
index 62dbc05311..e2fec687da 100644
--- a/drivers/misc/pmic_max8997.c
+++ b/include/power/battery.h
@@ -21,23 +21,18 @@
* MA 02111-1307 USA
*/
-#include <common.h>
-#include <pmic.h>
-#include <max8997_pmic.h>
+#ifndef __POWER_BATTERY_H_
+#define __POWER_BATTERY_H_
-int pmic_init(void)
-{
- struct pmic *p = get_pmic();
- static const char name[] = "MAX8997_PMIC";
+struct battery {
+ unsigned int version;
+ unsigned int state_of_chrg;
+ unsigned int time_to_empty;
+ unsigned int capacity;
+ unsigned int voltage_uV;
- puts("Board PMIC init\n");
+ unsigned int state;
+};
- p->name = name;
- p->interface = PMIC_I2C;
- p->number_of_regs = PMIC_NUM_OF_REGS;
- p->hw.i2c.addr = MAX8997_I2C_ADDR;
- p->hw.i2c.tx_num = 1;
- p->bus = I2C_PMIC;
-
- return 0;
-}
+int power_bat_init(unsigned char bus);
+#endif /* __POWER_BATTERY_H_ */
diff --git a/include/power/fg_battery_cell_params.h b/include/power/fg_battery_cell_params.h
new file mode 100644
index 0000000000..7ddf6f2ffa
--- /dev/null
+++ b/include/power/fg_battery_cell_params.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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 __FG_BATTERY_CELL_PARAMS_H_
+#define __FG_BATTERY_CELL_PARAMS_H_
+
+#if defined(CONFIG_POWER_FG_MAX17042) && defined(CONFIG_TRATS)
+
+/* Cell characteristics - Exynos4 TRATS development board */
+/* Shall be written to addr 0x80h */
+u16 cell_character0[16] = {
+ 0xA2A0,
+ 0xB6E0,
+ 0xB850,
+ 0xBAD0,
+ 0xBB20,
+ 0xBB70,
+ 0xBBC0,
+ 0xBC20,
+ 0xBC80,
+ 0xBCE0,
+ 0xBD80,
+ 0xBE20,
+ 0xC090,
+ 0xC420,
+ 0xC910,
+ 0xD070
+};
+
+/* Shall be written to addr 0x90h */
+u16 cell_character1[16] = {
+ 0x0090,
+ 0x1A50,
+ 0x02F0,
+ 0x2060,
+ 0x2060,
+ 0x2E60,
+ 0x26A0,
+ 0x2DB0,
+ 0x2DB0,
+ 0x1870,
+ 0x2A20,
+ 0x16F0,
+ 0x08F0,
+ 0x0D40,
+ 0x08C0,
+ 0x08C0
+};
+
+/* Shall be written to addr 0xA0h */
+u16 cell_character2[16] = {
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100,
+ 0x0100
+};
+#endif
+#endif /* __FG_BATTERY_CELL_PARAMS_H_ */
diff --git a/include/power/max17042_fg.h b/include/power/max17042_fg.h
new file mode 100644
index 0000000000..1103a483f2
--- /dev/null
+++ b/include/power/max17042_fg.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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 __MAX17042_FG_H_
+#define __MAX17042_FG_H_
+
+/* MAX 17042 registers */
+enum {
+ MAX17042_STATUS = 0x00,
+ MAX17042_SOCREP = 0x06,
+ MAX17042_VCELL = 0x09,
+ MAX17042_CURRENT = 0x0A,
+ MAX17042_AVG_CURRENT = 0x0B,
+ MAX17042_SOCMIX = 0x0D,
+ MAX17042_SOCAV = 0x0E,
+ MAX17042_DESIGN_CAP = 0x18,
+ MAX17042_AVG_VCELL = 0x19,
+ MAX17042_CONFIG = 0x1D,
+ MAX17042_VERSION = 0x21,
+ MAX17042_LEARNCFG = 0x28,
+ MAX17042_FILTERCFG = 0x29,
+ MAX17042_RELAXCFG = 0x2A,
+ MAX17042_MISCCFG = 0x2B,
+ MAX17042_CGAIN = 0x2E,
+ MAX17042_COFF = 0x2F,
+ MAX17042_RCOMP0 = 0x38,
+ MAX17042_TEMPCO = 0x39,
+ MAX17042_FSTAT = 0x3D,
+ MAX17042_MLOCKReg1 = 0x62,
+ MAX17042_MLOCKReg2 = 0x63,
+ MAX17042_MODEL1 = 0x80,
+ MAX17042_MODEL2 = 0x90,
+ MAX17042_MODEL3 = 0xA0,
+ MAX17042_VFOCV = 0xFB,
+ MAX17042_VFSOC = 0xFF,
+
+ FG_NUM_OF_REGS = 0x100,
+};
+
+#define RCOMP0 0x0060
+#define TempCo 0x1015
+
+
+#define MAX17042_POR (1 << 1)
+
+#define MODEL_UNLOCK1 0x0059
+#define MODEL_UNLOCK2 0x00c4
+#define MODEL_LOCK1 0x0000
+#define MODEL_LOCK2 0x0000
+
+#define MAX17042_I2C_ADDR (0x6C >> 1)
+
+int power_fg_init(unsigned char bus);
+#endif /* __MAX17042_FG_H_ */
diff --git a/include/power/max8997_muic.h b/include/power/max8997_muic.h
new file mode 100644
index 0000000000..0149c12435
--- /dev/null
+++ b/include/power/max8997_muic.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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 __MAX8997_MUIC_H_
+#define __MAX8997_MUIC_H_
+
+#include <power/power_chrg.h>
+
+/* MAX8997_MUIC_STATUS2 */
+#define MAX8997_MUIC_CHG_NO 0x00
+#define MAX8997_MUIC_CHG_USB 0x01
+#define MAX8997_MUIC_CHG_USB_D 0x02
+#define MAX8997_MUIC_CHG_TA 0x03
+#define MAX8997_MUIC_CHG_TA_500 0x04
+#define MAX8997_MUIC_CHG_TA_1A 0x05
+#define MAX8997_MUIC_CHG_MASK 0x07
+
+/* MAX 8997 MUIC registers */
+enum {
+ MAX8997_MUIC_ID = 0x00,
+ MAX8997_MUIC_INT1 = 0x01,
+ MAX8997_MUIC_INT2 = 0x02,
+ MAX8997_MUIC_INT3 = 0x03,
+ MAX8997_MUIC_STATUS1 = 0x04,
+ MAX8997_MUIC_STATUS2 = 0x05,
+ MAX8997_MUIC_STATUS3 = 0x06,
+ MAX8997_MUIC_INTMASK1 = 0x07,
+ MAX8997_MUIC_INTMASK2 = 0x08,
+ MAX8997_MUIC_INTMASK3 = 0x09,
+ MAX8997_MUIC_CDETCTRL = 0x0A,
+ MAX8997_MUIC_CONTROL1 = 0x0C,
+ MAX8997_MUIC_CONTROL2 = 0x0D,
+ MAX8997_MUIC_CONTROL3 = 0x0E,
+
+ MUIC_NUM_OF_REGS = 0x0F,
+};
+
+#define MAX8997_MUIC_I2C_ADDR (0x4A >> 1)
+
+int power_muic_init(unsigned int bus);
+#endif /* __MAX8997_MUIC_H_ */
diff --git a/include/max8997_pmic.h b/include/power/max8997_pmic.h
index 17ae24ea6a..5d2d94df9b 100644
--- a/include/max8997_pmic.h
+++ b/include/power/max8997_pmic.h
@@ -111,7 +111,7 @@ enum {
MAX8997_REG_MBCCTRL6 = 0x55,
MAX8997_REG_OTPCGHCVS = 0x56,
- MAX8997_REG_SAFEOUTCTRL = 0x5a,
+ MAX8997_REG_SAFEOUTCTRL = 0x5a,
MAX8997_REG_LBCNFG1 = 0x5e,
MAX8997_REG_LBCNFG2 = 0x5f,
@@ -171,9 +171,31 @@ enum {
PMIC_NUM_OF_REGS = 0x9b,
};
+#define ACTDISSAFEO1 (1 << 4)
+#define ACTDISSAFEO2 (1 << 5)
#define ENSAFEOUT1 (1 << 6)
#define ENSAFEOUT2 (1 << 7)
+#define ENBUCK (1 << 0)
+#define ACTIVE_DISCHARGE (1 << 3)
+#define GNSLCT (1 << 2)
+#define LDO_ADE (1 << 1)
+#define SAFEOUT_4_85V 0x00
+#define SAFEOUT_4_90V 0x01
+#define SAFEOUT_4_95V 0x02
+#define SAFEOUT_3_30V 0x03
+
+/* Charger */
+enum {CHARGER_ENABLE, CHARGER_DISABLE};
+#define DETBAT (1 << 2)
+#define MBCICHFCSET (1 << 4)
+#define MBCHOSTEN (1 << 6)
+#define VCHGR_FC (1 << 7)
+
+#define CHARGER_MIN_CURRENT 200
+#define CHARGER_MAX_CURRENT 950
+#define CHARGER_CURRENT_RESOLUTION 50
+
#define MAX8997_I2C_ADDR (0xCC >> 1)
#define MAX8997_RTC_ADDR (0x0C >> 1)
#define MAX8997_MUIC_ADDR (0x4A >> 1)
@@ -187,4 +209,6 @@ enum {
EN_LDO = (0x3 << 6),
};
+#define MAX8997_LDO_MAX_VAL 0x3F
+unsigned char max8997_reg_ldo(int uV);
#endif /* __MAX8997_PMIC_H_ */
diff --git a/include/max8998_pmic.h b/include/power/max8998_pmic.h
index 0e559f986a..0e559f986a 100644
--- a/include/max8998_pmic.h
+++ b/include/power/max8998_pmic.h
diff --git a/include/pmic.h b/include/power/pmic.h
index 6a05b40aef..1ecfc0543c 100644
--- a/include/pmic.h
+++ b/include/power/pmic.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Samsung Electronics
+ * Copyright (C) 2011-2012 Samsung Electronics
* Lukasz Majewski <l.majewski@samsung.com>
*
* See file CREDITS for list of people who contributed to this
@@ -24,9 +24,15 @@
#ifndef __CORE_PMIC_H_
#define __CORE_PMIC_H_
-enum { PMIC_I2C, PMIC_SPI, };
+#include <common.h>
+#include <linux/list.h>
+#include <i2c.h>
+#include <power/power_chrg.h>
+
+enum { PMIC_I2C, PMIC_SPI, PMIC_NONE};
enum { I2C_PMIC, I2C_NUM, };
enum { PMIC_READ, PMIC_WRITE, };
+enum { PMIC_SENSOR_BYTE_ORDER_LITTLE, PMIC_SENSOR_BYTE_ORDER_BIG, };
struct p_i2c {
unsigned char addr;
@@ -43,21 +49,52 @@ struct p_spi {
u32 (*prepare_tx)(u32 reg, u32 *val, u32 write);
};
+struct pmic;
+struct power_fg {
+ int (*fg_battery_check) (struct pmic *p, struct pmic *bat);
+ int (*fg_battery_update) (struct pmic *p, struct pmic *bat);
+};
+
+struct power_chrg {
+ int (*chrg_type) (struct pmic *p);
+ int (*chrg_bat_present) (struct pmic *p);
+ int (*chrg_state) (struct pmic *p, int state, int current);
+};
+
+struct power_battery {
+ struct battery *bat;
+ int (*battery_init) (struct pmic *bat, struct pmic *p1,
+ struct pmic *p2, struct pmic *p3);
+ int (*battery_charge) (struct pmic *bat);
+ /* Keep info about power devices involved with battery operation */
+ struct pmic *chrg, *fg, *muic;
+};
+
struct pmic {
const char *name;
unsigned char bus;
unsigned char interface;
- unsigned char number_of_regs;
+ unsigned char sensor_byte_order;
+ unsigned int number_of_regs;
union hw {
struct p_i2c i2c;
struct p_spi spi;
} hw;
+
+ void (*low_power_mode) (void);
+ struct power_battery *pbat;
+ struct power_chrg *chrg;
+ struct power_fg *fg;
+
+ struct pmic *parent;
+ struct list_head list;
};
-int pmic_init(void);
-int pmic_dialog_init(void);
-int check_reg(u32 reg);
-struct pmic *get_pmic(void);
+int pmic_init(unsigned char bus);
+int pmic_dialog_init(unsigned char bus);
+int check_reg(struct pmic *p, u32 reg);
+struct pmic *pmic_alloc(void);
+struct pmic *pmic_get(const char *s);
int pmic_probe(struct pmic *p);
int pmic_reg_read(struct pmic *p, u32 reg, u32 *val);
int pmic_reg_write(struct pmic *p, u32 reg, u32 val);
diff --git a/nand_spl/board/freescale/common.c b/include/power/power_chrg.h
index 0e099bc7c6..24c4cde739 100644
--- a/nand_spl/board/freescale/common.c
+++ b/include/power/power_chrg.h
@@ -1,6 +1,9 @@
/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Author: Matthew McClintock <msm@freescale.com>
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.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
@@ -10,31 +13,31 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public 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>
-
-DECLARE_GLOBAL_DATA_PTR;
+#ifndef __POWER_CHARGER_H_
+#define __POWER_CHARGER_H_
-#ifndef CONFIG_SYS_FSL_TBCLK_DIV
-#define CONFIG_SYS_FSL_TBCLK_DIV 8
-#endif
+/* Type of available chargers */
+enum {
+ CHARGER_NO = 0,
+ CHARGER_TA,
+ CHARGER_USB,
+ CHARGER_TA_500,
+ CHARGER_UNKNOWN,
+};
-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);
+enum {
+ UNKNOWN,
+ EXT_SOURCE,
+ CHARGE,
+ NORMAL,
+};
- while ((mfspr(SPRN_TBRL) - s) < ticks);
-}
+#endif /* __POWER_CHARGER_H_ */
diff --git a/include/sdhci.h b/include/sdhci.h
index c44793d5ec..cffbe53621 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -225,6 +225,7 @@
#define SDHCI_QUIRK_BROKEN_VOLTAGE (1 << 4)
#define SDHCI_QUIRK_NO_CD (1 << 5)
#define SDHCI_QUIRK_WAIT_SEND_CMD (1 << 6)
+#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 7)
/* to make gcc happy */
struct sdhci_host;
diff --git a/include/status_led.h b/include/status_led.h
index da9fae9203..27e9127694 100644
--- a/include/status_led.h
+++ b/include/status_led.h
@@ -273,9 +273,6 @@ void status_led_set (int led, int state);
#elif defined(CONFIG_STXXTC)
/* XXX empty just to avoid the error */
/************************************************************************/
-#elif defined(CONFIG_NIOS2)
-/* XXX empty just to avoid the error */
-/************************************************************************/
#elif defined(CONFIG_V38B)
# define STATUS_LED_BIT 0x0010 /* Timer7 GPIO */
diff --git a/include/stdio_dev.h b/include/stdio_dev.h
index 23e0ee15f2..932d093345 100644
--- a/include/stdio_dev.h
+++ b/include/stdio_dev.h
@@ -120,5 +120,8 @@ int drv_nc_init (void);
#ifdef CONFIG_JTAG_CONSOLE
int drv_jtag_console_init (void);
#endif
+#ifdef CONFIG_CBMEM_CONSOLE
+int cbmemc_init(void);
+#endif
#endif
diff --git a/include/usb.h b/include/usb.h
index 9dd8791947..8d8a2c9b9d 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -27,7 +27,7 @@
#define _USB_H_
#include <usb_defs.h>
-#include <usbdescriptors.h>
+#include <linux/usb/ch9.h>
/*
* The EHCI spec says that we must align to at least 32 bytes. However,
@@ -67,12 +67,6 @@ struct devrequest {
unsigned short length;
} __attribute__ ((packed));
-/* All standard descriptors have these 2 fields in common */
-struct usb_descriptor_header {
- unsigned char bLength;
- unsigned char bDescriptorType;
-} __attribute__ ((packed));
-
/* Interface */
struct usb_interface {
struct usb_interface_descriptor desc;
@@ -86,7 +80,7 @@ struct usb_interface {
/* Configuration information.. */
struct usb_config {
- struct usb_configuration_descriptor desc;
+ struct usb_config_descriptor desc;
unsigned char no_of_if; /* number of interfaces */
struct usb_interface if_desc[USB_MAXINTERFACES];
@@ -153,7 +147,9 @@ struct usb_device {
defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \
defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI) || \
defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \
- defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X)
+ defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X) || \
+ defined(CONFIG_USB_MUSB_DSPS) || defined(CONFIG_USB_MUSB_AM35X) || \
+ defined(CONFIG_USB_MUSB_OMAP2PLUS)
int usb_lowlevel_init(int index, void **controller);
int usb_lowlevel_stop(int index);
@@ -285,7 +281,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
* - device: bits 8-14
* - endpoint: bits 15-18
* - Data0/1: bit 19
- * - speed: bit 26 (0 = Full, 1 = Low Speed, 2 = High)
* - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt,
* 10 = control, 11 = bulk)
*
@@ -297,7 +292,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
/* Create various pipes... */
#define create_pipe(dev,endpoint) \
(((dev)->devnum << 8) | ((endpoint) << 15) | \
- ((dev)->speed << 26) | (dev)->maxpacketsize)
+ (dev)->maxpacketsize)
#define default_pipe(dev) ((dev)->speed << 26)
#define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \
@@ -348,8 +343,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
#define usb_pipedata(pipe) (((pipe) >> 19) & 1)
-#define usb_pipespeed(pipe) (((pipe) >> 26) & 3)
-#define usb_pipeslow(pipe) (usb_pipespeed(pipe) == USB_SPEED_LOW)
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT)
diff --git a/include/usb/s3c_udc.h b/include/usb/s3c_udc.h
index 6a8fd44244..7114dae75d 100644
--- a/include/usb/s3c_udc.h
+++ b/include/usb/s3c_udc.h
@@ -24,7 +24,6 @@
#include <asm/errno.h>
#include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
#include <linux/usb/gadget.h>
#include <linux/list.h>
#include <usb/lin_gadget_compat.h>
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 8032e57125..9502544b21 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -80,12 +80,6 @@
#define USB_DIR_OUT 0
#define USB_DIR_IN 0x80
-/* USB device speeds */
-#define USB_SPEED_FULL 0x0 /* 12Mbps */
-#define USB_SPEED_LOW 0x1 /* 1.5Mbps */
-#define USB_SPEED_HIGH 0x2 /* 480Mbps */
-#define USB_SPEED_RESERVED 0x3
-
/* Descriptor types */
#define USB_DT_DEVICE 0x01
#define USB_DT_CONFIG 0x02
diff --git a/include/video.h b/include/video.h
index 9519ceaf98..f7e27f8477 100644
--- a/include/video.h
+++ b/include/video.h
@@ -15,4 +15,52 @@ int video_init (void *videobase);
void video_putc (const char c);
void video_puts (const char *s);
+/**
+ * Display a BMP format bitmap on the screen
+ *
+ * @param bmp_image Address of BMP image
+ * @param x X position to draw image
+ * @param y Y position to draw image
+ */
+int video_display_bitmap(ulong bmp_image, int x, int y);
+
+/**
+ * Get the width of the screen in pixels
+ *
+ * @return width of screen in pixels
+ */
+int video_get_pixel_width(void);
+
+/**
+ * Get the height of the screen in pixels
+ *
+ * @return height of screen in pixels
+ */
+int video_get_pixel_height(void);
+
+/**
+ * Get the number of text lines/rows on the screen
+ *
+ * @return number of rows
+ */
+int video_get_screen_rows(void);
+
+/**
+ * Get the number of text columns on the screen
+ *
+ * @return number of columns
+ */
+int video_get_screen_columns(void);
+
+/**
+ * Set the position of the text cursor
+ *
+ * @param col Column to place cursor (0 = left side)
+ * @param row Row to place cursor (0 = top line)
+ */
+void video_position_cursor(unsigned col, unsigned row);
+
+/* Clear the display */
+void video_clear(void);
+
#endif
diff --git a/lib/Makefile b/lib/Makefile
index e44e045233..f83f6e8d8c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -48,6 +48,7 @@ COBJS-$(CONFIG_LMB) += lmb.o
COBJS-y += ldiv.o
COBJS-$(CONFIG_MD5) += md5.o
COBJS-y += net_utils.o
+COBJS-$(CONFIG_PHYSMEM) += physmem.o
COBJS-y += qsort.o
COBJS-$(CONFIG_SHA1) += sha1.o
COBJS-$(CONFIG_SHA256) += sha256.o
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 23e0205721..6dba4389f2 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -54,28 +54,6 @@ const char *fdtdec_get_compatible(enum fdt_compat_id id)
return compat_names[id];
}
-/**
- * Look in the FDT for an alias with the given name and return its node.
- *
- * @param blob FDT blob
- * @param name alias name to look up
- * @return node offset if found, or an error code < 0 otherwise
- */
-static int find_alias_node(const void *blob, const char *name)
-{
- const char *path;
- int alias_node;
-
- debug("find_alias_node: %s\n", name);
- alias_node = fdt_path_offset(blob, "/aliases");
- if (alias_node < 0)
- return alias_node;
- path = fdt_getprop(blob, alias_node, name, NULL);
- if (!path)
- return -FDT_ERR_NOTFOUND;
- return fdt_path_offset(blob, path);
-}
-
fdt_addr_t fdtdec_get_addr(const void *blob, int node,
const char *prop_name)
{
@@ -113,6 +91,19 @@ s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
return default_val;
}
+uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
+ uint64_t default_val)
+{
+ const uint64_t *cell64;
+ int length;
+
+ cell64 = fdt_getprop(blob, node, prop_name, &length);
+ if (!cell64 || length < sizeof(*cell64))
+ return default_val;
+
+ return fdt64_to_cpu(*cell64);
+}
+
int fdtdec_get_is_enabled(const void *blob, int node)
{
const char *cell;
@@ -130,7 +121,7 @@ int fdtdec_get_is_enabled(const void *blob, int node)
return 1;
}
-enum fdt_compat_id fd_dec_lookup(const void *blob, int node)
+enum fdt_compat_id fdtdec_lookup(const void *blob, int node)
{
enum fdt_compat_id id;
@@ -173,7 +164,7 @@ int fdtdec_next_alias(const void *blob, const char *name,
/* snprintf() is not available */
assert(strlen(name) < MAX_STR_LEN);
sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
- node = find_alias_node(blob, str);
+ node = fdt_path_offset(blob, str);
if (node < 0)
return node;
err = fdt_node_check_compatible(blob, node, compat_names[id]);
@@ -428,9 +419,8 @@ int fdtdec_get_bool(const void *blob, int node, const char *prop_name)
* @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would
* be exceeded, or -FDT_ERR_NOTFOUND if the property is missing.
*/
-static int fdtdec_decode_gpios(const void *blob, int node,
- const char *prop_name, struct fdt_gpio_state *gpio,
- int max_count)
+int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name,
+ struct fdt_gpio_state *gpio, int max_count)
{
const struct fdt_property *prop;
const u32 *cell;
@@ -477,6 +467,26 @@ int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name,
return err == 1 ? 0 : err;
}
+int fdtdec_get_gpio(struct fdt_gpio_state *gpio)
+{
+ int val;
+
+ if (!fdt_gpio_isvalid(gpio))
+ return -1;
+
+ val = gpio_get_value(gpio->gpio);
+ return gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val;
+}
+
+int fdtdec_set_gpio(struct fdt_gpio_state *gpio, int val)
+{
+ if (!fdt_gpio_isvalid(gpio))
+ return -1;
+
+ val = gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val;
+ return gpio_set_value(gpio->gpio, val);
+}
+
int fdtdec_setup_gpio(struct fdt_gpio_state *gpio)
{
/*
@@ -514,3 +524,64 @@ const u8 *fdtdec_locate_byte_array(const void *blob, int node,
return NULL;
return cell;
}
+
+int fdtdec_get_config_int(const void *blob, const char *prop_name,
+ int default_val)
+{
+ int config_node;
+
+ debug("%s: %s\n", __func__, prop_name);
+ config_node = fdt_path_offset(blob, "/config");
+ if (config_node < 0)
+ return default_val;
+ return fdtdec_get_int(blob, config_node, prop_name, default_val);
+}
+
+int fdtdec_get_config_bool(const void *blob, const char *prop_name)
+{
+ int config_node;
+ const void *prop;
+
+ debug("%s: %s\n", __func__, prop_name);
+ config_node = fdt_path_offset(blob, "/config");
+ if (config_node < 0)
+ return 0;
+ prop = fdt_get_property(blob, config_node, prop_name, NULL);
+
+ return prop != NULL;
+}
+
+char *fdtdec_get_config_string(const void *blob, const char *prop_name)
+{
+ const char *nodep;
+ int nodeoffset;
+ int len;
+
+ debug("%s: %s\n", __func__, prop_name);
+ nodeoffset = fdt_path_offset(blob, "/config");
+ if (nodeoffset < 0)
+ return NULL;
+
+ nodep = fdt_getprop(blob, nodeoffset, prop_name, &len);
+ if (!nodep)
+ return NULL;
+
+ return (char *)nodep;
+}
+
+int fdtdec_decode_region(const void *blob, int node,
+ const char *prop_name, void **ptrp, size_t *size)
+{
+ const fdt_addr_t *cell;
+ int len;
+
+ debug("%s: %s\n", __func__, prop_name);
+ cell = fdt_getprop(blob, node, prop_name, &len);
+ if (!cell || (len != sizeof(fdt_addr_t) * 2))
+ return -1;
+
+ *ptrp = (void *)fdt_addr_to_cpu(*cell);
+ *size = fdt_size_to_cpu(cell[1]);
+ debug("%s: size=%zx\n", __func__, *size);
+ return 0;
+}
diff --git a/lib/lzma/LzmaDec.c b/lib/lzma/LzmaDec.c
index f941da27dd..4f45f80fe2 100644
--- a/lib/lzma/LzmaDec.c
+++ b/lib/lzma/LzmaDec.c
@@ -1,5 +1,5 @@
/* LzmaDec.c -- LZMA Decoder
-2008-11-06 : Igor Pavlov : Public domain */
+2009-09-20 : Igor Pavlov : Public domain */
#include <config.h>
#include <common.h>
@@ -116,12 +116,6 @@
StopCompilingDueBUG
#endif
-static const Byte kLiteralNextStates[kNumStates * 2] =
-{
- 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5,
- 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
-};
-
#define LZMA_DIC_MIN (1 << 12)
/* First LZMA-symbol is always decoded.
@@ -180,6 +174,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (state < kNumLitStates)
{
+ state -= (state < 4) ? state : 3;
symbol = 1;
WATCHDOG_RESET();
@@ -190,6 +185,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
{
unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
unsigned offs = 0x100;
+ state -= (state < 10) ? 3 : 6;
symbol = 1;
WATCHDOG_RESET();
@@ -207,9 +203,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
}
dic[dicPos++] = (Byte)symbol;
processedPos++;
-
- state = kLiteralNextStates[state];
- /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
continue;
}
else
@@ -395,7 +388,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
else if (distance >= checkDicSize)
return SZ_ERROR_DATA;
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
- /* state = kLiteralNextStates[state]; */
}
len += kMatchMinLen;
diff --git a/lib/lzma/LzmaDec.h b/lib/lzma/LzmaDec.h
index 7fba87f076..63aa505e8c 100644
--- a/lib/lzma/LzmaDec.h
+++ b/lib/lzma/LzmaDec.h
@@ -1,8 +1,8 @@
/* LzmaDec.h -- LZMA Decoder
-2008-10-04 : Igor Pavlov : Public domain */
+2009-02-07 : Igor Pavlov : Public domain */
-#ifndef __LZMADEC_H
-#define __LZMADEC_H
+#ifndef __LZMA_DEC_H
+#define __LZMA_DEC_H
#include "Types.h"
diff --git a/lib/lzma/Types.h b/lib/lzma/Types.h
index 1af5cfc4d8..8afcba556e 100644
--- a/lib/lzma/Types.h
+++ b/lib/lzma/Types.h
@@ -1,5 +1,5 @@
/* Types.h -- Basic types
-2008-11-23 : Igor Pavlov : Public domain */
+2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
@@ -65,9 +65,11 @@ typedef unsigned long UInt64;
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
+#define UINT64_CONST(n) n
#else
typedef long long int Int64;
typedef unsigned long long int UInt64;
+#define UINT64_CONST(n) n ## ULL
#endif
#endif
@@ -92,13 +94,11 @@ typedef int Bool;
#endif
#define MY_CDECL __cdecl
-#define MY_STD_CALL __stdcall
-#define MY_FAST_CALL MY_NO_INLINE __fastcall
+#define MY_FAST_CALL __fastcall
#else
#define MY_CDECL
-#define MY_STD_CALL
#define MY_FAST_CALL
#endif
@@ -108,6 +108,16 @@ typedef int Bool;
typedef struct
{
+ Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
+} IByteIn;
+
+typedef struct
+{
+ void (*Write)(void *p, Byte b);
+} IByteOut;
+
+typedef struct
+{
SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
@@ -140,7 +150,7 @@ typedef struct
typedef struct
{
- SRes (*Look)(void *p, void **buf, size_t *size);
+ SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */
@@ -205,4 +215,20 @@ typedef struct
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
+#ifdef _WIN32
+
+#define CHAR_PATH_SEPARATOR '\\'
+#define WCHAR_PATH_SEPARATOR L'\\'
+#define STRING_PATH_SEPARATOR "\\"
+#define WSTRING_PATH_SEPARATOR L"\\"
+
+#else
+
+#define CHAR_PATH_SEPARATOR '/'
+#define WCHAR_PATH_SEPARATOR L'/'
+#define STRING_PATH_SEPARATOR "/"
+#define WSTRING_PATH_SEPARATOR L"/"
+
+#endif
+
#endif
diff --git a/lib/lzma/history.txt b/lib/lzma/history.txt
index aadf8255ed..443511bdd4 100644
--- a/lib/lzma/history.txt
+++ b/lib/lzma/history.txt
@@ -1,6 +1,41 @@
HISTORY of the LZMA SDK
-----------------------
+9.18 beta 2010-11-02
+-------------------------
+- New small SFX module for installers (SfxSetup).
+
+
+9.12 beta 2010-03-24
+-------------------------
+- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work,
+ if more than 10 threads were used (or more than 20 threads in some modes).
+
+
+9.11 beta 2010-03-15
+-------------------------
+- PPMd compression method support
+
+
+9.09 2009-12-12
+-------------------------
+- The bug was fixed:
+ Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c
+ incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8.
+- Some bugs were fixed
+
+
+9.06 2009-08-17
+-------------------------
+- Some changes in ANSI-C 7z Decoder interfaces.
+
+
+9.04 2009-05-30
+-------------------------
+- LZMA2 compression method support
+- xz format support
+
+
4.65 2009-02-03
-------------------------
- Some minor fixes
diff --git a/lib/lzma/lzma.txt b/lib/lzma/lzma.txt
index aa20f9dc5c..144cd9aee2 100644
--- a/lib/lzma/lzma.txt
+++ b/lib/lzma/lzma.txt
@@ -1,4 +1,4 @@
-LZMA SDK 4.65
+LZMA SDK 9.20
-------------
LZMA SDK provides the documentation, samples, header files, libraries,
@@ -20,6 +20,10 @@ LICENSE
LZMA SDK is written and placed in the public domain by Igor Pavlov.
+Some code in LZMA SDK is based on public domain code from another developers:
+ 1) PPMd var.H (2001): Dmitry Shkarin
+ 2) SHA-256: Wei Dai (Crypto++ library)
+
LZMA SDK Contents
-----------------
@@ -33,7 +37,7 @@ LZMA SDK includes:
UNIX/Linux version
------------------
To compile C++ version of file->file LZMA encoding, go to directory
-C++/7zip/Compress/LZMA_Alone
+CPP/7zip/Bundles/LzmaCon
and call make to recompile it:
make -f makefile.gcc clean all
@@ -49,6 +53,7 @@ lzma.txt - LZMA SDK description (this file)
7zC.txt - 7z ANSI-C Decoder description
methods.txt - Compression method IDs for .7z
lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
+7zr.exe - 7-Zip with 7z/lzma/xz support.
history.txt - history of the LZMA SDK
@@ -66,7 +71,7 @@ C/ - C files
LzmaEnc.* - LZMA encoding
LzmaLib.* - LZMA Library for DLL calling
Types.h - Basic types for another .c files
- Threads.* - The code for multithreading.
+ Threads.* - The code for multithreading.
LzmaLib - LZMA Library (.DLL for Windows)
@@ -86,12 +91,6 @@ CPP/ -- CPP files
Compress - files related to compression/decompression
- Copy - Copy coder
- RangeCoder - Range Coder (special code of compression/decompression)
- LZMA - LZMA compression/decompression on C++
- LZMA_Alone - file->file LZMA compression/decompression
- Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
-
Archive - files related to archiving
Common - common files for archive handling
@@ -100,6 +99,7 @@ CPP/ -- CPP files
Bundles - Modules that are bundles of other modules
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
+ LzmaCon - lzma.exe: LZMA compression/decompression
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
@@ -369,8 +369,8 @@ Interface:
propData - LZMA properties (5 bytes)
propSize - size of propData buffer (5 bytes)
finishMode - It has meaning only if the decoding reaches output limit (*destLen).
- LZMA_FINISH_ANY - Decode just destLen bytes.
- LZMA_FINISH_END - Stream must be finished after (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
You can use LZMA_FINISH_END, when you know that
current output buffer covers last bytes of stream.
alloc - Memory allocator.
@@ -431,7 +431,7 @@ Memory Requirements:
{
...
int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
- const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
...
}
@@ -527,7 +527,8 @@ static ISzAlloc g_Alloc = { SzAlloc, SzFree };
LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
-If callback function return some error code, LzmaEnc_Encode also returns that code.
+If callback function return some error code, LzmaEnc_Encode also returns that code
+or it can return the code like SZ_ERROR_READ, SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.
Single-call RAM->RAM Compression
@@ -549,8 +550,8 @@ Return code:
-LZMA Defines
-------------
+Defines
+-------
_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
@@ -562,6 +563,9 @@ _LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is
_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type.
+_7ZIP_PPMD_SUPPPORT - Define it if you don't want to support PPMD method in AMSI-C .7z decoder.
+
+
C++ LZMA Encoder/Decoder
~~~~~~~~~~~~~~~~~~~~~~~~
C++ LZMA code use COM-like interfaces. So if you want to use it,
diff --git a/lib/physmem.c b/lib/physmem.c
new file mode 100644
index 0000000000..0f035edcbe
--- /dev/null
+++ b/lib/physmem.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#include <common.h>
+#include <physmem.h>
+
+static phys_addr_t __arch_phys_memset(phys_addr_t s, int c, phys_size_t n)
+{
+ void *s_ptr = (void *)(uintptr_t)s;
+
+ assert(((phys_addr_t)(uintptr_t)s) == s);
+ assert(((phys_addr_t)(uintptr_t)(s + n)) == s + n);
+ return (phys_addr_t)(uintptr_t)memset(s_ptr, c, n);
+}
+
+phys_addr_t arch_phys_memset(phys_addr_t s, int c, phys_size_t n)
+ __attribute__((weak, alias("__arch_phys_memset")));
diff --git a/nand_spl/board/freescale/mpc8536ds/Makefile b/nand_spl/board/freescale/mpc8536ds/Makefile
index e5388d89c8..9c778261b6 100644
--- a/nand_spl/board/freescale/mpc8536ds/Makefile
+++ b/nand_spl/board/freescale/mpc8536ds/Makefile
@@ -39,7 +39,7 @@ AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL
SOBJS = start.o resetvec.o
-COBJS = cache.o cpu_init_early.o cpu_init_nand.o fsl_law.o law.o \
+COBJS = cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
nand_boot.o nand_boot_fsl_elbc.o ns16550.o tlb.o tlb_table.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
@@ -67,7 +67,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot-nand_spl.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)/board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
# create symbolic links for common files
@@ -79,13 +80,13 @@ $(obj)cpu_init_early.c:
@rm -f $(obj)cpu_init_early.c
ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_early.c $(obj)cpu_init_early.c
-$(obj)cpu_init_nand.c:
- @rm -f $(obj)cpu_init_nand.c
- ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c $(obj)cpu_init_nand.c
+$(obj)spl_minimal.c:
+ @rm -f $(obj)spl_minimal.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/spl_minimal.c $(obj)spl_minimal.c
$(obj)fsl_law.c:
@rm -f $(obj)fsl_law.c
- ln -sf $(SRCTREE)/drivers/misc/fsl_law.c $(obj)fsl_law.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
$(obj)law.c:
@rm -f $(obj)law.c
diff --git a/nand_spl/board/freescale/mpc8569mds/Makefile b/nand_spl/board/freescale/mpc8569mds/Makefile
index e5388d89c8..9c778261b6 100644
--- a/nand_spl/board/freescale/mpc8569mds/Makefile
+++ b/nand_spl/board/freescale/mpc8569mds/Makefile
@@ -39,7 +39,7 @@ AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL
SOBJS = start.o resetvec.o
-COBJS = cache.o cpu_init_early.o cpu_init_nand.o fsl_law.o law.o \
+COBJS = cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
nand_boot.o nand_boot_fsl_elbc.o ns16550.o tlb.o tlb_table.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
@@ -67,7 +67,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot-nand_spl.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)/board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
# create symbolic links for common files
@@ -79,13 +80,13 @@ $(obj)cpu_init_early.c:
@rm -f $(obj)cpu_init_early.c
ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_early.c $(obj)cpu_init_early.c
-$(obj)cpu_init_nand.c:
- @rm -f $(obj)cpu_init_nand.c
- ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c $(obj)cpu_init_nand.c
+$(obj)spl_minimal.c:
+ @rm -f $(obj)spl_minimal.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/spl_minimal.c $(obj)spl_minimal.c
$(obj)fsl_law.c:
@rm -f $(obj)fsl_law.c
- ln -sf $(SRCTREE)/drivers/misc/fsl_law.c $(obj)fsl_law.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
$(obj)law.c:
@rm -f $(obj)law.c
diff --git a/nand_spl/board/freescale/mpc8572ds/Makefile b/nand_spl/board/freescale/mpc8572ds/Makefile
index e5388d89c8..9c778261b6 100644
--- a/nand_spl/board/freescale/mpc8572ds/Makefile
+++ b/nand_spl/board/freescale/mpc8572ds/Makefile
@@ -39,7 +39,7 @@ AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL
SOBJS = start.o resetvec.o
-COBJS = cache.o cpu_init_early.o cpu_init_nand.o fsl_law.o law.o \
+COBJS = cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
nand_boot.o nand_boot_fsl_elbc.o ns16550.o tlb.o tlb_table.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
@@ -67,7 +67,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot-nand_spl.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)/board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
# create symbolic links for common files
@@ -79,13 +80,13 @@ $(obj)cpu_init_early.c:
@rm -f $(obj)cpu_init_early.c
ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_early.c $(obj)cpu_init_early.c
-$(obj)cpu_init_nand.c:
- @rm -f $(obj)cpu_init_nand.c
- ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c $(obj)cpu_init_nand.c
+$(obj)spl_minimal.c:
+ @rm -f $(obj)spl_minimal.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/spl_minimal.c $(obj)spl_minimal.c
$(obj)fsl_law.c:
@rm -f $(obj)fsl_law.c
- ln -sf $(SRCTREE)/drivers/misc/fsl_law.c $(obj)fsl_law.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
$(obj)law.c:
@rm -f $(obj)law.c
diff --git a/nand_spl/board/freescale/mx31pdk/Makefile b/nand_spl/board/freescale/mx31pdk/Makefile
index 43e72c42d4..f67ed09d03 100644
--- a/nand_spl/board/freescale/mx31pdk/Makefile
+++ b/nand_spl/board/freescale/mx31pdk/Makefile
@@ -42,7 +42,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)/board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
#########################################################################
diff --git a/nand_spl/board/freescale/p1010rdb/Makefile b/nand_spl/board/freescale/p1010rdb/Makefile
index f270faae02..c3495ec0df 100644
--- a/nand_spl/board/freescale/p1010rdb/Makefile
+++ b/nand_spl/board/freescale/p1010rdb/Makefile
@@ -39,9 +39,8 @@ AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL
SOBJS = start.o resetvec.o ticks.o
-COBJS = cache.o cpu_init_early.o cpu_init_nand.o fsl_law.o law.o \
- nand_boot.o nand_boot_fsl_ifc.o ns16550.o tlb.o tlb_table.o \
- ../common.o
+COBJS = cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
+ nand_boot.o nand_boot_fsl_ifc.o ns16550.o tlb.o tlb_table.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
@@ -68,7 +67,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot-nand_spl.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
# create symbolic links for common files
@@ -80,13 +80,13 @@ $(obj)cpu_init_early.c:
@rm -f $(obj)cpu_init_early.c
ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_early.c $(obj)cpu_init_early.c
-$(obj)cpu_init_nand.c:
- @rm -f $(obj)cpu_init_nand.c
- ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_nand.c $(obj)cpu_init_nand.c
+$(obj)spl_minimal.c:
+ @rm -f $(obj)spl_minimal.c
+ ln -sf $(SRCTREE)/$(CPUDIR)/spl_minimal.c $(obj)spl_minimal.c
$(obj)fsl_law.c:
@rm -f $(obj)fsl_law.c
- ln -sf $(SRCTREE)/drivers/misc/fsl_law.c $(obj)fsl_law.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
$(obj)law.c:
@rm -f $(obj)law.c
@@ -129,9 +129,6 @@ ifneq ($(OBJTREE), $(SRCTREE))
$(obj)nand_boot.c:
@rm -f $(obj)nand_boot.c
ln -s $(SRCTREE)/nand_spl/board/$(BOARDDIR)/nand_boot.c $(obj)nand_boot.c
-$(obj)../common.c:
- @rm -f $(obj)../common.c
- ln -s $(SRCTREE)/nand_spl/board/freescale/common.c $(obj)../common.c
endif
#########################################################################
diff --git a/nand_spl/board/freescale/p1010rdb/nand_boot.c b/nand_spl/board/freescale/p1010rdb/nand_boot.c
index 9c356901b1..3c7bc2bc65 100644
--- a/nand_spl/board/freescale/p1010rdb/nand_boot.c
+++ b/nand_spl/board/freescale/p1010rdb/nand_boot.c
@@ -35,7 +35,7 @@ unsigned long ddr_freq_mhz;
void sdram_init(void)
{
- ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
/* mask off E bit */
u32 svr = SVR_SOC_VER(mfspr(SPRN_SVR));
diff --git a/nand_spl/board/freescale/p1023rds/Makefile b/nand_spl/board/freescale/p1023rds/Makefile
index b2882844b3..9b2c0d7f35 100644
--- a/nand_spl/board/freescale/p1023rds/Makefile
+++ b/nand_spl/board/freescale/p1023rds/Makefile
@@ -34,9 +34,8 @@ AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL
SOBJS = start.o resetvec.o
-COBJS = cache.o cpu_init_early.o cpu_init_nand.o fsl_law.o law.o \
- nand_boot.o nand_boot_fsl_elbc.o ns16550.o tlb.o tlb_table.o \
- ../common.o
+COBJS = cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
+ nand_boot.o nand_boot_fsl_elbc.o ns16550.o tlb.o tlb_table.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
@@ -63,7 +62,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot-nand_spl.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)/board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
# create symbolic links for common files
@@ -75,13 +75,13 @@ $(obj)cpu_init_early.c:
@rm -f $(obj)cpu_init_early.c
ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_early.c $(obj)cpu_init_early.c
-$(obj)cpu_init_nand.c:
- @rm -f $(obj)cpu_init_nand.c
- ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_nand.c $(obj)cpu_init_nand.c
+$(obj)spl_minimal.c:
+ @rm -f $(obj)spl_minimal.c
+ ln -sf $(SRCTREE)/$(CPUDIR)/spl_minimal.c $(obj)spl_minimal.c
$(obj)fsl_law.c:
@rm -f $(obj)fsl_law.c
- ln -sf $(SRCTREE)/drivers/misc/fsl_law.c $(obj)fsl_law.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
$(obj)law.c:
@rm -f $(obj)law.c
@@ -120,9 +120,6 @@ ifneq ($(OBJTREE), $(SRCTREE))
$(obj)nand_boot.c:
@rm -f $(obj)nand_boot.c
ln -s $(SRCTREE)/nand_spl/board/$(BOARDDIR)/nand_boot.c $(obj)nand_boot.c
-$(obj)../common.c:
- @rm -f $(obj)../common.c
- ln -s $(SRCTREE)/nand_spl/board/freescale/common.c $(obj)../common.c
endif
#########################################################################
diff --git a/nand_spl/board/freescale/p1023rds/nand_boot.c b/nand_spl/board/freescale/p1023rds/nand_boot.c
index 89e339d512..d6756fbf80 100644
--- a/nand_spl/board/freescale/p1023rds/nand_boot.c
+++ b/nand_spl/board/freescale/p1023rds/nand_boot.c
@@ -33,7 +33,7 @@ DECLARE_GLOBAL_DATA_PTR;
/* Fixed sdram init -- doesn't use serial presence detect. */
void sdram_init(void)
{
- ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC85xx_DDR_ADDR;
+ ccsr_ddr_t *ddr = (ccsr_ddr_t *)CONFIG_SYS_MPC8xxx_DDR_ADDR;
set_next_law(0, LAW_SIZE_2G, LAW_TRGT_IF_DDR_1);
diff --git a/nand_spl/board/freescale/p1_p2_rdb/Makefile b/nand_spl/board/freescale/p1_p2_rdb/Makefile
index e5388d89c8..9c778261b6 100644
--- a/nand_spl/board/freescale/p1_p2_rdb/Makefile
+++ b/nand_spl/board/freescale/p1_p2_rdb/Makefile
@@ -39,7 +39,7 @@ AFLAGS += -DCONFIG_NAND_SPL
CFLAGS += -DCONFIG_NAND_SPL
SOBJS = start.o resetvec.o
-COBJS = cache.o cpu_init_early.o cpu_init_nand.o fsl_law.o law.o \
+COBJS = cache.o cpu_init_early.o spl_minimal.o fsl_law.o law.o \
nand_boot.o nand_boot_fsl_elbc.o ns16550.o tlb.o tlb_table.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
@@ -67,7 +67,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot-nand_spl.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)/board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
# create symbolic links for common files
@@ -79,13 +80,13 @@ $(obj)cpu_init_early.c:
@rm -f $(obj)cpu_init_early.c
ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_early.c $(obj)cpu_init_early.c
-$(obj)cpu_init_nand.c:
- @rm -f $(obj)cpu_init_nand.c
- ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/cpu_init_nand.c $(obj)cpu_init_nand.c
+$(obj)spl_minimal.c:
+ @rm -f $(obj)spl_minimal.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc85xx/spl_minimal.c $(obj)spl_minimal.c
$(obj)fsl_law.c:
@rm -f $(obj)fsl_law.c
- ln -sf $(SRCTREE)/drivers/misc/fsl_law.c $(obj)fsl_law.c
+ ln -sf $(SRCTREE)/arch/powerpc/cpu/mpc8xxx/law.c $(obj)fsl_law.c
$(obj)law.c:
@rm -f $(obj)law.c
diff --git a/nand_spl/board/freescale/p1_p2_rdb_pc/Makefile b/nand_spl/board/freescale/p1_p2_rdb_pc/Makefile
deleted file mode 100644
index 7146d16a27..0000000000
--- a/nand_spl/board/freescale/p1_p2_rdb_pc/Makefile
+++ /dev/null
@@ -1,146 +0,0 @@
-#
-# (C) Copyright 2007
-# Stefan Roese, DENX Software Engineering, sr@denx.de.
-#
-# 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
-#
-
-NAND_SPL := y
-CONFIG_SYS_TEXT_BASE_SPL := 0xfff00000
-PAD_TO := 0xff801000
-
-include $(TOPDIR)/config.mk
-
-nandobj := $(OBJTREE)/nand_spl/
-
-LDSCRIPT= $(TOPDIR)/$(CPUDIR)/u-boot-nand_spl.lds
-LSTSCRIPT= $(nandobj)/board/$(BOARDDIR)/u-boot.lst
-LDFLAGS := -T $(nandobj)u-boot-nand_spl.lds -Ttext $(CONFIG_SYS_TEXT_BASE_SPL) \
- $(LDFLAGS) $(LDFLAGS_FINAL)
-AFLAGS += -DCONFIG_NAND_SPL
-CFLAGS += -DCONFIG_NAND_SPL
-
-SOBJS = start.o resetvec.o
-COBJS = cache.o cpu_init_early.o cpu_init_nand.o fsl_law.o law.o \
- nand_boot.o nand_boot_fsl_elbc.o ns16550.o tlb.o tlb_table.o \
- ../common.o
-
-SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
-OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
-__OBJS := $(SOBJS) $(COBJS)
-LNDIR := $(nandobj)board/$(BOARDDIR)
-
-ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin
-
-all: $(obj).depend $(ALL)
-
-$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl
- $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@
-
-$(nandobj)u-boot-spl.bin: $(nandobj)u-boot-spl
- $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
-
-$(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot-nand_spl.lds
- cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) $(PLATFORM_LIBS) \
- -Map $(nandobj)u-boot-spl.map \
- -o $(nandobj)u-boot-spl
-
-# The following line expands into whole rule which generates $(LSTSCRIPT),
-# the file containing u-boots LG-array linker section. This is included into
-# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
-$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
-$(nandobj)u-boot-nand_spl.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
-
-# create symbolic links for common files
-
-$(obj)cache.c:
- @rm -f $(obj)cache.c
- ln -sf $(SRCTREE)/arch/powerpc/lib/cache.c $(obj)cache.c
-
-$(obj)cpu_init_early.c:
- @rm -f $(obj)cpu_init_early.c
- ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_early.c $(obj)cpu_init_early.c
-
-$(obj)cpu_init_nand.c:
- @rm -f $(obj)cpu_init_nand.c
- ln -sf $(SRCTREE)/$(CPUDIR)/cpu_init_nand.c $(obj)cpu_init_nand.c
-
-$(obj)fsl_law.c:
- @rm -f $(obj)fsl_law.c
- ln -sf $(SRCTREE)/drivers/misc/fsl_law.c $(obj)fsl_law.c
-
-$(obj)law.c:
- @rm -f $(obj)law.c
- ln -sf $(SRCTREE)/board/$(BOARDDIR)/law.c $(obj)law.c
-
-$(obj)nand_boot_fsl_elbc.c:
- @rm -f $(obj)nand_boot_fsl_elbc.c
- ln -sf $(SRCTREE)/nand_spl/nand_boot_fsl_elbc.c \
- $(obj)nand_boot_fsl_elbc.c
-
-$(obj)ns16550.c:
- @rm -f $(obj)ns16550.c
- ln -sf $(SRCTREE)/drivers/serial/ns16550.c $(obj)ns16550.c
-
-$(obj)resetvec.S:
- @rm -f $(obj)resetvec.S
- ln -s $(SRCTREE)/$(CPUDIR)/resetvec.S $(obj)resetvec.S
-
-$(obj)fixed_ivor.S:
- @rm -f $(obj)fixed_ivor.S
- ln -sf $(SRCTREE)/$(CPUDIR)/fixed_ivor.S $(obj)fixed_ivor.S
-
-$(obj)start.S: $(obj)fixed_ivor.S
- @rm -f $(obj)start.S
- ln -sf $(SRCTREE)/$(CPUDIR)/start.S $(obj)start.S
-
-$(obj)tlb.c:
- @rm -f $(obj)tlb.c
- ln -sf $(SRCTREE)/$(CPUDIR)/tlb.c $(obj)tlb.c
-
-$(obj)tlb_table.c:
- @rm -f $(obj)tlb_table.c
- ln -sf $(SRCTREE)/board/$(BOARDDIR)/tlb.c $(obj)tlb_table.c
-
-ifneq ($(OBJTREE), $(SRCTREE))
-$(obj)nand_boot.c:
- @rm -f $(obj)nand_boot.c
- ln -s $(SRCTREE)/nand_spl/board/$(BOARDDIR)/nand_boot.c $(obj)nand_boot.c
-$(obj)../common.c:
- @rm -f $(obj)../common.c
- ln -s $(SRCTREE)/nand_spl/board/freescale/common.c $(obj)../common.c
-endif
-
-#########################################################################
-
-$(obj)%.o: $(obj)%.S
- $(CC) $(AFLAGS) -c -o $@ $<
-
-$(obj)%.o: $(obj)%.c
- $(CC) $(CFLAGS) -c -o $@ $<
-
-# defines $(obj).depend target
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
diff --git a/nand_spl/board/karo/tx25/Makefile b/nand_spl/board/karo/tx25/Makefile
index becf7fa99e..b27189d9b5 100644
--- a/nand_spl/board/karo/tx25/Makefile
+++ b/nand_spl/board/karo/tx25/Makefile
@@ -63,7 +63,8 @@ $(nandobj)u-boot-spl: $(OBJS) $(nandobj)u-boot.lds
# $(LDSCRIPT). The function make_u_boot_list is defined in helper.mk file.
$(eval $(call make_u_boot_list, $(LSTSCRIPT), $(OBJS)))
$(nandobj)u-boot.lds: $(LDSCRIPT) $(LSTSCRIPT)
- $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(obj) -ansi -D__ASSEMBLY__ -P - <$< >$@
+ $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -I$(nandobj)/board/$(BOARDDIR) \
+ -ansi -D__ASSEMBLY__ -P - <$< >$@
#########################################################################
diff --git a/spl/Makefile b/spl/Makefile
index 6a79c3cd38..6dbb1055b6 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -32,9 +32,30 @@ START_PATH := $(CPUDIR)
endif
START := $(START_PATH)/start.o
+ifeq ($(CPU),x86)
+START += $(START_PATH)/start16.o
+START += $(START_PATH)/resetvec.o
+endif
+ifeq ($(CPU),ppc4xx)
+START += $(START_PATH)/resetvec.o
+endif
+ifeq ($(CPU),mpc85xx)
+START += $(START_PATH)/resetvec.o
+endif
LIBS-y += arch/$(ARCH)/lib/lib$(ARCH).o
+
LIBS-y += $(CPUDIR)/lib$(CPU).o
+ifeq ($(CPU),mpc83xx)
+LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
+endif
+ifeq ($(CPU),mpc85xx)
+LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
+endif
+ifeq ($(CPU),mpc86xx)
+LIBS-y += arch/powerpc/cpu/mpc8xxx/lib8xxx.o
+endif
+
ifdef SOC
LIBS-y += $(CPUDIR)/$(SOC)/lib$(SOC).o
endif
diff --git a/tools/patman/series.py b/tools/patman/series.py
index a283a2d1f4..d2971f4898 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -145,10 +145,11 @@ class Series(dict):
Return:
The change log as a list of strings, one per line
- Changes in v2:
+ Changes in v4:
- Jog the dial back closer to the widget
- Changes in v1:
+ Changes in v3: None
+ Changes in v2:
- Fix the widget
- Jog the dial
@@ -162,12 +163,16 @@ class Series(dict):
if commit and this_commit != commit:
continue
out.append(text)
- if out:
- out = ['Changes in v%d:' % change] + out
- if need_blank:
- out = [''] + out
- final += out
- need_blank = True
+ line = 'Changes in v%d:' % change
+ have_changes = len(out) > 0
+ if have_changes:
+ out.insert(0, line)
+ else:
+ out = [line + ' None']
+ if need_blank:
+ out.insert(0, '')
+ final += out
+ need_blank = have_changes
if self.changes:
final.append('')
return final